mirror of https://github.com/pyodide/pyodide.git
137 lines
4.6 KiB
Diff
137 lines
4.6 KiB
Diff
![]() |
From f6125bff9fd373d86a222185b42ea7d1d5221cbe Mon Sep 17 00:00:00 2001
|
||
|
From: Hood Chatham <roberthoodchatham@gmail.com>
|
||
|
Date: Sat, 11 Jun 2022 11:19:42 -0700
|
||
|
Subject: [PATCH] ENH: Add support for platforms with missing fenv flags
|
||
|
|
||
|
For instance wasm has no fenv support. 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
|
||
|
---
|
||
|
numpy/core/src/npymath/ieee754.c.src | 67 ++++++++++++++++++++++------
|
||
|
1 file changed, 54 insertions(+), 13 deletions(-)
|
||
|
|
||
|
diff --git a/numpy/core/src/npymath/ieee754.c.src b/numpy/core/src/npymath/ieee754.c.src
|
||
|
index 6aecb7577..857cdd31d 100644
|
||
|
--- a/numpy/core/src/npymath/ieee754.c.src
|
||
|
+++ b/numpy/core/src/npymath/ieee754.c.src
|
||
|
@@ -775,10 +775,52 @@ int npy_clear_floatstatus_barrier(char *param)
|
||
|
/* General GCC code, should work on most platforms */
|
||
|
# 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
|
||
|
+#endif
|
||
|
+#ifdef FE_DIVBYZERO
|
||
|
+#define DIVBYZERO FE_DIVBYZERO
|
||
|
+#else
|
||
|
+#define DIVBYZERO 0
|
||
|
+#endif
|
||
|
+#ifdef FE_UNDERFLOW
|
||
|
+#define UNDERFLOW FE_UNDERFLOW
|
||
|
+#else
|
||
|
+#define UNDERFLOW 0
|
||
|
+#endif
|
||
|
+#ifdef FE_OVERFLOW
|
||
|
+#define OVERFLOW FE_OVERFLOW
|
||
|
+#else
|
||
|
+#define OVERFLOW 0
|
||
|
+#endif
|
||
|
+
|
||
|
+
|
||
|
int npy_get_floatstatus_barrier(char* param)
|
||
|
{
|
||
|
- int fpstatus = fetestexcept(FE_DIVBYZERO | FE_OVERFLOW |
|
||
|
- FE_UNDERFLOW | FE_INVALID);
|
||
|
+ int fpstatus = fetestexcept(DIVBYZERO | OVERFLOW |
|
||
|
+ UNDERFLOW | INVALID);
|
||
|
/*
|
||
|
* By using a volatile, the compiler cannot reorder this call
|
||
|
*/
|
||
|
@@ -786,10 +828,10 @@ int npy_get_floatstatus_barrier(char* param)
|
||
|
volatile char NPY_UNUSED(c) = *(char*)param;
|
||
|
}
|
||
|
|
||
|
- 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);
|
||
|
+ 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);
|
||
|
}
|
||
|
|
||
|
int npy_clear_floatstatus_barrier(char * param)
|
||
|
@@ -797,8 +839,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(FE_DIVBYZERO | FE_OVERFLOW |
|
||
|
- FE_UNDERFLOW | FE_INVALID);
|
||
|
+ feclearexcept(DIVBYZERO | OVERFLOW |
|
||
|
+ UNDERFLOW | INVALID);
|
||
|
}
|
||
|
|
||
|
return fpstatus;
|
||
|
@@ -807,22 +849,21 @@ int npy_clear_floatstatus_barrier(char * param)
|
||
|
|
||
|
void npy_set_floatstatus_divbyzero(void)
|
||
|
{
|
||
|
- feraiseexcept(FE_DIVBYZERO);
|
||
|
+ feraiseexcept(DIVBYZERO);
|
||
|
}
|
||
|
|
||
|
void npy_set_floatstatus_overflow(void)
|
||
|
{
|
||
|
- feraiseexcept(FE_OVERFLOW);
|
||
|
+ feraiseexcept(OVERFLOW);
|
||
|
}
|
||
|
|
||
|
void npy_set_floatstatus_underflow(void)
|
||
|
{
|
||
|
- feraiseexcept(FE_UNDERFLOW);
|
||
|
+ feraiseexcept(UNDERFLOW);
|
||
|
}
|
||
|
|
||
|
void npy_set_floatstatus_invalid(void)
|
||
|
{
|
||
|
- feraiseexcept(FE_INVALID);
|
||
|
+ feraiseexcept(INVALID);
|
||
|
}
|
||
|
-
|
||
|
#endif
|
||
|
--
|
||
|
2.25.1
|
||
|
|