[Patches] fix overflow bug in ldexp(x, exp)

Guido van Rossum guido@python.org
Tue, 09 May 2000 10:05:27 -0400


[me]
> > On Solaris 2.7, I'm now getting this:
> > 
> >   >>> ldexp(1, 100000000)
> >   Traceback (most recent call last):
> >     File "<stdin>", line 1, in ?
> >   OverflowError: math range error
> >   >>> ldexp(1, sys.maxint-1)
> >   Traceback (most recent call last):
> >     File "<stdin>", line 1, in ?
> >   OverflowError: math range error
> >   >>> ldexp(1, sys.maxint)			# this takes a second or two...
> >   Infinity					# ...expected OverflowError!
> >   >>>
> > 
> > I have a feeling though that this is a bug in the C math library --
> > not sure if it's worth fixing.  On Linux I get an OverflowError as
> > expected for sys.maxint.

[Trent]
> It seems to me, as well, that that is a C math library bug. It is not
> returning an ERANGE errno. Can you reproduce this with a simple C program, on
> Solaris?
> 
> #include <stdio.h>
> #include <math.h>
> #include <errno.h>
> #include <linits.h>

<limits.h> !

> int main(void)
> {
> 	double x;
> 	printf("ldexp(1.0, %d)=%lf\n", INT_MAX, ldexp(1.0, INT_MAX));
> 	printf("errno = %d (ERANGE=%d)\n", errno, ERANGE);
> }

This takes over a second to run and then prints

ldexp(1.0, 2147483647)=Inf
errno = 0 (ERANGE=34)

Clearly a C library bug.  I won't bother to report it to Sun.

> > Note that ldexp(1, 3.14) is still accepted!  The 'i' format calls
> > tp_int for floats and int(3.14) is 3.
> 
> That is another matter. I don't know what I should expect the 'i' formatter
> to do. It calls PyInt_AsLong. Should PyInt_AsLong complain if it is given a
> PyFloatObject? That is a philosophical question that is kind of moot here
> (its behaviour is not going to change).

See other discusssion.  I agree.

> I think that ldexp() should *not* accept a float for the 'exp' argument
> because the rounding to an int is not obvious to the user. I suppose the 'O&'
> formatter could be used with a special converter that raises a TypeError if
> the argument is not an integral type (i.e. PyInt or PyLong). Is it worth
> making that change? Is it even desired to make that change because it might
> break some code out there.

See other discussion.  It's not worth the change -- too many other
places suffer in the same way.

--Guido van Rossum (home page: http://www.python.org/~guido/)