8000 MAINT: Rely on Py_NAN and Py_HUGE_VAL being correctly defined · python/cpython@c88a6fb · GitHub
[go: up one dir, main page]

Skip to content

Commit c88a6fb

Browse files
committed
MAINT: Rely on Py_NAN and Py_HUGE_VAL being correctly defined
It seems to me code all around relies on both being correct anyway. The actual value for Py_NAN is subtly incorrect on MIPS (depending on settings) or at least nonstandard, which seems to confuse some builtin functions. (Probably it is signalling, but NumPy saw this with fmin, which probably should also ignore signalling NaNs, see also numpy/numpy#23158). The guards about `_PY_SHORT_FLOAT_REPR` making sense are relatively unrelated to NAN and INF being available. Nevertheless, I currently hide the Py_NAN definition if that is not set, since I am not sure what good alternative there is to be certain that Py_NAN is well defined. OTOH, I do suspect there is no platform where it is not and it should probably be changed?!
1 parent e5b8b19 commit c88a6fb

File tree

6 files changed

+17
-170
lines changed

6 files changed

+17
-170
lines changed

Include/internal/pycore_dtoa.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,6 @@ PyAPI_FUNC(double) _Py_dg_strtod(const char *str, char **ptr);
6464
PyAPI_FUNC(char *) _Py_dg_dtoa(double d, int mode, int ndigits,
6565
int *decpt, int *sign, char **rve);
6666
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);
6967

7068
#endif // _PY_SHORT_FLOAT_REPR == 1
7169

Modules/cmathmodule.c

Lines changed: 10 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
#include "Python.h"
1010
#include "pycore_pymath.h" // _PY_SHORT_FLOAT_REPR
11-
#include "pycore_dtoa.h" // _Py_dg_stdnan()
1211
/* we need DBL_MAX, DBL_MIN, DBL_EPSILON, DBL_MANT_DIG and FLT_RADIX from
1312
float.h. We assume that FLT_RADIX is either 2 or 16. */
1413
#include <float.h>
@@ -88,53 +87,6 @@ else {
8887
#endif
8988
#define CM_SCALE_DOWN (-(CM_SCALE_UP+1)/2)
9089

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
13890

13991
/* forward declarations */
14092
static Py_complex cmath_asinh_impl(PyObject *, Py_complex);
@@ -1274,20 +1226,26 @@ cmath_exec(PyObject *mod)
12741226
if (PyModule_AddObject(mod, "tau", PyFloat_FromDouble(Py_MATH_TAU)) < 0) {
12751227
return -1;
12761228
}
1277-
if (PyModule_AddObject(mod, "inf", PyFloat_FromDouble(m_inf())) < 0) {
1229+
if (PyModule_AddObject(mod, "inf", PyFloat_FromDouble(Py_HUGE_VAL)) < 0) {
12781230
return -1;
12791231
}
12801232

1233+
Py_complex infj = {0.0, Py_HUGE_VAL};
12811234
if (PyModule_AddObject(mod, "infj",
1282-
PyComplex_FromCComplex(c_infj())) < 0) {
1235+
PyComplex_FromCComplex(infj)) < 0) {
12831236
return -1;
12841237
}
12851238
#if _PY_SHORT_FLOAT_REPR == 1
1286-
if (PyModule_AddObject(mod, "nan", PyFloat_FromDouble(m_nan())) < 0) {
1239+
/*
1240+
* NaN exposure is guarded by having IEEE doubles via _PY_SHORT_FLOAT_REPR.
1241+
* This is probably an overly restrictive guard.
1242+
*/
1243+
if (PyModule_AddObject(mod, "nan", PyFloat_FromDouble(Py_NAN)) < 0) {
12871244
return -1;
12881245
}
1246+
Py_complex nanj = {0.0, Py_NAN};
12891247
if (PyModule_AddObject(mod, "nanj",
1290-
PyComplex_FromCComplex(c_nanj())) < 0) {
1248+
PyComplex_FromCComplex(nanj)) < 0) {
12911249
return -1;
12921250
}
12931251
#endif

Modules/mathmodule.c

Lines changed: 7 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ raised for division by zero and mod by zero.
5959
#include "Python.h"
6060
#include "pycore_bitutils.h" // _Py_bit_length()
6161
#include "pycore_call.h" // _PyObject_CallNoArgs()
62-
#include "pycore_dtoa.h" // _Py_dg_infinity()
6362
#include "pycore_long.h" // _PyLong_GetZero()
6463
#include "pycore_moduleobject.h" // _PyModule_GetState()
6564
#include "pycore_object.h" // _PyObject_LookupSpecial()
@@ -389,34 +388,6 @@ lanczos_sum(double x)
389388
return num/den;
390389
}
391390

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
420391

