diff --git a/numpy/core/include/numpy/npy_common.h b/numpy/core/include/numpy/npy_common.h index d5a586c56a39..93b303d9c2fa 100644 --- a/numpy/core/include/numpy/npy_common.h +++ b/numpy/core/include/numpy/npy_common.h @@ -28,6 +28,7 @@ #ifndef NPY_USE_NEW_CASTINGIMPL #define NPY_USE_NEW_CASTINGIMPL 0 #endif + /* * using static inline modifiers when defining npy_math functions * allows the compiler to make optimizations when possible diff --git a/numpy/core/src/common/npy_config.h b/numpy/core/src/common/npy_config.h index 61cc3c7f18d4..4d66d533c10b 100644 --- a/numpy/core/src/common/npy_config.h +++ b/numpy/core/src/common/npy_config.h @@ -91,6 +91,60 @@ #endif #endif /* defined(_MSC_VER) && defined(__INTEL_COMPILER) */ +/* Disable functions that give undesired floating-point outputs on + Cygwin. */ +#ifdef __CYGWIN__ + +#undef HAVE_CABS +#undef HAVE_CABSF +#undef HAVE_CABSL + +/* These work for me in C++, even for the failing test case (2 ** 29), + but the tests fail. No idea if the functions I'm getting are used + or not. */ +#undef HAVE_LOG2 +#undef HAVE_LOG2F +#undef HAVE_LOG2L + +/* Complex square root does not use sign of zero to find branch + cuts. */ +#undef HAVE_CSQRT +#undef HAVE_CSQRTF +#undef HAVE_CSQRTL + +/* C++ Real asinh works fine, complex asinh says asinh(1e-20+0j) = + 0 */ +#undef HAVE_CASINH +#undef HAVE_CASINHF +#undef HAVE_CASINHL + +/* _check_branch_cut(np.arcsin, ...) fails */ +#undef HAVE_CASIN +#undef HAVE_CASINF +#undef HAVE_CASINL + +/* Branch cuts for arccosine also fail */ +#undef HAVE_CACOS +#undef HAVE_CACOSF +#undef HAVE_CACOSL + +/* Branch cuts for arctan fail as well */ +#undef HAVE_CATAN +#undef HAVE_CATANF +#undef HAVE_CATANL + +/* check_loss_of_precision fails in arctanh */ +#undef HAVE_CATANH +#undef HAVE_CATANHF +#undef HAVE_CATANHL + +/* modfl segfaults on 64-bit Cygwin 3.1.5-3.1.7 */ +#ifdef __x86_64__ +#undef HAVE_MODFL +#endif + +#endif + /* powl gives zero division warning on OS X, see gh-8307 */ #if defined(HAVE_POWL) && defined(NPY_OS_DARWIN) #undef HAVE_POWL diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py index 048b1688f2a7..e4e6a74b623d 100644 --- a/numpy/core/tests/test_multiarray.py +++ b/numpy/core/tests/test_multiarray.py @@ -8576,23 +8576,36 @@ class MyAlwaysEqualNew(MyAlwaysEqual): assert_equal(array != my_always_equal, 'ne') -def test_npymath_complex(): +@pytest.mark.parametrize( + ["fun", "npfun", "x", "y", "dtype"], + [ + pytest.param( + fun, npfun, x, y, dtype, marks=pytest.mark.xfail( + sys.platform == "cygwin" and + dtype in (np.clongdouble,) and + fun == _multiarray_tests.npy_cabs and + np.isinf([x, y]).any() and np.isnan([x, y]).any(), + reason='abs(inf+nanj) short-circuits to inf', + strict=True, + ) + ) + for (fun, npfun), x, y, dtype in itertools.product( + [ + (_multiarray_tests.npy_cabs, np.absolute), + (_multiarray_tests.npy_carg, np.angle), + ], + [1, np.inf, -np.inf, np.nan], + [1, np.inf, -np.inf, np.nan], + [np.complex64, np.complex128, np.clongdouble], + ) + ], +) +def test_npymath_complex(fun, npfun, x, y, dtype): # Smoketest npymath functions - from numpy.core._multiarray_tests import ( - npy_cabs, npy_carg) - - funcs = {npy_cabs: np.absolute, - npy_carg: np.angle} - vals = (1, np.inf, -np.inf, np.nan) - types = (np.complex64, np.complex128, np.clongdouble) - - for fun, npfun in funcs.items(): - for x, y in itertools.product(vals, vals): - for t in types: - z = t(complex(x, y)) - got = fun(z) - expected = npfun(z) - assert_allclose(got, expected) + z = dtype(complex(x, y)) + 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 866a96e31c1c..1af22a4bb291 100644 --- a/numpy/core/tests/test_numeric.py +++ b/numpy/core/tests/test_numeric.py @@ -636,6 +636,12 @@ def assert_op_raises_fpe(self, fpeerr, flop, sc1, sc2): self.assert_raises_fpe(fpeerr, flop, sc1, sc2[()]) self.assert_raises_fpe(fpeerr, flop, sc1[()], sc2[()]) + @pytest.mark.xfail( + sys.platform == "cygwin", + reason="complex256(2 ** (2 ** nexp_256)) is inf+infj without OverflowError", + raises=AssertionError, + strict=True, + ) def test_floating_exceptions(self): # Test basic arithmetic function errors with np.errstate(all='raise'): diff --git a/numpy/core/tests/test_scalarmath.py b/numpy/core/tests/test_scalarmath.py index d8529418e58b..53f978bf6d0d 100644 --- a/numpy/core/tests/test_scalarmath.py +++ b/numpy/core/tests/test_scalarmath.py @@ -653,32 +653,67 @@ def test_result(self): class TestAbs: - def _test_abs_func(self, absfunc): - for tp in floating_types + complex_floating_types: - x = tp(-1.5) - assert_equal(absfunc(x), 1.5) - x = tp(0.0) - res = absfunc(x) - # assert_equal() checks zero signedness - assert_equal(res, 0.0) - x = tp(-0.0) - res = absfunc(x) - assert_equal(res, 0.0) - - x = tp(np.finfo(tp).max) - assert_equal(absfunc(x), x.real) - - x = tp(np.finfo(tp).tiny) - assert_equal(absfunc(x), x.real) - - x = tp(np.finfo(tp).min) - assert_equal(absfunc(x), -x.real) - - def test_builtin_abs(self): - self._test_abs_func(abs) - - def test_numpy_abs(self): - self._test_abs_func(np.abs) + def _test_abs_func(self, absfunc, tp): + x = tp(-1.5) + assert_equal(absfunc(x), 1.5) + x = tp(0.0) + res = absfunc(x) + # assert_equal() checks zero signedness + assert_equal(res, 0.0) + x = tp(-0.0) + res = absfunc(x) + assert_equal(res, 0.0) + + x = tp(np.finfo(tp).max) + assert_equal(absfunc(x), x.real) + + x = tp(np.finfo(tp).tiny) + assert_equal(absfunc(x), x.real) + + x = tp(np.finfo(tp).min) + assert_equal(absfunc(x), -x.real) + + @pytest.mark.parametrize( + "dtype", + [ + pytest.param( + dtype, + marks=( + pytest.mark.xfail( + sys.platform == 'cygwin', + reason='abs(np.complex256.max) overflows', + raises=AssertionError, + strict=True, + ) + if sys.platform == 'cygwin' and dtype == np.complex256 else () + ) + ) + for dtype in floating_types + complex_floating_types + ], + ) + def test_builtin_abs(self, dtype): + self._test_abs_func(abs, dtype) + + @pytest.mark.parametrize( + "dtype", + [ + pytest.param( + dtype, + marks=( + pytest.mark.xfail( + sys.platform == 'cygwin', + reason='abs(np.complex256.max) overflows', + raises=RuntimeWarning, + strict=True, + ) + if sys.platform == 'cygwin' and dtype == np.complex256 else () + ) + ) + for dtype in floating_types + complex_floating_types + ], + ) + def test_numpy_abs(self, dtype): + self._test_abs_func(np.abs, dtype) class TestBitShifts: diff --git a/numpy/core/tests/test_umath.py b/numpy/core/tests/test_umath.py index bc72aa862a73..b54657c847f8 100644 --- a/numpy/core/tests/test_umath.py +++ b/numpy/core/tests/test_umath.py @@ -3011,6 +3011,11 @@ def test_precisions_consistent(self): assert_almost_equal(fcf, fcd, decimal=6, err_msg='fch-fcd %s' % f) assert_almost_equal(fcl, fcd, decimal=15, err_msg='fch-fcl %s' % f) + @pytest.mark.xfail( + sys.platform == 'cygwin', + reason='Cygwin does not use the sign of zero for branch cuts along an axis', + strict=True, + ) def test_branch_cuts(self): # check branch cuts and continuity on them _check_branch_cut(np.log, -0.5, 1j, 1, -1, True) @@ -3036,6 +3041,11 @@ def test_branch_cuts(self): _check_branch_cut(np.arccosh, [0-2j, 2j, 2], [1, 1, 1j], 1, 1) _check_branch_cut(np.arctanh, [0-2j, 2j, 0], [1, 1, 1j], 1, 1) + @pytest.mark.xfail( + sys.platform == 'cygwin', + reason='Cygwin does not use sign of zero for branch cuts along an axis', + strict=True, + ) def test_branch_cuts_complex64(self): # check branch cuts and continuity on them _check_branch_cut(np.log, -0.5, 1j, 1, -1, True, np.complex64) diff --git a/numpy/distutils/fcompiler/gnu.py b/numpy/distutils/fcompiler/gnu.py index 68d1501eee6a..7127aef912b5 100644 --- a/numpy/distutils/fcompiler/gnu.py +++ b/numpy/distutils/fcompiler/gnu.py @@ -246,8 +246,10 @@ def get_flags_arch(self): return [] def runtime_library_dir_option(self, dir): - if sys.platform == 'win32': - # Linux/Solaris/Unix support RPATH, Windows does not + if ( + sys.platform[:3] == 'aix' or sys.platform == 'win32' or sys.platform == 'cygwin' + ): + # Linux/Solaris/Unix support RPATH, Windows and AIX do not raise NotImplementedError # TODO: could use -Xlinker here, if it's supported diff --git a/numpy/distutils/tests/test_system_info.py b/numpy/distutils/tests/test_system_info.py index ec15126f7f7b..fe44ef139602 100644 --- a/numpy/distutils/tests/test_system_info.py +++ b/numpy/distutils/tests/test_system_info.py @@ -277,7 +277,7 @@ def test_overrides(self): # Also, the values will be taken from a section named '[DEFAULT]' with open(cfg, 'r') as fid: - dflt = fid.read().replace('mkl', 'DEFAULT') + dflt = fid.read().replace('[mkl]', '[DEFAULT]', 1) with open(cfg, 'w') as fid: fid.write(dflt) info = mkl_info() diff --git a/numpy/f2py/tests/test_compile_function.py b/numpy/f2py/tests/test_compile_function.py index f76fd644807c..b25349685033 100644 --- a/numpy/f2py/tests/test_compile_function.py +++ b/numpy/f2py/tests/test_compile_function.py @@ -10,6 +10,7 @@ import numpy.f2py from numpy.testing import assert_equal +from numpy.testing._private.utils import IS_32BIT_CYGWIN from . import util @@ -26,6 +27,8 @@ def setup_module(): "extra_args", [['--noopt', '--debug'], '--noopt --debug', ''] ) @pytest.mark.leaks_references(reason="Imported module seems never deleted.") +@pytest.mark.xfail(IS_32BIT_CYGWIN, reason="Random fork failures", + raises=BlockingIOError) def test_f2py_init_compile(extra_args): # flush through the f2py __init__ compile() function code path as a # crude test for input handling following migration from @@ -83,6 +86,8 @@ def test_f2py_init_compile(extra_args): del sys.modules[modname] +@pytest.mark.xfail(IS_32BIT_CYGWIN, reason="Random fork failures", + raises=BlockingIOError) def test_f2py_init_compile_failure(): # verify an appropriate integer status value returned by # f2py.compile() when invalid Fortran is provided @@ -111,6 +116,8 @@ def test_f2py_init_compile_bad_cmd(): @pytest.mark.parametrize('fsource', ['program test_f2py\nend program test_f2py', b'program test_f2py\nend program test_f2py',]) +@pytest.mark.xfail(IS_32BIT_CYGWIN, reason="Random fork failures", + raises=BlockingIOError) def test_compile_from_strings(tmpdir, fsource): # Make sure we can compile str and bytes gh-12796 cwd = os.getcwd() diff --git a/numpy/f2py/tests/util.py b/numpy/f2py/tests/util.py index d5fa76fedf27..f867d6db7021 100644 --- a/numpy/f2py/tests/util.py +++ b/numpy/f2py/tests/util.py @@ -17,6 +17,7 @@ from numpy.compat import asbytes, asstr from numpy.testing import temppath +from numpy.testing._private.utils import IS_32BIT_CYGWIN from importlib import import_module # @@ -317,6 +318,12 @@ class F2PyTest: module = None module_name = None + # Pytest seems to ignore this, but I'm not sure where else to put + # it, besides trying to make a metaclass that decorates every + # method of a subclass of F2PyTest + @pytest.mark.xfail(IS_32BIT_CYGWIN, + reason='Fork() randomly fails on cygwin', + raises=BlockingIOError) def setup(self): if sys.platform == 'win32': pytest.skip('Fails with MinGW64 Gfortran (Issue #9673)') diff --git a/numpy/linalg/tests/test_linalg.py b/numpy/linalg/tests/test_linalg.py index 21fab58e1d42..6fc5ab5d65f1 100644 --- a/numpy/linalg/tests/test_linalg.py +++ b/numpy/linalg/tests/test_linalg.py @@ -1837,6 +1837,9 @@ def test_xerbla_override(): @pytest.mark.slow +@pytest.mark.xfail(sys.platform == 'cygwin', + reason='Fork() fails randomly on cygwin', + raises=BlockingIOError) def test_sdot_bug_8577(): # Regression test that loading certain other libraries does not # result to wrong results in float32 linear algebra. diff --git a/numpy/random/src/distributions/random_hypergeometric.c b/numpy/random/src/distributions/random_hypergeometric.c index 0da49bd62ad0..668e10a9f483 100644 --- a/numpy/random/src/distributions/random_hypergeometric.c +++ b/numpy/random/src/distributions/random_hypergeometric.c @@ -1,6 +1,6 @@ +#include #include "numpy/random/distributions.h" #include "logfactorial.h" -#include /* * Generate a sample from the hypergeometric distribution. diff --git a/numpy/random/tests/test_extending.py b/numpy/random/tests/test_extending.py index 99a819efb576..0080b70be382 100644 --- a/numpy/random/tests/test_extending.py +++ b/numpy/random/tests/test_extending.py @@ -5,6 +5,7 @@ import sys import warnings import numpy as np +from numpy.testing._private.utils import IS_32BIT_CYGWIN try: import cffi @@ -42,6 +43,9 @@ @pytest.mark.skipif(cython is None, reason="requires cython") @pytest.mark.slow +@pytest.mark.xfail(IS_32BIT_CYGWIN, + reason="Random fork() failures", + raises=BlockingIOError) def test_cython(tmp_path): srcdir = os.path.join(os.path.dirname(__file__), '..') shutil.copytree(srcdir, tmp_path / 'random') diff --git a/numpy/testing/_private/utils.py b/numpy/testing/_private/utils.py index b4d42728e3cd..519893aa7ac1 100644 --- a/numpy/testing/_private/utils.py +++ b/numpy/testing/_private/utils.py @@ -35,7 +35,7 @@ 'SkipTest', 'KnownFailureException', 'temppath', 'tempdir', 'IS_PYPY', 'HAS_REFCOUNT', 'suppress_warnings', 'assert_array_compare', '_assert_valid_refcount', '_gen_alignment_data', 'assert_no_gc_cycles', - 'break_cycles', 'HAS_LAPACK64' + 'break_cycles', 'HAS_LAPACK64', 'IS_32BIT_CYGWIN' ] @@ -48,6 +48,7 @@ class KnownFailureException(Exception): verbose = 0 IS_PYPY = platform.python_implementation() == 'PyPy' +IS_32BIT_CYGWIN = (sys.platform == 'cygwin' and (sys.maxsize >> 30) == 1) HAS_REFCOUNT = getattr(sys, 'getrefcount', None) is not None HAS_LAPACK64 = numpy.linalg.lapack_lite._ilp64 diff --git a/numpy/tests/test_public_api.py b/numpy/tests/test_public_api.py index 69430eeda089..711f81659f00 100644 --- a/numpy/tests/test_public_api.py +++ b/numpy/tests/test_public_api.py @@ -7,6 +7,7 @@ import numpy as np import numpy +from numpy.testing._private.utils import IS_32BIT_CYGWIN import pytest try: @@ -77,6 +78,8 @@ def test_numpy_namespace(): @pytest.mark.parametrize('name', ['testing', 'Tester']) +@pytest.mark.xfail(IS_32BIT_CYGWIN, reason="Random fork failures", + raises=BlockingIOError) def test_import_lazy_import(name): """Make sure we can actually use the modules we lazy load. diff --git a/numpy/tests/test_scripts.py b/numpy/tests/test_scripts.py index e67a829471dc..2e3b1ea1dd4e 100644 --- a/numpy/tests/test_scripts.py +++ b/numpy/tests/test_scripts.py @@ -10,6 +10,7 @@ import numpy as np from numpy.testing import assert_equal +from numpy.testing._private.utils import IS_32BIT_CYGWIN is_inplace = isfile(pathjoin(dirname(np.__file__), '..', 'setup.py')) @@ -41,6 +42,8 @@ def test_f2py(f2py_cmd): assert_equal(stdout.strip(), np.__version__.encode('ascii')) +@pytest.mark.xfail(IS_32BIT_CYGWIN, reason="Random fork failures", + raises=BlockingIOError) def test_pep338(): stdout = subprocess.check_output([sys.executable, '-mnumpy.f2py', '-v']) assert_equal(stdout.strip(), np.__version__.encode('ascii'))