summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Berg <sebastian@sipsolutions.net>2022-06-14 09:43:58 -0700
committerSebastian Berg <sebastian@sipsolutions.net>2022-06-14 09:43:58 -0700
commit7be59f1787f6a900b8fe4a0013ba3e9f2b7cea95 (patch)
treecea56cd05690bd84b8a8744091b8000730f32410
parent3cb57d5902a6b2b120ecaeb7c7722a460eda8232 (diff)
downloadnumpy-7be59f1787f6a900b8fe4a0013ba3e9f2b7cea95.tar.gz
MAINT: Simplify FE_INVALID redefine logic slightly and copy to cpp
This builds on the previous, but just redefines them in the C/C++ file since this is not a header and defining an undefined macro value should not be a problem locally. Also tweaks the comment a bit.
-rw-r--r--numpy/core/src/npymath/ieee754.c.src78
-rw-r--r--numpy/core/src/npymath/ieee754.cpp24
2 files changed, 54 insertions, 48 deletions
diff --git a/numpy/core/src/npymath/ieee754.c.src b/numpy/core/src/npymath/ieee754.c.src
index 5751ee2df..5d1ea3a69 100644
--- a/numpy/core/src/npymath/ieee754.c.src
+++ b/numpy/core/src/npymath/ieee754.c.src
@@ -575,52 +575,34 @@ int npy_get_floatstatus() {
*/
# include <fenv.h>
-// musl-libc defines all the fenv functions unconditionally (fesetexcept,
-// feclearexcept, etc) but on unsupported platforms they are no-ops:
-// https://git.musl-libc.org/cgit/musl/tree/src/fenv/fenv.c
-// However, the platform is expected to only define flags like
-// FE_OVERFLOW if they are supported. I haven't found an explanation
-// of the design decision, but it seems to be aimed at fine-grained
-// feature detection. musl-libc-test has code that uses fenv and wants
-// it to silently decay to a no-op on platforms missing support. I
-// copied their implementation of this behavior:
-// http://nsz.repo.hu/git/?p=libc-test;a=blob;f=src/common/mtest.h;h=706c1ba23ea8989b17a2f72ed1a919e187c06b6a;hb=HEAD#l30
-#undef INEXACT
-#undef INVALID
-#undef DIVBYZERO
-#undef UNDERFLOW
-#undef OVERFLOW
-#ifdef FE_INEXACT
-#define INEXACT FE_INEXACT
-#else
-#define INEXACT 0
-#endif
-#ifdef FE_INVALID
-#define INVALID FE_INVALID
-#else
-#define INVALID 0
+/*
+ * According to the C99 standard FE_DIVBYZERO, etc. may not be provided when
+ * unsupported. In such cases NumPy will not report these correctly, but we
+ * should still allow compiling (whether tests pass or not).
+ * By defining them as 0 locally, we make them no-ops. Unlike these defines,
+ * for example `musl` still defines all of the functions (as no-ops):
+ * https://git.musl-libc.org/cgit/musl/tree/src/fenv/fenv.c
+ * and does similar replacement in its tests:
+ * http://nsz.repo.hu/git/?p=libc-test;a=blob;f=src/common/mtest.h;h=706c1ba23ea8989b17a2f72ed1a919e187c06b6a;hb=HEAD#l30
+ */
+#ifndef FE_DIVBYZERO
+ #define FE_DIVBYZERO 0
#endif
-#ifdef FE_DIVBYZERO
-#define DIVBYZERO FE_DIVBYZERO
-#else
-#define DIVBYZERO 0
+#ifndef FE_OVERFLOW
+ #define FE_OVERFLOW 0
#endif
-#ifdef FE_UNDERFLOW
-#define UNDERFLOW FE_UNDERFLOW
-#else
-#define UNDERFLOW 0
+#ifndef FE_UNDERFLOW
+ #define FE_UNDERFLOW 0
#endif
-#ifdef FE_OVERFLOW
-#define OVERFLOW FE_OVERFLOW
-#else
-#define OVERFLOW 0
+#ifndef FE_INVALID
+ #define FE_INVALID 0
#endif
int npy_get_floatstatus_barrier(char* param)
{
- int fpstatus = fetestexcept(DIVBYZERO | OVERFLOW |
- UNDERFLOW | INVALID);
+ int fpstatus = fetestexcept(FE_DIVBYZERO | FE_OVERFLOW |
+ FE_UNDERFLOW | FE_INVALID);
/*
* By using a volatile, the compiler cannot reorder this call
*/
@@ -628,10 +610,10 @@ int npy_get_floatstatus_barrier(char* param)
volatile char NPY_UNUSED(c) = *(char*)param;
}
- return ((DIVBYZERO & fpstatus) ? NPY_FPE_DIVIDEBYZERO : 0) |
- ((OVERFLOW & fpstatus) ? NPY_FPE_OVERFLOW : 0) |
- ((UNDERFLOW & fpstatus) ? NPY_FPE_UNDERFLOW : 0) |
- ((INVALID & fpstatus) ? NPY_FPE_INVALID : 0);
+ return ((FE_DIVBYZERO & fpstatus) ? NPY_FPE_DIVIDEBYZERO : 0) |
+ ((FE_OVERFLOW & fpstatus) ? NPY_FPE_OVERFLOW : 0) |
+ ((FE_UNDERFLOW & fpstatus) ? NPY_FPE_UNDERFLOW : 0) |
+ ((FE_INVALID & fpstatus) ? NPY_FPE_INVALID : 0);
}
int npy_clear_floatstatus_barrier(char * param)
@@ -639,8 +621,8 @@ int npy_clear_floatstatus_barrier(char * param)
/* testing float status is 50-100 times faster than clearing on x86 */
int fpstatus = npy_get_floatstatus_barrier(param);
if (fpstatus != 0) {
- feclearexcept(DIVBYZERO | OVERFLOW |
- UNDERFLOW | INVALID);
+ feclearexcept(FE_DIVBYZERO | FE_OVERFLOW |
+ FE_UNDERFLOW | FE_INVALID);
}
return fpstatus;
@@ -649,21 +631,21 @@ int npy_clear_floatstatus_barrier(char * param)
void npy_set_floatstatus_divbyzero(void)
{
- feraiseexcept(DIVBYZERO);
+ feraiseexcept(FE_DIVBYZERO);
}
void npy_set_floatstatus_overflow(void)
{
- feraiseexcept(OVERFLOW);
+ feraiseexcept(FE_OVERFLOW);
}
void npy_set_floatstatus_underflow(void)
{
- feraiseexcept(UNDERFLOW);
+ feraiseexcept(FE_UNDERFLOW);
}
void npy_set_floatstatus_invalid(void)
{
- feraiseexcept(INVALID);
+ feraiseexcept(FE_INVALID);
}
diff --git a/numpy/core/src/npymath/ieee754.cpp b/numpy/core/src/npymath/ieee754.cpp
index 2244004c0..27fcf7c6e 100644
--- a/numpy/core/src/npymath/ieee754.cpp
+++ b/numpy/core/src/npymath/ieee754.cpp
@@ -655,6 +655,30 @@ npy_get_floatstatus()
*/
#include <fenv.h>
+/*
+ * According to the C99 standard FE_DIVBYZERO, etc. may not be provided when
+ * unsupported. In such cases NumPy will not report these correctly, but we
+ * should still allow compiling (whether tests pass or not).
+ * By defining them as 0 locally, we make them no-ops. Unlike these defines,
+ * for example `musl` still defines all of the functions (as no-ops):
+ * https://git.musl-libc.org/cgit/musl/tree/src/fenv/fenv.c
+ * and does similar replacement in its tests:
+ * http://nsz.repo.hu/git/?p=libc-test;a=blob;f=src/common/mtest.h;h=706c1ba23ea8989b17a2f72ed1a919e187c06b6a;hb=HEAD#l30
+ */
+#ifndef FE_DIVBYZERO
+ #define FE_DIVBYZERO 0
+#endif
+#ifndef FE_OVERFLOW
+ #define FE_OVERFLOW 0
+#endif
+#ifndef FE_UNDERFLOW
+ #define FE_UNDERFLOW 0
+#endif
+#ifndef FE_INVALID
+ #define FE_INVALID 0
+#endif
+
+
extern "C" int
npy_get_floatstatus_barrier(char *param)
{