421392
static double
422393
m_tgamma(double x)
@@ -3938,7 +3909,7 @@ math_ulp_impl(PyObject *module, double x)
39383909
if (Py_IS_INFINITY(x)) {
39393910
return x;
39403911
}
3941-
double inf = m_inf();
3912+
double inf = Py_HUGE_VAL;
39423913
double x2 = nextafter(x, inf);
39433914
if (Py_IS_INFINITY(x2)) {
39443915
/* special case: x is the largest positive representable float */
@@ -3975,11 +3946,15 @@ math_exec(PyObject *module)
39753946
if (PyModule_AddObject(module, "tau", PyFloat_FromDouble(Py_MATH_TAU)) < 0) {
39763947
return -1;
39773948
}
3978-
if (PyModule_AddObject(module, "inf", PyFloat_FromDouble(m_inf())) < 0) {
3949+
if (PyModule_AddObject(module, "inf", PyFloat_FromDouble(Py_HUGE_VAL)) < 0) {
39793950
return -1;
39803951
}
39813952
#if _PY_SHORT_FLOAT_REPR == 1
3982-
if (PyModule_AddObject(module, "nan", PyFloat_FromDouble(m_nan())) < 0) {
3953+
/*
3954+
* NaN exposure is guarded by having IEEE doubles via _PY_SHORT_FLOAT_REPR.
3955+
* This is probably an overly restrictive guard.
3956+
*/
3957+
if (PyModule_AddObject(module, "nan", PyFloat_FromDouble(Py_NAN)) < 0) {
39833958
return -1;
39843959
}
39853960
#endif

Objects/floatobject.c

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2424,7 +2424,6 @@ PyFloat_Unpack2(const char *data, int le)
24242424
f |= *p;
24252425

24262426
if (e == 0x1f) {
2427-
#if _PY_SHORT_FLOAT_REPR == 0
24282427
if (f == 0) {
24292428
/* Infinity */
24302429
return sign ? -Py_HUGE_VAL : Py_HUGE_VAL;
@@ -2433,16 +2432,6 @@ PyFloat_Unpack2(const char *data, int le)
24332432
/* NaN */
24342433
return sign ? -Py_NAN : Py_NAN;
24352434
}
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
24462435
}
24472436

24482437
x = (double)f / 1024.0;

Python/dtoa.c

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -273,11 +273,6 @@ typedef union { double d; ULong L[2]; } U;
273273
#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1))
274274
#define Big1 0xffffffff
275275

276-
/* Standard NaN used by _Py_dg_stdnan. */
277-
278-
#define NAN_WORD0 0x7ff80000
279-
#define NAN_WORD1 0
280-
281276
/* Bits of the representation of positive infinity. */
282277

283278
#define POSINF_WORD0 0x7ff00000
@@ -1399,35 +1394,6 @@ bigcomp(U *rv, const char *s0, BCinfo *bc)
13991394
return 0;
14001395
}
14011396

1402-
/* Return a 'standard' NaN value.
1403-
1404-
There are exactly two quiet NaNs that don't arise by 'quieting' signaling
1405-
NaNs (see IEEE 754-2008, section 6.2.1). If sign == 0, return the one whose
1406-
sign bit is cleared. Otherwise, return the one whose sign bit is set.
1407-
*/
1408-
1409-
double
1410-
_Py_dg_stdnan(int sign)
1411-
{
1412-
U rv;
1413-
word0(&rv) = NAN_WORD0;
1414-
word1(&rv) = NAN_WORD1;
1415-
if (sign)
1416-
word0(&rv) |= Sign_bit;
1417-
return dval(&rv);
1418-
}
1419-
1420-
/* Return positive or negative infinity, according to the given sign (0 for
1421-
* positive infinity, 1 for negative infinity). */
1422-
1423-
double
1424-
_Py_dg_infinity(int sign)
1425-
{
1426-
U rv;
1427-
word0(&rv) = POSINF_WORD0;
1428-
word1(&rv) = POSINF_WORD1;
1429-
return sign ? -dval(&rv) : dval(&rv);
1430-
}
14311397

14321398
double
14331399
_Py_dg_strtod(const char *s00, char **se)

Python/pystrtod.c

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -23,44 +23,6 @@ case_insensitive_match(const char *s, const char *t)
2323
return the NaN or Infinity as a double and set *endptr to point just beyond
2424
the successfully parsed portion of the string. On failure, return -1.0 and
2525
set *endptr to point to the start of the string. */
26-
27-
#if _PY_SHORT_FLOAT_REPR == 1
28-
29-
double
30-
_Py_parse_inf_or_nan(const char *p, char **endptr)
31-
{
32-
double retval;
33-
const char *s;
34-
int negate = 0;
35-
36-
s = p;
37-
if (*s == '-') {
38-
negate = 1;
39-
s++;
40-
}
41-
else if (*s == '+') {
42-
s++;
43-
}
44-
if (case_insensitive_match(s, "inf")) {
45-
s += 3;
46-
if (case_insensitive_match(s, "inity"))
47-
s += 5;
48-
retval = _Py_dg_infinity(negate);
49-
}
50-
else if (case_insensitive_match(s, "nan")) {
51-
s += 3;
52-
retval = _Py_dg_stdnan(negate);
53-
}
54-
else {
55-
s = p;
56-
retval = -1.0;
57-
}
58-
*endptr = (char *)s;
59-
return retval;
60-
}
61-
62-
#else
63-
6426
double
6527
_Py_parse_inf_or_nan(const char *p, char **endptr)
6628
{
@@ -94,7 +56,6 @@ _Py_parse_inf_or_nan(const char *p, char **endptr)
9456
return retval;
9557
}
9658

97-
#endif
9859

9960
/**
10061
* _PyOS_ascii_strtod:

0 commit comments

Comments
 (0)
0