diff --git a/numpy/core/meson.build b/numpy/core/meson.build index 473362f1b7e9..a1fc7e9d8a84 100644 --- a/numpy/core/meson.build +++ b/numpy/core/meson.build @@ -149,20 +149,32 @@ endif # Mandatory functions: if not found, fail the build # Some of these can still be blocklisted if the C99 implementation # is buggy, see numpy/core/src/common/npy_config.h -mandatory_funcs = [ +mandatory_math_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', + 'rint', 'trunc', 'exp2', 'copysign', 'nextafter', 'cbrt', 'log2', 'pow', 'hypot', 'atan2', - 'csin', 'csinh', 'ccos', 'ccosh', 'ctan', 'ctanh', - 'creal', 'cimag', 'conj' ] -foreach func: mandatory_funcs - if not cc.has_function(func) - error('Function `{func}` not found') +foreach func: mandatory_math_funcs + if not cc.has_function(func, prefix: '#include ', dependencies: m_dep) + error(f'Function `@func@` not found') + endif +endforeach + +mandatory_complex_math_funcs = [ + 'csin', 'csinh', 'ccos', 'ccosh', 'ctan', 'ctanh', 'creal', 'cimag', 'conj' +] +foreach func: mandatory_complex_math_funcs + if not cc.has_function(func, prefix: '#include ', dependencies: m_dep) + error(f'Function `@func@` not found') + endif +endforeach + +foreach func: ['strtoll', 'strtoull'] + if not cc.has_function(func, prefix: '#include ') + error(f'Function `@func@` not found') endif endforeach @@ -177,13 +189,13 @@ c99_complex_funcs = [ foreach func: c99_complex_funcs func_single = func + 'f' func_longdouble = func + 'l' - if cc.has_function(func) + if cc.has_function(func, prefix: '#include ', dependencies: m_dep) cdata.set10('HAVE_' + func.to_upper(), true) endif - if cc.has_function(func_single) + if cc.has_function(func_single, prefix: '#include ', dependencies: m_dep) cdata.set10('HAVE_' + func_single.to_upper(), true) endif - if cc.has_function(func_longdouble) + if cc.has_function(func_longdouble, prefix: '#include ', dependencies: m_dep) cdata.set10('HAVE_' + func_longdouble.to_upper(), true) endif endforeach @@ -192,7 +204,7 @@ endforeach # libnpymath as a C99 compat layer, these may still be relevant. c99_macros = ['isfinite', 'isinf', 'isnan', 'signbit'] foreach macro: c99_macros - if cc.has_function(macro) + if cc.has_function(macro, prefix: '#include ', dependencies: m_dep) cdata.set10('NPY_HAVE_DECL_' + macro.to_upper(), true) if not cc.has_header_symbol('Python.h', macro, dependencies: py_dep) # Add in config.h as well, except if it will clash with Python's config.h content diff --git a/numpy/core/src/npymath/npy_math_complex.c.src b/numpy/core/src/npymath/npy_math_complex.c.src index eb9d810b7d82..8e1decbfd9d5 100644 --- a/numpy/core/src/npymath/npy_math_complex.c.src +++ b/numpy/core/src/npymath/npy_math_complex.c.src @@ -158,7 +158,9 @@ npy_carg@c@(@ctype@ z) #define SCALED_CEXP_LOWERL 11357.216553474703895L #define SCALED_CEXP_UPPERL 22756.021937783004509L -#if !defined(HAVE_CEXP@C@) +#if !defined(HAVE_CSINH@C@) || \ + !defined(HAVE_CCOSH@C@) || \ + !defined(HAVE_CEXP@C@) static @ctype@ diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py index a2ddc4f8341e..ace40049fd83 100644 --- a/numpy/core/tests/test_multiarray.py +++ b/numpy/core/tests/test_multiarray.py @@ -9723,9 +9723,12 @@ def test_ragged_comparison_fails(op): def test_npymath_complex(fun, npfun, x, y, test_dtype): # Smoketest npymath functions z = test_dtype(complex(x, y)) - got = fun(z) - expected = npfun(z) - assert_allclose(got, expected) + with np.errstate(invalid='ignore'): + # Fallback implementations may emit a warning for +-inf (see gh-24876): + # RuntimeWarning: invalid value encountered in absolute + got = fun(z) + expected = npfun(z) + assert_allclose(got, expected) def test_npymath_real(): diff --git a/numpy/core/tests/test_numeric.py b/numpy/core/tests/test_numeric.py index 832a47c926cf..d2d041f71ef2 100644 --- a/numpy/core/tests/test_numeric.py +++ b/numpy/core/tests/test_numeric.py @@ -645,6 +645,11 @@ def assert_op_raises_fpe(self, fpeerr, flop, sc1, sc2): @pytest.mark.skipif(IS_WASM, reason="no wasm fp exception support") @pytest.mark.parametrize("typecode", np.typecodes["AllFloat"]) def test_floating_exceptions(self, typecode): + if 'bsd' in sys.platform and typecode in 'gG': + pytest.skip(reason="Fallback impl for (c)longdouble may not raise " + "FPE errors as expected on BSD OSes, " + "see gh-24876, gh-23379") + # Test basic arithmetic function errors with np.errstate(all='raise'): ftype = np.obj2sctype(typecode) diff --git a/numpy/core/tests/test_umath.py b/numpy/core/tests/test_umath.py index 0e07a6cb937b..5567244d14a9 100644 --- a/numpy/core/tests/test_umath.py +++ b/numpy/core/tests/test_umath.py @@ -1646,6 +1646,8 @@ def test_sinh(self): np.array(1200.0, dtype='d')) @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm") + @pytest.mark.skipif('bsd' in sys.platform, + reason="fallback implementation may not raise, see gh-2487") def test_cosh(self): in_ = [np.nan, -np.nan, np.inf, -np.inf] out = [np.nan, np.nan, np.inf, np.inf] diff --git a/numpy/core/tests/test_umath_complex.py b/numpy/core/tests/test_umath_complex.py index 8aa9a28ff48d..e54300589094 100644 --- a/numpy/core/tests/test_umath_complex.py +++ b/numpy/core/tests/test_umath_complex.py @@ -576,8 +576,8 @@ def test_array(self, stride, astype): complex(0., 0.), complex(np.nan, np.nan), complex(np.nan, np.nan)], dtype=astype) - assert_equal(np.abs(arr[::stride]), abs_true[::stride]) with np.errstate(invalid='ignore'): + assert_equal(np.abs(arr[::stride]), abs_true[::stride]) assert_equal(np.square(arr[::stride]), sq_true[::stride]) class TestComplexAbsoluteAVX: diff --git a/tools/ci/cirrus_arm.yml b/tools/ci/cirrus_arm.yml index c3daf953d751..a28f182ae8ba 100644 --- a/tools/ci/cirrus_arm.yml +++ b/tools/ci/cirrus_arm.yml @@ -96,7 +96,7 @@ macos_arm64_test_task: RUNNER_OS="macOS" SDKROOT=/Applications/Xcode-14.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk - + # NOTE: OpenBLAS is not used in this job; if that's done in the future, ensure # PKG_CONFIG_PATH points to the directory containing the openblas.pc file # that's installed with the cibw_before_build.sh command. @@ -110,8 +110,50 @@ macos_arm64_test_task: pip install -r build_requirements.txt pip install pytest pytest-xdist hypothesis typing_extensions - + spin build -- -Dallow-noblas=true spin test -j auto ccache -s + + +freebsd_test_task: + use_compute_credits: $CIRRUS_USER_COLLABORATOR == 'true' + compute_engine_instance: + image_project: freebsd-org-cloud-dev + image: family/freebsd-13-2 + platform: freebsd + cpu: 1 + memory: 4G + + install_devtools_script: | + pkg install -y git bash ninja ccache + + <<: *MODIFIED_CLONE + + ccache_cache: + folder: .ccache + populate_script: + - mkdir -p .ccache + fingerprint_key: ccache-freebsd + + prepare_env_script: | + # Create a venv (the `source` command needs bash, not the default sh shell) + chsh -s /usr/local/bin/bash + python -m venv .venv + source .venv/bin/activate + # Minimal build and test requirements + python -m pip install -U pip + python -m pip install meson-python Cython pytest hypothesis + + build_script: | + chsh -s /usr/local/bin/bash + source .venv/bin/activate + python -m pip install . --no-build-isolation -v -Csetup-args="-Dallow-noblas=true" + + test_script: | + chsh -s /usr/local/bin/bash + source .venv/bin/activate + cd tools + python -m pytest --pyargs numpy -m "not slow" + ccache -s