From 9f1dd221968bfce597c5d8e214e83679c1bd6188 Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Fri, 20 Oct 2023 21:12:24 +0200 Subject: [PATCH] BLD: clean up incorrect-but-hardcoded define for `strtold_l` check. GNU-specific and missing on many platforms, see https://www.gnu.org/software///gnulib/manual/html_node/strtold_005fl.html If it does go missing, the only problem seems to be some minor changes in long double printing code, failing two tests: ``` ______________________________ test_str_roundtrip ______________________________ @pytest.mark.skipif(IS_MUSL, reason="test flaky on musllinux") @pytest.mark.skipif(LD_INFO.precision + 2 >= repr_precision, reason="repr precision not enough to show eps") def test_str_roundtrip(): # We will only see eps in repr if within printing precision. o = 1 + LD_INFO.eps > assert_equal(np.longdouble(str(o)), o, "str was %s" % str(o)) E AssertionError: E Items are not equal: str was 1.0000000000000000001 E ACTUAL: np.longdouble('1.0') E DESIRED: np.longdouble('1.0000000000000000001') o = np.longdouble('1.0000000000000000001') numpy/_core/tests/test_longdouble.py:43: AssertionError ____________________ TestRealScalars.test_dragon4_interface ____________________ self = def test_dragon4_interface(self): tps = [np.float16, np.float32, np.float64] # test is flaky for musllinux on np.float128 if hasattr(np, 'float128') and not IS_MUSL: tps.append(np.float128) fpos = np.format_float_positional fsci = np.format_float_scientific for tp in tps: # test padding assert_equal(fpos(tp('1.0'), pad_left=4, pad_right=4), " 1. ") assert_equal(fpos(tp('-1.0'), pad_left=4, pad_right=4), " -1. ") > assert_equal(fpos(tp('-10.2'), pad_left=4, pad_right=4), " -10.2 ") E AssertionError: E Items are not equal: E ACTUAL: ' -10.1999999999999992895' E DESIRED: ' -10.2 ' fpos = fsci = self = tp = tps = [, , , ] numpy/_core/tests/test_scalarprint.py:276: AssertionError =========================== short test summary info ============================ FAILED numpy/_core/tests/test_longdouble.py::test_str_roundtrip - AssertionError: Items are not equal: str was 1.0000000000000000001 ACTUAL: np.longdouble('1.0') DESIRED: np.longdouble('1.0000000000000000001') FAILED numpy/_core/tests/test_scalarprint.py::TestRealScalars::test_dragon4_interface - AssertionError: Items are not equal: ACTUAL: ' -10.1999999999999992895' DESIRED: ' -10.2 ' ``` put GNU-source above locale.h fix issue in numpyos.c --- numpy/_core/feature_detection_locale.h | 2 -- numpy/_core/meson.build | 46 ++++++++------------------ numpy/_core/src/common/numpyos.c | 3 ++ 3 files changed, 17 insertions(+), 34 deletions(-) delete mode 100644 numpy/_core/feature_detection_locale.h diff --git a/numpy/_core/feature_detection_locale.h b/numpy/_core/feature_detection_locale.h deleted file mode 100644 index 59e78936d8d8..000000000000 --- a/numpy/_core/feature_detection_locale.h +++ /dev/null @@ -1,2 +0,0 @@ -#pragma GCC diagnostic ignored "-Wnonnull" -long double strtold_l(const char*, char**, locale_t); diff --git a/numpy/_core/meson.build b/numpy/_core/meson.build index 56dabf9c168a..8ed696531b4c 100644 --- a/numpy/_core/meson.build +++ b/numpy/_core/meson.build @@ -255,37 +255,6 @@ foreach filefunc_maybe: optional_file_funcs endif endforeach -# Optional locale function -have_strtold_l = cc.has_function('strtold_l', include_directories: inc_curdir, - prefix:''' - #include - #include - #include "feature_detection_locale.h" -''') -if not have_strtold_l - # Retry with locale.h, seems to vary across Linux distros - have_strtold_l = cc.has_function('strtold_l', include_directories: inc_curdir, - prefix:''' - #include - #include - #include "feature_detection_locale.h" - ''') -endif -if have_strtold_l - cdata.set10('HAVE_STRTOLD_L', true) -else - # FIXME: this is wrong! the HAVE_ define should not exist, or it'll be - # interpreted as the function being available (true/false does nothing, see - # note on HAVE_ defines higher up). This is necessary though in order to make - # the Linux CI job pass. So either the check is wrong somehow, or this - # function is not available in CI. For the latter there is a fallback path, - # but that is broken because we don't have the exact long double - # representation checks. - if cc.get_argument_syntax() != 'msvc' - cdata.set10('HAVE_STRTOLD_L', false) - endif -endif - # Other optional functions optional_misc_funcs = [ 'backtrace', @@ -303,7 +272,7 @@ endforeach # SSE headers only enabled automatically on amd64/x32 builds optional_headers = [ 'features.h', # for glibc version linux - 'xlocale.h', # see GH#8367 + 'xlocale.h', # removed in glibc 2.26, but may still be useful - see gh-8367 'dlfcn.h', # dladdr 'execinfo.h', # backtrace 'libunwind.h', # backtrace for LLVM/Clang using libunwind @@ -315,6 +284,19 @@ foreach header: optional_headers endif endforeach +# Optional locale function - GNU-specific +_strtold_prefix = ''' +#define _GNU_SOURCE +#include +#include +''' +if cdata.get('HAVE_XLOCALE_H', 0) == 1 + _strtold_prefix += '#include ' +endif +if cc.has_function('strtold_l', include_directories: inc_curdir, prefix: _strtold_prefix) + cdata.set10('HAVE_STRTOLD_L', true) +endif + # Optional compiler attributes # TODO: this doesn't work with cc.has_function_attribute, see # https://github.com/mesonbuild/meson/issues/10732 diff --git a/numpy/_core/src/common/numpyos.c b/numpy/_core/src/common/numpyos.c index 9c3eb7bd0298..6ccd380fb4ed 100644 --- a/numpy/_core/src/common/numpyos.c +++ b/numpy/_core/src/common/numpyos.c @@ -11,6 +11,9 @@ #include "npy_pycompat.h" +#if defined(HAVE_STRTOLD_L) && !defined(_GNU_SOURCE) +# define _GNU_SOURCE +#endif #include #include