| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent a7a2dbb commit 7a3b035
12 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -64,8 +64,6 @@ PyAPI_FUNC(double) _Py_dg_strtod(const char *str, char **ptr); | |||
| 64 | 64 | PyAPI_FUNC(char *) _Py_dg_dtoa(double d, int mode, int ndigits, | |
| 65 | 65 | int *decpt, int *sign, char **rve); | |
| 66 | 66 | PyAPI_FUNC(void) _Py_dg_freedtoa(char *s); | |
| 67 | - PyAPI_FUNC(double) _Py_dg_stdnan(int sign); | ||
| 68 | - PyAPI_FUNC(double) _Py_dg_infinity(int sign); | ||
| 69 | 67 | ||
| 70 | 68 | #endif // _PY_SHORT_FLOAT_REPR == 1 | |
| 71 | 69 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -39,27 +39,24 @@ | |||
| 39 | 39 | // Return 1 if float or double arg is neither infinite nor NAN, else 0. | |
| 40 | 40 | #define Py_IS_FINITE(X) isfinite(X) | |
| 41 | 41 | ||
| 42 | - /* HUGE_VAL is supposed to expand to a positive double infinity. Python | ||
| 43 | - * uses Py_HUGE_VAL instead because some platforms are broken in this | ||
| 44 | - * respect. We used to embed code in pyport.h to try to worm around that, | ||
| 45 | - * but different platforms are broken in conflicting ways. If you're on | ||
| 46 | - * a platform where HUGE_VAL is defined incorrectly, fiddle your Python | ||
| 47 | - * config to #define Py_HUGE_VAL to something that works on your platform. | ||
| 42 | + // Py_INFINITY: Value that evaluates to a positive double infinity. | ||
| 43 | + #ifndef Py_INFINITY | ||
| 44 | + # define Py_INFINITY ((double)INFINITY) | ||
| 45 | + #endif | ||
| 46 | + | ||
| 47 | + /* Py_HUGE_VAL should always be the same as Py_INFINITY. But historically | ||
| 48 | + * this was not reliable and Python did not require IEEE floats and C99 | ||
| 49 | + * conformity. Prefer Py_INFINITY for new code. | ||
| 48 | 50 | */ | |
| 49 | 51 | #ifndef Py_HUGE_VAL | |
| 50 | 52 | # define Py_HUGE_VAL HUGE_VAL | |
| 51 | 53 | #endif | |
| 52 | 54 | ||
| 53 | - // Py_NAN: Value that evaluates to a quiet Not-a-Number (NaN). | ||
| 55 | + /* Py_NAN: Value that evaluates to a quiet Not-a-Number (NaN). The sign is | ||
| 56 | + * undefined and normally not relevant, but e.g. fixed for float("nan"). | ||
| 57 | + */ | ||
| 54 | 58 | #if !defined(Py_NAN) | |
| 55 | - # if _Py__has_builtin(__builtin_nan) | ||
| 56 | - // Built-in implementation of the ISO C99 function nan(): quiet NaN. | ||
| 57 | - # define Py_NAN (__builtin_nan("")) | ||
| 58 | - #else | ||
| 59 | - // Use C99 NAN constant: quiet Not-A-Number. | ||
| 60 | - // NAN is a float, Py_NAN is a double: cast to double. | ||
| 61 | 59 | # define Py_NAN ((double)NAN) | |
| 62 | - # endif | ||
| 63 | 60 | #endif | |
| 64 | 61 | ||
| 65 | 62 | #endif /* Py_PYMATH_H */ | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -166,6 +166,11 @@ def test_infinity_and_nan_constants(self): | |||
| 166 | 166 | self.assertEqual(cmath.nan.imag, 0.0) | |
| 167 | 167 | self.assertEqual(cmath.nanj.real, 0.0) | |
| 168 | 168 | self.assertTrue(math.isnan(cmath.nanj.imag)) | |
| 169 | + # Also check that the sign of all of these is positive: | ||
| 170 | + self.assertEqual(math.copysign(1., cmath.nan.real), 1.) | ||
| 171 | + self.assertEqual(math.copysign(1., cmath.nan.imag), 1.) | ||
| 172 | + self.assertEqual(math.copysign(1., cmath.nanj.real), 1.) | ||
| 173 | + self.assertEqual(math.copysign(1., cmath.nanj.imag), 1.) | ||
| 169 | 174 | ||
| 170 | 175 | # Check consistency with reprs. | |
| 171 | 176 | self.assertEqual(repr(cmath.inf), "inf") | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -529,6 +529,12 @@ class complex2(complex): | |||
| 529 | 529 | self.assertFloatsAreIdentical(z.real, x) | |
| 530 | 530 | self.assertFloatsAreIdentical(z.imag, y) | |
| 531 | 531 | ||
| 532 | + def test_constructor_negative_nans_from_string(self): | ||
| 533 | + self.assertEqual(copysign(1., complex("-nan").real), -1.) | ||
| 534 | + self.assertEqual(copysign(1., complex("-nanj").imag), -1.) | ||
| 535 | + self.assertEqual(copysign(1., complex("-nan-nanj").real), -1.) | ||
| 536 | + self.assertEqual(copysign(1., complex("-nan-nanj").imag), -1.) | ||
| 537 | + | ||
| 532 | 538 | def test_underscores(self): | |
| 533 | 539 | # check underscores | |
| 534 | 540 | for lit in VALID_UNDERSCORE_LITERALS: | |
@@ -569,6 +575,7 @@ def test(v, expected, test_fn=self.assertEqual): | |||
| 569 | 575 | test(complex(NAN, 1), "(nan+1j)") | |
| 570 | 576 | test(complex(1, NAN), "(1+nanj)") | |
| 571 | 577 | test(complex(NAN, NAN), "(nan+nanj)") | |
| 578 | + test(complex(-NAN, -NAN), "(nan+nanj)") | ||
| 572 | 579 | ||
| 573 | 580 | test(complex(0, INF), "infj") | |
| 574 | 581 | test(complex(0, -INF), "-infj") | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1040,11 +1040,8 @@ def test_inf_signs(self): | |||
| 1040 | 1040 | self.assertEqual(copysign(1.0, float('inf')), 1.0) | |
| 1041 | 1041 | self.assertEqual(copysign(1.0, float('-inf')), -1.0) | |
| 1042 | 1042 | ||
| 1043 | - @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short', | ||
| 1044 | - "applies only when using short float repr style") | ||
| 1045 | 1043 | def test_nan_signs(self): | |
| 1046 | - # When using the dtoa.c code, the sign of float('nan') should | ||
| 1047 | - # be predictable. | ||
| 1044 | + # The sign of float('nan') should be predictable. | ||
| 1048 | 1045 | self.assertEqual(copysign(1.0, float('nan')), 1.0) | |
| 1049 | 1046 | self.assertEqual(copysign(1.0, float('-nan')), -1.0) | |
| 1050 | 1047 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1881,11 +1881,11 @@ def testIsinf(self): | |||
| 1881 | 1881 | self.assertFalse(math.isinf(0.)) | |
| 1882 | 1882 | self.assertFalse(math.isinf(1.)) | |
| 1883 | 1883 | ||
| 1884 | - @requires_IEEE_754 | ||
| 1885 | 1884 | def test_nan_constant(self): | |
| 1885 | + # `math.nan` must be a quiet NaN with positive sign bit | ||
| 1886 | 1886 | self.assertTrue(math.isnan(math.nan)) | |
| 1887 | + self.assertEqual(math.copysign(1., math.nan), 1.) | ||
| 1887 | 1888 | ||
| 1888 | - @requires_IEEE_754 | ||
| 1889 | 1889 | def test_inf_constant(self): | |
| 1890 | 1890 | self.assertTrue(math.isinf(math.inf)) | |
| 1891 | 1891 | self.assertGreater(math.inf, 0.0) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,6 @@ | |||
| 1 | + Fix ``float("nan")`` to produce a quiet NaN on platforms (like MIPS) where | ||
| 2 | + the meaning of the signalling / quiet bit is inverted from its usual | ||
| 3 | + meaning. Also introduce a new macro ``Py_INFINITY`` matching C99's | ||
| 4 | + ``INFINITY``, and refactor internals to rely on C99's ``NAN`` and | ||
| 5 | + ``INFINITY`` macros instead of hard-coding bit patterns for infinities and | ||
| 6 | + NaNs. Thanks Sebastian Berg. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -8,7 +8,6 @@ | |||
| 8 | 8 | ||
| 9 | 9 | #include "Python.h" | |
| 10 | 10 | #include "pycore_pymath.h" // _PY_SHORT_FLOAT_REPR | |
| 11 | - #include "pycore_dtoa.h" // _Py_dg_stdnan() | ||
| 12 | 11 | /* we need DBL_MAX, DBL_MIN, DBL_EPSILON, DBL_MANT_DIG and FLT_RADIX from | |
| 13 | 12 | float.h. We assume that FLT_RADIX is either 2 or 16. */ | |
| 14 | 13 | #include <float.h> | |
@@ -88,53 +87,6 @@ else { | |||
| 88 | 87 | #endif | |
| 89 | 88 | #define CM_SCALE_DOWN (-(CM_SCALE_UP+1)/2) | |
| 90 | 89 | ||
| 91 | - /* Constants cmath.inf, cmath.infj, cmath.nan, cmath.nanj. | ||
| 92 | - cmath.nan and cmath.nanj are defined only when either | ||
| 93 | - _PY_SHORT_FLOAT_REPR is 1 (which should be | ||
| 94 | - the most common situation on machines using an IEEE 754 | ||
| 95 | - representation), or Py_NAN is defined. */ | ||
| 96 | - | ||
| 97 | - static double | ||
| 98 | - m_inf(void) | ||
| 99 | - { | ||
| 100 | - #if _PY_SHORT_FLOAT_REPR == 1 | ||
| 101 | - return _Py_dg_infinity(0); | ||
| 102 | - #else | ||
| 103 | - return Py_HUGE_VAL; | ||
| 104 | - #endif | ||
| 105 | - } | ||
| 106 | - | ||
| 107 | - static Py_complex | ||
| 108 | - c_infj(void) | ||
| 109 | - { | ||
| 110 | - Py_complex r; | ||
| 111 | - r.real = 0.0; | ||
| 112 | - r.imag = m_inf(); | ||
| 113 | - return r; | ||
| 114 | - } | ||
| 115 | - | ||
| 116 | - #if _PY_SHORT_FLOAT_REPR == 1 | ||
| 117 | - | ||
| 118 | - static double | ||
| 119 | - m_nan(void) | ||
| 120 | - { | ||
| 121 | - #if _PY_SHORT_FLOAT_REPR == 1 | ||
| 122 | - return _Py_dg_stdnan(0); | ||
| 123 | - #else | ||
| 124 | - return Py_NAN; | ||
| 125 | - #endif | ||
| 126 | - } | ||
| 127 | - | ||
| 128 | - static Py_complex | ||
| 129 | - c_nanj(void) | ||
| 130 | - { | ||
| 131 | - Py_complex r; | ||
| 132 | - r.real = 0.0; | ||
| 133 | - r.imag = m_nan(); | ||
| 134 | - return r; | ||
| 135 | - } | ||
| 136 | - | ||
| 137 | - #endif | ||
| 138 | 90 | ||
| 139 | 91 | /* forward declarations */ | |
| 140 | 92 | static Py_complex cmath_asinh_impl(PyObject *, Py_complex); | |
@@ -1274,23 +1226,22 @@ cmath_exec(PyObject *mod) | |||
| 1274 | 1226 | if (PyModule_AddObject(mod, "tau", PyFloat_FromDouble(Py_MATH_TAU)) < 0) { | |
| 1275 | 1227 | return -1; | |
| 1276 | 1228 | } | |
| 1277 | - if (PyModule_AddObject(mod, "inf", PyFloat_FromDouble(m_inf())) < 0) { | ||
| 1229 | + if (PyModule_AddObject(mod, "inf", PyFloat_FromDouble(Py_INFINITY)) < 0) { | ||
| 1278 | 1230 | return -1; | |
| 1279 | 1231 | } | |
| 1280 | 1232 | ||
| 1233 | + Py_complex infj = {0.0, Py_INFINITY}; | ||
| 1281 | 1234 | if (PyModule_AddObject(mod, "infj", | |
| 1282 | - PyComplex_FromCComplex(c_infj())) < 0) { | ||
| 1235 | + PyComplex_FromCComplex(infj)) < 0) { | ||
| 1283 | 1236 | return -1; | |
| 1284 | 1237 | } | |
| 1285 | - #if _PY_SHORT_FLOAT_REPR == 1 | ||
| 1286 | - if (PyModule_AddObject(mod, "nan", PyFloat_FromDouble(m_nan())) < 0) { | ||
| 1238 | + if (PyModule_AddObject(mod, "nan", PyFloat_FromDouble(fabs(Py_NAN))) < 0) { | ||
| 1287 | 1239 | return -1; | |
| 1288 | 1240 | } | |
| 1289 | - if (PyModule_AddObject(mod, "nanj", | ||
| 1290 | - PyComplex_FromCComplex(c_nanj())) < 0) { | ||
| 1241 | + Py_complex nanj = {0.0, fabs(Py_NAN)}; | ||
| 1242 | + if (PyModule_AddObject(mod, "nanj", PyComplex_FromCComplex(nanj)) < 0) { | ||
| 1291 | 1243 | return -1; | |
| 1292 | 1244 | } | |
| 1293 | - #endif | ||
| 1294 | 1245 | ||
| 1295 | 1246 | /* initialize special value tables */ | |
| 1296 | 1247 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -59,7 +59,6 @@ raised for division by zero and mod by zero. | |||
| 59 | 59 | #include "Python.h" | |
| 60 | 60 | #include "pycore_bitutils.h" // _Py_bit_length() | |
| 61 | 61 | #include "pycore_call.h" // _PyObject_CallNoArgs() | |
| 62 | - #include "pycore_dtoa.h" // _Py_dg_infinity() | ||
| 63 | 62 | #include "pycore_long.h" // _PyLong_GetZero() | |
| 64 | 63 | #include "pycore_moduleobject.h" // _PyModule_GetState() | |
| 65 | 64 | #include "pycore_object.h" // _PyObject_LookupSpecial() | |
@@ -389,34 +388,6 @@ lanczos_sum(double x) | |||
| 389 | 388 | return num/den; | |
| 390 | 389 | } | |
| 391 | 390 | ||
| 392 | - /* Constant for +infinity, generated in the same way as float('inf'). */ | ||
| 393 | - | ||
| 394 | - static double | ||
| 395 | - m_inf(void) | ||
| 396 | - { | ||
| 397 | - #if _PY_SHORT_FLOAT_REPR == 1 | ||
| 398 | - return _Py_dg_infinity(0); | ||
| 399 | - #else | ||
| 400 | - return Py_HUGE_VAL; | ||
| 401 | - #endif | ||
| 402 | - } | ||
| 403 | - | ||
| 404 | - /* Constant nan value, generated in the same way as float('nan'). */ | ||
| 405 | - /* We don't currently assume that Py_NAN is defined everywhere. */ | ||
| 406 | - | ||
| 407 | - #if _PY_SHORT_FLOAT_REPR == 1 | ||
| 408 | - | ||
| 409 | - static double | ||
| 410 | - m_nan(void) | ||
| 411 | - { | ||
| 412 | - #if _PY_SHORT_FLOAT_REPR == 1 | ||
| 413 | - return _Py_dg_stdnan(0); | ||
| 414 | - #else | ||
| 415 | - return Py_NAN; | ||
| 416 | - #endif | ||
| 417 | - } | ||
| 418 | - | ||
| 419 | - #endif | ||
| 420 | 391 | ||
| 421 | 392 | static double | |
| 422 | 393 | m_tgamma(double x) | |
@@ -435,7 +406,7 @@ m_tgamma(double x) | |||
| 435 | 406 | if (x == 0.0) { | |
| 436 | 407 | errno = EDOM; | |
| 437 | 408 | /* tgamma(+-0.0) = +-inf, divide-by-zero */ | |
| 438 | - return copysign(Py_HUGE_VAL, x); | ||
| 409 | + return copysign(Py_INFINITY, x); | ||
| 439 | 410 | } | |
| 440 | 411 | ||
| 441 | 412 | /* integer arguments */ | |
@@ -3938,7 +3909,7 @@ math_ulp_impl(PyObject *module, double x) | |||
| 3938 | 3909 | if (Py_IS_INFINITY(x)) { | |
| 3939 | 3910 | return x; | |
| 3940 | 3911 | } | |
| 3941 | - double inf = m_inf(); | ||
| 3912 | + double inf = Py_INFINITY; | ||
| 3942 | 3913 | double x2 = nextafter(x, inf); | |
| 3943 | 3914 | if (Py_IS_INFINITY(x2)) { | |
| 3944 | 3915 | /* special case: x is the largest positive representable float */ | |
@@ -3975,14 +3946,12 @@ math_exec(PyObject *module) | |||
| 3975 | 3946 | if (PyModule_AddObject(module, "tau", PyFloat_FromDouble(Py_MATH_TAU)) < 0) { | |
| 3976 | 3947 | return -1; | |
| 3977 | 3948 | } | |
| 3978 | - if (PyModule_AddObject(module, "inf", PyFloat_FromDouble(m_inf())) < 0) { | ||
| 3949 | + if (PyModule_AddObject(module, "inf", PyFloat_FromDouble(Py_INFINITY)) < 0) { | ||
| 3979 | 3950 | return -1; | |
| 3980 | 3951 | } | |
| 3981 | - #if _PY_SHORT_FLOAT_REPR == 1 | ||
| 3982 | - if (PyModule_AddObject(module, "nan", PyFloat_FromDouble(m_nan())) < 0) { | ||
| 3952 | + if (PyModule_AddObject(module, "nan", PyFloat_FromDouble(fabs(Py_NAN))) < 0) { | ||
| 3983 | 3953 | return -1; | |
| 3984 | 3954 | } | |
| 3985 | - #endif | ||
| 3986 | 3955 | return 0; | |
| 3987 | 3956 | } | |
| 3988 | 3957 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2424,25 +2424,14 @@ PyFloat_Unpack2(const char *data, int le) | |||
| 2424 | 2424 | f |= *p; | |
| 2425 | 2425 | ||
| 2426 | 2426 | if (e == 0x1f) { | |
| 2427 | - #if _PY_SHORT_FLOAT_REPR == 0 | ||
| 2428 | 2427 | if (f == 0) { | |
| 2429 | 2428 | /* Infinity */ | |
| 2430 | 2429 | return sign ? -Py_HUGE_VAL : Py_HUGE_VAL; | |
| 2431 | 2430 | } | |
| 2432 | 2431 | else { | |
| 2433 | 2432 | /* NaN */ | |
| 2434 | - return sign ? -Py_NAN : Py_NAN; | ||
| 2433 | + return sign ? -fabs(Py_NAN) : fabs(Py_NAN); | ||
| 2435 | 2434 | } | |
| 2436 | - #else // _PY_SHORT_FLOAT_REPR == 1 | ||
| 2437 | - if (f == 0) { | ||
| 2438 | - /* Infinity */ | ||
| 2439 | - return _Py_dg_infinity(sign); | ||
| 2440 | - } | ||
| 2441 | - else { | ||
| 2442 | - /* NaN */ | ||
| 2443 | - return _Py_dg_stdnan(sign); | ||
| 2444 | - } | ||
| 2445 | - #endif // _PY_SHORT_FLOAT_REPR == 1 | ||
| 2446 | 2435 | } | |
| 2447 | 2436 | ||
| 2448 | 2437 | x = (double)f / 1024.0; | |
| Back | FazBrowse Home | New Git URL |
0 commit comments