Skip to content

Commit 09d5154

Browse files
committed
Relax sin/cos ULP test for float32 on non-FMA
Allow up to 3 ULP error for float32 sin/cos when native FMA is not available.
1 parent ab3559f commit 09d5154

2 files changed

Lines changed: 26 additions & 4 deletions

File tree

numpy/_core/tests/test_umath.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
from numpy.testing._private.utils import (
3535
LONG_DOUBLE_IS_IBM_DOUBLE_DOUBLE,
3636
_glibc_older_than,
37+
_ufunc_has_fma,
3738
)
3839

3940
UFUNCS = [obj for obj in np._core.umath.__dict__.values()
@@ -2202,19 +2203,30 @@ def test_sincos_float32(self):
22022203
# this is known to be problematic on old glibc, so skip it there
22032204
x_f32[index] = np.float32(10E+10 * np.random.rand(M))
22042205
x_f64 = np.float64(x_f32)
2205-
assert_array_max_ulp(np.sin(x_f32), np.float32(np.sin(x_f64)), maxulp=2)
2206-
assert_array_max_ulp(np.cos(x_f32), np.float32(np.cos(x_f64)), maxulp=2)
2206+
# numpy-simd-rounding gives ~3 ulp when fma is not available and kLowAccuracy
2207+
# been set in the precision mode
2208+
maxulp_f32 = 2 if _ufunc_has_fma(np.sin, np.float32) else 3
2209+
assert_array_max_ulp(
2210+
np.sin(x_f32),
2211+
np.float32(np.sin(x_f64)),
2212+
maxulp=maxulp_f32
2213+
)
2214+
assert_array_max_ulp(
2215+
np.cos(x_f32),
2216+
np.float32(np.cos(x_f64)),
2217+
maxulp=maxulp_f32
2218+
)
22072219
# test aliasing(issue #17761)
22082220
tx_f32 = x_f32.copy()
22092221
assert_array_max_ulp(
22102222
np.sin(x_f32, out=x_f32),
22112223
np.float32(np.sin(x_f64)),
2212-
maxulp=2,
2224+
maxulp=maxulp_f32,
22132225
)
22142226
assert_array_max_ulp(
22152227
np.cos(tx_f32, out=tx_f32),
22162228
np.float32(np.cos(x_f64)),
2217-
maxulp=2,
2229+
maxulp=maxulp_f32,
22182230
)
22192231

22202232
def test_strided_float32(self):

numpy/testing/_private/utils.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2733,6 +2733,16 @@ def check_free_memory(free_bytes):
27332733
return msg if mem_free < free_bytes else None
27342734

27352735

2736+
# avx2 implies fma
2737+
_fma_pattern = re.compile("fma|avx2|avx512|vsx|vx|asimd|vpfv4|rvv|lsx", re.IGNORECASE)
2738+
2739+
def _ufunc_has_fma(ufunc, dtype) -> bool:
2740+
"""Check if a ufunc has SIMD kernel with native FMA support for a given dtype."""
2741+
ufunc_name = ufunc.__name__
2742+
res = np.lib.introspect.opt_func_info(ufunc_name, signature=dtype.__name__)
2743+
dres = res[ufunc_name]
2744+
return all(bool(_fma_pattern.search(v["current"])) for v in dres.values())
2745+
27362746
def _parse_size(size_str):
27372747
"""Convert memory size strings ('12 GB' etc.) to float"""
27382748
suffixes = {'': 1, 'b': 1,

0 commit comments

Comments
 (0)