diff options
author | Christian Heimes <christian@cheimes.de> | 2008-04-19 00:31:39 (GMT) |
---|---|---|
committer | Christian Heimes <christian@cheimes.de> | 2008-04-19 00:31:39 (GMT) |
commit | 53876d9cd8a67d9e67772e082deab92a598f74b3 (patch) | |
tree | 2d605900cab56cbfe55c6ca6e41f1a0c0cb6f91b /Objects | |
parent | dc3e06ce3a24882a6b68ec19544910095770111e (diff) | |
download | cpython-53876d9cd8a67d9e67772e082deab92a598f74b3.zip cpython-53876d9cd8a67d9e67772e082deab92a598f74b3.tar.gz cpython-53876d9cd8a67d9e67772e082deab92a598f74b3.tar.bz2 |
Merged revisions 62380,62382-62383 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r62380 | christian.heimes | 2008-04-19 01:13:07 +0200 (Sat, 19 Apr 2008) | 3 lines
I finally got the time to update and merge Mark's and my trunk-math branch. The patch is collaborated work of Mark Dickinson and me. It was mostly done a few months ago. The patch fixes a lot of loose ends and edge cases related to operations with NaN, INF, very small values and complex math.
The patch also adds acosh, asinh, atanh, log1p and copysign to all platforms. Finally it fixes differences between platforms like different results or exceptions for edge cases. Have fun :)
........
r62382 | christian.heimes | 2008-04-19 01:40:40 +0200 (Sat, 19 Apr 2008) | 2 lines
Added new files to Windows project files
More Windows related fixes are coming soon
........
r62383 | christian.heimes | 2008-04-19 01:49:11 +0200 (Sat, 19 Apr 2008) | 1 line
Stupid me. Py_RETURN_NAN should actually return something ...
........
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/complexobject.c | 64 | ||||
-rw-r--r-- | Objects/doubledigits.c | 601 | ||||
-rw-r--r-- | Objects/floatobject.c | 201 | ||||
-rw-r--r-- | Objects/longobject.c | 12 |
4 files changed, 150 insertions, 728 deletions
diff --git a/Objects/complexobject.c b/Objects/complexobject.c index 90b970e..acd5a4a 100644 --- a/Objects/complexobject.c +++ b/Objects/complexobject.c @@ -187,6 +187,38 @@ c_powi(Py_complex x, long n) } +double +c_abs(Py_complex z) +{ + /* sets errno = ERANGE on overflow; otherwise errno = 0 */ + double result; + + if (!Py_IS_FINITE(z.real) || !Py_IS_FINITE(z.imag)) { + /* C99 rules: if either the real or the imaginary part is an + infinity, return infinity, even if the other part is a + NaN. */ + if (Py_IS_INFINITY(z.real)) { + result = fabs(z.real); + errno = 0; + return result; + } + if (Py_IS_INFINITY(z.imag)) { + result = fabs(z.imag); + errno = 0; + return result; + } + /* either the real or imaginary part is a NaN, + and neither is infinite. Result should be NaN. */ + return Py_NAN; + } + result = hypot(z.real, z.imag); + if (!Py_IS_FINITE(result)) + errno = ERANGE; + else + errno = 0; + return result; +} + static PyObject * complex_subtype_from_c_complex(PyTypeObject *type, Py_complex cval) { @@ -321,8 +353,7 @@ complex_to_buf(char *buf, int bufsz, PyComplexObject *v, int precision) if (!Py_IS_FINITE(v->cval.imag)) { if (Py_IS_NAN(v->cval.imag)) strncpy(buf, "nan*j", 6); - /* else if (copysign(1, v->cval.imag) == 1) */ - else if (v->cval.imag > 0) + else if (copysign(1, v->cval.imag) == 1) strncpy(buf, "inf*j", 6); else strncpy(buf, "-inf*j", 7); @@ -578,9 +609,16 @@ static PyObject * complex_abs(PyComplexObject *v) { double result; + PyFPE_START_PROTECT("complex_abs", return 0) - result = hypot(v->cval.real,v->cval.imag); + result = c_abs(v->cval); PyFPE_END_PROTECT(result) + + if (errno == ERANGE) { + PyErr_SetString(PyExc_OverflowError, + "absolute value too large"); + return NULL; + } return PyFloat_FromDouble(result); } @@ -658,9 +696,29 @@ complex_getnewargs(PyComplexObject *v) return Py_BuildValue("(D)", &v->cval); } +#if 0 +static PyObject * +complex_is_finite(PyObject *self) +{ + Py_complex c; + c = ((PyComplexObject *)self)->cval; + return PyBool_FromLong((long)(Py_IS_FINITE(c.real) && + Py_IS_FINITE(c.imag))); +} + +PyDoc_STRVAR(complex_is_finite_doc, +"complex.is_finite() -> bool\n" +"\n" +"Returns True if the real and the imaginary part is finite."); +#endif + static PyMethodDef complex_methods[] = { {"conjugate", (PyCFunction)complex_conjugate, METH_NOARGS, complex_conjugate_doc}, +#if 0 + {"is_finite", (PyCFunction)complex_is_finite, METH_NOARGS, + complex_is_finite_doc}, +#endif {"__getnewargs__", (PyCFunction)complex_getnewargs, METH_NOARGS}, {NULL, NULL} /* sentinel */ }; diff --git a/Objects/doubledigits.c b/Objects/doubledigits.c deleted file mode 100644 index 1f1c91c..0000000 --- a/Objects/doubledigits.c +++ /dev/null @@ -1,601 +0,0 @@ -/* Free-format floating point printer - * - * Based on "Floating-Point Printer Sample Code", by Robert G. Burger, - * http://www.cs.indiana.edu/~burger/fp/index.html - */ - -#include "Python.h" - -#if defined(__alpha) || defined(__i386) || defined(_M_IX86) || defined(_M_X64) || defined(_M_IA64) -#define LITTLE_ENDIAN_IEEE_DOUBLE -#elif !(defined(__ppc__) || defined(sparc) || defined(__sgi) || defined(_IBMR2) || defined(hpux)) -#error unknown machine type -#endif - -#if defined(_M_IX86) -#define UNSIGNED64 unsigned __int64 -#elif defined(__alpha) -#define UNSIGNED64 unsigned long -#else -#define UNSIGNED64 unsigned long long -#endif - -#ifndef U32 -#define U32 unsigned int -#endif - -/* exponent stored + 1024, hidden bit to left of decimal point */ -#define bias 1023 -#define bitstoright 52 -#define m1mask 0xf -#define hidden_bit 0x100000 -#ifdef LITTLE_ENDIAN_IEEE_DOUBLE -struct dblflt { - unsigned int m4: 16; - unsigned int m3: 16; - unsigned int m2: 16; - unsigned int m1: 4; - unsigned int e: 11; - unsigned int s: 1; -}; -#else -/* Big Endian IEEE Double Floats */ -struct dblflt { - unsigned int s: 1; - unsigned int e: 11; - unsigned int m1: 4; - unsigned int m2: 16; - unsigned int m3: 16; - unsigned int m4: 16; -}; -#endif -#define float_radix 2.147483648e9 - - -typedef UNSIGNED64 Bigit; -#define BIGSIZE 24 -#define MIN_E -1074 -#define MAX_FIVE 325 -#define B_P1 ((Bigit)1 << 52) - -typedef struct { - int l; - Bigit d[BIGSIZE]; -} Bignum; - -static Bignum R, S, MP, MM, five[MAX_FIVE]; -static Bignum S2, S3, S4, S5, S6, S7, S8, S9; -static int ruf, k, s_n, use_mp, qr_shift, sl, slr; - -static void mul10(Bignum *x); -static void big_short_mul(Bignum *x, Bigit y, Bignum *z); -/* -static void print_big(Bignum *x); -*/ -static int estimate(int n); -static void one_shift_left(int y, Bignum *z); -static void short_shift_left(Bigit x, int y, Bignum *z); -static void big_shift_left(Bignum *x, int y, Bignum *z); -static int big_comp(Bignum *x, Bignum *y); -static int sub_big(Bignum *x, Bignum *y, Bignum *z); -static void add_big(Bignum *x, Bignum *y, Bignum *z); -static int add_cmp(void); -static int qr(void); - -/*static int _PyFloat_Digits(char *buf, double v, int *signum);*/ -/*static void _PyFloat_DigitsInit(void);*/ - -#define ADD(x, y, z, k) {\ - Bigit x_add, z_add;\ - x_add = (x);\ - if ((k))\ - z_add = x_add + (y) + 1, (k) = (z_add <= x_add);\ - else\ - z_add = x_add + (y), (k) = (z_add < x_add);\ - (z) = z_add;\ -} - -#define SUB(x, y, z, b) {\ - Bigit x_sub, y_sub;\ - x_sub = (x); y_sub = (y);\ - if ((b))\ - (z) = x_sub - y_sub - 1, b = (y_sub >= x_sub);\ - else\ - (z) = x_sub - y_sub, b = (y_sub > x_sub);\ -} - -#define MUL(x, y, z, k) {\ - Bigit x_mul, low, high;\ - x_mul = (x);\ - low = (x_mul & 0xffffffff) * (y) + (k);\ - high = (x_mul >> 32) * (y) + (low >> 32);\ - (k) = high >> 32;\ - (z) = (low & 0xffffffff) | (high << 32);\ -} - -#define SLL(x, y, z, k) {\ - Bigit x_sll = (x);\ - (z) = (x_sll << (y)) | (k);\ - (k) = x_sll >> (64 - (y));\ -} - -static void -mul10(Bignum *x) -{ - int i, l; - Bigit *p, k; - - l = x->l; - for (i = l, p = &x->d[0], k = 0; i >= 0; i--) - MUL(*p, 10, *p++, k); - if (k != 0) - *p = k, x->l = l+1; -} - -static void -big_short_mul(Bignum *x, Bigit y, Bignum *z) -{ - int i, xl, zl; - Bigit *xp, *zp, k; - U32 high, low; - - xl = x->l; - xp = &x->d[0]; - zl = xl; - zp = &z->d[0]; - high = y >> 32; - low = y & 0xffffffff; - for (i = xl, k = 0; i >= 0; i--, xp++, zp++) { - Bigit xlow, xhigh, z0, t, c, z1; - xlow = *xp & 0xffffffff; - xhigh = *xp >> 32; - z0 = (xlow * low) + k; /* Cout is (z0 < k) */ - t = xhigh * low; - z1 = (xlow * high) + t; - c = (z1 < t); - t = z0 >> 32; - z1 += t; - c += (z1 < t); - *zp = (z1 << 32) | (z0 & 0xffffffff); - k = (xhigh * high) + (c << 32) + (z1 >> 32) + (z0 < k); - } - if (k != 0) - *zp = k, zl++; - z->l = zl; -} - -/* -static void -print_big(Bignum *x) -{ - int i; - Bigit *p; - - printf("#x"); - i = x->l; - p = &x->d[i]; - for (p = &x->d[i]; i >= 0; i--) { - Bigit b = *p--; - printf("%08x%08x", (int)(b >> 32), (int)(b & 0xffffffff)); - } -} -*/ - -static int -estimate(int n) -{ - if (n < 0) - return (int)(n*0.3010299956639812); - else - return 1+(int)(n*0.3010299956639811); -} - -static void -one_shift_left(int y, Bignum *z) -{ - int n, m, i; - Bigit *zp; - - n = y / 64; - m = y % 64; - zp = &z->d[0]; - for (i = n; i > 0; i--) *zp++ = 0; - *zp = (Bigit)1 << m; - z->l = n; -} - -static void -short_shift_left(Bigit x, int y, Bignum *z) -{ - int n, m, i, zl; - Bigit *zp; - - n = y / 64; - m = y % 64; - zl = n; - zp = &(z->d[0]); - for (i = n; i > 0; i--) *zp++ = 0; - if (m == 0) - *zp = x; - else { - Bigit high = x >> (64 - m); - *zp = x << m; - if (high != 0) - *++zp = high, zl++; - } - z->l = zl; -} - -static void -big_shift_left(Bignum *x, int y, Bignum *z) -{ - int n, m, i, xl, zl; - Bigit *xp, *zp, k; - - n = y / 64; - m = y % 64; - xl = x->l; - xp = &(x->d[0]); - zl = xl + n; - zp = &(z->d[0]); - for (i = n; i > 0; i--) *zp++ = 0; - if (m == 0) - for (i = xl; i >= 0; i--) *zp++ = *xp++; - else { - for (i = xl, k = 0; i >= 0; i--) - SLL(*xp++, m, *zp++, k); - if (k != 0) - *zp = k, zl++; - } - z->l = zl; -} - - -static int -big_comp(Bignum *x, Bignum *y) -{ - int i, xl, yl; - Bigit *xp, *yp; - - xl = x->l; - yl = y->l; - if (xl > yl) return 1; - if (xl < yl) return -1; - xp = &x->d[xl]; - yp = &y->d[xl]; - for (i = xl; i >= 0; i--, xp--, yp--) { - Bigit a = *xp; - Bigit b = *yp; - - if (a > b) return 1; - else if (a < b) return -1; - } - return 0; -} - -static int -sub_big(Bignum *x, Bignum *y, Bignum *z) -{ - int xl, yl, zl, b, i; - Bigit *xp, *yp, *zp; - - xl = x->l; - yl = y->l; - if (yl > xl) return 1; - xp = &x->d[0]; - yp = &y->d[0]; - zp = &z->d[0]; - - for (i = yl, b = 0; i >= 0; i--) - SUB(*xp++, *yp++, *zp++, b); - for (i = xl-yl; b && i > 0; i--) { - Bigit x_sub; - x_sub = *xp++; - *zp++ = x_sub - 1; - b = (x_sub == 0); - } - for (; i > 0; i--) *zp++ = *xp++; - if (b) return 1; - zl = xl; - while (*--zp == 0) zl--; - z->l = zl; - return 0; -} - -static void -add_big(Bignum *x, Bignum *y, Bignum *z) -{ - int xl, yl, k, i; - Bigit *xp, *yp, *zp; - - xl = x->l; - yl = y->l; - if (yl > xl) { - int tl; - Bignum *tn; - tl = xl; xl = yl; yl = tl; - tn = x; x = y; y = tn; - } - - xp = &x->d[0]; - yp = &y->d[0]; - zp = &z->d[0]; - - for (i = yl, k = 0; i >= 0; i--) - ADD(*xp++, *yp++, *zp++, k); - for (i = xl-yl; k && i > 0; i--) { - Bigit z_add; - z_add = *xp++ + 1; - k = (z_add == 0); - *zp++ = z_add; - } - for (; i > 0; i--) *zp++ = *xp++; - if (k) - *zp = 1, z->l = xl+1; - else - z->l = xl; -} - -static int -add_cmp() -{ - int rl, ml, sl, suml; - static Bignum sum; - - rl = R.l; - ml = (use_mp ? MP.l : MM.l); - sl = S.l; - - suml = rl >= ml ? rl : ml; - if ((sl > suml+1) || ((sl == suml+1) && (S.d[sl] > 1))) return -1; - if (sl < suml) return 1; - - add_big(&R, (use_mp ? &MP : &MM), &sum); - return big_comp(&sum, &S); -} - -static int -qr() -{ - if (big_comp(&R, &S5) < 0) - if (big_comp(&R, &S2) < 0) - if (big_comp(&R, &S) < 0) - return 0; - else { - sub_big(&R, &S, &R); - return 1; - } - else if (big_comp(&R, &S3) < 0) { - sub_big(&R, &S2, &R); - return 2; - } - else if (big_comp(&R, &S4) < 0) { - sub_big(&R, &S3, &R); - return 3; - } - else { - sub_big(&R, &S4, &R); - return 4; - } - else if (big_comp(&R, &S7) < 0) - if (big_comp(&R, &S6) < 0) { - sub_big(&R, &S5, &R); - return 5; - } - else { - sub_big(&R, &S6, &R); - return 6; - } - else if (big_comp(&R, &S9) < 0) - if (big_comp(&R, &S8) < 0) { - sub_big(&R, &S7, &R); - return 7; - } - else { - sub_big(&R, &S8, &R); - return 8; - } - else { - sub_big(&R, &S9, &R); - return 9; - } -} - -#define OUTDIG(d) { *buf++ = (d) + '0'; *buf = 0; return k; } - -int -_PyFloat_Digits(char *buf, double v, int *signum) -{ - struct dblflt *x; - int sign, e, f_n, m_n, i, d, tc1, tc2; - Bigit f; - - /* decompose float into sign, mantissa & exponent */ - x = (struct dblflt *)&v; - sign = x->s; - e = x->e; - f = (Bigit)(x->m1 << 16 | x->m2) << 32 | (U32)(x->m3 << 16 | x->m4); - if (e != 0) { - e = e - bias - bitstoright; - f |= (Bigit)hidden_bit << 32; - } - else if (f != 0) - /* denormalized */ - e = 1 - bias - bitstoright; - - *signum = sign; - if (f == 0) { - *buf++ = '0'; - *buf = 0; - return 0; - } - - ruf = !(f & 1); /* ruf = (even? f) */ - - /* Compute the scaling factor estimate, k */ - if (e > MIN_E) - k = estimate(e+52); - else { - int n; - Bigit y; - - for (n = e+52, y = (Bigit)1 << 52; f < y; n--) y >>= 1; - k = estimate(n); - } - - if (e >= 0) - if (f != B_P1) - use_mp = 0, f_n = e+1, s_n = 1, m_n = e; - else - use_mp = 1, f_n = e+2, s_n = 2, m_n = e; - else - if ((e == MIN_E) || (f != B_P1)) - use_mp = 0, f_n = 1, s_n = 1-e, m_n = 0; - else - use_mp = 1, f_n = 2, s_n = 2-e, m_n = 0; - - /* Scale it! */ - if (k == 0) { - short_shift_left(f, f_n, &R); - one_shift_left(s_n, &S); - one_shift_left(m_n, &MM); - if (use_mp) one_shift_left(m_n+1, &MP); - qr_shift = 1; - } - else if (k > 0) { - s_n += k; - if (m_n >= s_n) - f_n -= s_n, m_n -= s_n, s_n = 0; - else - f_n -= m_n, s_n -= m_n, m_n = 0; - short_shift_left(f, f_n, &R); - big_shift_left(&five[k-1], s_n, &S); - one_shift_left(m_n, &MM); - if (use_mp) one_shift_left(m_n+1, &MP); - qr_shift = 0; - } - else { - Bignum *power = &five[-k-1]; - - s_n += k; - big_short_mul(power, f, &S); - big_shift_left(&S, f_n, &R); - one_shift_left(s_n, &S); - big_shift_left(power, m_n, &MM); - if (use_mp) big_shift_left(power, m_n+1, &MP); - qr_shift = 1; - } - - /* fixup */ - if (add_cmp() <= -ruf) { - k--; - mul10(&R); - mul10(&MM); - if (use_mp) mul10(&MP); - } - - /* - printf("\nk = %d\n", k); - printf("R = "); print_big(&R); - printf("\nS = "); print_big(&S); - printf("\nM- = "); print_big(&MM); - if (use_mp) printf("\nM+ = "), print_big(&MP); - putchar('\n'); - fflush(0); - */ - - if (qr_shift) { - sl = s_n / 64; - slr = s_n % 64; - } - else { - big_shift_left(&S, 1, &S2); - add_big(&S2, &S, &S3); - big_shift_left(&S2, 1, &S4); - add_big(&S4, &S, &S5); - add_big(&S4, &S2, &S6); - add_big(&S4, &S3, &S7); - big_shift_left(&S4, 1, &S8); - add_big(&S8, &S, &S9); - } - -again: - if (qr_shift) { /* Take advantage of the fact that S = (ash 1 s_n) */ - if (R.l < sl) - d = 0; - else if (R.l == sl) { - Bigit *p; - - p = &R.d[sl]; - d = *p >> slr; - *p &= ((Bigit)1 << slr) - 1; - for (i = sl; (i > 0) && (*p == 0); i--) p--; - R.l = i; - } - else { - Bigit *p; - - p = &R.d[sl+1]; - d = *p << (64 - slr) | *(p-1) >> slr; - p--; - *p &= ((Bigit)1 << slr) - 1; - for (i = sl; (i > 0) && (*p == 0); i--) p--; - R.l = i; - } - } - else /* We need to do quotient-remainder */ - d = qr(); - - tc1 = big_comp(&R, &MM) < ruf; - tc2 = add_cmp() > -ruf; - if (!tc1) - if (!tc2) { - mul10(&R); - mul10(&MM); - if (use_mp) mul10(&MP); - *buf++ = d + '0'; - goto again; - } - else - OUTDIG(d+1) - else - if (!tc2) - OUTDIG(d) - else { - big_shift_left(&R, 1, &MM); - if (big_comp(&MM, &S) == -1) - OUTDIG(d) - else - OUTDIG(d+1) - } -} - -void -_PyFloat_DigitsInit() -{ - int n, i, l; - Bignum *b; - Bigit *xp, *zp, k; - - five[0].l = l = 0; - five[0].d[0] = 5; - for (n = MAX_FIVE-1, b = &five[0]; n > 0; n--) { - xp = &b->d[0]; - b++; - zp = &b->d[0]; - for (i = l, k = 0; i >= 0; i--) - MUL(*xp++, 5, *zp++, k); - if (k != 0) - *zp = k, l++; - b->l = l; - } - - /* - for (n = 1, b = &five[0]; n <= MAX_FIVE; n++) { - big_shift_left(b++, n, &R); - print_big(&R); - putchar('\n'); - } - fflush(0); - */ -} diff --git a/Objects/floatobject.c b/Objects/floatobject.c index 745dfc3..a748abb 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -16,10 +16,6 @@ #include <ieeefp.h> #endif -#if !defined(__STDC__) -extern double fmod(double, double); -extern double pow(double, double); -#endif #ifdef _OSF_SOURCE /* OSF1 5.1 doesn't make this available with XOPEN_SOURCE_EXTENDED defined */ @@ -224,11 +220,11 @@ PyFloat_FromString(PyObject *v) p++; } if (PyOS_strnicmp(p, "inf", 4) == 0) { - return PyFloat_FromDouble(sign * Py_HUGE_VAL); + Py_RETURN_INF(sign); } #ifdef Py_NAN if(PyOS_strnicmp(p, "nan", 4) == 0) { - return PyFloat_FromDouble(Py_NAN); + Py_RETURN_NAN; } #endif PyOS_snprintf(buffer, sizeof(buffer), @@ -378,110 +374,6 @@ format_float(char *buf, size_t buflen, PyFloatObject *v, int precision) format_double(buf, buflen, PyFloat_AS_DOUBLE(v), precision); } -#ifdef Py_BROKEN_REPR -/* The following function is based on Tcl_PrintDouble, - * from tclUtil.c. - */ - -#define is_infinite(d) ( (d) > DBL_MAX || (d) < -DBL_MAX ) -#define is_nan(d) ((d) != (d)) - -static void -format_double_repr(char *dst, double value) -{ - char *p, c; - int exp; - int signum; - char buffer[30]; - - /* - * Handle NaN. - */ - - if (is_nan(value)) { - strcpy(dst, "nan"); - return; - } - - /* - * Handle infinities. - */ - - if (is_infinite(value)) { - if (value < 0) { - strcpy(dst, "-inf"); - } else { - strcpy(dst, "inf"); - } - return; - } - - /* - * Ordinary (normal and denormal) values. - */ - - exp = _PyFloat_Digits(buffer, value, &signum)+1; - if (signum) { - *dst++ = '-'; - } - p = buffer; - if (exp < -3 || exp > 17) { - /* - * E format for numbers < 1e-3 or >= 1e17. - */ - - *dst++ = *p++; - c = *p; - if (c != '\0') { - *dst++ = '.'; - while (c != '\0') { - *dst++ = c; - c = *++p; - } - } - sprintf(dst, "e%+d", exp-1); - } else { - /* - * F format for others. - */ - - if (exp <= 0) { - *dst++ = '0'; - } - c = *p; - while (exp-- > 0) { - if (c != '\0') { - *dst++ = c; - c = *++p; - } else { - *dst++ = '0'; - } - } - *dst++ = '.'; - if (c == '\0') { - *dst++ = '0'; - } else { - while (++exp < 0) { - *dst++ = '0'; - } - while (c != '\0') { - *dst++ = c; - c = *++p; - } - } - *dst++ = '\0'; - } -} - -static void -format_float_repr(char *buf, PyFloatObject *v) -{ - assert(PyFloat_Check(v)); - format_double_repr(buf, PyFloat_AS_DOUBLE(v)); -} - -#endif /* Py_BROKEN_REPR */ - /* Macro and helper that convert PyObject obj to a C double and store the value in dbl. If conversion to double raises an exception, obj is set to NULL, and the function invoking this macro returns NULL. If @@ -534,13 +426,8 @@ convert_to_double(PyObject **v, double *dbl) static PyObject * float_repr(PyFloatObject *v) { -#ifdef Py_BROKEN_REPR - char buf[30]; - format_float_repr(buf, v); -#else char buf[100]; format_float(buf, sizeof(buf), v, PREC_REPR); -#endif return PyUnicode_FromString(buf); } @@ -804,10 +691,13 @@ float_div(PyObject *v, PyObject *w) double a,b; CONVERT_TO_DOUBLE(v, a); CONVERT_TO_DOUBLE(w, b); +#ifdef Py_NAN if (b == 0.0) { - PyErr_SetString(PyExc_ZeroDivisionError, "float division"); + PyErr_SetString(PyExc_ZeroDivisionError, + "float division"); return NULL; } +#endif PyFPE_START_PROTECT("divide", return 0) a = a / b; PyFPE_END_PROTECT(a) @@ -819,12 +709,15 @@ float_rem(PyObject *v, PyObject *w) { double vx, wx; double mod; - CONVERT_TO_DOUBLE(v, vx); - CONVERT_TO_DOUBLE(w, wx); + CONVERT_TO_DOUBLE(v, vx); + CONVERT_TO_DOUBLE(w, wx); +#ifdef Py_NAN if (wx == 0.0) { - PyErr_SetString(PyExc_ZeroDivisionError, "float modulo"); + PyErr_SetString(PyExc_ZeroDivisionError, + "float modulo"); return NULL; } +#endif PyFPE_START_PROTECT("modulo", return 0) mod = fmod(vx, wx); /* note: checking mod*wx < 0 is incorrect -- underflows to @@ -928,6 +821,9 @@ float_pow(PyObject *v, PyObject *w, PyObject *z) } return PyFloat_FromDouble(0.0); } + if (iv == 1.0) { /* 1**w is 1, even 1**inf and 1**nan */ + return PyFloat_FromDouble(1.0); + } if (iv < 0.0) { /* Whether this is an error is a mess, and bumps into libm * bugs so we have to figure it out ourselves. @@ -995,6 +891,57 @@ float_bool(PyFloatObject *v) } static PyObject * +float_is_integer(PyObject *v) +{ + double x = PyFloat_AsDouble(v); + PyObject *o; + + if (x == -1.0 && PyErr_Occurred()) + return NULL; + if (!Py_IS_FINITE(x)) + Py_RETURN_FALSE; + PyFPE_START_PROTECT("is_integer", return NULL) + o = (floor(x) == x) ? Py_True : Py_False; + PyFPE_END_PROTECT(x) + if (errno != 0) { + PyErr_SetFromErrno(errno == ERANGE ? PyExc_OverflowError : + PyExc_ValueError); + return NULL; + } + Py_INCREF(o); + return o; +} + +#if 0 +static PyObject * +float_is_inf(PyObject *v) +{ + double x = PyFloat_AsDouble(v); + if (x == -1.0 && PyErr_Occurred()) + return NULL; + return PyBool_FromLong((long)Py_IS_INFINITY(x)); +} + +static PyObject * +float_is_nan(PyObject *v) +{ + double x = PyFloat_AsDouble(v); + if (x == -1.0 && PyErr_Occurred()) + return NULL; + return PyBool_FromLong((long)Py_IS_NAN(x)); +} + +static PyObject * +float_is_finite(PyObject *v) +{ + double x = PyFloat_AsDouble(v); + if (x == -1.0 && PyErr_Occurred()) + return NULL; + return PyBool_FromLong((long)Py_IS_FINITE(x)); +} +#endif + +static PyObject * float_trunc(PyObject *v) { double x = PyFloat_AsDouble(v); @@ -1368,7 +1315,7 @@ PyDoc_STRVAR(float__format__doc, static PyMethodDef float_methods[] = { - {"conjugate", (PyCFunction)float_float, METH_NOARGS, + {"conjugate", (PyCFunction)float_float, METH_NOARGS, "Returns self, the complex conjugate of any float."}, {"__trunc__", (PyCFunction)float_trunc, METH_NOARGS, "Returns the Integral closest to x between 0 and x."}, @@ -1377,6 +1324,16 @@ static PyMethodDef float_methods[] = { "When an argument is passed, works like built-in round(x, ndigits)."}, {"as_integer_ratio", (PyCFunction)float_as_integer_ratio, METH_NOARGS, float_as_integer_ratio_doc}, + {"is_integer", (PyCFunction)float_is_integer, METH_NOARGS, + "Returns True if the float is an integer."}, +#if 0 + {"is_inf", (PyCFunction)float_is_inf, METH_NOARGS, + "Returns True if the float is positive or negative infinite."}, + {"is_finite", (PyCFunction)float_is_finite, METH_NOARGS, + "Returns True if the float is finite, neither infinite nor NaN."}, + {"is_nan", (PyCFunction)float_is_nan, METH_NOARGS, + "Returns True if the float is not a number (NaN)."}, +#endif {"__getnewargs__", (PyCFunction)float_getnewargs, METH_NOARGS}, {"__getformat__", (PyCFunction)float_getformat, METH_O|METH_CLASS, float_getformat_doc}, @@ -1534,10 +1491,6 @@ _PyFloat_Init(void) double_format = detected_double_format; float_format = detected_float_format; -#ifdef Py_BROKEN_REPR - /* Initialize floating point repr */ - _PyFloat_DigitsInit(); -#endif /* Init float info */ if (FloatInfoType.tp_name == 0) PyStructSequence_InitType(&FloatInfoType, &floatinfo_desc); diff --git a/Objects/longobject.c b/Objects/longobject.c index 44b040c..d88a13e 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -3611,9 +3611,21 @@ long_round(PyObject *self, PyObject *args) #undef UNDEF_NDIGITS } +#if 0 +static PyObject * +long_is_finite(PyObject *v) +{ + Py_RETURN_TRUE; +} +#endif + static PyMethodDef long_methods[] = { {"conjugate", (PyCFunction)long_long, METH_NOARGS, "Returns self, the complex conjugate of any int."}, +#if 0 + {"is_finite", (PyCFunction)long_is_finite, METH_NOARGS, + "Returns always True."}, +#endif {"__trunc__", (PyCFunction)long_long, METH_NOARGS, "Truncating an Integral returns itself."}, {"__floor__", (PyCFunction)long_long, METH_NOARGS, |