From 457e7c0b43e6a56810970de0a1767fb74166baa7 Mon Sep 17 00:00:00 2001 From: Lysandros Nikolaou Date: Mon, 17 Jul 2023 16:24:40 +0200 Subject: [PATCH] More changes to build without std::complex --- numpy/core/include/numpy/ndarraytypes.h | 1 + numpy/core/include/numpy/npy_common.h | 6 ++ numpy/core/include/numpy/npy_math.h | 56 ----------- numpy/core/src/umath/clip.cpp | 82 +++++++++------- numpy/linalg/umath_linalg.cpp | 119 ++++++++++++++++-------- 5 files changed, 135 insertions(+), 129 deletions(-) diff --git a/numpy/core/include/numpy/ndarraytypes.h b/numpy/core/include/numpy/ndarraytypes.h index 1155120b24cd..f7aa9e6c3601 100644 --- a/numpy/core/include/numpy/ndarraytypes.h +++ b/numpy/core/include/numpy/ndarraytypes.h @@ -2,6 +2,7 @@ #define NUMPY_CORE_INCLUDE_NUMPY_NDARRAYTYPES_H_ #include "npy_common.h" +#include "npy_math.h" #include "npy_endian.h" #include "npy_cpu.h" #include "utils.h" diff --git a/numpy/core/include/numpy/npy_common.h b/numpy/core/include/numpy/npy_common.h index 95c73b670de2..5c81e7f698e4 100644 --- a/numpy/core/include/numpy/npy_common.h +++ b/numpy/core/include/numpy/npy_common.h @@ -386,7 +386,13 @@ typedef _Dcomplex npy_cdouble; typedef _Fcomplex npy_cfloat; typedef _Lcomplex npy_clongdouble; #else /* !defined(__cplusplus) && (!defined(_MSC_VER) || defined(__INTEL_COMPILER)) */ +#ifdef __cplusplus +extern "C++" { +#endif #include +#ifdef __cplusplus +} +#endif #undef complex typedef double _Complex npy_cdouble; typedef float _Complex npy_cfloat; diff --git a/numpy/core/include/numpy/npy_math.h b/numpy/core/include/numpy/npy_math.h index 276095db7631..766bba3f6e5b 100644 --- a/numpy/core/include/numpy/npy_math.h +++ b/numpy/core/include/numpy/npy_math.h @@ -357,7 +357,6 @@ NPY_INPLACE npy_longdouble npy_heavisidel(npy_longdouble x, npy_longdouble h0); * Complex declarations */ -#ifndef __cplusplus typedef union { double *arr; const npy_cdouble *comp; @@ -372,132 +371,77 @@ typedef union { longdouble_t *arr; const npy_clongdouble *comp; } _npy_clongdouble_to_arr; -#endif static inline double NPY_CDOUBLE_GET_REAL(const npy_cdouble *c) { -#ifdef __cplusplus - return reinterpret_cast(c)[0]; -#else _npy_cdouble_to_arr tmp; tmp.comp = c; return tmp.arr[0]; -#endif } static inline double NPY_CDOUBLE_GET_IMAG(const npy_cdouble *c) { -#ifdef __cplusplus - return reinterpret_cast(c)[1]; -#else _npy_cdouble_to_arr tmp; tmp.comp = c; return tmp.arr[1]; -#endif } static inline void NPY_CDOUBLE_SET_REAL(npy_cdouble *c, double real) { -#ifdef __cplusplus - double *tmp = reinterpret_cast(c); - tmp[0] = real; -#else _npy_cdouble_to_arr tmp; tmp.comp = c; tmp.arr[0] = real; -#endif } static inline void NPY_CDOUBLE_SET_IMAG(npy_cdouble *c, double imag) { -#ifdef __cplusplus - double *tmp = reinterpret_cast(c); - tmp[1] = imag; -#else _npy_cdouble_to_arr tmp; tmp.comp = c; tmp.arr[1] = imag; -#endif } static inline float NPY_CFLOAT_GET_REAL(const npy_cfloat *c) { -#ifdef __cplusplus - return reinterpret_cast(c)[0]; -#else _npy_cfloat_to_arr tmp; tmp.comp = c; return tmp.arr[0]; -#endif } static inline float NPY_CFLOAT_GET_IMAG(const npy_cfloat *c) { -#ifdef __cplusplus - return reinterpret_cast(c)[1]; -#else _npy_cfloat_to_arr tmp; tmp.comp = c; return tmp.arr[1]; -#endif } static inline void NPY_CFLOAT_SET_REAL(npy_cfloat *c, float real) { -#ifdef __cplusplus - float *tmp = reinterpret_cast(c); - tmp[0] = real; -#else _npy_cfloat_to_arr tmp; tmp.comp = c; tmp.arr[0] = real; -#endif } static inline void NPY_CFLOAT_SET_IMAG(npy_cfloat *c, float imag) { -#ifdef __cplusplus - float *tmp = reinterpret_cast(c); - tmp[1] = imag; -#else _npy_cfloat_to_arr tmp; tmp.comp = c; tmp.arr[1] = imag; -#endif } static inline longdouble_t NPY_CLONGDOUBLE_GET_REAL(const npy_clongdouble *c) { -#ifdef __cplusplus - return reinterpret_cast(c)[0]; -#else _npy_clongdouble_to_arr tmp; tmp.comp = c; return tmp.arr[0]; -#endif } static inline longdouble_t NPY_CLONGDOUBLE_GET_IMAG(const npy_clongdouble *c) { -#ifdef __cplusplus - return reinterpret_cast(c)[1]; -#else _npy_clongdouble_to_arr tmp; tmp.comp = c; return tmp.arr[1]; -#endif } static inline void NPY_CLONGDOUBLE_SET_REAL(npy_clongdouble *c, longdouble_t real) { -#ifdef __cplusplus - longdouble_t *tmp = reinterpret_cast(c); - tmp[0] = real; -#else _npy_clongdouble_to_arr tmp; tmp.comp = c; tmp.arr[0] = real; -#endif } static inline void NPY_CLONGDOUBLE_SET_IMAG(npy_clongdouble *c, longdouble_t imag) { -#ifdef __cplusplus - longdouble_t *tmp = reinterpret_cast(c); - tmp[1] = imag; -#else _npy_clongdouble_to_arr tmp; tmp.comp = c; tmp.arr[1] = imag; -#endif } static inline npy_cdouble npy_cpack(double x, double y) diff --git a/numpy/core/src/umath/clip.cpp b/numpy/core/src/umath/clip.cpp index 5548c9f0ddd5..d90ae5c279e5 100644 --- a/numpy/core/src/umath/clip.cpp +++ b/numpy/core/src/umath/clip.cpp @@ -55,47 +55,57 @@ _NPY_MAX(T a, T b, npy::floating_point_tag const &) return npy_isnan(a) ? (a) : PyArray_MAX(a, b); } -template -T -_NPY_MIN(T a, T b, npy::complex_tag const &) +npy_cdouble +_NPY_MIN(npy_cdouble a, npy_cdouble b, npy::complex_tag const &) { - if (std::is_same::value) { - return npy_isnan(a.real()) || npy_isnan(a.imag()) || PyArray_CLT(a, b, CDOUBLE) - ? (a) - : (b); - } - else if (std::is_same::value) { - return npy_isnan(a.real()) || npy_isnan(a.imag()) || PyArray_CLT(a, b, CFLOAT) - ? (a) - : (b); - } - else { - return npy_isnan(a.real()) || npy_isnan(a.imag()) || PyArray_CLT(a, b, CLONGDOUBLE) - ? (a) - : (b); - } + return npy_isnan(NPY_CDOUBLE_GET_REAL(&a)) || npy_isnan(NPY_CDOUBLE_GET_IMAG(&a)) || PyArray_CLT(a, b, CDOUBLE) + ? (a) + : (b); } -template -T -_NPY_MAX(T a, T b, npy::complex_tag const &) +npy_cfloat +_NPY_MIN(npy_cfloat a, npy_cfloat b, npy::complex_tag const &) { - if (std::is_same::value) { - return npy_isnan(a.real()) || npy_isnan(a.imag()) || PyArray_CGT(a, b, CDOUBLE) - ? (a) - : (b); - } - else if (std::is_same::value) { - return npy_isnan(a.real()) || npy_isnan(a.imag()) || PyArray_CGT(a, b, CFLOAT) - ? (a) - : (b); - } - else { - return npy_isnan(a.real()) || npy_isnan(a.imag()) || PyArray_CGT(a, b, CLONGDOUBLE) - ? (a) - : (b); - } + return npy_isnan(NPY_CFLOAT_GET_REAL(&a)) || npy_isnan(NPY_CFLOAT_GET_IMAG(&a)) || PyArray_CLT(a, b, CFLOAT) + ? (a) + : (b); +} + +#if NPY_SIZEOF_COMPLEX_LONGDOUBLE != NPY_SIZEOF_COMPLEX_DOUBLE +npy_clongdouble +_NPY_MIN(npy_clongdouble a, npy_clongdouble b, npy::complex_tag const &) +{ + return npy_isnan(NPY_CLONGDOUBLE_GET_REAL(&a)) || npy_isnan(NPY_CLONGDOUBLE_GET_IMAG(&a)) || PyArray_CLT(a, b, CLONGDOUBLE) + ? (a) + : (b); +} +#endif + +npy_cdouble +_NPY_MAX(npy_cdouble a, npy_cdouble b, npy::complex_tag const &) +{ + return npy_isnan(NPY_CDOUBLE_GET_REAL(&a)) || npy_isnan(NPY_CDOUBLE_GET_IMAG(&a)) || PyArray_CGT(a, b, CDOUBLE) + ? (a) + : (b); +} + +npy_cfloat +_NPY_MAX(npy_cfloat a, npy_cfloat b, npy::complex_tag const &) +{ + return npy_isnan(NPY_CFLOAT_GET_REAL(&a)) || npy_isnan(NPY_CFLOAT_GET_IMAG(&a)) || PyArray_CGT(a, b, CFLOAT) + ? (a) + : (b); +} + +#if NPY_SIZEOF_COMPLEX_LONGDOUBLE != NPY_SIZEOF_COMPLEX_DOUBLE +npy_clongdouble +_NPY_MAX(npy_clongdouble a, npy_clongdouble b, npy::complex_tag const &) +{ + return npy_isnan(NPY_CLONGDOUBLE_GET_REAL(&a)) || npy_isnan(NPY_CLONGDOUBLE_GET_IMAG(&a)) || PyArray_CGT(a, b, CLONGDOUBLE) + ? (a) + : (b); } +#endif template T diff --git a/numpy/linalg/umath_linalg.cpp b/numpy/linalg/umath_linalg.cpp index 880cdb0fd98a..ee2d6587bd9e 100644 --- a/numpy/linalg/umath_linalg.cpp +++ b/numpy/linalg/umath_linalg.cpp @@ -11,6 +11,7 @@ #define NPY_NO_DEPRECATED_API NPY_API_VERSION #include "numpy/arrayobject.h" #include "numpy/ufuncobject.h" +#include "numpy/npy_math.h" #include "npy_pycompat.h" @@ -469,19 +470,35 @@ constexpr double numeric_limits::minus_one; const double numeric_limits::ninf = -NPY_INFINITY; const double numeric_limits::nan = NPY_NAN; +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) template<> -struct numeric_limits> { -static constexpr std::complex one (1.0f, 0.0f); -static constexpr std::complex zero (0.0f, 0.0f); -static constexpr std::complex minus_one (-1.0f, 0.0f); -static const std::complex ninf; -static const std::complex nan; +struct numeric_limits { +static constexpr npy_cfloat one = {1.0f, 0.0f}; +static constexpr npy_cfloat zero = {0.0f, 0.0f}; +static constexpr npy_cfloat minus_one = {-1.0f, 0.0f}; +static const npy_cfloat ninf; +static const npy_cfloat nan; }; -constexpr std::complex numeric_limits>::one; -constexpr std::complex numeric_limits>::zero; -constexpr std::complex numeric_limits>::minus_one; -const std::complex numeric_limits>::ninf (-NPY_INFINITYF, 0.0f); -const std::complex numeric_limits>::nan = (NPY_NANF, NPY_NANF); +constexpr npy_cfloat numeric_limits::one; +constexpr npy_cfloat numeric_limits::zero; +constexpr npy_cfloat numeric_limits::minus_one; +const npy_cfloat numeric_limits::ninf = {-NPY_INFINITYF, 0.0f}; +const npy_cfloat numeric_limits::nan = {NPY_NANF, NPY_NANF}; +#else +template<> +struct numeric_limits { +static constexpr npy_cfloat one = 1.0f; +static constexpr npy_cfloat zero = 0.0f; +static constexpr npy_cfloat minus_one = -1.0f; +static const npy_cfloat ninf; +static const npy_cfloat nan; +}; +constexpr npy_cfloat numeric_limits::one; +constexpr npy_cfloat numeric_limits::zero; +constexpr npy_cfloat numeric_limits::minus_one; +const npy_cfloat numeric_limits::ninf = -NPY_INFINITYF; +const npy_cfloat numeric_limits::nan = NPY_NANF; +#endif template<> struct numeric_limits { @@ -497,19 +514,35 @@ constexpr f2c_complex numeric_limits::minus_one; const f2c_complex numeric_limits::ninf = {-NPY_INFINITYF, 0.0f}; const f2c_complex numeric_limits::nan = {NPY_NANF, NPY_NANF}; +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) +template<> +struct numeric_limits { +static constexpr npy_cdouble one = {1.0, 0.0}; +static constexpr npy_cdouble zero = {0.0, 0.0}; +static constexpr npy_cdouble minus_one = {-1.0, 0.0}; +static const npy_cdouble ninf; +static const npy_cdouble nan; +}; +constexpr npy_cdouble numeric_limits::one; +constexpr npy_cdouble numeric_limits::zero; +constexpr npy_cdouble numeric_limits::minus_one; +const npy_cdouble numeric_limits::ninf = {-NPY_INFINITY, 0.0}; +const npy_cdouble numeric_limits::nan = {NPY_NAN, NPY_NAN}; +#else template<> -struct numeric_limits> { -static constexpr std::complex one (1.0, 0.0); -static constexpr std::complex zero (0.0, 0.0); -static constexpr std::complex minus_one (-1.0, 0.0); -static const std::complex ninf; -static const std::complex nan; +struct numeric_limits { +static constexpr npy_cdouble one = 1.0; +static constexpr npy_cdouble zero = 0.0; +static constexpr npy_cdouble minus_one = -1.0; +static const npy_cdouble ninf; +static const npy_cdouble nan; }; -constexpr std::complex numeric_limits>::one; -constexpr std::complex numeric_limits>::zero; -constexpr std::complex numeric_limits>::minus_one; -const std::complex numeric_limits>::ninf (-NPY_INFINITY, 0.0); -const std::complex numeric_limits>::nan (NPY_NAN, NPY_NAN); +constexpr npy_cdouble numeric_limits::one; +constexpr npy_cdouble numeric_limits::zero; +constexpr npy_cdouble numeric_limits::minus_one; +const npy_cdouble numeric_limits::ninf = -NPY_INFINITY; +const npy_cdouble numeric_limits::nan = NPY_NAN; +#endif template<> struct numeric_limits { @@ -1046,10 +1079,26 @@ det_from_slogdet(typ sign, typ logdet) npy_float npyabs(npy_cfloat z) { return npy_cabsf(z);} npy_double npyabs(npy_cdouble z) { return npy_cabs(z);} -#define RE(COMPLEX) (COMPLEX).real() -#define IM(COMPLEX) (COMPLEX).imag() -#define SETRE(COMPLEX, VALUE) (COMPLEX).real(VALUE) -#define SETIM(COMPLEX, VALUE) (COMPLEX).imag(VALUE) +inline float RE(npy_cfloat *c) { return NPY_CFLOAT_GET_REAL(c); } +inline double RE(npy_cdouble *c) { return NPY_CDOUBLE_GET_REAL(c); } +#if NPY_SIZEOF_COMPLEX_LONGDOUBLE != NPY_SIZEOF_COMPLEX_DOUBLE +inline longdouble_t RE(npy_clongdouble *c) { return NPY_CLONGDOUBLE_GET_REAL(c); } +#endif +inline float IM(npy_cfloat *c) { return NPY_CFLOAT_GET_IMAG(c); } +inline double IM(npy_cdouble *c) { return NPY_CDOUBLE_GET_IMAG(c); } +#if NPY_SIZEOF_COMPLEX_LONGDOUBLE != NPY_SIZEOF_COMPLEX_DOUBLE +inline longdouble_t IM(npy_clongdouble *c) { return NPY_CLONGDOUBLE_GET_IMAG(c); } +#endif +inline void SETRE(npy_cfloat *c, float real) { NPY_CFLOAT_SET_REAL(c, real); } +inline void SETRE(npy_cdouble *c, double real) { NPY_CDOUBLE_SET_REAL(c, real); } +#if NPY_SIZEOF_COMPLEX_LONGDOUBLE != NPY_SIZEOF_COMPLEX_DOUBLE +inline void SETRE(npy_clongdouble *c, double real) { NPY_CLONGDOUBLE_SET_REAL(c, real); } +#endif +inline void SETIM(npy_cfloat *c, float real) { NPY_CFLOAT_SET_IMAG(c, real); } +inline void SETIM(npy_cdouble *c, double real) { NPY_CDOUBLE_SET_IMAG(c, real); } +#if NPY_SIZEOF_COMPLEX_LONGDOUBLE != NPY_SIZEOF_COMPLEX_DOUBLE +inline void SETIM(npy_clongdouble *c, double real) { NPY_CLONGDOUBLE_SET_IMAG(c, real); } +#endif template static inline typ @@ -1057,8 +1106,8 @@ mult(typ op1, typ op2) { typ rv; - SETRE(rv, RE(op1)*RE(op2) - IM(op1)*IM(op2)); - SETIM(rv, RE(op1)*IM(op2) + IM(op1)*RE(op2)); + SETRE(&rv, RE(&op1)*RE(&op2) - IM(&op1)*IM(&op2)); + SETIM(&rv, RE(&op1)*IM(&op2) + IM(&op1)*RE(&op2)); return rv; } @@ -1079,8 +1128,8 @@ slogdet_from_factored_diagonal(typ* src, { basetyp abs_element = npyabs(*src); typ sign_element; - SETRE(sign_element, RE(*src) / abs_element); - SETIM(sign_element, IM(*src) / abs_element); + SETRE(&sign_element, RE(src) / abs_element); + SETIM(&sign_element, IM(src) / abs_element); sign_acc = mult(sign_acc, sign_element); logdet_acc += npylog(abs_element); @@ -1096,14 +1145,10 @@ static inline typ det_from_slogdet(typ sign, basetyp logdet) { typ tmp; - SETRE(tmp, npyexp(logdet)); - SETIM(tmp, numeric_limits::zero); + SETRE(&tmp, npyexp(logdet)); + SETIM(&tmp, numeric_limits::zero); return mult(sign, tmp); } -#undef RE -#undef IM -#undef SETRE -#undef SETIM /* As in the linalg package, the determinant is computed via LU factorization @@ -3986,7 +4031,7 @@ abs2(typ *p, npy_intp n, complex_trait) { basetype_t res = 0; for (i = 0; i < n; i++) { typ el = p[i]; - res += el.real()*el.real() + el.imag()*el.imag(); + res += RE(&el)*RE(&el) + IM(&el)*IM(&el); } return res; }