/home/mdboom/Work/builds/cpython/Include/internal/pycore_pymath.h
Line | Count | Source (jump to first uncovered line) |
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 | static inline void _Py_ADJUST_ERANGE1(double x) |
34 | { |
35 | if (errno == 0) { Branch (35:9): [True: 253k, False: 20]
|
36 | if (x == Py_HUGE_VAL || x == -Py_HUGE_VAL) { Branch (36:13): [True: 0, False: 253k]
Branch (36:33): [True: 0, False: 253k]
|
37 | errno = ERANGE; |
38 | } |
39 | } |
40 | else if (errno == ERANGE && x == 0.0) { Branch (40:14): [True: 20, False: 0]
Branch (40:33): [True: 20, False: 0]
|
41 | errno = 0; |
42 | } |
43 | } Unexecuted instantiation: complexobject.c:_Py_ADJUST_ERANGE1 floatobject.c:_Py_ADJUST_ERANGE1 Line | Count | Source | 34 | { | 35 | if (errno == 0) { Branch (35:9): [True: 253k, False: 20]
| 36 | if (x == Py_HUGE_VAL || x == -Py_HUGE_VAL) { Branch (36:13): [True: 0, False: 253k]
Branch (36:33): [True: 0, False: 253k]
| 37 | errno = ERANGE; | 38 | } | 39 | } | 40 | else if (errno == ERANGE && x == 0.0) { Branch (40:14): [True: 20, False: 0]
Branch (40:33): [True: 20, False: 0]
| 41 | errno = 0; | 42 | } | 43 | } |
Unexecuted instantiation: pytime.c:_Py_ADJUST_ERANGE1 Unexecuted instantiation: sysmodule.c:_Py_ADJUST_ERANGE1 Unexecuted instantiation: pystrtod.c:_Py_ADJUST_ERANGE1 Unexecuted instantiation: dtoa.c:_Py_ADJUST_ERANGE1 |
44 | |
45 | static inline void _Py_ADJUST_ERANGE2(double x, double y) |
46 | { |
47 | if (x == Py_HUGE_VAL || x == -225 Py_HUGE_VAL225 || Branch (47:9): [True: 21, False: 225]
Branch (47:29): [True: 1, False: 224]
|
48 | y == 224 Py_HUGE_VAL224 || y == -221 Py_HUGE_VAL221 ) Branch (48:9): [True: 3, False: 221]
Branch (48:29): [True: 0, False: 221]
|
49 | { |
50 | if (errno == 0) { Branch (50:13): [True: 6, False: 19]
|
51 | errno = ERANGE; |
52 | } |
53 | } |
54 | else if (errno == ERANGE) { Branch (54:14): [True: 58, False: 163]
|
55 | errno = 0; |
56 | } |
57 | } complexobject.c:_Py_ADJUST_ERANGE2 Line | Count | Source | 46 | { | 47 | if (x == Py_HUGE_VAL || x == -225 Py_HUGE_VAL225 || Branch (47:9): [True: 21, False: 225]
Branch (47:29): [True: 1, False: 224]
| 48 | y == 224 Py_HUGE_VAL224 || y == -221 Py_HUGE_VAL221 ) Branch (48:9): [True: 3, False: 221]
Branch (48:29): [True: 0, False: 221]
| 49 | { | 50 | if (errno == 0) { Branch (50:13): [True: 6, False: 19]
| 51 | errno = ERANGE; | 52 | } | 53 | } | 54 | else if (errno == ERANGE) { Branch (54:14): [True: 58, False: 163]
| 55 | errno = 0; | 56 | } | 57 | } |
Unexecuted instantiation: floatobject.c:_Py_ADJUST_ERANGE2 Unexecuted instantiation: pytime.c:_Py_ADJUST_ERANGE2 Unexecuted instantiation: sysmodule.c:_Py_ADJUST_ERANGE2 Unexecuted instantiation: pystrtod.c:_Py_ADJUST_ERANGE2 Unexecuted instantiation: dtoa.c:_Py_ADJUST_ERANGE2 |
58 | |
59 | // Return the maximum value of integral type *type*. |
60 | #define _Py_IntegralTypeMax(type) \ |
61 | (_Py_IS_TYPE_SIGNED375k (type) ? (((((type)1 << (sizeof(type)*CHAR_BIT - 2)) - 1) << 1) + 1)375k : ~(type)00 ) |
62 | |
63 | // Return the minimum value of integral type *type*. |
64 | #define _Py_IntegralTypeMin(type) \ |
65 | (_Py_IS_TYPE_SIGNED(type) ? -_Py_IntegralTypeMax(type) - 1 : 00 ) |
66 | |
67 | // Check whether *v* is in the range of integral type *type*. This is most |
68 | // useful if *v* is floating-point, since demoting a floating-point *v* to an |
69 | // integral type that cannot represent *v*'s integral part is undefined |
70 | // behavior. |
71 | #define _Py_InIntegralTypeRange(type, v) \ |
72 | (_Py_IntegralTypeMin(type) <= v && v <= 187k _Py_IntegralTypeMax187k (type)) |
73 | |
74 | |
75 | //--- HAVE_PY_SET_53BIT_PRECISION macro ------------------------------------ |
76 | // |
77 | // The functions _Py_dg_strtod() and _Py_dg_dtoa() in Python/dtoa.c (which are |
78 | // required to support the short float repr introduced in Python 3.1) require |
79 | // that the floating-point unit that's being used for arithmetic operations on |
80 | // C doubles is set to use 53-bit precision. It also requires that the FPU |
81 | // rounding mode is round-half-to-even, but that's less often an issue. |
82 | // |
83 | // If your FPU isn't already set to 53-bit precision/round-half-to-even, and |
84 | // you want to make use of _Py_dg_strtod() and _Py_dg_dtoa(), then you should: |
85 | // |
86 | // #define HAVE_PY_SET_53BIT_PRECISION 1 |
87 | // |
88 | // and also give appropriate definitions for the following three macros: |
89 | // |
90 | // * _Py_SET_53BIT_PRECISION_HEADER: any variable declarations needed to |
91 | // use the two macros below. |
92 | // * _Py_SET_53BIT_PRECISION_START: store original FPU settings, and |
93 | // set FPU to 53-bit precision/round-half-to-even |
94 | // * _Py_SET_53BIT_PRECISION_END: restore original FPU settings |
95 | // |
96 | // The macros are designed to be used within a single C function: see |
97 | // Python/pystrtod.c for an example of their use. |
98 | |
99 | |
100 | // Get and set x87 control word for gcc/x86 |
101 | #ifdef HAVE_GCC_ASM_FOR_X87 |
102 | #define HAVE_PY_SET_53BIT_PRECISION 1 |
103 | |
104 | // Functions defined in Python/pymath.c |
105 | extern unsigned short _Py_get_387controlword(void); |
106 | extern void _Py_set_387controlword(unsigned short); |
107 | |
108 | #define _Py_SET_53BIT_PRECISION_HEADER \ |
109 | unsigned short old_387controlword, new_387controlword |
110 | #define _Py_SET_53BIT_PRECISION_START \ |
111 | do { \ |
112 | old_387controlword = _Py_get_387controlword(); \ |
113 | new_387controlword = (old_387controlword & ~0x0f00) | 0x0200; \ |
114 | if (new_387controlword != old_387controlword) { \ |
115 | _Py_set_387controlword(new_387controlword); \ |
116 | } \ |
117 | } while (0) |
118 | #define _Py_SET_53BIT_PRECISION_END \ |
119 | do { \ |
120 | if (new_387controlword != old_387controlword) { \ |
121 | _Py_set_387controlword(old_387controlword); \ |
122 | } \ |
123 | } while (0) |
124 | #endif |
125 | |
126 | // Get and set x87 control word for VisualStudio/x86. |
127 | // x87 is not supported in 64-bit or ARM. |
128 | #if defined(_MSC_VER) && !defined(_WIN64) && !defined(_M_ARM) |
129 | #define HAVE_PY_SET_53BIT_PRECISION 1 |
130 | |
131 | #include <float.h> // __control87_2() |
132 | |
133 | #define _Py_SET_53BIT_PRECISION_HEADER \ |
134 | unsigned int old_387controlword, new_387controlword, out_387controlword |
135 | // We use the __control87_2 function to set only the x87 control word. |
136 | // The SSE control word is unaffected. |
137 | #define _Py_SET_53BIT_PRECISION_START \ |
138 | do { \ |
139 | __control87_2(0, 0, &old_387controlword, NULL); \ |
140 | new_387controlword = \ |
141 | (old_387controlword & ~(_MCW_PC | _MCW_RC)) | (_PC_53 | _RC_NEAR); \ |
142 | if (new_387controlword != old_387controlword) { \ |
143 | __control87_2(new_387controlword, _MCW_PC | _MCW_RC, \ |
144 | &out_387controlword, NULL); \ |
145 | } \ |
146 | } while (0) |
147 | #define _Py_SET_53BIT_PRECISION_END \ |
148 | do { \ |
149 | if (new_387controlword != old_387controlword) { \ |
150 | __control87_2(old_387controlword, _MCW_PC | _MCW_RC, \ |
151 | &out_387controlword, NULL); \ |
152 | } \ |
153 | } while (0) |
154 | #endif |
155 | |
156 | |
157 | // MC68881 |
158 | #ifdef HAVE_GCC_ASM_FOR_MC68881 |
159 | #define HAVE_PY_SET_53BIT_PRECISION 1 |
160 | #define _Py_SET_53BIT_PRECISION_HEADER \ |
161 | unsigned int old_fpcr, new_fpcr |
162 | #define _Py_SET_53BIT_PRECISION_START \ |
163 | do { \ |
164 | __asm__ ("fmove.l %%fpcr,%0" : "=g" (old_fpcr)); \ |
165 | /* Set double precision / round to nearest. */ \ |
166 | new_fpcr = (old_fpcr & ~0xf0) | 0x80; \ |
167 | if (new_fpcr != old_fpcr) { \ |
168 | __asm__ volatile ("fmove.l %0,%%fpcr" : : "g" (new_fpcr));\ |
169 | } \ |
170 | } while (0) |
171 | #define _Py_SET_53BIT_PRECISION_END \ |
172 | do { \ |
173 | if (new_fpcr != old_fpcr) { \ |
174 | __asm__ volatile ("fmove.l %0,%%fpcr" : : "g" (old_fpcr)); \ |
175 | } \ |
176 | } while (0) |
177 | #endif |
178 | |
179 | // Default definitions are empty |
180 | #ifndef _Py_SET_53BIT_PRECISION_HEADER |
181 | # define _Py_SET_53BIT_PRECISION_HEADER |
182 | # define _Py_SET_53BIT_PRECISION_START |
183 | # define _Py_SET_53BIT_PRECISION_END |
184 | #endif |
185 | |
186 | |
187 | //--- _PY_SHORT_FLOAT_REPR macro ------------------------------------------- |
188 | |
189 | // If we can't guarantee 53-bit precision, don't use the code |
190 | // in Python/dtoa.c, but fall back to standard code. This |
191 | // means that repr of a float will be long (17 significant digits). |
192 | // |
193 | // Realistically, there are two things that could go wrong: |
194 | // |
195 | // (1) doubles aren't IEEE 754 doubles, or |
196 | // (2) we're on x86 with the rounding precision set to 64-bits |
197 | // (extended precision), and we don't know how to change |
198 | // the rounding precision. |
199 | #if !defined(DOUBLE_IS_LITTLE_ENDIAN_IEEE754) && \ |
200 | !defined(DOUBLE_IS_BIG_ENDIAN_IEEE754) && \ |
201 | !defined(DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754) |
202 | # define _PY_SHORT_FLOAT_REPR 0 |
203 | #endif |
204 | |
205 | // Double rounding is symptomatic of use of extended precision on x86. |
206 | // If we're seeing double rounding, and we don't have any mechanism available |
207 | // for changing the FPU rounding precision, then don't use Python/dtoa.c. |
208 | #if defined(X87_DOUBLE_ROUNDING) && !defined(HAVE_PY_SET_53BIT_PRECISION) |
209 | # define _PY_SHORT_FLOAT_REPR 0 |
210 | #endif |
211 | |
212 | #ifndef _PY_SHORT_FLOAT_REPR |
213 | # define _PY_SHORT_FLOAT_REPR 1 |
214 | #endif |
215 | |
216 | |
217 | #ifdef __cplusplus |
218 | } |
219 | #endif |
220 | #endif /* !Py_INTERNAL_PYMATH_H */ |