diff -r f6191e14808f Include/dtoa.h --- a/Include/dtoa.h Mon Apr 09 17:06:44 2012 +0200 +++ b/Include/dtoa.h Mon Apr 09 23:55:24 2012 +0300 @@ -8,6 +8,7 @@ PyAPI_FUNC(char *) _Py_dg_dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve); PyAPI_FUNC(void) _Py_dg_freedtoa(char *s); +PyAPI_FUNC(double) _Py_dg_stdnan(void); #ifdef __cplusplus diff -r f6191e14808f Lib/test/test_math.py --- a/Lib/test/test_math.py Mon Apr 09 17:06:44 2012 +0200 +++ b/Lib/test/test_math.py Mon Apr 09 23:55:24 2012 +0300 @@ -13,6 +13,7 @@ eps = 1E-05 NAN = float('nan') +NNAN = float('-nan') INF = float('inf') NINF = float('-inf') @@ -361,12 +362,17 @@ self.assertTrue(math.isnan(math.copysign(NAN, INF))) self.assertTrue(math.isnan(math.copysign(NAN, NINF))) self.assertTrue(math.isnan(math.copysign(NAN, NAN))) - # copysign(INF, NAN) may be INF or it may be NINF, since - # we don't know whether the sign bit of NAN is set on any - # given platform. - self.assertTrue(math.isinf(math.copysign(INF, NAN))) - # similarly, copysign(2., NAN) could be 2. or -2. - self.assertEqual(abs(math.copysign(2., NAN)), 2.) + # copysign(INF, NAN) must be INF since we create NAN + # explicitely with signbit not set + self.assertEqual(math.copysign(INF, NAN), INF) + # similarly, copysign(2., NAN) must be 2. + self.assertEqual(math.copysign(2., NAN), 2.) + + @requires_IEEE_754 + def testNAN(self): + import struct + self.assertEqual(struct.pack('!d', NAN)[0], 0x7f) + self.assertEqual(struct.pack('!d', NNAN)[0], 0xff) def testCos(self): self.assertRaises(TypeError, math.cos) diff -r f6191e14808f Python/dtoa.c --- a/Python/dtoa.c Mon Apr 09 17:06:44 2012 +0200 +++ b/Python/dtoa.c Mon Apr 09 23:55:24 2012 +0300 @@ -265,6 +265,11 @@ #define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1)) #define Big1 0xffffffff +/* Standard NaN used by _Py_dg_stdnan. */ + +#define NAN_WORD0 0x7ff80000 +#define NAN_WORD1 0 + /* struct BCinfo is used to pass information from _Py_dg_strtod to bigcomp */ typedef struct BCinfo BCinfo; @@ -1486,6 +1491,21 @@ return 0; } +/* Return a 'standard' NaN value. + + There are exactly two quiet NaNs that don't arise by 'quieting' signaling + NaNs (see IEEE 754-2008, section 6.2.1); we choose as our standard NaN value + the one whose sign bit is cleared. */ + +double +_Py_dg_stdnan() +{ + U rv; + word0(&rv) = NAN_WORD0; + word1(&rv) = NAN_WORD1; + return dval(&rv); +} + double _Py_dg_strtod(const char *s00, char **se) { diff -r f6191e14808f Python/pystrtod.c --- a/Python/pystrtod.c Mon Apr 09 17:06:44 2012 +0200 +++ b/Python/pystrtod.c Mon Apr 09 23:55:24 2012 +0300 @@ -46,7 +46,11 @@ #ifdef Py_NAN else if (case_insensitive_match(s, "nan")) { s += 3; +#ifdef PY_NO_SHORT_FLOAT_REPR retval = negate ? -Py_NAN : Py_NAN; +#else + retval = negate ? -_Py_dg_stdnan() : _Py_dg_stdnan(); +#endif } #endif else {