Branch data Line data Source code
1 : : #ifndef Py_INTERNAL_PYMATH_H 2 : : #define Py_INTERNAL_PYMATH_H 3 : : #ifdef __cplusplus 4 : : extern "C" { 5 : : #endif 6 : : 7 : : #ifndef Py_BUILD_CORE 8 : : # error "this header requires Py_BUILD_CORE define" 9 : : #endif 10 : : 11 : : 12 : : /* _Py_ADJUST_ERANGE1(x) 13 : : * _Py_ADJUST_ERANGE2(x, y) 14 : : * Set errno to 0 before calling a libm function, and invoke one of these 15 : : * macros after, passing the function result(s) (_Py_ADJUST_ERANGE2 is useful 16 : : * for functions returning complex results). This makes two kinds of 17 : : * adjustments to errno: (A) If it looks like the platform libm set 18 : : * errno=ERANGE due to underflow, clear errno. (B) If it looks like the 19 : : * platform libm overflowed but didn't set errno, force errno to ERANGE. In 20 : : * effect, we're trying to force a useful implementation of C89 errno 21 : : * behavior. 22 : : * Caution: 23 : : * This isn't reliable. C99 no longer requires libm to set errno under 24 : : * any exceptional condition, but does require +- HUGE_VAL return 25 : : * values on overflow. A 754 box *probably* maps HUGE_VAL to a 26 : : * double infinity, and we're cool if that's so, unless the input 27 : : * was an infinity and an infinity is the expected result. A C89 28 : : * system sets errno to ERANGE, so we check for that too. We're 29 : : * out of luck if a C99 754 box doesn't map HUGE_VAL to +Inf, or 30 : : * if the returned result is a NaN, or if a C89 box returns HUGE_VAL 31 : : * in non-overflow cases. 32 : : */ 33 : 204349 : static inline void _Py_ADJUST_ERANGE1(double x) 34 : : { 35 [ + - ]: 204349 : if (errno == 0) { 36 [ + - - + ]: 204349 : if (x == Py_HUGE_VAL || x == -Py_HUGE_VAL) { 37 : 0 : errno = ERANGE; 38 : : } 39 : : } 40 [ # # # # ]: 0 : else if (errno == ERANGE && x == 0.0) { 41 : 0 : errno = 0; 42 : : } 43 : 204349 : } 44 : : 45 : 0 : static inline void _Py_ADJUST_ERANGE2(double x, double y) 46 : : { 47 [ # # # # : 0 : if (x == Py_HUGE_VAL || x == -Py_HUGE_VAL || # # ] 48 [ # # ]: 0 : y == Py_HUGE_VAL || y == -Py_HUGE_VAL) 49 : : { 50 [ # # ]: 0 : if (errno == 0) { 51 : 0 : errno = ERANGE; 52 : : } 53 : : } 54 [ # # ]: 0 : else if (errno == ERANGE) { 55 : 0 : errno = 0; 56 : : } 57 : 0 : } 58 : : 59 : : 60 : : //--- HAVE_PY_SET_53BIT_PRECISION macro ------------------------------------ 61 : : // 62 : : // The functions _Py_dg_strtod() and _Py_dg_dtoa() in Python/dtoa.c (which are 63 : : // required to support the short float repr introduced in Python 3.1) require 64 : : // that the floating-point unit that's being used for arithmetic operations on 65 : : // C doubles is set to use 53-bit precision. It also requires that the FPU 66 : : // rounding mode is round-half-to-even, but that's less often an issue. 67 : : // 68 : : // If your FPU isn't already set to 53-bit precision/round-half-to-even, and 69 : : // you want to make use of _Py_dg_strtod() and _Py_dg_dtoa(), then you should: 70 : : // 71 : : // #define HAVE_PY_SET_53BIT_PRECISION 1 72 : : // 73 : : // and also give appropriate definitions for the following three macros: 74 : : // 75 : : // * _Py_SET_53BIT_PRECISION_HEADER: any variable declarations needed to 76 : : // use the two macros below. 77 : : // * _Py_SET_53BIT_PRECISION_START: store original FPU settings, and 78 : : // set FPU to 53-bit precision/round-half-to-even 79 : : // * _Py_SET_53BIT_PRECISION_END: restore original FPU settings 80 : : // 81 : : // The macros are designed to be used within a single C function: see 82 : : // Python/pystrtod.c for an example of their use. 83 : : 84 : : 85 : : // Get and set x87 control word for gcc/x86 86 : : #ifdef HAVE_GCC_ASM_FOR_X87 87 : : #define HAVE_PY_SET_53BIT_PRECISION 1 88 : : 89 : : // Functions defined in Python/pymath.c 90 : : extern unsigned short _Py_get_387controlword(void); 91 : : extern void _Py_set_387controlword(unsigned short); 92 : : 93 : : #define _Py_SET_53BIT_PRECISION_HEADER \ 94 : : unsigned short old_387controlword, new_387controlword 95 : : #define _Py_SET_53BIT_PRECISION_START \ 96 : : do { \ 97 : : old_387controlword = _Py_get_387controlword(); \ 98 : : new_387controlword = (old_387controlword & ~0x0f00) | 0x0200; \ 99 : : if (new_387controlword != old_387controlword) { \ 100 : : _Py_set_387controlword(new_387controlword); \ 101 : : } \ 102 : : } while (0) 103 : : #define _Py_SET_53BIT_PRECISION_END \ 104 : : do { \ 105 : : if (new_387controlword != old_387controlword) { \ 106 : : _Py_set_387controlword(old_387controlword); \ 107 : : } \ 108 : : } while (0) 109 : : #endif 110 : : 111 : : // Get and set x87 control word for VisualStudio/x86. 112 : : // x87 is not supported in 64-bit or ARM. 113 : : #if defined(_MSC_VER) && !defined(_WIN64) && !defined(_M_ARM) 114 : : #define HAVE_PY_SET_53BIT_PRECISION 1 115 : : 116 : : #include <float.h> // __control87_2() 117 : : 118 : : #define _Py_SET_53BIT_PRECISION_HEADER \ 119 : : unsigned int old_387controlword, new_387controlword, out_387controlword 120 : : // We use the __control87_2 function to set only the x87 control word. 121 : : // The SSE control word is unaffected. 122 : : #define _Py_SET_53BIT_PRECISION_START \ 123 : : do { \ 124 : : __control87_2(0, 0, &old_387controlword, NULL); \ 125 : : new_387controlword = \ 126 : : (old_387controlword & ~(_MCW_PC | _MCW_RC)) | (_PC_53 | _RC_NEAR); \ 127 : : if (new_387controlword != old_387controlword) { \ 128 : : __control87_2(new_387controlword, _MCW_PC | _MCW_RC, \ 129 : : &out_387controlword, NULL); \ 130 : : } \ 131 : : } while (0) 132 : : #define _Py_SET_53BIT_PRECISION_END \ 133 : : do { \ 134 : : if (new_387controlword != old_387controlword) { \ 135 : : __control87_2(old_387controlword, _MCW_PC | _MCW_RC, \ 136 : : &out_387controlword, NULL); \ 137 : : } \ 138 : : } while (0) 139 : : #endif 140 : : 141 : : 142 : : // MC68881 143 : : #ifdef HAVE_GCC_ASM_FOR_MC68881 144 : : #define HAVE_PY_SET_53BIT_PRECISION 1 145 : : #define _Py_SET_53BIT_PRECISION_HEADER \ 146 : : unsigned int old_fpcr, new_fpcr 147 : : #define _Py_SET_53BIT_PRECISION_START \ 148 : : do { \ 149 : : __asm__ ("fmove.l %%fpcr,%0" : "=g" (old_fpcr)); \ 150 : : /* Set double precision / round to nearest. */ \ 151 : : new_fpcr = (old_fpcr & ~0xf0) | 0x80; \ 152 : : if (new_fpcr != old_fpcr) { \ 153 : : __asm__ volatile ("fmove.l %0,%%fpcr" : : "g" (new_fpcr));\ 154 : : } \ 155 : : } while (0) 156 : : #define _Py_SET_53BIT_PRECISION_END \ 157 : : do { \ 158 : : if (new_fpcr != old_fpcr) { \ 159 : : __asm__ volatile ("fmove.l %0,%%fpcr" : : "g" (old_fpcr)); \ 160 : : } \ 161 : : } while (0) 162 : : #endif 163 : : 164 : : // Default definitions are empty 165 : : #ifndef _Py_SET_53BIT_PRECISION_HEADER 166 : : # define _Py_SET_53BIT_PRECISION_HEADER 167 : : # define _Py_SET_53BIT_PRECISION_START 168 : : # define _Py_SET_53BIT_PRECISION_END 169 : : #endif 170 : : 171 : : 172 : : //--- _PY_SHORT_FLOAT_REPR macro ------------------------------------------- 173 : : 174 : : // If we can't guarantee 53-bit precision, don't use the code 175 : : // in Python/dtoa.c, but fall back to standard code. This 176 : : // means that repr of a float will be long (17 significant digits). 177 : : // 178 : : // Realistically, there are two things that could go wrong: 179 : : // 180 : : // (1) doubles aren't IEEE 754 doubles, or 181 : : // (2) we're on x86 with the rounding precision set to 64-bits 182 : : // (extended precision), and we don't know how to change 183 : : // the rounding precision. 184 : : #if !defined(DOUBLE_IS_LITTLE_ENDIAN_IEEE754) && \ 185 : : !defined(DOUBLE_IS_BIG_ENDIAN_IEEE754) && \ 186 : : !defined(DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754) 187 : : # define _PY_SHORT_FLOAT_REPR 0 188 : : #endif 189 : : 190 : : // Double rounding is symptomatic of use of extended precision on x86. 191 : : // If we're seeing double rounding, and we don't have any mechanism available 192 : : // for changing the FPU rounding precision, then don't use Python/dtoa.c. 193 : : #if defined(X87_DOUBLE_ROUNDING) && !defined(HAVE_PY_SET_53BIT_PRECISION) 194 : : # define _PY_SHORT_FLOAT_REPR 0 195 : : #endif 196 : : 197 : : #ifndef _PY_SHORT_FLOAT_REPR 198 : : # define _PY_SHORT_FLOAT_REPR 1 199 : : #endif 200 : : 201 : : 202 : : #ifdef __cplusplus 203 : : } 204 : : #endif 205 : : #endif /* !Py_INTERNAL_PYMATH_H */