Index: Include/longobject.h =================================================================== --- Include/longobject.h (révision 70631) +++ Include/longobject.h (copie de travail) @@ -33,12 +33,12 @@ PyAPI_DATA(int) _PyLong_DigitValue[256]; /* _PyLong_AsScaledDouble returns a double x and an exponent e such that - the true value is approximately equal to x * 2**(SHIFT*e). e is >= 0. + the true value is approximately equal to x * 2**e. x is 0.0 if and only if the input is 0 (in which case, e and x are both zeroes). Overflow is impossible. Note that the exponent returned must be multiplied by SHIFT! There may not be enough room in an int to store e*SHIFT directly. */ -PyAPI_FUNC(double) _PyLong_AsScaledDouble(PyObject *vv, int *e); +PyAPI_FUNC(double) _PyLong_AsScaledDouble(PyObject *vv, unsigned int *e); PyAPI_FUNC(double) PyLong_AsDouble(PyObject *); PyAPI_FUNC(PyObject *) PyLong_FromVoidPtr(void *); Index: Objects/longobject.c =================================================================== --- Objects/longobject.c (révision 70631) +++ Objects/longobject.c (copie de travail) @@ -676,8 +676,12 @@ } +/** + * Convert a long integer into result * 2^exponent. If exponent is + * bigger than INT_MAX, return -1.0 and raise an OverflowError. + */ double -_PyLong_AsScaledDouble(PyObject *vv, int *exponent) +_PyLong_AsScaledDouble(PyObject *vv, unsigned int *exponent) { /* NBITS_WANTED should be > the number of bits in a double's precision, but small enough so that 2**NBITS_WANTED is within the normal double @@ -723,10 +727,17 @@ } /* There are i digits we didn't shift in. Pretending they're all zeroes, the true value is x * 2**(i*PyLong_SHIFT). */ - *exponent = i; + if (i > UINT_MAX / PyLong_SHIFT) + goto overflow; + *exponent = (unsigned long)i * PyLong_SHIFT; assert(x > 0.0); return x * sign; #undef NBITS_WANTED + +overflow: + PyErr_SetString(PyExc_OverflowError, + "Python int too large to convert to C double"); + return -1.0; } /* Get a C double from a long int object. */ @@ -734,7 +745,7 @@ double PyLong_AsDouble(PyObject *vv) { - int e = -1; + unsigned int e; double x; if (vv == NULL || !PyLong_Check(vv)) { @@ -744,13 +755,8 @@ x = _PyLong_AsScaledDouble(vv, &e); if (x == -1.0 && PyErr_Occurred()) return -1.0; - /* 'e' initialized to -1 to silence gcc-4.0.x, but it should be - set correctly after a successful _PyLong_AsScaledDouble() call */ - assert(e >= 0); - if (e > INT_MAX / PyLong_SHIFT) - goto overflow; errno = 0; - x = ldexp(x, e * PyLong_SHIFT); + x = ldexp(x, e); if (Py_OVERFLOWED(x)) goto overflow; return x; @@ -2714,7 +2720,8 @@ { PyLongObject *a, *b; double ad, bd; - int failed, aexp = -1, bexp = -1; + int failed, exp; + unsigned int aexp, bexp; CONVERT_BINOP(v, w, &a, &b); ad = _PyLong_AsScaledDouble((PyObject *)a, &aexp); @@ -2724,10 +2731,6 @@ Py_DECREF(b); if (failed) return NULL; - /* 'aexp' and 'bexp' were initialized to -1 to silence gcc-4.0.x, - but should really be set correctly after sucessful calls to - _PyLong_AsScaledDouble() */ - assert(aexp >= 0 && bexp >= 0); if (bd == 0.0) { PyErr_SetString(PyExc_ZeroDivisionError, @@ -2735,15 +2738,11 @@ return NULL; } - /* True value is very close to ad/bd * 2**(PyLong_SHIFT*(aexp-bexp)) */ + /* True value is very close to ad/bd * 2**(aexp-bexp) */ ad /= bd; /* overflow/underflow impossible here */ - aexp -= bexp; - if (aexp > INT_MAX / PyLong_SHIFT) - goto overflow; - else if (aexp < -(INT_MAX / PyLong_SHIFT)) - return PyFloat_FromDouble(0.0); /* underflow to 0 */ + exp = (int)aexp - bexp; errno = 0; - ad = ldexp(ad, aexp * PyLong_SHIFT); + ad = ldexp(ad, exp); if (Py_OVERFLOWED(ad)) /* ignore underflow to 0.0 */ goto overflow; return PyFloat_FromDouble(ad); Index: Modules/mathmodule.c =================================================================== --- Modules/mathmodule.c (révision 70631) +++ Modules/mathmodule.c (copie de travail) @@ -783,18 +783,18 @@ /* If it is long, do it ourselves. */ if (PyLong_Check(arg)) { double x; - int e; + unsigned int e; x = _PyLong_AsScaledDouble(arg, &e); + if (x == -1.0 && PyErr_Occurred()) + return NULL; if (x <= 0.0) { PyErr_SetString(PyExc_ValueError, "math domain error"); return NULL; } - /* Value is ~= x * 2**(e*PyLong_SHIFT), so the log ~= - log(x) + log(2) * e * PyLong_SHIFT. - CAUTION: e*PyLong_SHIFT may overflow using int arithmetic, - so force use of double. */ - x = func(x) + (e * (double)PyLong_SHIFT) * func(2.0); + /* Value is ~= x * 2**e, + * so the log ~= log(x) + log(2) * e */ + x = func(x) + e * func(2.0); return PyFloat_FromDouble(x); }