summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
Diffstat (limited to 'numpy')
-rw-r--r--numpy/core/include/numpy/npy_common.h28
-rw-r--r--numpy/core/src/multiarray/_multiarray_tests.c.src2
-rw-r--r--numpy/core/src/npymath/npy_math_internal.h.src40
3 files changed, 50 insertions, 20 deletions
diff --git a/numpy/core/include/numpy/npy_common.h b/numpy/core/include/numpy/npy_common.h
index 57cc592b9..88794ca07 100644
--- a/numpy/core/include/numpy/npy_common.h
+++ b/numpy/core/include/numpy/npy_common.h
@@ -356,14 +356,32 @@ typedef unsigned long npy_ulonglong;
typedef unsigned char npy_bool;
#define NPY_FALSE 0
#define NPY_TRUE 1
-
-
+/*
+ * `NPY_SIZEOF_LONGDOUBLE` isn't usually equal to sizeof(long double).
+ * In some certain cases, it may forced to be equal to sizeof(double)
+ * even against the compiler implementation and the same goes for
+ * `complex long double`.
+ *
+ * Therefore, avoid `long double`, use `npy_longdouble` instead,
+ * and when it comes to standard math functions make sure of using
+ * the double version when `NPY_SIZEOF_LONGDOUBLE` == `NPY_SIZEOF_DOUBLE`.
+ * For example:
+ * npy_longdouble *ptr, x;
+ * #if NPY_SIZEOF_LONGDOUBLE == NPY_SIZEOF_DOUBLE
+ * npy_longdouble r = modf(x, ptr);
+ * #else
+ * npy_longdouble r = modfl(x, ptr);
+ * #endif
+ *
+ * See https://github.com/numpy/numpy/issues/20348
+ */
#if NPY_SIZEOF_LONGDOUBLE == NPY_SIZEOF_DOUBLE
- #define NPY_LONGDOUBLE_FMT "g"
+ #define NPY_LONGDOUBLE_FMT "g"
+ typedef double npy_longdouble;
#else
- #define NPY_LONGDOUBLE_FMT "Lg"
+ #define NPY_LONGDOUBLE_FMT "Lg"
+ typedef long double npy_longdouble;
#endif
-typedef long double npy_longdouble;
#ifndef Py_USING_UNICODE
#error Must use Python with unicode enabled.
diff --git a/numpy/core/src/multiarray/_multiarray_tests.c.src b/numpy/core/src/multiarray/_multiarray_tests.c.src
index e945d0771..d7dfa4829 100644
--- a/numpy/core/src/multiarray/_multiarray_tests.c.src
+++ b/numpy/core/src/multiarray/_multiarray_tests.c.src
@@ -2193,7 +2193,7 @@ PrintFloat_Printf_g(PyObject *obj, int precision)
}
else if (PyArray_IsScalar(obj, LongDouble)) {
npy_longdouble x = PyArrayScalar_VAL(obj, LongDouble);
- PyOS_snprintf(str, sizeof(str), "%.*Lg", precision, x);
+ PyOS_snprintf(str, sizeof(str), "%.*" NPY_LONGDOUBLE_FMT, precision, x);
}
else{
double val = PyFloat_AsDouble(obj);
diff --git a/numpy/core/src/npymath/npy_math_internal.h.src b/numpy/core/src/npymath/npy_math_internal.h.src
index dd2424db8..5b418342f 100644
--- a/numpy/core/src/npymath/npy_math_internal.h.src
+++ b/numpy/core/src/npymath/npy_math_internal.h.src
@@ -477,10 +477,16 @@ NPY_INPLACE @type@ npy_frexp@c@(@type@ x, int* exp)
/**begin repeat
* #type = npy_longdouble, npy_double, npy_float#
+ * #TYPE = LONGDOUBLE, DOUBLE, FLOAT#
* #c = l,,f#
* #C = L,,F#
*/
-
+#undef NPY__FP_SFX
+#if NPY_SIZEOF_@TYPE@ == NPY_SIZEOF_DOUBLE
+ #define NPY__FP_SFX(X) X
+#else
+ #define NPY__FP_SFX(X) NPY_CAT(X, @c@)
+#endif
/*
* On arm64 macOS, there's a bug with sin, cos, and tan where they don't
* raise "invalid" when given INFINITY as input.
@@ -506,7 +512,7 @@ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x)
return (x - x);
}
#endif
- return @kind@@c@(x);
+ return NPY__FP_SFX(@kind@)(x);
}
#endif
@@ -521,7 +527,7 @@ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x)
#ifdef HAVE_@KIND@@C@
NPY_INPLACE @type@ npy_@kind@@c@(@type@ x, @type@ y)
{
- return @kind@@c@(x, y);
+ return NPY__FP_SFX(@kind@)(x, y);
}
#endif
/**end repeat1**/
@@ -529,21 +535,21 @@ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x, @type@ y)
#ifdef HAVE_MODF@C@
NPY_INPLACE @type@ npy_modf@c@(@type@ x, @type@ *iptr)
{
- return modf@c@(x, iptr);
+ return NPY__FP_SFX(modf)(x, iptr);
}
#endif
#ifdef HAVE_LDEXP@C@
NPY_INPLACE @type@ npy_ldexp@c@(@type@ x, int exp)
{
- return ldexp@c@(x, exp);
+ return NPY__FP_SFX(ldexp)(x, exp);
}
#endif
#ifdef HAVE_FREXP@C@
NPY_INPLACE @type@ npy_frexp@c@(@type@ x, int* exp)
{
- return frexp@c@(x, exp);
+ return NPY__FP_SFX(frexp)(x, exp);
}
#endif
@@ -566,10 +572,10 @@ NPY_INPLACE @type@ npy_cbrt@c@(@type@ x)
#else
NPY_INPLACE @type@ npy_cbrt@c@(@type@ x)
{
- return cbrt@c@(x);
+ return NPY__FP_SFX(cbrt)(x);
}
#endif
-
+#undef NPY__FP_SFX
/**end repeat**/
@@ -579,10 +585,16 @@ NPY_INPLACE @type@ npy_cbrt@c@(@type@ x)
/**begin repeat
* #type = npy_float, npy_double, npy_longdouble#
+ * #TYPE = FLOAT, DOUBLE, LONGDOUBLE#
* #c = f, ,l#
* #C = F, ,L#
*/
-
+#undef NPY__FP_SFX
+#if NPY_SIZEOF_@TYPE@ == NPY_SIZEOF_DOUBLE
+ #define NPY__FP_SFX(X) X
+#else
+ #define NPY__FP_SFX(X) NPY_CAT(X, @c@)
+#endif
@type@ npy_heaviside@c@(@type@ x, @type@ h0)
{
if (npy_isnan(x)) {
@@ -599,10 +611,10 @@ NPY_INPLACE @type@ npy_cbrt@c@(@type@ x)
}
}
-#define LOGE2 NPY_LOGE2@c@
-#define LOG2E NPY_LOG2E@c@
-#define RAD2DEG (180.0@c@/NPY_PI@c@)
-#define DEG2RAD (NPY_PI@c@/180.0@c@)
+#define LOGE2 NPY__FP_SFX(NPY_LOGE2)
+#define LOG2E NPY__FP_SFX(NPY_LOG2E)
+#define RAD2DEG (NPY__FP_SFX(180.0)/NPY__FP_SFX(NPY_PI))
+#define DEG2RAD (NPY__FP_SFX(NPY_PI)/NPY__FP_SFX(180.0))
NPY_INPLACE @type@ npy_rad2deg@c@(@type@ x)
{
@@ -756,7 +768,7 @@ npy_divmod@c@(@type@ a, @type@ b, @type@ *modulus)
#undef LOG2E
#undef RAD2DEG
#undef DEG2RAD
-
+#undef NPY__FP_SFX
/**end repeat**/
/**begin repeat