summaryrefslogtreecommitdiffstats
path: root/Include/pymath.h
diff options
context:
space:
mode:
authorBenjamin Peterson <benjamin@python.org>2017-09-07 18:13:59 (GMT)
committerGitHub <noreply@github.com>2017-09-07 18:13:59 (GMT)
commita853a8ba7850381d49b284295dd6f0dc491dbe44 (patch)
treedb901475288d8942c221c336fc4ad61f596761c3 /Include/pymath.h
parentc988ae01fec2e0510d53728e01a5e4bb06761bda (diff)
downloadcpython-a853a8ba7850381d49b284295dd6f0dc491dbe44.zip
cpython-a853a8ba7850381d49b284295dd6f0dc491dbe44.tar.gz
cpython-a853a8ba7850381d49b284295dd6f0dc491dbe44.tar.bz2
bpo-31373: fix undefined floating-point demotions (#3396)
Diffstat (limited to 'Include/pymath.h')
-rw-r--r--Include/pymath.h34
1 files changed, 23 insertions, 11 deletions
diff --git a/Include/pymath.h b/Include/pymath.h
index 7216a09..6cf69f9 100644
--- a/Include/pymath.h
+++ b/Include/pymath.h
@@ -187,14 +187,14 @@ PyAPI_FUNC(void) _Py_set_387controlword(unsigned short);
* result.
* Caution:
* This isn't reliable. C99 no longer requires libm to set errno under
- * any exceptional condition, but does require +- HUGE_VAL return
- * values on overflow. A 754 box *probably* maps HUGE_VAL to a
- * double infinity, and we're cool if that's so, unless the input
- * was an infinity and an infinity is the expected result. A C89
- * system sets errno to ERANGE, so we check for that too. We're
- * out of luck if a C99 754 box doesn't map HUGE_VAL to +Inf, or
- * if the returned result is a NaN, or if a C89 box returns HUGE_VAL
- * in non-overflow cases.
+ * any exceptional condition, but does require +- HUGE_VAL return
+ * values on overflow. A 754 box *probably* maps HUGE_VAL to a
+ * double infinity, and we're cool if that's so, unless the input
+ * was an infinity and an infinity is the expected result. A C89
+ * system sets errno to ERANGE, so we check for that too. We're
+ * out of luck if a C99 754 box doesn't map HUGE_VAL to +Inf, or
+ * if the returned result is a NaN, or if a C89 box returns HUGE_VAL
+ * in non-overflow cases.
* X is evaluated more than once.
* Some platforms have better way to spell this, so expect some #ifdef'ery.
*
@@ -211,8 +211,20 @@ PyAPI_FUNC(void) _Py_set_387controlword(unsigned short);
#define Py_OVERFLOWED(X) isinf(X)
#else
#define Py_OVERFLOWED(X) ((X) != 0.0 && (errno == ERANGE || \
- (X) == Py_HUGE_VAL || \
- (X) == -Py_HUGE_VAL))
-#endif
+ (X) == Py_HUGE_VAL || \
+ (X) == -Py_HUGE_VAL))
+#endif
+
+/* Return whether integral type *type* is signed or not. */
+#define _Py_IntegralTypeSigned(type) ((type)(-1) < 0)
+/* Return the maximum value of integral type *type*. */
+#define _Py_IntegralTypeMax(type) ((_Py_IntegralTypeSigned(type)) ? (((((type)1 << (sizeof(type)*CHAR_BIT - 2)) - 1) << 1) + 1) : ~(type)0)
+/* Return the minimum value of integral type *type*. */
+#define _Py_IntegralTypeMin(type) ((_Py_IntegralTypeSigned(type)) ? -_Py_IntegralTypeMax(type) - 1 : 0)
+/* Check whether *v* is in the range of integral type *type*. This is most
+ * useful if *v* is floating-point, since demoting a floating-point *v* to an
+ * integral type that cannot represent *v*'s integral part is undefined
+ * behavior. */
+#define _Py_InIntegralTypeRange(type, v) (_Py_IntegralTypeMin(type) <= v && v <= _Py_IntegralTypeMax(type))
#endif /* Py_PYMATH_H */