88
99#include "Python.h"
1010#include "pycore_complexobject.h" // _Py_c_neg()
11- #include "pycore_lock.h" // _PyOnceFlag_CallOnce()
1211#include "pycore_pymath.h" // _PY_SHORT_FLOAT_REPR
1312/* we need DBL_MAX, DBL_MIN, DBL_EPSILON, DBL_MANT_DIG and FLT_RADIX from
1413 float.h. We assume that FLT_RADIX is either 2 or 16. */
@@ -140,21 +139,40 @@ special_type(double d)
140139 return ST_NINF ;
141140}
142141
142+ #define P Py_MATH_PI
143+ /* Precomputed for static initialization with MSVC /fp:strict. */
144+ #define P14 0.78539816339744830962 /* P/4: 0x3fe921fb54442d18 */
145+ #define P12 1.57079632679489661923 /* P/2: 0x3ff921fb54442d18 */
146+ #define P34 2.35619449019234492885 /* P*3/4: 0x4002d97c7f3321d2 */
147+ #define INF INFINITY
148+ /* MSVC /fp:strict does not accept NAN in static initializers. This finite
149+ value does not otherwise occur in the tables and is decoded when read. */
150+ #define N 9.5426319407711027e33
151+ #define U -9.5426319407711027e33 /* unlikely value, used as placeholder */
152+
153+ static Py_complex
154+ special_value (const Py_complex table [7 ][7 ],
155+ enum special_types real_type ,
156+ enum special_types imag_type )
157+ {
158+ Py_complex value = table [real_type ][imag_type ];
159+ if (value .real == N ) {
160+ value .real = fabs (nan ("" ));
161+ }
162+ if (value .imag == N ) {
163+ value .imag = fabs (nan ("" ));
164+ }
165+ return value ;
166+ }
167+
143168#define SPECIAL_VALUE (z , table ) \
144169 if (!isfinite((z).real) || !isfinite((z).imag)) { \
145170 errno = 0; \
146- return table[special_type((z).real)] \
147- [special_type((z).imag)]; \
171+ return special_value( \
172+ table, special_type((z).real), \
173+ special_type((z).imag)); \
148174 }
149175
150- #define P Py_MATH_PI
151- #define P14 0.78539816339744830962
152- #define P12 1.57079632679489661923
153- #define P34 2.35619449019234492885
154- #define INF INFINITY
155- #define N 9.5426319407711027e33 /* finite placeholder for NaN */
156- #define U -9.5426319407711027e33 /* unlikely value, used as placeholder */
157-
158176/* First, the C functions that do the real work. Each of the c_*
159177 functions computes and returns the C99 Annex G recommended result
160178 and also sets errno as follows: errno = 0 if no floating-point
@@ -164,7 +182,7 @@ special_type(double d)
164182 raised.
165183*/
166184
167- static Py_complex acos_special_values [7 ][7 ] = {
185+ static const Py_complex acos_special_values [7 ][7 ] = {
168186 { {P34 ,INF }, {P ,INF }, {P ,INF }, {P ,- INF }, {P ,- INF }, {P34 ,- INF }, {N ,INF } },
169187 { {P12 ,INF }, {U ,U }, {U ,U }, {U ,U }, {U ,U }, {P12 ,- INF }, {N ,N } },
170188 { {P12 ,INF }, {U ,U }, {P12 ,0. }, {P12 ,-0. }, {U ,U }, {P12 ,- INF }, {P12 ,N } },
@@ -210,7 +228,7 @@ cmath_acos_impl(PyObject *module, Py_complex z)
210228}
211229
212230
213- static Py_complex acosh_special_values [7 ][7 ] = {
231+ static const Py_complex acosh_special_values [7 ][7 ] = {
214232 { {INF ,- P34 }, {INF ,- P }, {INF ,- P }, {INF ,P }, {INF ,P }, {INF ,P34 }, {INF ,N } },
215233 { {INF ,- P12 }, {U ,U }, {U ,U }, {U ,U }, {U ,U }, {INF ,P12 }, {N ,N } },
216234 { {INF ,- P12 }, {U ,U }, {0. ,- P12 }, {0. ,P12 }, {U ,U }, {INF ,P12 }, {N ,P12 } },
@@ -273,7 +291,7 @@ cmath_asin_impl(PyObject *module, Py_complex z)
273291}
274292
275293
276- static Py_complex asinh_special_values [7 ][7 ] = {
294+ static const Py_complex asinh_special_values [7 ][7 ] = {
277295 { {- INF ,- P14 }, {- INF ,-0. }, {- INF ,-0. }, {- INF ,0. }, {- INF ,0. }, {- INF ,P14 }, {- INF ,N } },
278296 { {- INF ,- P12 }, {U ,U }, {U ,U }, {U ,U }, {U ,U }, {- INF ,P12 }, {N ,N } },
279297 { {- INF ,- P12 }, {U ,U }, {-0. ,-0. }, {-0. ,0. }, {U ,U }, {- INF ,P12 }, {N ,N } },
@@ -342,7 +360,7 @@ cmath_atan_impl(PyObject *module, Py_complex z)
342360}
343361
344362
345- static Py_complex atanh_special_values [7 ][7 ] = {
363+ static const Py_complex atanh_special_values [7 ][7 ] = {
346364 { {-0. ,- P12 }, {-0. ,- P12 }, {-0. ,- P12 }, {-0. ,P12 }, {-0. ,P12 }, {-0. ,P12 }, {-0. ,N } },
347365 { {-0. ,- P12 }, {U ,U }, {U ,U }, {U ,U }, {U ,U }, {-0. ,P12 }, {N ,N } },
348366 { {-0. ,- P12 }, {U ,U }, {-0. ,-0. }, {-0. ,0. }, {U ,U }, {-0. ,P12 }, {-0. ,N } },
@@ -423,7 +441,7 @@ cmath_cos_impl(PyObject *module, Py_complex z)
423441
424442
425443/* cosh(infinity + i*y) needs to be dealt with specially */
426- static Py_complex cosh_special_values [7 ][7 ] = {
444+ static const Py_complex cosh_special_values [7 ][7 ] = {
427445 { {INF ,N }, {U ,U }, {INF ,0. }, {INF ,-0. }, {U ,U }, {INF ,N }, {INF ,N } },
428446 { {N ,N }, {U ,U }, {U ,U }, {U ,U }, {U ,U }, {N ,N }, {N ,N } },
429447 { {N ,0. }, {U ,U }, {1. ,0. }, {1. ,-0. }, {U ,U }, {N ,0. }, {N ,0. } },
@@ -460,8 +478,9 @@ cmath_cosh_impl(PyObject *module, Py_complex z)
460478 }
461479 }
462480 else {
463- r = cosh_special_values [special_type (z .real )]
464- [special_type (z .imag )];
481+ r = special_value (cosh_special_values ,
482+ special_type (z .real ),
483+ special_type (z .imag ));
465484 }
466485 /* need to set errno = EDOM if y is +/- infinity and x is not
467486 a NaN */
@@ -493,7 +512,7 @@ cmath_cosh_impl(PyObject *module, Py_complex z)
493512
494513/* exp(infinity + i*y) and exp(-infinity + i*y) need special treatment for
495514 finite y */
496- static Py_complex exp_special_values [7 ][7 ] = {
515+ static const Py_complex exp_special_values [7 ][7 ] = {
497516 { {0. ,0. }, {U ,U }, {0. ,-0. }, {0. ,0. }, {U ,U }, {0. ,0. }, {0. ,0. } },
498517 { {N ,N }, {U ,U }, {U ,U }, {U ,U }, {U ,U }, {N ,N }, {N ,N } },
499518 { {N ,N }, {U ,U }, {1. ,-0. }, {1. ,0. }, {U ,U }, {N ,N }, {N ,N } },
@@ -529,8 +548,9 @@ cmath_exp_impl(PyObject *module, Py_complex z)
529548 }
530549 }
531550 else {
532- r = exp_special_values [special_type (z .real )]
533- [special_type (z .imag )];
551+ r = special_value (exp_special_values ,
552+ special_type (z .real ),
553+ special_type (z .imag ));
534554 }
535555 /* need to set errno = EDOM if y is +/- infinity and x is not
536556 a NaN and not -infinity */
@@ -560,7 +580,7 @@ cmath_exp_impl(PyObject *module, Py_complex z)
560580 return r ;
561581}
562582
563- static Py_complex log_special_values [7 ][7 ] = {
583+ static const Py_complex log_special_values [7 ][7 ] = {
564584 { {INF ,- P34 }, {INF ,- P }, {INF ,- P }, {INF ,P }, {INF ,P }, {INF ,P34 }, {INF ,N } },
565585 { {INF ,- P12 }, {U ,U }, {U ,U }, {U ,U }, {U ,U }, {INF ,P12 }, {N ,N } },
566586 { {INF ,- P12 }, {U ,U }, {- INF ,- P }, {- INF ,P }, {U ,U }, {INF ,P12 }, {N ,N } },
@@ -684,7 +704,7 @@ cmath_sin_impl(PyObject *module, Py_complex z)
684704
685705
686706/* sinh(infinity + i*y) needs to be dealt with specially */
687- static Py_complex sinh_special_values [7 ][7 ] = {
707+ static const Py_complex sinh_special_values [7 ][7 ] = {
688708 { {INF ,N }, {U ,U }, {- INF ,-0. }, {- INF ,0. }, {U ,U }, {INF ,N }, {INF ,N } },
689709 { {N ,N }, {U ,U }, {U ,U }, {U ,U }, {U ,U }, {N ,N }, {N ,N } },
690710 { {0. ,N }, {U ,U }, {-0. ,-0. }, {-0. ,0. }, {U ,U }, {0. ,N }, {0. ,N } },
@@ -722,8 +742,9 @@ cmath_sinh_impl(PyObject *module, Py_complex z)
722742 }
723743 }
724744 else {
725- r = sinh_special_values [special_type (z .real )]
726- [special_type (z .imag )];
745+ r = special_value (sinh_special_values ,
746+ special_type (z .real ),
747+ special_type (z .imag ));
727748 }
728749 /* need to set errno = EDOM if y is +/- infinity and x is not
729750 a NaN */
@@ -751,7 +772,7 @@ cmath_sinh_impl(PyObject *module, Py_complex z)
751772}
752773
753774
754- static Py_complex sqrt_special_values [7 ][7 ] = {
775+ static const Py_complex sqrt_special_values [7 ][7 ] = {
755776 { {INF ,- INF }, {0. ,- INF }, {0. ,- INF }, {0. ,INF }, {0. ,INF }, {INF ,INF }, {N ,INF } },
756777 { {INF ,- INF }, {U ,U }, {U ,U }, {U ,U }, {U ,U }, {INF ,INF }, {N ,N } },
757778 { {INF ,- INF }, {U ,U }, {0. ,-0. }, {0. ,0. }, {U ,U }, {INF ,INF }, {N ,N } },
@@ -858,7 +879,7 @@ cmath_tan_impl(PyObject *module, Py_complex z)
858879
859880
860881/* tanh(infinity + i*y) needs to be dealt with specially */
861- static Py_complex tanh_special_values [7 ][7 ] = {
882+ static const Py_complex tanh_special_values [7 ][7 ] = {
862883 { {-1. ,0. }, {U ,U }, {-1. ,-0. }, {-1. ,0. }, {U ,U }, {-1. ,0. }, {-1. ,0. } },
863884 { {N ,N }, {U ,U }, {U ,U }, {U ,U }, {U ,U }, {N ,N }, {N ,N } },
864885 { {-0.0 ,N }, {U ,U }, {-0. ,-0. }, {-0. ,0. }, {U ,U }, {-0.0 ,N }, {-0. ,N } },
@@ -910,8 +931,9 @@ cmath_tanh_impl(PyObject *module, Py_complex z)
910931 }
911932 }
912933 else {
913- r = tanh_special_values [special_type (z .real )]
914- [special_type (z .imag )];
934+ r = special_value (tanh_special_values ,
935+ special_type (z .real ),
936+ special_type (z .imag ));
915937 }
916938 /* need to set errno = EDOM if z.imag is +/-infinity and
917939 z.real is finite */
@@ -1050,7 +1072,7 @@ cmath_polar_impl(PyObject *module, Py_complex z)
10501072
10511073*/
10521074
1053- static Py_complex rect_special_values [7 ][7 ] = {
1075+ static const Py_complex rect_special_values [7 ][7 ] = {
10541076 { {INF ,N }, {U ,U }, {- INF ,0. }, {- INF ,-0. }, {U ,U }, {INF ,N }, {INF ,N } },
10551077 { {N ,N }, {U ,U }, {U ,U }, {U ,U }, {U ,U }, {N ,N }, {N ,N } },
10561078 { {0. ,0. }, {U ,U }, {-0. ,0. }, {-0. ,-0. }, {U ,U }, {0. ,0. }, {0. ,0. } },
@@ -1094,8 +1116,9 @@ cmath_rect_impl(PyObject *module, double r, double phi)
10941116 }
10951117 }
10961118 else {
1097- z = rect_special_values [special_type (r )]
1098- [special_type (phi )];
1119+ z = special_value (rect_special_values ,
1120+ special_type (r ),
1121+ special_type (phi ));
10991122 }
11001123 /* need to set errno = EDOM if r is a nonzero number and phi
11011124 is infinite */
@@ -1231,41 +1254,6 @@ PyDoc_STRVAR(module_doc,
12311254"This module provides access to mathematical functions for complex\n"
12321255"numbers." );
12331256
1234- static _PyOnceFlag special_values_init_once = {0 };
1235-
1236- static int
1237- init_special_values (void * Py_UNUSED (arg ))
1238- {
1239- Py_complex * tables [] = {
1240- acos_special_values [0 ],
1241- acosh_special_values [0 ],
1242- asinh_special_values [0 ],
1243- atanh_special_values [0 ],
1244- cosh_special_values [0 ],
1245- exp_special_values [0 ],
1246- log_special_values [0 ],
1247- sinh_special_values [0 ],
1248- sqrt_special_values [0 ],
1249- tanh_special_values [0 ],
1250- rect_special_values [0 ],
1251- };
1252-
1253- /* MSVC with /fp:strict does not treat NAN as a constant expression.
1254- Replace its finite placeholders once all static initialization is
1255- complete. */
1256- for (size_t i = 0 ; i < Py_ARRAY_LENGTH (tables ); i ++ ) {
1257- for (size_t j = 0 ; j < 7 * 7 ; j ++ ) {
1258- if (tables [i ][j ].real == N ) {
1259- tables [i ][j ].real = Py_NAN ;
1260- }
1261- if (tables [i ][j ].imag == N ) {
1262- tables [i ][j ].imag = Py_NAN ;
1263- }
1264- }
1265- }
1266- return 0 ;
1267- }
1268-
12691257static PyMethodDef cmath_methods [] = {
12701258 CMATH_ACOS_METHODDEF
12711259 CMATH_ACOSH_METHODDEF
@@ -1296,10 +1284,6 @@ static PyMethodDef cmath_methods[] = {
12961284static int
12971285cmath_exec (PyObject * mod )
12981286{
1299- /* init cannot fail */
1300- (void )_PyOnceFlag_CallOnce (
1301- & special_values_init_once , init_special_values , NULL );
1302-
13031287 if (PyModule_Add (mod , "pi" , PyFloat_FromDouble (Py_MATH_PI )) < 0 ) {
13041288 return -1 ;
13051289 }
@@ -1318,10 +1302,11 @@ cmath_exec(PyObject *mod)
13181302 if (PyModule_Add (mod , "infj" , PyComplex_FromCComplex (infj )) < 0 ) {
13191303 return -1 ;
13201304 }
1321- if (PyModule_Add (mod , "nan" , PyFloat_FromDouble (fabs (Py_NAN ))) < 0 ) {
1305+ double nan_value = fabs (nan ("" ));
1306+ if (PyModule_Add (mod , "nan" , PyFloat_FromDouble (nan_value )) < 0 ) {
13221307 return -1 ;
13231308 }
1324- Py_complex nanj = {0.0 , fabs ( Py_NAN ) };
1309+ Py_complex nanj = {0.0 , nan_value };
13251310 if (PyModule_Add (mod , "nanj" , PyComplex_FromCComplex (nanj )) < 0 ) {
13261311 return -1 ;
13271312 }
0 commit comments