[Python-Dev] Progress report on PEP 242

Tim Peters tim.one@home.com
Sun, 8 Apr 2001 02:41:55 -0400


[Paul F. Dubois]
> If I understand correctly I need to supply a reference implementation
> for PEP 242.

Somebody does, but not necessarily you.

> I have made considerable progress on this:

Cool!  I'm glad it was you <wink>.

> C:\Paul\Numerical\Packages\kinds>python
> Python 2.1b2 (#12, Mar 23 2001, 14:01:30) [MSC 32 bit (Intel)] on win32
> Type "copyright", "credits" or "license" for more information.
> >>> import kinds
> >>> f=kinds.float_kind(5,100)
> >>> f.max
> 1.7976931348623157e+308

What type of float is the result?  Is that defined?  Of the same float kind
as requested?  Or of some fixed float kind?  Or does/can it vary across
attributes?

> >>> f.min
> 2.2250738585072014e-308

Is it customary to ignore the existence of denorms?  All the same to me, but
since that's not the smallest positive non-zero double on a 754 box, the name
"min" is a fiction.  If it's a *useful* fiction, fine.

> >>> f.epsilon
> 2.2204460492503131e-016
> >>> f.radix
> 0.3010299956639812

I expect that, if you really try, you can think of a better name <wink -- but
log10radix would make a lot more sense here; + see below>.

> >>> f.epsilonbyradix
> 1.1102230246251565e-016
>
> These five attributes are the standard ones computed by routines such
> as d1mach.
> (See netlib.org, search for d1mach).

There are several.  Most are Fortran routines that ask you to first uncomment
the correct section of hard-coded DATA stmts for the platform you're running
on.  I trust you're using a dynamic approach.

Question:  are these attributes useful enough in the absence of the model
parameters from I1MACH?  That is, D1MACH exposes an idealized floating point
model approximating machine reality, parameterized by a base (radix), number
of digits, and minimum and maximum exponents.  Those four are all integers,
so were traditionally exposed via I1MACH instead (at I1MACH indices 10, 14,
15 and 16).  I expect people would find it useful if you exposed those as
attributes too, i.e. hypothetically continuing the above:

>>> f.radix  # assuming existing f.radix renamed
2
>>> f.numdigits
53
>>> f.emin
-1021
>>> f.emax
1024
>>>

Then the explanation of what the other attributes *mean* is easy, relating
them directly to the idealized f.p. model D1MACH is based on:

f.log10radix = log10(f.radix)
f.epsilon = f.radix ** (1-f.numdigits)
f.epsilonbyradix = f.radix ** -f.numdigits
f.min = f.radix ** (f.emin - 1)
f.max = f.radix**f.emax * (1 - f.epsilonbyradix)

(That last one isn't numerically correct, but mathematically; in code you'd
have to write it

    math.ldexp(1.0 - f.epsilonbyradix, f.emax)

and assuming f.radix is 2).  Note that exposing this stuff also makes clearer
why f.min doesn't tell the hardware's notion of truth for 754 boxes.

> These attributes I made up:
>
> f.name ('Float' in this case)

Since you're extending Python's floating type system with precision & range
parameters, I'd much rather see this one called 'double', since you're
obviously using a box with IEEE-754 doubles here, and all C implementations I
know of call this a double too; I expect that 99+% of all F77 implementations
also call this one double.  In addition, I expect you'll soon deal with IEEE
singles too, and then the question "single or double?" makes clear sense, but
"single or float?" is just baffling.

> f.typecode ('d' in this case, a typecode suitable for modules array or
> Numeric

Yet another reason to start f.name with "d", right?  Right <wink>.