Skip to content

Commit

Permalink
BLD: fix math func feature checks, fix FreeBSD build, add CI job (#24876
Browse files Browse the repository at this point in the history
) (#24879)

* BLD: fix incorrect feature checks for mandatory math functions

Should fix the build on FreeBSD and other OSes that are not
C99-compliant.

Closes gh-24873

* CI: add a FreeBSD job on Cirrus CI

* BUG: define `_npy_scaled_cexpl` when ccoshl/csinhl are missing

This was a regression in the 1.24.x branch, after a lot of churn
in this file. In 1.22.x/1.23.x, the conditional is the same as in
this fix.

* TST: avoid failures for FPE errors/warnings in `abs` on BSDs

Co-authored-by: Ralf Gommers <ralf.gommers@gmail.com>
  • Loading branch information
charris and rgommers committed Oct 7, 2023
1 parent d042bda commit c7e073c
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 19 deletions.
36 changes: 24 additions & 12 deletions numpy/core/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -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 <math.h>', 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 <complex.h>', dependencies: m_dep)
error(f'Function `@func@` not found')
endif
endforeach

foreach func: ['strtoll', 'strtoull']
if not cc.has_function(func, prefix: '#include <stdlib.h>')
error(f'Function `@func@` not found')
endif
endforeach

Expand All @@ -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 <complex.h>', 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 <complex.h>', 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 <complex.h>', dependencies: m_dep)
cdata.set10('HAVE_' + func_longdouble.to_upper(), true)
endif
endforeach
Expand All @@ -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 <math.h>', 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
Expand Down
4 changes: 3 additions & 1 deletion numpy/core/src/npymath/npy_math_complex.c.src
Original file line number Diff line number Diff line change
Expand Up @@ -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@
Expand Down
9 changes: 6 additions & 3 deletions numpy/core/tests/test_multiarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -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():
Expand Down
5 changes: 5 additions & 0 deletions numpy/core/tests/test_numeric.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions numpy/core/tests/test_umath.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
2 changes: 1 addition & 1 deletion numpy/core/tests/test_umath_complex.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
46 changes: 44 additions & 2 deletions tools/ci/cirrus_arm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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

0 comments on commit c7e073c

Please sign in to comment.