From f33e5790ee7fa338208749a052f129ff73e12404 Mon Sep 17 00:00:00 2001 From: mattip Date: Sun, 7 Aug 2022 21:42:45 +0300 Subject: [PATCH 01/16] remove obsolete support for Solaris --- numpy/core/include/numpy/npy_math.h | 3 --- numpy/core/src/common/npy_config.h | 9 --------- 2 files changed, 12 deletions(-) diff --git a/numpy/core/include/numpy/npy_math.h b/numpy/core/include/numpy/npy_math.h index 1f4cea613e46..6a86e25a860f 100644 --- a/numpy/core/include/numpy/npy_math.h +++ b/numpy/core/include/numpy/npy_math.h @@ -4,9 +4,6 @@ #include #include -#ifdef __SUNPRO_CC -#include -#endif /* By adding static inline specifiers to npy_math function definitions when appropriate, compiler is given the opportunity to optimize */ diff --git a/numpy/core/src/common/npy_config.h b/numpy/core/src/common/npy_config.h index 67b474d39f57..cca809c7f3af 100644 --- a/numpy/core/src/common/npy_config.h +++ b/numpy/core/src/common/npy_config.h @@ -10,15 +10,6 @@ /* blocklist */ -/* Disable broken Sun Workshop Pro math functions */ -#ifdef __SUNPRO_C - -#undef HAVE_ATAN2 -#undef HAVE_ATAN2F -#undef HAVE_ATAN2L - -#endif - /* Disable broken functions on z/OS */ #if defined (__MVS__) From e9e8cee18ad6aa0b500a0188e239f260b71dfb78 Mon Sep 17 00:00:00 2001 From: mattip Date: Sun, 7 Aug 2022 22:24:56 +0300 Subject: [PATCH 02/16] rearrange headers to make npy_config.h only about config --- numpy/core/src/_simd/_simd.h | 3 +++ numpy/core/src/common/npy_config.h | 4 +--- numpy/core/src/multiarray/common.h | 4 ++++ numpy/core/src/umath/_umath_tests.c.src | 3 +++ numpy/core/src/umath/umathmodule.c | 3 +++ 5 files changed, 14 insertions(+), 3 deletions(-) diff --git a/numpy/core/src/_simd/_simd.h b/numpy/core/src/_simd/_simd.h index d9905c80127c..dfe4d6bb44f3 100644 --- a/numpy/core/src/_simd/_simd.h +++ b/numpy/core/src/_simd/_simd.h @@ -17,6 +17,9 @@ #ifndef NPY_DISABLE_OPTIMIZATION // autogenerated, required for CPU dispatch macros +#include "npy_cpu_features.h" +#include "npy_cpu_dispatch.h" +#include "numpy/npy_cpu.h" #include "_simd.dispatch.h" #endif /** diff --git a/numpy/core/src/common/npy_config.h b/numpy/core/src/common/npy_config.h index cca809c7f3af..610216a34a54 100644 --- a/numpy/core/src/common/npy_config.h +++ b/numpy/core/src/common/npy_config.h @@ -2,10 +2,8 @@ #define NUMPY_CORE_SRC_COMMON_NPY_CONFIG_H_ #include "config.h" -#include "npy_cpu_features.h" -#include "npy_cpu_dispatch.h" #include "numpy/numpyconfig.h" -#include "numpy/npy_cpu.h" +#include "numpy/utils.h" #include "numpy/npy_os.h" /* blocklist */ diff --git a/numpy/core/src/multiarray/common.h b/numpy/core/src/multiarray/common.h index a6c117745b2f..3de8c842dbc2 100644 --- a/numpy/core/src/multiarray/common.h +++ b/numpy/core/src/multiarray/common.h @@ -4,6 +4,10 @@ #include #include "numpy/npy_common.h" #include "numpy/ndarraytypes.h" +#include "npy_cpu_features.h" +#include "npy_cpu_dispatch.h" +#include "numpy/npy_cpu.h" + #include "npy_import.h" #include diff --git a/numpy/core/src/umath/_umath_tests.c.src b/numpy/core/src/umath/_umath_tests.c.src index ce42fc2711a3..1bf459ce6664 100644 --- a/numpy/core/src/umath/_umath_tests.c.src +++ b/numpy/core/src/umath/_umath_tests.c.src @@ -16,6 +16,9 @@ #include "npy_pycompat.h" #include "npy_config.h" +#include "npy_cpu_features.h" +#include "npy_cpu_dispatch.h" +#include "numpy/npy_cpu.h" /* ***************************************************************************** diff --git a/numpy/core/src/umath/umathmodule.c b/numpy/core/src/umath/umathmodule.c index 17fedec6f73b..0aa32820d0ad 100644 --- a/numpy/core/src/umath/umathmodule.c +++ b/numpy/core/src/umath/umathmodule.c @@ -14,6 +14,9 @@ #include #include "npy_config.h" +#include "npy_cpu_features.h" +#include "npy_cpu_dispatch.h" +#include "numpy/npy_cpu.h" #include "numpy/arrayobject.h" #include "numpy/ufuncobject.h" From 9e481adde718e758cd6b9314d43ee6e6d88967c9 Mon Sep 17 00:00:00 2001 From: mattip Date: Sun, 7 Aug 2022 22:26:34 +0300 Subject: [PATCH 03/16] make optional C99 double routines mandatory --- numpy/core/setup.py | 21 +- numpy/core/setup_common.py | 10 +- .../core/src/npymath/npy_math_internal.h.src | 350 +----------------- 3 files changed, 13 insertions(+), 368 deletions(-) diff --git a/numpy/core/setup.py b/numpy/core/setup.py index 9e05aded0a9c..571d067e0259 100644 --- a/numpy/core/setup.py +++ b/numpy/core/setup.py @@ -145,7 +145,8 @@ def check_func( headers=headers, ) - def check_funcs_once(funcs_name, headers=["feature_detection_math.h"]): + def check_funcs_once(funcs_name, headers=["feature_detection_math.h"], + add_to_moredefs=True): call = dict([(f, True) for f in funcs_name]) call_args = dict([(f, FUNC_CALL_ARGS[f]) for f in funcs_name]) st = config.check_funcs_once( @@ -156,7 +157,7 @@ def check_funcs_once(funcs_name, headers=["feature_detection_math.h"]): call_args=call_args, headers=headers, ) - if st: + if st and add_to_moredefs: moredefs.extend([(fname2def(f), 1) for f in funcs_name]) return st @@ -173,7 +174,7 @@ def check_funcs(funcs_name, headers=["feature_detection_math.h"]): return 1 #use_msvc = config.check_decl("_MSC_VER") - if not check_funcs_once(MANDATORY_FUNCS): + if not check_funcs_once(MANDATORY_FUNCS, add_to_moredefs=False): raise SystemError("One of the required function to build numpy is not" " available (the list is %s)." % str(MANDATORY_FUNCS)) @@ -184,20 +185,12 @@ def check_funcs(funcs_name, headers=["feature_detection_math.h"]): # config.h in the public namespace, so we have a clash for the common # functions we test. We remove every function tested by python's # autoconf, hoping their own test are correct - for f in OPTIONAL_STDFUNCS_MAYBE: - if config.check_decl(fname2def(f), - headers=["Python.h", "math.h"]): - if f in OPTIONAL_STDFUNCS: - OPTIONAL_STDFUNCS.remove(f) - else: - OPTIONAL_FILE_FUNCS.remove(f) + for f in OPTIONAL_FUNCS_MAYBE: + if config.check_decl(fname2def(f), headers=["Python.h"]): + OPTIONAL_FILE_FUNCS.remove(f) - - check_funcs(OPTIONAL_STDFUNCS) check_funcs(OPTIONAL_FILE_FUNCS, headers=["feature_detection_stdio.h"]) check_funcs(OPTIONAL_MISC_FUNCS, headers=["feature_detection_misc.h"]) - - for h in OPTIONAL_HEADERS: if config.check_func("", decl=False, call=False, headers=[h]): diff --git a/numpy/core/setup_common.py b/numpy/core/setup_common.py index a751acc6fd62..d618fac69bed 100644 --- a/numpy/core/setup_common.py +++ b/numpy/core/setup_common.py @@ -124,9 +124,8 @@ def set_sig(sig): "floor", "ceil", "sqrt", "log10", "log", "exp", "asin", "acos", "atan", "fmod", 'modf', 'frexp', 'ldexp'] -# Standard functions which may not be available and for which we have a -# replacement implementation. Note that some of these are C99 functions. -OPTIONAL_STDFUNCS = ["expm1", "log1p", "acosh", "asinh", "atanh", +# Some of these are C99 functions. +MANDATORY_FUNCS += ["expm1", "log1p", "acosh", "asinh", "atanh", "rint", "trunc", "exp2", "log2", "hypot", "atan2", "pow", "copysign", "nextafter", "strtoll", "strtoull", "cbrt"] @@ -227,9 +226,8 @@ def set_sig(sig): # variable attributes tested via "int %s a" % attribute OPTIONAL_VARIABLE_ATTRIBUTES = ["__thread", "__declspec(thread)"] -# Subset of OPTIONAL_STDFUNCS which may already have HAVE_* defined by Python.h -OPTIONAL_STDFUNCS_MAYBE = [ - "expm1", "log1p", "acosh", "atanh", "asinh", "hypot", "copysign", +# Subset of OPTIONAL_*_FUNCS which may already have HAVE_* defined by Python.h +OPTIONAL_FUNCS_MAYBE = [ "ftello", "fseeko" ] diff --git a/numpy/core/src/npymath/npy_math_internal.h.src b/numpy/core/src/npymath/npy_math_internal.h.src index 0364aabb1a9b..b5e415c8a9fa 100644 --- a/numpy/core/src/npymath/npy_math_internal.h.src +++ b/numpy/core/src/npymath/npy_math_internal.h.src @@ -88,297 +88,13 @@ static const npy_uint64 MAGIC64[] = {0x5555555555555555ull, 0x3333333333333333ul */ /* Original code by Konrad Hinsen. */ -#ifndef HAVE_EXPM1 -NPY_INPLACE double npy_expm1(double x) -{ - if (npy_isinf(x) && x > 0) { - return x; - } - else { - const double u = npy_exp(x); - - if (u == 1.0) { - return x; - } else if (u - 1.0 == -1.0) { - return -1; - } else { - return (u - 1.0) * x/npy_log(u); - } - } -} -#endif - -#ifndef HAVE_LOG1P -NPY_INPLACE double npy_log1p(double x) -{ - if (npy_isinf(x) && x > 0) { - return x; - } - else { - const double u = 1. + x; - const double d = u - 1.; - - if (d == 0) { - return x; - } else { - return npy_log(u) * x / d; - } - } -} -#endif - /* Taken from FreeBSD mlib, adapted for numpy * * XXX: we could be a bit faster by reusing high/low words for inf/nan * classification instead of calling npy_isinf/npy_isnan: we should have some * macros for this, though, instead of doing it manually */ -#ifndef HAVE_ATAN2 -/* XXX: we should have this in npy_math.h */ -#define NPY_DBL_EPSILON 1.2246467991473531772E-16 -NPY_INPLACE double npy_atan2(double y, double x) -{ - npy_int32 k, m, iy, ix, hx, hy; - npy_uint32 lx,ly; - double z; - - EXTRACT_WORDS(hx, lx, x); - ix = hx & 0x7fffffff; - EXTRACT_WORDS(hy, ly, y); - iy = hy & 0x7fffffff; - - /* if x or y is nan, return nan */ - if (npy_isnan(x * y)) { - return x + y; - } - - if (x == 1.0) { - return npy_atan(y); - } - - m = 2 * (npy_signbit((x)) != 0) + (npy_signbit((y)) != 0); - if (y == 0.0) { - switch(m) { - case 0: - case 1: return y; /* atan(+-0,+anything)=+-0 */ - case 2: return NPY_PI;/* atan(+0,-anything) = pi */ - case 3: return -NPY_PI;/* atan(-0,-anything) =-pi */ - } - } - - if (x == 0.0) { - return y > 0 ? NPY_PI_2 : -NPY_PI_2; - } - - if (npy_isinf(x)) { - if (npy_isinf(y)) { - switch(m) { - case 0: return NPY_PI_4;/* atan(+INF,+INF) */ - case 1: return -NPY_PI_4;/* atan(-INF,+INF) */ - case 2: return 3.0*NPY_PI_4;/*atan(+INF,-INF)*/ - case 3: return -3.0*NPY_PI_4;/*atan(-INF,-INF)*/ - } - } else { - switch(m) { - case 0: return NPY_PZERO; /* atan(+...,+INF) */ - case 1: return NPY_NZERO; /* atan(-...,+INF) */ - case 2: return NPY_PI; /* atan(+...,-INF) */ - case 3: return -NPY_PI; /* atan(-...,-INF) */ - } - } - } - - if (npy_isinf(y)) { - return y > 0 ? NPY_PI_2 : -NPY_PI_2; - } - - /* compute y/x */ - k = (iy - ix) >> 20; - if (k > 60) { /* |y/x| > 2**60 */ - z = NPY_PI_2 + 0.5 * NPY_DBL_EPSILON; - m &= 1; - } else if (hx < 0 && k < -60) { - z = 0.0; /* 0 > |y|/x > -2**-60 */ - } else { - z = npy_atan(npy_fabs(y/x)); /* safe to do y/x */ - } - - switch (m) { - case 0: return z ; /* atan(+,+) */ - case 1: return -z ; /* atan(-,+) */ - case 2: return NPY_PI - (z - NPY_DBL_EPSILON);/* atan(+,-) */ - default: /* case 3 */ - return (z - NPY_DBL_EPSILON) - NPY_PI;/* atan(-,-) */ - } -} - -#endif - -#ifndef HAVE_HYPOT -NPY_INPLACE double npy_hypot(double x, double y) -{ - double yx; - - if (npy_isinf(x) || npy_isinf(y)) { - return NPY_INFINITY; - } - - if (npy_isnan(x) || npy_isnan(y)) { - return NPY_NAN; - } - - x = npy_fabs(x); - y = npy_fabs(y); - if (x < y) { - double temp = x; - x = y; - y = temp; - } - if (x == 0.) { - return 0.; - } - else { - yx = y/x; - return x*npy_sqrt(1.+yx*yx); - } -} -#endif - -#ifndef HAVE_ACOSH -NPY_INPLACE double npy_acosh(double x) -{ - if (x < 1.0) { - return NPY_NAN; - } - - if (npy_isfinite(x)) { - if (x > 1e8) { - return npy_log(x) + NPY_LOGE2; - } - else { - double u = x - 1.0; - return npy_log1p(u + npy_sqrt(2*u + u*u)); - } - } - return x; -} -#endif - -#ifndef HAVE_ASINH -NPY_INPLACE double npy_asinh(double xx) -{ - double x, d; - int sign; - if (xx < 0.0) { - sign = -1; - x = -xx; - } - else { - sign = 1; - x = xx; - } - if (x > 1e8) { - d = x; - } else { - d = npy_sqrt(x*x + 1); - } - return sign*npy_log1p(x*(1.0 + x/(d+1))); -} -#endif - -#ifndef HAVE_ATANH -NPY_INPLACE double npy_atanh(double x) -{ - if (x > 0) { - return -0.5*npy_log1p(-2.0*x/(1.0 + x)); - } - else { - return 0.5*npy_log1p(2.0*x/(1.0 - x)); - } -} -#endif - -#ifndef HAVE_RINT -#if defined(_MSC_VER) && (_MSC_VER == 1500) && !defined(_WIN64) -#pragma optimize("", off) -#endif -NPY_INPLACE double npy_rint(double x) -{ - double y, r; - - y = npy_floor(x); - r = x - y; - - if (r > 0.5) { - y += 1.0; - } - - /* Round to nearest even */ - if (r == 0.5) { - r = y - 2.0*npy_floor(0.5*y); - if (r == 1.0) { - y += 1.0; - } - } - return y; -} -#if defined(_MSC_VER) && (_MSC_VER == 1500) && !defined(_WIN64) -#pragma optimize("", on) -#endif -#endif - -#ifndef HAVE_TRUNC -NPY_INPLACE double npy_trunc(double x) -{ - return x < 0 ? npy_ceil(x) : npy_floor(x); -} -#endif - -#ifndef HAVE_EXP2 -NPY_INPLACE double npy_exp2(double x) -{ - return npy_exp(NPY_LOGE2*x); -} -#endif - -#ifndef HAVE_LOG2 -NPY_INPLACE double npy_log2(double x) -{ -#ifdef HAVE_FREXP - if (!npy_isfinite(x) || x <= 0.) { - /* special value result */ - return npy_log(x); - } - else { - /* - * fallback implementation copied from python3.4 math.log2 - * provides int(log(2**i)) == i for i 1-64 in default rounding mode. - * - * We want log2(m * 2**e) == log(m) / log(2) + e. Care is needed when - * x is just greater than 1.0: in that case e is 1, log(m) is negative, - * and we get significant cancellation error from the addition of - * log(m) / log(2) to e. The slight rewrite of the expression below - * avoids this problem. - */ - int e; - double m = frexp(x, &e); - if (x >= 1.0) { - return log(2.0 * m) / log(2.0) + (e - 1); - } - else { - return log(m) / log(2.0) + e; - } - } -#else - /* does not provide int(log(2**i)) == i */ - return NPY_LOG2E * npy_log(x); -#endif -} -#endif - /* - * if C99 extensions not available then define dummy functions that use the - * double versions for * * sin, cos, tan * sinh, cosh, tanh, @@ -388,7 +104,7 @@ NPY_INPLACE double npy_log2(double x) * asinh, acosh, atanh * * hypot, atan2, pow, fmod, modf - * ldexp, frexp + * ldexp, frexp, cbrt * * We assume the above are always available in their double versions. * @@ -404,40 +120,6 @@ NPY_INPLACE double npy_log2(double x) * #C = L,F# */ -/**begin repeat1 - * #kind = sin,cos,tan,sinh,cosh,tanh,fabs,floor,ceil,rint,trunc,sqrt,log10, - * log,exp,expm1,asin,acos,atan,asinh,acosh,atanh,log1p,exp2,log2# - * #KIND = SIN,COS,TAN,SINH,COSH,TANH,FABS,FLOOR,CEIL,RINT,TRUNC,SQRT,LOG10, - * LOG,EXP,EXPM1,ASIN,ACOS,ATAN,ASINH,ACOSH,ATANH,LOG1P,EXP2,LOG2# - */ - -#ifdef @kind@@c@ -#undef @kind@@c@ -#endif -#ifndef HAVE_@KIND@@C@ -NPY_INPLACE @type@ npy_@kind@@c@(@type@ x) -{ - return (@type@) npy_@kind@((double)x); -} -#endif - -/**end repeat1**/ - -/**begin repeat1 - * #kind = atan2,hypot,pow,fmod,copysign# - * #KIND = ATAN2,HYPOT,POW,FMOD,COPYSIGN# - */ -#ifdef @kind@@c@ -#undef @kind@@c@ -#endif -#ifndef HAVE_@KIND@@C@ -NPY_INPLACE @type@ npy_@kind@@c@(@type@ x, @type@ y) -{ - return (@type@) npy_@kind@((double)x, (double) y); -} -#endif -/**end repeat1**/ - #ifdef modf@c@ #undef modf@c@ #endif @@ -503,11 +185,8 @@ NPY_INPLACE @type@ npy_frexp@c@(@type@ x, int* exp) /**begin repeat1 * #kind = sin,cos,tan,sinh,cosh,tanh,fabs,floor,ceil,rint,trunc,sqrt,log10, * log,exp,expm1,asin,acos,atan,asinh,acosh,atanh,log1p,exp2,log2# - * #KIND = SIN,COS,TAN,SINH,COSH,TANH,FABS,FLOOR,CEIL,RINT,TRUNC,SQRT,LOG10, - * LOG,EXP,EXPM1,ASIN,ACOS,ATAN,ASINH,ACOSH,ATANH,LOG1P,EXP2,LOG2# * #TRIG_WORKAROUND = WORKAROUND_APPLE_TRIG_BUG*3, 0*22# */ -#ifdef HAVE_@KIND@@C@ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x) { #if @TRIG_WORKAROUND@ @@ -517,7 +196,6 @@ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x) #endif return NPY__FP_SFX(@kind@)(x); } -#endif /**end repeat1**/ @@ -527,57 +205,33 @@ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x) * #kind = atan2,hypot,pow,fmod,copysign# * #KIND = ATAN2,HYPOT,POW,FMOD,COPYSIGN# */ -#ifdef HAVE_@KIND@@C@ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x, @type@ y) { return NPY__FP_SFX(@kind@)(x, y); } -#endif /**end repeat1**/ -#ifdef HAVE_MODF@C@ NPY_INPLACE @type@ npy_modf@c@(@type@ x, @type@ *iptr) { return NPY__FP_SFX(modf)(x, iptr); } -#endif -#ifdef HAVE_LDEXP@C@ NPY_INPLACE @type@ npy_ldexp@c@(@type@ x, int exp) { return NPY__FP_SFX(ldexp)(x, exp); } -#endif -#ifdef HAVE_FREXP@C@ NPY_INPLACE @type@ npy_frexp@c@(@type@ x, int* exp) { return NPY__FP_SFX(frexp)(x, exp); } -#endif -/* C99 but not mandatory */ +/* C99 mandatory */ -#ifndef HAVE_CBRT@C@ -NPY_INPLACE @type@ npy_cbrt@c@(@type@ x) -{ - /* don't set invalid flag */ - if (npy_isnan(x)) { - return NPY_NAN; - } - else if (x < 0) { - return -npy_pow@c@(-x, 1. / 3.); - } - else { - return npy_pow@c@(x, 1. / 3.); - } -} -#else NPY_INPLACE @type@ npy_cbrt@c@(@type@ x) { return NPY__FP_SFX(cbrt)(x); } -#endif #undef NPY__FP_SFX /**end repeat**/ From aceba280d9484e5f7e66967bbf7c047aa6ded3fe Mon Sep 17 00:00:00 2001 From: Matti Picus Date: Wed, 10 Aug 2022 21:28:09 +0300 Subject: [PATCH 04/16] remove ifndef alterantives for mandatory functions --- .../core/src/npymath/npy_math_internal.h.src | 46 +------------------ 1 file changed, 2 insertions(+), 44 deletions(-) diff --git a/numpy/core/src/npymath/npy_math_internal.h.src b/numpy/core/src/npymath/npy_math_internal.h.src index b5e415c8a9fa..5d2f4f078866 100644 --- a/numpy/core/src/npymath/npy_math_internal.h.src +++ b/numpy/core/src/npymath/npy_math_internal.h.src @@ -113,48 +113,6 @@ static const npy_uint64 MAGIC64[] = {0x5555555555555555ull, 0x3333333333333333ul * instead test for the macro, but I am lazy to do that for now. */ -/**begin repeat - * #type = npy_longdouble, npy_float# - * #TYPE = NPY_LONGDOUBLE, FLOAT# - * #c = l,f# - * #C = L,F# - */ - -#ifdef modf@c@ -#undef modf@c@ -#endif -#ifndef HAVE_MODF@C@ -NPY_INPLACE @type@ npy_modf@c@(@type@ x, @type@ *iptr) -{ - double niptr; - double y = npy_modf((double)x, &niptr); - *iptr = (@type@) niptr; - return (@type@) y; -} -#endif - -#ifdef ldexp@c@ -#undef ldexp@c@ -#endif -#ifndef HAVE_LDEXP@C@ -NPY_INPLACE @type@ npy_ldexp@c@(@type@ x, int exp) -{ - return (@type@) npy_ldexp((double)x, exp); -} -#endif - -#ifdef frexp@c@ -#undef frexp@c@ -#endif -#ifndef HAVE_FREXP@C@ -NPY_INPLACE @type@ npy_frexp@c@(@type@ x, int* exp) -{ - return (@type@) npy_frexp(x, exp); -} -#endif - -/**end repeat**/ - /* * Decorate all the math functions which are available on the current platform @@ -211,6 +169,8 @@ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x, @type@ y) } /**end repeat1**/ +/* C99 mandatory */ + NPY_INPLACE @type@ npy_modf@c@(@type@ x, @type@ *iptr) { return NPY__FP_SFX(modf)(x, iptr); @@ -226,8 +186,6 @@ NPY_INPLACE @type@ npy_frexp@c@(@type@ x, int* exp) return NPY__FP_SFX(frexp)(x, exp); } -/* C99 mandatory */ - NPY_INPLACE @type@ npy_cbrt@c@(@type@ x) { return NPY__FP_SFX(cbrt)(x); From c35cb18f3e20c3b072adfc2f1bed86e6ca89d172 Mon Sep 17 00:00:00 2001 From: mattip Date: Thu, 11 Aug 2022 10:19:02 +0300 Subject: [PATCH 05/16] restore HAVE_LOG2 for cygwin blocklistingw --- numpy/core/setup.py | 1 + numpy/core/setup_common.py | 13 +++-- .../core/src/npymath/npy_math_internal.h.src | 54 ++++++++++++++++++- 3 files changed, 61 insertions(+), 7 deletions(-) diff --git a/numpy/core/setup.py b/numpy/core/setup.py index 571d067e0259..9fc7c2f2930e 100644 --- a/numpy/core/setup.py +++ b/numpy/core/setup.py @@ -189,6 +189,7 @@ def check_funcs(funcs_name, headers=["feature_detection_math.h"]): if config.check_decl(fname2def(f), headers=["Python.h"]): OPTIONAL_FILE_FUNCS.remove(f) + check_funcs(OPTIONAL_STDFUNCS) check_funcs(OPTIONAL_FILE_FUNCS, headers=["feature_detection_stdio.h"]) check_funcs(OPTIONAL_MISC_FUNCS, headers=["feature_detection_misc.h"]) diff --git a/numpy/core/setup_common.py b/numpy/core/setup_common.py index d618fac69bed..141b62e76b5b 100644 --- a/numpy/core/setup_common.py +++ b/numpy/core/setup_common.py @@ -122,13 +122,16 @@ def set_sig(sig): # Mandatory functions: if not found, fail the build MANDATORY_FUNCS = ["sin", "cos", "tan", "sinh", "cosh", "tanh", "fabs", "floor", "ceil", "sqrt", "log10", "log", "exp", "asin", - "acos", "atan", "fmod", 'modf', 'frexp', 'ldexp'] - -# Some of these are C99 functions. -MANDATORY_FUNCS += ["expm1", "log1p", "acosh", "asinh", "atanh", - "rint", "trunc", "exp2", "log2", "hypot", "atan2", "pow", + "acos", "atan", "fmod", 'modf', 'frexp', 'ldexp', + "expm1", "log1p", "acosh", "asinh", "atanh", + "rint", "trunc", "exp2", "hypot", "atan2", "pow", "copysign", "nextafter", "strtoll", "strtoull", "cbrt"] +OPTIONAL_STDFUNCS = [ + # cygwin + "log2", +] + OPTIONAL_LOCALE_FUNCS = ["strtold_l"] OPTIONAL_FILE_FUNCS = ["ftello", "fseeko", "fallocate"] OPTIONAL_MISC_FUNCS = ["backtrace", "madvise"] diff --git a/numpy/core/src/npymath/npy_math_internal.h.src b/numpy/core/src/npymath/npy_math_internal.h.src index 5d2f4f078866..ab5576a0bf39 100644 --- a/numpy/core/src/npymath/npy_math_internal.h.src +++ b/numpy/core/src/npymath/npy_math_internal.h.src @@ -94,6 +94,41 @@ static const npy_uint64 MAGIC64[] = {0x5555555555555555ull, 0x3333333333333333ul * classification instead of calling npy_isinf/npy_isnan: we should have some * macros for this, though, instead of doing it manually */ +#ifndef HAVE_LOG2 +NPY_INPLACE double npy_log2(double x) +{ +#ifdef HAVE_FREXP + if (!npy_isfinite(x) || x <= 0.) { + /* special value result */ + return npy_log(x); + } + else { + /* + * fallback implementation copied from python3.4 math.log2 + * provides int(log(2**i)) == i for i 1-64 in default rounding mode. + * + * We want log2(m * 2**e) == log(m) / log(2) + e. Care is needed when + * x is just greater than 1.0: in that case e is 1, log(m) is negative, + * and we get significant cancellation error from the addition of + * log(m) / log(2) to e. The slight rewrite of the expression below + * avoids this problem. + */ + int e; + double m = frexp(x, &e); + if (x >= 1.0) { + return log(2.0 * m) / log(2.0) + (e - 1); + } + else { + return log(m) / log(2.0) + e; + } + } +#else + /* does not provide int(log(2**i)) == i */ + return NPY_LOG2E * npy_log(x); +#endif +} +#endif + /* * * sin, cos, tan @@ -140,10 +175,12 @@ static const npy_uint64 MAGIC64[] = {0x5555555555555555ull, 0x3333333333333333ul #define WORKAROUND_APPLE_TRIG_BUG 0 #endif +/* mandatory C99 functions */ + /**begin repeat1 * #kind = sin,cos,tan,sinh,cosh,tanh,fabs,floor,ceil,rint,trunc,sqrt,log10, - * log,exp,expm1,asin,acos,atan,asinh,acosh,atanh,log1p,exp2,log2# - * #TRIG_WORKAROUND = WORKAROUND_APPLE_TRIG_BUG*3, 0*22# + * log,exp,expm1,asin,acos,atan,asinh,acosh,atanh,log1p,exp2# + * #TRIG_WORKAROUND = WORKAROUND_APPLE_TRIG_BUG*3, 0*21# */ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x) { @@ -155,6 +192,19 @@ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x) return NPY__FP_SFX(@kind@)(x); } +/**end repeat1**/ +/* Optional C99 functions */ +/**begin repeat1 + * #kind = log2# + * #KIND = LOG2# + */ +#ifdef HAVE_@KIND@@C@ +NPY_INPLACE @type@ npy_@kind@@c@(@type@ x) +{ + return NPY__FP_SFX(@kind@)(x); +} +#endif + /**end repeat1**/ #undef WORKAROUND_APPLE_TRIG_BUG From 16a64051c1d71579527dbfa70f3600eaf9cc6448 Mon Sep 17 00:00:00 2001 From: mattip Date: Thu, 11 Aug 2022 10:46:30 +0300 Subject: [PATCH 06/16] restore HAVE_POWL for macOS blocklisting Signed-off-by: mattip --- numpy/core/setup_common.py | 4 ++- .../core/src/npymath/npy_math_internal.h.src | 30 +++++++++++++++++-- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/numpy/core/setup_common.py b/numpy/core/setup_common.py index 141b62e76b5b..92f6f8af67dd 100644 --- a/numpy/core/setup_common.py +++ b/numpy/core/setup_common.py @@ -124,12 +124,14 @@ def set_sig(sig): "floor", "ceil", "sqrt", "log10", "log", "exp", "asin", "acos", "atan", "fmod", 'modf', 'frexp', 'ldexp', "expm1", "log1p", "acosh", "asinh", "atanh", - "rint", "trunc", "exp2", "hypot", "atan2", "pow", + "rint", "trunc", "exp2", "hypot", "atan2", "copysign", "nextafter", "strtoll", "strtoull", "cbrt"] OPTIONAL_STDFUNCS = [ # cygwin "log2", + # macos for powl + "pow", ] OPTIONAL_LOCALE_FUNCS = ["strtold_l"] diff --git a/numpy/core/src/npymath/npy_math_internal.h.src b/numpy/core/src/npymath/npy_math_internal.h.src index ab5576a0bf39..5d22d1191a11 100644 --- a/numpy/core/src/npymath/npy_math_internal.h.src +++ b/numpy/core/src/npymath/npy_math_internal.h.src @@ -193,7 +193,9 @@ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x) } /**end repeat1**/ + /* Optional C99 functions */ + /**begin repeat1 * #kind = log2# * #KIND = LOG2# @@ -210,17 +212,41 @@ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x) #undef WORKAROUND_APPLE_TRIG_BUG /**begin repeat1 - * #kind = atan2,hypot,pow,fmod,copysign# - * #KIND = ATAN2,HYPOT,POW,FMOD,COPYSIGN# + * #kind = pow# + * #KIND = POW# */ +#ifdef @kind@@c@ +#undef @kind@@c@ +#endif +#ifndef HAVE_@KIND@@C@ +NPY_INPLACE @type@ npy_@kind@@c@(@type@ x, @type@ y) +{ + return (@type@) npy_@kind@((double)x, (double) y); +} +#endif + +#ifdef HAVE_@KIND@@C@ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x, @type@ y) { return NPY__FP_SFX(@kind@)(x, y); } +#endif /**end repeat1**/ + /* C99 mandatory */ +/**begin repeat1 + * #kind = atan2,hypot,fmod,copysign# + * #KIND = ATAN2,HYPOT,FMOD,COPYSIGN# + */ +NPY_INPLACE @type@ npy_@kind@@c@(@type@ x, @type@ y) +{ + return NPY__FP_SFX(@kind@)(x, y); +} +/**end repeat1**/ + + NPY_INPLACE @type@ npy_modf@c@(@type@ x, @type@ *iptr) { return NPY__FP_SFX(modf)(x, iptr); From c304f6f2e9f8d319fe5aaa65d03292b5a8879068 Mon Sep 17 00:00:00 2001 From: mattip Date: Sun, 14 Aug 2022 19:10:05 +0300 Subject: [PATCH 07/16] move hypot to optional for windows, fix pow and log2 Signed-off-by: mattip --- numpy/core/setup_common.py | 4 +- .../core/src/npymath/npy_math_internal.h.src | 143 +++++++++++++----- 2 files changed, 108 insertions(+), 39 deletions(-) diff --git a/numpy/core/setup_common.py b/numpy/core/setup_common.py index 92f6f8af67dd..9e3b91c7f7f5 100644 --- a/numpy/core/setup_common.py +++ b/numpy/core/setup_common.py @@ -124,7 +124,7 @@ def set_sig(sig): "floor", "ceil", "sqrt", "log10", "log", "exp", "asin", "acos", "atan", "fmod", 'modf', 'frexp', 'ldexp', "expm1", "log1p", "acosh", "asinh", "atanh", - "rint", "trunc", "exp2", "hypot", "atan2", + "rint", "trunc", "exp2", "atan2", "copysign", "nextafter", "strtoll", "strtoull", "cbrt"] OPTIONAL_STDFUNCS = [ @@ -132,6 +132,8 @@ def set_sig(sig): "log2", # macos for powl "pow", + # 32-bit windows + "hypot" ] OPTIONAL_LOCALE_FUNCS = ["strtold_l"] diff --git a/numpy/core/src/npymath/npy_math_internal.h.src b/numpy/core/src/npymath/npy_math_internal.h.src index 5d22d1191a11..6a0b487c73b3 100644 --- a/numpy/core/src/npymath/npy_math_internal.h.src +++ b/numpy/core/src/npymath/npy_math_internal.h.src @@ -94,10 +94,11 @@ static const npy_uint64 MAGIC64[] = {0x5555555555555555ull, 0x3333333333333333ul * classification instead of calling npy_isinf/npy_isnan: we should have some * macros for this, though, instead of doing it manually */ -#ifndef HAVE_LOG2 NPY_INPLACE double npy_log2(double x) { -#ifdef HAVE_FREXP +#ifdef HAVE_LOG2 + return log2(x); +#elif defined(HAVE_FREXP) if (!npy_isfinite(x) || x <= 0.) { /* special value result */ return npy_log(x); @@ -127,7 +128,38 @@ NPY_INPLACE double npy_log2(double x) return NPY_LOG2E * npy_log(x); #endif } + +NPY_INPLACE double npy_hypot(double x, double y) +{ +#ifdef HAVE_HYPOT + return hypot(x, y); +#else + double yx; + + if (npy_isinf(x) || npy_isinf(y)) { + return NPY_INFINITY; + } + + if (npy_isnan(x) || npy_isnan(y)) { + return NPY_NAN; + } + + x = npy_fabs(x); + y = npy_fabs(y); + if (x < y) { + double temp = x; + x = y; + y = temp; + } + if (x == 0.) { + return 0.; + } + else { + yx = y/x; + return x*npy_sqrt(1.+yx*yx); + } #endif +} /* * @@ -194,12 +226,73 @@ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x) /**end repeat1**/ +#undef WORKAROUND_APPLE_TRIG_BUG + +/* C99 mandatory */ + +/**begin repeat1 + * #kind = atan2,fmod,copysign# + * #KIND = ATAN2,FMOD,COPYSIGN# + */ +NPY_INPLACE @type@ npy_@kind@@c@(@type@ x, @type@ y) +{ + return NPY__FP_SFX(@kind@)(x, y); +} +/**end repeat1**/ + + +NPY_INPLACE @type@ npy_modf@c@(@type@ x, @type@ *iptr) +{ + return NPY__FP_SFX(modf)(x, iptr); +} + +NPY_INPLACE @type@ npy_ldexp@c@(@type@ x, int exp) +{ + return NPY__FP_SFX(ldexp)(x, exp); +} + +NPY_INPLACE @type@ npy_frexp@c@(@type@ x, int* exp) +{ + return NPY__FP_SFX(frexp)(x, exp); +} + +NPY_INPLACE @type@ npy_cbrt@c@(@type@ x) +{ + return NPY__FP_SFX(cbrt)(x); +} + +/**end repeat**/ + /* Optional C99 functions */ +/**begin repeat + * #type = npy_longdouble, npy_float# + * #TYPE = LONGDOUBLE, 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 + /**begin repeat1 * #kind = log2# * #KIND = LOG2# */ + +#ifdef @kind@@c@ +#undef @kind@@c@ +#endif +#ifndef HAVE_@KIND@@C@ +NPY_INPLACE @type@ npy_@kind@@c@(@type@ x) +{ + return (@type@) npy_@kind@((double)x); +} +#endif + #ifdef HAVE_@KIND@@C@ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x) { @@ -209,11 +302,10 @@ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x) /**end repeat1**/ -#undef WORKAROUND_APPLE_TRIG_BUG /**begin repeat1 - * #kind = pow# - * #KIND = POW# + * #kind = hypot,pow# + * #KIND = HYPOT,POW# */ #ifdef @kind@@c@ #undef @kind@@c@ @@ -232,42 +324,10 @@ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x, @type@ y) } #endif /**end repeat1**/ +/**end repeat**/ -/* C99 mandatory */ - -/**begin repeat1 - * #kind = atan2,hypot,fmod,copysign# - * #KIND = ATAN2,HYPOT,FMOD,COPYSIGN# - */ -NPY_INPLACE @type@ npy_@kind@@c@(@type@ x, @type@ y) -{ - return NPY__FP_SFX(@kind@)(x, y); -} -/**end repeat1**/ - - -NPY_INPLACE @type@ npy_modf@c@(@type@ x, @type@ *iptr) -{ - return NPY__FP_SFX(modf)(x, iptr); -} - -NPY_INPLACE @type@ npy_ldexp@c@(@type@ x, int exp) -{ - return NPY__FP_SFX(ldexp)(x, exp); -} - -NPY_INPLACE @type@ npy_frexp@c@(@type@ x, int* exp) -{ - return NPY__FP_SFX(frexp)(x, exp); -} - -NPY_INPLACE @type@ npy_cbrt@c@(@type@ x) -{ - return NPY__FP_SFX(cbrt)(x); -} #undef NPY__FP_SFX -/**end repeat**/ /* @@ -603,3 +663,10 @@ npy_popcount@c@(npy_@type@ a) return npy_popcountu@c@(a < 0 ? -a : a); } /**end repeat**/ + +/* XXX: will moving this to a define break anything? */ + +NPY_INPLACE double npy_pow(double x, double y) +{ + return pow(x, y); +} From 37b2cf17cbf50122283f9737e4419a79fb32d6fb Mon Sep 17 00:00:00 2001 From: mattip Date: Sun, 14 Aug 2022 22:38:55 +0300 Subject: [PATCH 08/16] frexp is now mandatory --- numpy/core/src/npymath/npy_math_internal.h.src | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/numpy/core/src/npymath/npy_math_internal.h.src b/numpy/core/src/npymath/npy_math_internal.h.src index 6a0b487c73b3..055967951749 100644 --- a/numpy/core/src/npymath/npy_math_internal.h.src +++ b/numpy/core/src/npymath/npy_math_internal.h.src @@ -98,7 +98,7 @@ NPY_INPLACE double npy_log2(double x) { #ifdef HAVE_LOG2 return log2(x); -#elif defined(HAVE_FREXP) +#else if (!npy_isfinite(x) || x <= 0.) { /* special value result */ return npy_log(x); @@ -123,9 +123,6 @@ NPY_INPLACE double npy_log2(double x) return log(m) / log(2.0) + e; } } -#else - /* does not provide int(log(2**i)) == i */ - return NPY_LOG2E * npy_log(x); #endif } From b0878cff37cebe4471c3b5d1d0b3f72020b2cb44 Mon Sep 17 00:00:00 2001 From: mattip Date: Sun, 14 Aug 2022 23:06:11 +0300 Subject: [PATCH 09/16] copysign is mandatory, no HAVE_COPYSIGN is defined --- numpy/core/src/npymath/ieee754.c.src | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/numpy/core/src/npymath/ieee754.c.src b/numpy/core/src/npymath/ieee754.c.src index 5d1ea3a699bf..bda89e69c27c 100644 --- a/numpy/core/src/npymath/ieee754.c.src +++ b/numpy/core/src/npymath/ieee754.c.src @@ -8,17 +8,6 @@ #include "npy_math_private.h" #include "numpy/utils.h" -#ifndef HAVE_COPYSIGN -double npy_copysign(double x, double y) -{ - npy_uint32 hx, hy; - GET_HIGH_WORD(hx, x); - GET_HIGH_WORD(hy, y); - SET_HIGH_WORD(x, (hx & 0x7fffffff) | (hy & 0x80000000)); - return x; -} -#endif - /* The below code is provided for compilers which do not yet provide C11 compatibility (gcc 4.5 and older) */ From ee2103b53474d1aa65e5cf51795263e98c901e6c Mon Sep 17 00:00:00 2001 From: mattip Date: Sun, 14 Aug 2022 23:19:26 +0300 Subject: [PATCH 10/16] rearrange badly placed header includes --- numpy/core/src/_simd/_simd.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/numpy/core/src/_simd/_simd.h b/numpy/core/src/_simd/_simd.h index dfe4d6bb44f3..f3b0a8ccdda9 100644 --- a/numpy/core/src/_simd/_simd.h +++ b/numpy/core/src/_simd/_simd.h @@ -14,12 +14,12 @@ #include #include "numpy/npy_common.h" - -#ifndef NPY_DISABLE_OPTIMIZATION -// autogenerated, required for CPU dispatch macros #include "npy_cpu_features.h" #include "npy_cpu_dispatch.h" #include "numpy/npy_cpu.h" + +#ifndef NPY_DISABLE_OPTIMIZATION +// autogenerated, required for CPU dispatch macros #include "_simd.dispatch.h" #endif /** From 759e0cdbc2642211ad2f0adce3ef247428a1e3b3 Mon Sep 17 00:00:00 2001 From: mattip Date: Mon, 15 Aug 2022 12:47:03 +0300 Subject: [PATCH 11/16] strtoull and strtoll are mandatory --- azure-pipelines.yml | 2 +- numpy/core/src/common/numpyos.c | 15 --------------- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index c2220001f558..922b7c8b2b43 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -114,7 +114,7 @@ stages: python3 -m pip install -v . && \ python3 runtests.py -n --debug-info --mode=full -- -rsx --junitxml=junit/test-results.xml && \ python3 tools/openblas_support.py --check_version" - displayName: 'Run 32-bit manylinux2010 Docker Build / Tests' + displayName: 'Run 32-bit manylinux2014 Docker Build / Tests' - task: PublishTestResults@2 condition: succeededOrFailed() inputs: diff --git a/numpy/core/src/common/numpyos.c b/numpy/core/src/common/numpyos.c index 4551a06a2ba1..5ee95191dabd 100644 --- a/numpy/core/src/common/numpyos.c +++ b/numpy/core/src/common/numpyos.c @@ -770,27 +770,12 @@ NumPyOS_ascii_ftoLf(FILE *fp, long double *value) NPY_NO_EXPORT npy_longlong NumPyOS_strtoll(const char *str, char **endptr, int base) { -#if defined HAVE_STRTOLL return strtoll(str, endptr, base); -#elif defined _MSC_VER - return _strtoi64(str, endptr, base); -#else - /* ok on 64 bit posix */ - return PyOS_strtol(str, endptr, base); -#endif } NPY_NO_EXPORT npy_ulonglong NumPyOS_strtoull(const char *str, char **endptr, int base) { -#if defined HAVE_STRTOULL return strtoull(str, endptr, base); -#elif defined _MSC_VER - return _strtoui64(str, endptr, base); -#else - /* ok on 64 bit posix */ - return PyOS_strtoul(str, endptr, base); -#endif } - From 2c4cc10b8076f00419a2f7bd3042b2400fd73e6f Mon Sep 17 00:00:00 2001 From: mattip Date: Mon, 15 Aug 2022 23:49:54 +0300 Subject: [PATCH 12/16] restore atan2 implementation, clean up c99 mandatory functions --- numpy/core/setup.py | 4 - numpy/core/setup_common.py | 42 ++++---- .../core/src/npymath/npy_math_internal.h.src | 100 +++++++++++++++++- 3 files changed, 116 insertions(+), 30 deletions(-) diff --git a/numpy/core/setup.py b/numpy/core/setup.py index 9fc7c2f2930e..ec3929ca8c99 100644 --- a/numpy/core/setup.py +++ b/numpy/core/setup.py @@ -243,10 +243,6 @@ def check_funcs(funcs_name, headers=["feature_detection_math.h"]): m = fn.replace("(", "_").replace(")", "_") moredefs.append((fname2def(m), 1)) - # C99 functions: float and long double versions - check_funcs(C99_FUNCS_SINGLE) - check_funcs(C99_FUNCS_EXTENDED) - def check_complex(config, mathlibs): priv = [] pub = [] diff --git a/numpy/core/setup_common.py b/numpy/core/setup_common.py index 9e3b91c7f7f5..d246db8e022e 100644 --- a/numpy/core/setup_common.py +++ b/numpy/core/setup_common.py @@ -120,20 +120,28 @@ def set_sig(sig): set_sig(line) # Mandatory functions: if not found, fail the build -MANDATORY_FUNCS = ["sin", "cos", "tan", "sinh", "cosh", "tanh", "fabs", - "floor", "ceil", "sqrt", "log10", "log", "exp", "asin", - "acos", "atan", "fmod", 'modf', 'frexp', 'ldexp', - "expm1", "log1p", "acosh", "asinh", "atanh", - "rint", "trunc", "exp2", "atan2", - "copysign", "nextafter", "strtoll", "strtoull", "cbrt"] +MANDATORY_FUNCS = [ + "sin", "cos", "tan", "sinh", "cosh", "tanh", "fabs", + "floor", "ceil", "sqrt", "log10", "log", "exp", "asin", + "acos", "atan", "fmod", 'modf', 'frexp', 'ldexp', + "expm1", "log1p", "acosh", "asinh", "atanh", + "rint", "trunc", "exp2", + "copysign", "nextafter", "strtoll", "strtoull", "cbrt", + # C99, mandatory + "sin", "cos", "tan", "sinh", "cosh", "tanh", "fabs", "floor", "ceil", + "rint", "trunc", "sqrt", "log10", "log", "log1p", "exp", "expm1", + "asin", "acos", "atan", "asinh", "acosh", "atanh", +] OPTIONAL_STDFUNCS = [ - # cygwin - "log2", - # macos for powl - "pow", - # 32-bit windows - "hypot" + # cygwin + "log2", + # macos for powl + "pow", + # 32-bit windows + "hypot", + # 32-bit mingw, visual studio 2015 + "atan2", ] OPTIONAL_LOCALE_FUNCS = ["strtold_l"] @@ -238,16 +246,6 @@ def set_sig(sig): "ftello", "fseeko" ] -# C99 functions: float and long double versions -C99_FUNCS = [ - "sin", "cos", "tan", "sinh", "cosh", "tanh", "fabs", "floor", "ceil", - "rint", "trunc", "sqrt", "log10", "log", "log1p", "exp", "expm1", - "asin", "acos", "atan", "asinh", "acosh", "atanh", "hypot", "atan2", - "pow", "fmod", "modf", 'frexp', 'ldexp', "exp2", "log2", "copysign", - "nextafter", "cbrt" - ] -C99_FUNCS_SINGLE = [f + 'f' for f in C99_FUNCS] -C99_FUNCS_EXTENDED = [f + 'l' for f in C99_FUNCS] C99_COMPLEX_TYPES = [ 'complex double', 'complex float', 'complex long double' ] diff --git a/numpy/core/src/npymath/npy_math_internal.h.src b/numpy/core/src/npymath/npy_math_internal.h.src index 055967951749..dd0c5fa149e4 100644 --- a/numpy/core/src/npymath/npy_math_internal.h.src +++ b/numpy/core/src/npymath/npy_math_internal.h.src @@ -126,6 +126,98 @@ NPY_INPLACE double npy_log2(double x) #endif } +/* Taken from FreeBSD mlib, adapted for numpy + * + * XXX: we could be a bit faster by reusing high/low words for inf/nan + * classification instead of calling npy_isinf/npy_isnan: we should have some + * macros for this, though, instead of doing it manually + */ +/* XXX: we should have this in npy_math.h */ +#define NPY_DBL_EPSILON 1.2246467991473531772E-16 +NPY_INPLACE double npy_atan2(double y, double x) +{ +#ifdef HAVE_ATAN2 + return atan2(y, x); +#else + npy_int32 k, m, iy, ix, hx, hy; + npy_uint32 lx,ly; + double z; + + EXTRACT_WORDS(hx, lx, x); + ix = hx & 0x7fffffff; + EXTRACT_WORDS(hy, ly, y); + iy = hy & 0x7fffffff; + + /* if x or y is nan, return nan */ + if (npy_isnan(x * y)) { + return x + y; + } + + if (x == 1.0) { + return npy_atan(y); + } + + m = 2 * (npy_signbit((x)) != 0) + (npy_signbit((y)) != 0); + if (y == 0.0) { + switch(m) { + case 0: + case 1: return y; /* atan(+-0,+anything)=+-0 */ + case 2: return NPY_PI;/* atan(+0,-anything) = pi */ + case 3: return -NPY_PI;/* atan(-0,-anything) =-pi */ + } + } + + if (x == 0.0) { + return y > 0 ? NPY_PI_2 : -NPY_PI_2; + } + + if (npy_isinf(x)) { + if (npy_isinf(y)) { + switch(m) { + case 0: return NPY_PI_4;/* atan(+INF,+INF) */ + case 1: return -NPY_PI_4;/* atan(-INF,+INF) */ + case 2: return 3.0*NPY_PI_4;/*atan(+INF,-INF)*/ + case 3: return -3.0*NPY_PI_4;/*atan(-INF,-INF)*/ + } + } else { + switch(m) { + case 0: return NPY_PZERO; /* atan(+...,+INF) */ + case 1: return NPY_NZERO; /* atan(-...,+INF) */ + case 2: return NPY_PI; /* atan(+...,-INF) */ + case 3: return -NPY_PI; /* atan(-...,-INF) */ + } + } + } + + if (npy_isinf(y)) { + return y > 0 ? NPY_PI_2 : -NPY_PI_2; + } + + /* compute y/x */ + k = (iy - ix) >> 20; + if (k > 60) { /* |y/x| > 2**60 */ + z = NPY_PI_2 + 0.5 * NPY_DBL_EPSILON; + m &= 1; + } else if (hx < 0 && k < -60) { + z = 0.0; /* 0 > |y|/x > -2**-60 */ + } else { + z = npy_atan(npy_fabs(y/x)); /* safe to do y/x */ + } + + switch (m) { + case 0: return z ; /* atan(+,+) */ + case 1: return -z ; /* atan(-,+) */ + case 2: return NPY_PI - (z - NPY_DBL_EPSILON);/* atan(+,-) */ + default: /* case 3 */ + return (z - NPY_DBL_EPSILON) - NPY_PI;/* atan(-,-) */ + } +#endif +} + + + + + NPY_INPLACE double npy_hypot(double x, double y) { #ifdef HAVE_HYPOT @@ -228,8 +320,8 @@ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x) /* C99 mandatory */ /**begin repeat1 - * #kind = atan2,fmod,copysign# - * #KIND = ATAN2,FMOD,COPYSIGN# + * #kind = fmod,copysign# + * #KIND = FMOD,COPYSIGN# */ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x, @type@ y) { @@ -301,8 +393,8 @@ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x) /**begin repeat1 - * #kind = hypot,pow# - * #KIND = HYPOT,POW# + * #kind = atan2,hypot,pow# + * #KIND = ATAN2,HYPOT,POW# */ #ifdef @kind@@c@ #undef @kind@@c@ From 704ca94f75246439c6b6575d654c96f5405b49d9 Mon Sep 17 00:00:00 2001 From: mattip Date: Tue, 16 Aug 2022 00:09:01 +0300 Subject: [PATCH 13/16] nextafter is mandatory --- numpy/core/src/npymath/ieee754.c.src | 201 ------------------------- numpy/core/src/npymath/ieee754.cpp | 211 --------------------------- 2 files changed, 412 deletions(-) diff --git a/numpy/core/src/npymath/ieee754.c.src b/numpy/core/src/npymath/ieee754.c.src index bda89e69c27c..5d8cb06a4de3 100644 --- a/numpy/core/src/npymath/ieee754.c.src +++ b/numpy/core/src/npymath/ieee754.c.src @@ -310,201 +310,6 @@ static npy_longdouble _nextl(npy_longdouble x, int p) } #endif -/* - * nextafter code taken from BSD math lib, the code contains the following - * notice: - * - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -#ifndef HAVE_NEXTAFTER -double npy_nextafter(double x, double y) -{ - volatile double t; - npy_int32 hx, hy, ix, iy; - npy_uint32 lx, ly; - - EXTRACT_WORDS(hx, lx, x); - EXTRACT_WORDS(hy, ly, y); - ix = hx & 0x7fffffff; /* |x| */ - iy = hy & 0x7fffffff; /* |y| */ - - if (((ix >= 0x7ff00000) && ((ix - 0x7ff00000) | lx) != 0) || /* x is nan */ - ((iy >= 0x7ff00000) && ((iy - 0x7ff00000) | ly) != 0)) /* y is nan */ - return x + y; - if (x == y) - return y; /* x=y, return y */ - if ((ix | lx) == 0) { /* x == 0 */ - INSERT_WORDS(x, hy & 0x80000000, 1); /* return +-minsubnormal */ - t = x * x; - if (t == x) - return t; - else - return x; /* raise underflow flag */ - } - if (hx >= 0) { /* x > 0 */ - if (hx > hy || ((hx == hy) && (lx > ly))) { /* x > y, x -= ulp */ - if (lx == 0) - hx -= 1; - lx -= 1; - } else { /* x < y, x += ulp */ - lx += 1; - if (lx == 0) - hx += 1; - } - } else { /* x < 0 */ - if (hy >= 0 || hx > hy || ((hx == hy) && (lx > ly))) { /* x < y, x -= ulp */ - if (lx == 0) - hx -= 1; - lx -= 1; - } else { /* x > y, x += ulp */ - lx += 1; - if (lx == 0) - hx += 1; - } - } - hy = hx & 0x7ff00000; - if (hy >= 0x7ff00000) - return x + x; /* overflow */ - if (hy < 0x00100000) { /* underflow */ - t = x * x; - if (t != x) { /* raise underflow flag */ - INSERT_WORDS(y, hx, lx); - return y; - } - } - INSERT_WORDS(x, hx, lx); - return x; -} -#endif - -#ifndef HAVE_NEXTAFTERF -float npy_nextafterf(float x, float y) -{ - volatile float t; - npy_int32 hx, hy, ix, iy; - - GET_FLOAT_WORD(hx, x); - GET_FLOAT_WORD(hy, y); - ix = hx & 0x7fffffff; /* |x| */ - iy = hy & 0x7fffffff; /* |y| */ - - if ((ix > 0x7f800000) || /* x is nan */ - (iy > 0x7f800000)) /* y is nan */ - return x + y; - if (x == y) - return y; /* x=y, return y */ - if (ix == 0) { /* x == 0 */ - SET_FLOAT_WORD(x, (hy & 0x80000000) | 1); /* return +-minsubnormal */ - t = x * x; - if (t == x) - return t; - else - return x; /* raise underflow flag */ - } - if (hx >= 0) { /* x > 0 */ - if (hx > hy) { /* x > y, x -= ulp */ - hx -= 1; - } else { /* x < y, x += ulp */ - hx += 1; - } - } else { /* x < 0 */ - if (hy >= 0 || hx > hy) { /* x < y, x -= ulp */ - hx -= 1; - } else { /* x > y, x += ulp */ - hx += 1; - } - } - hy = hx & 0x7f800000; - if (hy >= 0x7f800000) - return x + x; /* overflow */ - if (hy < 0x00800000) { /* underflow */ - t = x * x; - if (t != x) { /* raise underflow flag */ - SET_FLOAT_WORD(y, hx); - return y; - } - } - SET_FLOAT_WORD(x, hx); - return x; -} -#endif - -#ifndef HAVE_NEXTAFTERL -npy_longdouble npy_nextafterl(npy_longdouble x, npy_longdouble y) -{ - volatile npy_longdouble t; - union IEEEl2bitsrep ux; - union IEEEl2bitsrep uy; - - ux.e = x; - uy.e = y; - - if ((GET_LDOUBLE_EXP(ux) == 0x7fff && - ((GET_LDOUBLE_MANH(ux) & ~LDBL_NBIT) | GET_LDOUBLE_MANL(ux)) != 0) || - (GET_LDOUBLE_EXP(uy) == 0x7fff && - ((GET_LDOUBLE_MANH(uy) & ~LDBL_NBIT) | GET_LDOUBLE_MANL(uy)) != 0)) { - return ux.e + uy.e; /* x or y is nan */ - } - if (ux.e == uy.e) { - return uy.e; /* x=y, return y */ - } - if (ux.e == 0.0) { - SET_LDOUBLE_MANH(ux, 0); /* return +-minsubnormal */ - SET_LDOUBLE_MANL(ux, 1); - SET_LDOUBLE_SIGN(ux, GET_LDOUBLE_SIGN(uy)); - t = ux.e * ux.e; - if (t == ux.e) { - return t; - } else { - return ux.e; /* raise underflow flag */ - } - } - if ((ux.e > 0.0) ^ (ux.e < uy.e)) { /* x -= ulp */ - if (GET_LDOUBLE_MANL(ux) == 0) { - if ((GET_LDOUBLE_MANH(ux) & ~LDBL_NBIT) == 0) { - SET_LDOUBLE_EXP(ux, GET_LDOUBLE_EXP(ux) - 1); - } - SET_LDOUBLE_MANH(ux, - (GET_LDOUBLE_MANH(ux) - 1) | - (GET_LDOUBLE_MANH(ux) & LDBL_NBIT)); - } - SET_LDOUBLE_MANL(ux, GET_LDOUBLE_MANL(ux) - 1); - } else { /* x += ulp */ - SET_LDOUBLE_MANL(ux, GET_LDOUBLE_MANL(ux) + 1); - if (GET_LDOUBLE_MANL(ux) == 0) { - SET_LDOUBLE_MANH(ux, - (GET_LDOUBLE_MANH(ux) + 1) | - (GET_LDOUBLE_MANH(ux) & LDBL_NBIT)); - if ((GET_LDOUBLE_MANH(ux) & ~LDBL_NBIT) == 0) { - SET_LDOUBLE_EXP(ux, GET_LDOUBLE_EXP(ux) + 1); - } - } - } - if (GET_LDOUBLE_EXP(ux) == 0x7fff) { - return ux.e + ux.e; /* overflow */ - } - if (GET_LDOUBLE_EXP(ux) == 0) { /* underflow */ - if (LDBL_NBIT) { - SET_LDOUBLE_MANH(ux, GET_LDOUBLE_MANH(ux) & ~LDBL_NBIT); - } - t = ux.e * ux.e; - if (t != ux.e) { /* raise underflow flag */ - return ux.e; - } - } - - return ux.e; -} -#endif - /**begin repeat * #suff = f,,l# * #SUFF = F,,L# @@ -525,26 +330,20 @@ npy_longdouble npy_nextafterl(npy_longdouble x, npy_longdouble y) * Decorate all the math functions which are available on the current platform */ -#ifdef HAVE_NEXTAFTERF float npy_nextafterf(float x, float y) { return nextafterf(x, y); } -#endif -#ifdef HAVE_NEXTAFTER double npy_nextafter(double x, double y) { return nextafter(x, y); } -#endif -#ifdef HAVE_NEXTAFTERL npy_longdouble npy_nextafterl(npy_longdouble x, npy_longdouble y) { return nextafterl(x, y); } -#endif int npy_clear_floatstatus() { char x=0; diff --git a/numpy/core/src/npymath/ieee754.cpp b/numpy/core/src/npymath/ieee754.cpp index 27fcf7c6e8cf..3eb89d1d87b9 100644 --- a/numpy/core/src/npymath/ieee754.cpp +++ b/numpy/core/src/npymath/ieee754.cpp @@ -344,211 +344,6 @@ _next(long double x, int p) } #endif -/* - * nextafter code taken from BSD math lib, the code contains the following - * notice: - * - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -#ifndef HAVE_NEXTAFTER -double -npy_nextafter(double x, double y) -{ - volatile double t; - npy_int32 hx, hy, ix, iy; - npy_uint32 lx, ly; - - EXTRACT_WORDS(hx, lx, x); - EXTRACT_WORDS(hy, ly, y); - ix = hx & 0x7fffffff; /* |x| */ - iy = hy & 0x7fffffff; /* |y| */ - - if (((ix >= 0x7ff00000) && ((ix - 0x7ff00000) | lx) != 0) || /* x is nan */ - ((iy >= 0x7ff00000) && ((iy - 0x7ff00000) | ly) != 0)) /* y is nan */ - return x + y; - if (x == y) - return y; /* x=y, return y */ - if ((ix | lx) == 0) { /* x == 0 */ - INSERT_WORDS(x, hy & 0x80000000, 1); /* return +-minsubnormal */ - t = x * x; - if (t == x) - return t; - else - return x; /* raise underflow flag */ - } - if (hx >= 0) { /* x > 0 */ - if (hx > hy || ((hx == hy) && (lx > ly))) { /* x > y, x -= ulp */ - if (lx == 0) - hx -= 1; - lx -= 1; - } - else { /* x < y, x += ulp */ - lx += 1; - if (lx == 0) - hx += 1; - } - } - else { /* x < 0 */ - if (hy >= 0 || hx > hy || - ((hx == hy) && (lx > ly))) { /* x < y, x -= ulp */ - if (lx == 0) - hx -= 1; - lx -= 1; - } - else { /* x > y, x += ulp */ - lx += 1; - if (lx == 0) - hx += 1; - } - } - hy = hx & 0x7ff00000; - if (hy >= 0x7ff00000) - return x + x; /* overflow */ - if (hy < 0x00100000) { /* underflow */ - t = x * x; - if (t != x) { /* raise underflow flag */ - INSERT_WORDS(y, hx, lx); - return y; - } - } - INSERT_WORDS(x, hx, lx); - return x; -} -#endif - -#ifndef HAVE_NEXTAFTERF -float -npy_nextafterf(float x, float y) -{ - volatile float t; - npy_int32 hx, hy, ix, iy; - - GET_FLOAT_WORD(hx, x); - GET_FLOAT_WORD(hy, y); - ix = hx & 0x7fffffff; /* |x| */ - iy = hy & 0x7fffffff; /* |y| */ - - if ((ix > 0x7f800000) || /* x is nan */ - (iy > 0x7f800000)) /* y is nan */ - return x + y; - if (x == y) - return y; /* x=y, return y */ - if (ix == 0) { /* x == 0 */ - SET_FLOAT_WORD(x, (hy & 0x80000000) | 1); /* return +-minsubnormal */ - t = x * x; - if (t == x) - return t; - else - return x; /* raise underflow flag */ - } - if (hx >= 0) { /* x > 0 */ - if (hx > hy) { /* x > y, x -= ulp */ - hx -= 1; - } - else { /* x < y, x += ulp */ - hx += 1; - } - } - else { /* x < 0 */ - if (hy >= 0 || hx > hy) { /* x < y, x -= ulp */ - hx -= 1; - } - else { /* x > y, x += ulp */ - hx += 1; - } - } - hy = hx & 0x7f800000; - if (hy >= 0x7f800000) - return x + x; /* overflow */ - if (hy < 0x00800000) { /* underflow */ - t = x * x; - if (t != x) { /* raise underflow flag */ - SET_FLOAT_WORD(y, hx); - return y; - } - } - SET_FLOAT_WORD(x, hx); - return x; -} -#endif - -#ifndef HAVE_NEXTAFTERL -npy_longdouble -npy_nextafterl(npy_longdouble x, npy_longdouble y) -{ - volatile npy_longdouble t; - union IEEEl2bitsrep ux; - union IEEEl2bitsrep uy; - - ux.e = x; - uy.e = y; - - if ((GET_LDOUBLE_EXP(ux) == 0x7fff && - ((GET_LDOUBLE_MANH(ux) & ~LDBL_NBIT) | GET_LDOUBLE_MANL(ux)) != 0) || - (GET_LDOUBLE_EXP(uy) == 0x7fff && - ((GET_LDOUBLE_MANH(uy) & ~LDBL_NBIT) | GET_LDOUBLE_MANL(uy)) != 0)) { - return ux.e + uy.e; /* x or y is nan */ - } - if (ux.e == uy.e) { - return uy.e; /* x=y, return y */ - } - if (ux.e == 0.0) { - SET_LDOUBLE_MANH(ux, 0); /* return +-minsubnormal */ - SET_LDOUBLE_MANL(ux, 1); - SET_LDOUBLE_SIGN(ux, GET_LDOUBLE_SIGN(uy)); - t = ux.e * ux.e; - if (t == ux.e) { - return t; - } - else { - return ux.e; /* raise underflow flag */ - } - } - if ((ux.e > 0.0) ^ (ux.e < uy.e)) { /* x -= ulp */ - if (GET_LDOUBLE_MANL(ux) == 0) { - if ((GET_LDOUBLE_MANH(ux) & ~LDBL_NBIT) == 0) { - SET_LDOUBLE_EXP(ux, GET_LDOUBLE_EXP(ux) - 1); - } - SET_LDOUBLE_MANH(ux, (GET_LDOUBLE_MANH(ux) - 1) | - (GET_LDOUBLE_MANH(ux) & LDBL_NBIT)); - } - SET_LDOUBLE_MANL(ux, GET_LDOUBLE_MANL(ux) - 1); - } - else { /* x += ulp */ - SET_LDOUBLE_MANL(ux, GET_LDOUBLE_MANL(ux) + 1); - if (GET_LDOUBLE_MANL(ux) == 0) { - SET_LDOUBLE_MANH(ux, (GET_LDOUBLE_MANH(ux) + 1) | - (GET_LDOUBLE_MANH(ux) & LDBL_NBIT)); - if ((GET_LDOUBLE_MANH(ux) & ~LDBL_NBIT) == 0) { - SET_LDOUBLE_EXP(ux, GET_LDOUBLE_EXP(ux) + 1); - } - } - } - if (GET_LDOUBLE_EXP(ux) == 0x7fff) { - return ux.e + ux.e; /* overflow */ - } - if (GET_LDOUBLE_EXP(ux) == 0) { /* underflow */ - if (LDBL_NBIT) { - SET_LDOUBLE_MANH(ux, GET_LDOUBLE_MANH(ux) & ~LDBL_NBIT); - } - t = ux.e * ux.e; - if (t != ux.e) { /* raise underflow flag */ - return ux.e; - } - } - - return ux.e; -} -#endif - namespace { template struct numeric_limits; @@ -609,29 +404,23 @@ npy_spacingl(npy_longdouble x) * Decorate all the math functions which are available on the current platform */ -#ifdef HAVE_NEXTAFTERF extern "C" float npy_nextafterf(float x, float y) { return nextafterf(x, y); } -#endif -#ifdef HAVE_NEXTAFTER extern "C" double npy_nextafter(double x, double y) { return nextafter(x, y); } -#endif -#ifdef HAVE_NEXTAFTERL extern "C" npy_longdouble npy_nextafterl(npy_longdouble x, npy_longdouble y) { return nextafterl(x, y); } -#endif extern "C" int npy_clear_floatstatus() From b6d52fc2b0611207ae5d554de09d7d6305a8b22b Mon Sep 17 00:00:00 2001 From: mattip Date: Tue, 16 Aug 2022 10:05:51 +0300 Subject: [PATCH 14/16] remove duplicate C99 functions, ensure optional variant HAVE_ macros are generated --- numpy/core/setup_common.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/numpy/core/setup_common.py b/numpy/core/setup_common.py index d246db8e022e..d9ebd7b1df21 100644 --- a/numpy/core/setup_common.py +++ b/numpy/core/setup_common.py @@ -127,13 +127,9 @@ def set_sig(sig): "expm1", "log1p", "acosh", "asinh", "atanh", "rint", "trunc", "exp2", "copysign", "nextafter", "strtoll", "strtoull", "cbrt", - # C99, mandatory - "sin", "cos", "tan", "sinh", "cosh", "tanh", "fabs", "floor", "ceil", - "rint", "trunc", "sqrt", "log10", "log", "log1p", "exp", "expm1", - "asin", "acos", "atan", "asinh", "acosh", "atanh", ] -OPTIONAL_STDFUNCS = [ +OPTIONAL_STDFUNCS_BASE = [ # cygwin "log2", # macos for powl @@ -144,6 +140,10 @@ def set_sig(sig): "atan2", ] +OPTIONAL_STDFUNCS = OPTIONAL_STDFUNCS_BASE[:] +OPTIONAL_STDFUNCS += [f + 'f' for f in OPTIONAL_STDFUNCS_BASE] +OPTIONAL_STDFUNCS += [f + 'l' for f in OPTIONAL_STDFUNCS_BASE] + OPTIONAL_LOCALE_FUNCS = ["strtold_l"] OPTIONAL_FILE_FUNCS = ["ftello", "fseeko", "fallocate"] OPTIONAL_MISC_FUNCS = ["backtrace", "madvise"] From d1cbf3fe0316b1a97d9c3c8806b31fd7f90ab2e4 Mon Sep 17 00:00:00 2001 From: mattip Date: Tue, 16 Aug 2022 17:33:17 +0300 Subject: [PATCH 15/16] BUILD: convert HAVE_ macros to BLOCK_, cleanup --- numpy/core/setup.py | 1 - numpy/core/setup_common.py | 51 ++++------ numpy/core/src/common/npy_config.h | 32 +++---- .../core/src/npymath/npy_math_internal.h.src | 95 ++++++++++++------- 4 files changed, 98 insertions(+), 81 deletions(-) diff --git a/numpy/core/setup.py b/numpy/core/setup.py index ec3929ca8c99..65aacfdadadb 100644 --- a/numpy/core/setup.py +++ b/numpy/core/setup.py @@ -189,7 +189,6 @@ def check_funcs(funcs_name, headers=["feature_detection_math.h"]): if config.check_decl(fname2def(f), headers=["Python.h"]): OPTIONAL_FILE_FUNCS.remove(f) - check_funcs(OPTIONAL_STDFUNCS) check_funcs(OPTIONAL_FILE_FUNCS, headers=["feature_detection_stdio.h"]) check_funcs(OPTIONAL_MISC_FUNCS, headers=["feature_detection_misc.h"]) diff --git a/numpy/core/setup_common.py b/numpy/core/setup_common.py index d9ebd7b1df21..e6ba578e4ade 100644 --- a/numpy/core/setup_common.py +++ b/numpy/core/setup_common.py @@ -127,27 +127,31 @@ def set_sig(sig): "expm1", "log1p", "acosh", "asinh", "atanh", "rint", "trunc", "exp2", "copysign", "nextafter", "strtoll", "strtoull", "cbrt", + "log2", "pow", "hypot", "atan2", ] -OPTIONAL_STDFUNCS_BASE = [ - # cygwin - "log2", - # macos for powl - "pow", - # 32-bit windows - "hypot", - # 32-bit mingw, visual studio 2015 - "atan2", -] - -OPTIONAL_STDFUNCS = OPTIONAL_STDFUNCS_BASE[:] -OPTIONAL_STDFUNCS += [f + 'f' for f in OPTIONAL_STDFUNCS_BASE] -OPTIONAL_STDFUNCS += [f + 'l' for f in OPTIONAL_STDFUNCS_BASE] - OPTIONAL_LOCALE_FUNCS = ["strtold_l"] OPTIONAL_FILE_FUNCS = ["ftello", "fseeko", "fallocate"] OPTIONAL_MISC_FUNCS = ["backtrace", "madvise"] +# variable attributes tested via "int %s a" % attribute +OPTIONAL_VARIABLE_ATTRIBUTES = ["__thread", "__declspec(thread)"] + +# Subset of OPTIONAL_*_FUNCS which may already have HAVE_* defined by Python.h +OPTIONAL_FUNCS_MAYBE = [ + "ftello", "fseeko" + ] + +# TODO: make these mandatory and use BLOCK_ macros rather than HAVE_ macros +# in npy_config.h and throughout the code +C99_COMPLEX_TYPES = [ + 'complex double', 'complex float', 'complex long double' + ] +C99_COMPLEX_FUNCS = [ + "cabs", "cacos", "cacosh", "carg", "casin", "casinh", "catan", + "catanh", "ccos", "ccosh", "cexp", "cimag", "clog", "conj", "cpow", + "cproj", "creal", "csin", "csinh", "csqrt", "ctan", "ctanh" + ] OPTIONAL_HEADERS = [ # sse headers only enabled automatically on amd64/x32 builds @@ -238,23 +242,6 @@ def set_sig(sig): 'immintrin.h'), ] -# variable attributes tested via "int %s a" % attribute -OPTIONAL_VARIABLE_ATTRIBUTES = ["__thread", "__declspec(thread)"] - -# Subset of OPTIONAL_*_FUNCS which may already have HAVE_* defined by Python.h -OPTIONAL_FUNCS_MAYBE = [ - "ftello", "fseeko" - ] - -C99_COMPLEX_TYPES = [ - 'complex double', 'complex float', 'complex long double' - ] -C99_COMPLEX_FUNCS = [ - "cabs", "cacos", "cacosh", "carg", "casin", "casinh", "catan", - "catanh", "ccos", "ccosh", "cexp", "cimag", "clog", "conj", "cpow", - "cproj", "creal", "csin", "csinh", "csqrt", "ctan", "ctanh" - ] - def fname2def(name): return "HAVE_%s" % name.upper() diff --git a/numpy/core/src/common/npy_config.h b/numpy/core/src/common/npy_config.h index 610216a34a54..bd6e06e2e270 100644 --- a/numpy/core/src/common/npy_config.h +++ b/numpy/core/src/common/npy_config.h @@ -11,8 +11,8 @@ /* Disable broken functions on z/OS */ #if defined (__MVS__) -#undef HAVE_POWF -#undef HAVE_EXPF +#define BLOCK_POWF +#define BLOCK_EXPF #undef HAVE___THREAD #endif @@ -20,13 +20,13 @@ /* Disable broken MS math functions */ #if defined(__MINGW32_VERSION) -#undef HAVE_ATAN2 -#undef HAVE_ATAN2F -#undef HAVE_ATAN2L +#define BLOCK_ATAN2 +#define BLOCK_ATAN2F +#define BLOCK_ATAN2L -#undef HAVE_HYPOT -#undef HAVE_HYPOTF -#undef HAVE_HYPOTL +#define BLOCK_HYPOT +#define BLOCK_HYPOTF +#define BLOCK_HYPOTL #endif @@ -66,23 +66,23 @@ #undef HAVE_CABSF #undef HAVE_CABSL -#undef HAVE_HYPOT -#undef HAVE_HYPOTF -#undef HAVE_HYPOTL +#define BLOCK_HYPOT +#define BLOCK_HYPOTF +#define BLOCK_HYPOTL #endif /* Intel C for Windows uses POW for 64 bits longdouble*/ #if defined(_MSC_VER) && defined(__INTEL_COMPILER) -#if defined(HAVE_POWL) && (NPY_SIZEOF_LONGDOUBLE == 8) -#undef HAVE_POWL +#if NPY_SIZEOF_LONGDOUBLE == 8 +#define BLOCK_POWL #endif #endif /* defined(_MSC_VER) && defined(__INTEL_COMPILER) */ /* powl gives zero division warning on OS X, see gh-8307 */ -#if defined(HAVE_POWL) && defined(NPY_OS_DARWIN) -#undef HAVE_POWL +#if defined(NPY_OS_DARWIN) +#define BLOCK_POWL #endif #ifdef __CYGWIN__ @@ -119,7 +119,7 @@ #undef HAVE_CACOS /* log2(exp2(i)) off by a few eps */ -#undef HAVE_LOG2 +#define BLOCK_LOG2 /* np.power(..., dtype=np.complex256) doesn't report overflow */ #undef HAVE_CPOWL diff --git a/numpy/core/src/npymath/npy_math_internal.h.src b/numpy/core/src/npymath/npy_math_internal.h.src index dd0c5fa149e4..f046798368d9 100644 --- a/numpy/core/src/npymath/npy_math_internal.h.src +++ b/numpy/core/src/npymath/npy_math_internal.h.src @@ -83,10 +83,33 @@ static const npy_uint64 MAGIC64[] = {0x5555555555555555ull, 0x3333333333333333ul /* ***************************************************************************** - ** BASIC MATH FUNCTIONS ** + ** BLOCKLIST-ABLE BASIC MATH FUNCTIONS ** ***************************************************************************** */ +/* The double variant for these functions are never blocked */ + +NPY_INPLACE double npy_exp(double x){ + return exp(x); +} + +NPY_INPLACE double npy_pow(double x, double y) +{ + return pow(x, y); +} + +NPY_INPLACE double npy_sqrt(double x) +{ + return sqrt(x); +} + +NPY_INPLACE double npy_modf(double x, double *iptr) +{ + return modf(x, iptr); +} + +/* The following functions can be blocked, even for doubles */ + /* Original code by Konrad Hinsen. */ /* Taken from FreeBSD mlib, adapted for numpy * @@ -96,7 +119,7 @@ static const npy_uint64 MAGIC64[] = {0x5555555555555555ull, 0x3333333333333333ul */ NPY_INPLACE double npy_log2(double x) { -#ifdef HAVE_LOG2 +#ifndef BLOCK_LOG2 return log2(x); #else if (!npy_isfinite(x) || x <= 0.) { @@ -136,7 +159,7 @@ NPY_INPLACE double npy_log2(double x) #define NPY_DBL_EPSILON 1.2246467991473531772E-16 NPY_INPLACE double npy_atan2(double y, double x) { -#ifdef HAVE_ATAN2 +#ifndef BLOCK_ATAN2 return atan2(y, x); #else npy_int32 k, m, iy, ix, hx, hy; @@ -220,7 +243,7 @@ NPY_INPLACE double npy_atan2(double y, double x) NPY_INPLACE double npy_hypot(double x, double y) { -#ifdef HAVE_HYPOT +#ifndef BLOCK_HYPOT return hypot(x, y); #else double yx; @@ -296,12 +319,10 @@ NPY_INPLACE double npy_hypot(double x, double y) #define WORKAROUND_APPLE_TRIG_BUG 0 #endif -/* mandatory C99 functions */ - /**begin repeat1 - * #kind = sin,cos,tan,sinh,cosh,tanh,fabs,floor,ceil,rint,trunc,sqrt,log10, - * log,exp,expm1,asin,acos,atan,asinh,acosh,atanh,log1p,exp2# - * #TRIG_WORKAROUND = WORKAROUND_APPLE_TRIG_BUG*3, 0*21# + * #kind = sin,cos,tan,sinh,cosh,tanh,fabs,floor,ceil,rint,trunc,log10, + * log,expm1,asin,acos,atan,asinh,acosh,atanh,log1p,exp2# + * #TRIG_WORKAROUND = WORKAROUND_APPLE_TRIG_BUG*3, 0*19# */ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x) { @@ -329,12 +350,6 @@ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x, @type@ y) } /**end repeat1**/ - -NPY_INPLACE @type@ npy_modf@c@(@type@ x, @type@ *iptr) -{ - return NPY__FP_SFX(modf)(x, iptr); -} - NPY_INPLACE @type@ npy_ldexp@c@(@type@ x, int exp) { return NPY__FP_SFX(ldexp)(x, exp); @@ -352,13 +367,13 @@ NPY_INPLACE @type@ npy_cbrt@c@(@type@ x) /**end repeat**/ -/* Optional C99 functions */ +/* Blocklist-able C99 functions */ /**begin repeat - * #type = npy_longdouble, npy_float# - * #TYPE = LONGDOUBLE, FLOAT# - * #c = l,f# - * #C = L,F# + * #type = npy_float,npy_longdouble# + * #TYPE = FLOAT,LONGDOUBLE# + * #c = f,l# + * #C = F,L# */ #undef NPY__FP_SFX #if NPY_SIZEOF_@TYPE@ == NPY_SIZEOF_DOUBLE @@ -368,21 +383,21 @@ NPY_INPLACE @type@ npy_cbrt@c@(@type@ x) #endif /**begin repeat1 - * #kind = log2# - * #KIND = LOG2# + * #kind = exp,log2,sqrt# + * #KIND = EXP,LOG2,SQRT# */ #ifdef @kind@@c@ #undef @kind@@c@ #endif -#ifndef HAVE_@KIND@@C@ +#ifdef BLOCK_@KIND@@C@ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x) { return (@type@) npy_@kind@((double)x); } #endif -#ifdef HAVE_@KIND@@C@ +#ifndef BLOCK_@KIND@@C@ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x) { return NPY__FP_SFX(@kind@)(x); @@ -399,20 +414,42 @@ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x) #ifdef @kind@@c@ #undef @kind@@c@ #endif -#ifndef HAVE_@KIND@@C@ +#ifdef BLOCK_@KIND@@C@ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x, @type@ y) { return (@type@) npy_@kind@((double)x, (double) y); } #endif -#ifdef HAVE_@KIND@@C@ +#ifndef BLOCK_@KIND@@C@ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x, @type@ y) { return NPY__FP_SFX(@kind@)(x, y); } #endif /**end repeat1**/ + +#ifdef modf@c@ +#undef modf@c@ +#endif +#ifdef BLOCK_MODF@C@ +NPY_INPLACE @type@ npy_modf@c@(@type@ x, @type@ *iptr) +{ + double niptr; + double y = npy_modf((double)x, &niptr); + *iptr = (@type@) niptr; + return (@type@) y; +} +#endif + +#ifndef BLOCK_MODF@C@ +NPY_INPLACE @type@ npy_modf@c@(@type@ x, @type@ *iptr) +{ + return NPY__FP_SFX(modf)(x, iptr); +} +#endif + + /**end repeat**/ @@ -753,9 +790,3 @@ npy_popcount@c@(npy_@type@ a) } /**end repeat**/ -/* XXX: will moving this to a define break anything? */ - -NPY_INPLACE double npy_pow(double x, double y) -{ - return pow(x, y); -} From 25629dd1e1c08d6846e51d39bc265724a7c5ab82 Mon Sep 17 00:00:00 2001 From: mattip Date: Sun, 21 Aug 2022 19:45:10 +0300 Subject: [PATCH 16/16] TASK: rename macros (from review) --- numpy/core/setup_common.py | 2 -- numpy/core/src/common/npy_config.h | 28 +++++++++---------- .../core/src/npymath/npy_math_internal.h.src | 18 ++++++------ 3 files changed, 23 insertions(+), 25 deletions(-) diff --git a/numpy/core/setup_common.py b/numpy/core/setup_common.py index e6ba578e4ade..c19a8479f0b2 100644 --- a/numpy/core/setup_common.py +++ b/numpy/core/setup_common.py @@ -142,8 +142,6 @@ def set_sig(sig): "ftello", "fseeko" ] -# TODO: make these mandatory and use BLOCK_ macros rather than HAVE_ macros -# in npy_config.h and throughout the code C99_COMPLEX_TYPES = [ 'complex double', 'complex float', 'complex long double' ] diff --git a/numpy/core/src/common/npy_config.h b/numpy/core/src/common/npy_config.h index bd6e06e2e270..d6886c5ea90a 100644 --- a/numpy/core/src/common/npy_config.h +++ b/numpy/core/src/common/npy_config.h @@ -11,8 +11,8 @@ /* Disable broken functions on z/OS */ #if defined (__MVS__) -#define BLOCK_POWF -#define BLOCK_EXPF +#define NPY_BLOCK_POWF +#define NPY_BLOCK_EXPF #undef HAVE___THREAD #endif @@ -20,13 +20,13 @@ /* Disable broken MS math functions */ #if defined(__MINGW32_VERSION) -#define BLOCK_ATAN2 -#define BLOCK_ATAN2F -#define BLOCK_ATAN2L +#define NPY_BLOCK_ATAN2 +#define NPY_BLOCK_ATAN2F +#define NPY_BLOCK_ATAN2L -#define BLOCK_HYPOT -#define BLOCK_HYPOTF -#define BLOCK_HYPOTL +#define NPY_BLOCK_HYPOT +#define NPY_BLOCK_HYPOTF +#define NPY_BLOCK_HYPOTL #endif @@ -66,9 +66,9 @@ #undef HAVE_CABSF #undef HAVE_CABSL -#define BLOCK_HYPOT -#define BLOCK_HYPOTF -#define BLOCK_HYPOTL +#define NPY_BLOCK_HYPOT +#define NPY_BLOCK_HYPOTF +#define NPY_BLOCK_HYPOTL #endif @@ -76,13 +76,13 @@ /* Intel C for Windows uses POW for 64 bits longdouble*/ #if defined(_MSC_VER) && defined(__INTEL_COMPILER) #if NPY_SIZEOF_LONGDOUBLE == 8 -#define BLOCK_POWL +#define NPY_BLOCK_POWL #endif #endif /* defined(_MSC_VER) && defined(__INTEL_COMPILER) */ /* powl gives zero division warning on OS X, see gh-8307 */ #if defined(NPY_OS_DARWIN) -#define BLOCK_POWL +#define NPY_BLOCK_POWL #endif #ifdef __CYGWIN__ @@ -119,7 +119,7 @@ #undef HAVE_CACOS /* log2(exp2(i)) off by a few eps */ -#define BLOCK_LOG2 +#define NPY_BLOCK_LOG2 /* np.power(..., dtype=np.complex256) doesn't report overflow */ #undef HAVE_CPOWL diff --git a/numpy/core/src/npymath/npy_math_internal.h.src b/numpy/core/src/npymath/npy_math_internal.h.src index f046798368d9..52aaa7102ace 100644 --- a/numpy/core/src/npymath/npy_math_internal.h.src +++ b/numpy/core/src/npymath/npy_math_internal.h.src @@ -119,7 +119,7 @@ NPY_INPLACE double npy_modf(double x, double *iptr) */ NPY_INPLACE double npy_log2(double x) { -#ifndef BLOCK_LOG2 +#ifndef NPY_BLOCK_LOG2 return log2(x); #else if (!npy_isfinite(x) || x <= 0.) { @@ -159,7 +159,7 @@ NPY_INPLACE double npy_log2(double x) #define NPY_DBL_EPSILON 1.2246467991473531772E-16 NPY_INPLACE double npy_atan2(double y, double x) { -#ifndef BLOCK_ATAN2 +#ifndef NPY_BLOCK_ATAN2 return atan2(y, x); #else npy_int32 k, m, iy, ix, hx, hy; @@ -243,7 +243,7 @@ NPY_INPLACE double npy_atan2(double y, double x) NPY_INPLACE double npy_hypot(double x, double y) { -#ifndef BLOCK_HYPOT +#ifndef NPY_BLOCK_HYPOT return hypot(x, y); #else double yx; @@ -390,14 +390,14 @@ NPY_INPLACE @type@ npy_cbrt@c@(@type@ x) #ifdef @kind@@c@ #undef @kind@@c@ #endif -#ifdef BLOCK_@KIND@@C@ +#ifdef NPY_BLOCK_@KIND@@C@ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x) { return (@type@) npy_@kind@((double)x); } #endif -#ifndef BLOCK_@KIND@@C@ +#ifndef NPY_BLOCK_@KIND@@C@ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x) { return NPY__FP_SFX(@kind@)(x); @@ -414,14 +414,14 @@ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x) #ifdef @kind@@c@ #undef @kind@@c@ #endif -#ifdef BLOCK_@KIND@@C@ +#ifdef NPY_BLOCK_@KIND@@C@ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x, @type@ y) { return (@type@) npy_@kind@((double)x, (double) y); } #endif -#ifndef BLOCK_@KIND@@C@ +#ifndef NPY_BLOCK_@KIND@@C@ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x, @type@ y) { return NPY__FP_SFX(@kind@)(x, y); @@ -432,7 +432,7 @@ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x, @type@ y) #ifdef modf@c@ #undef modf@c@ #endif -#ifdef BLOCK_MODF@C@ +#ifdef NPY_BLOCK_MODF@C@ NPY_INPLACE @type@ npy_modf@c@(@type@ x, @type@ *iptr) { double niptr; @@ -442,7 +442,7 @@ NPY_INPLACE @type@ npy_modf@c@(@type@ x, @type@ *iptr) } #endif -#ifndef BLOCK_MODF@C@ +#ifndef NPY_BLOCK_MODF@C@ NPY_INPLACE @type@ npy_modf@c@(@type@ x, @type@ *iptr) { return NPY__FP_SFX(modf)(x, iptr);