aboutsummaryrefslogtreecommitdiff
path: root/math/test/ulp.h
diff options
context:
space:
mode:
authorAndrew Turner <andrew@FreeBSD.org>2025-01-10 10:34:52 +0000
committerAndrew Turner <andrew@FreeBSD.org>2025-01-10 10:39:34 +0000
commit9d1de25930735261c16ed874a933b4c1f1d9041e (patch)
treeb0cac1c933cc1ecb885c7e757b89ffbf13f1f012 /math/test/ulp.h
parentedc5c0de794f521eb620d2b6cbaee2434442a8f3 (diff)
Diffstat (limited to 'math/test/ulp.h')
-rw-r--r--math/test/ulp.h41
1 files changed, 24 insertions, 17 deletions
diff --git a/math/test/ulp.h b/math/test/ulp.h
index b0bc59aeef8d..de122257d3b1 100644
--- a/math/test/ulp.h
+++ b/math/test/ulp.h
@@ -1,13 +1,13 @@
/*
* Generic functions for ULP error estimation.
*
- * Copyright (c) 2019-2023, Arm Limited.
+ * Copyright (c) 2019-2024, Arm Limited.
* SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
*/
/* For each different math function type,
T(x) should add a different suffix to x.
- RT(x) should add a return type specific suffix to x. */
+ RT(x) should add a return type specific suffix to x. */
#ifdef NEW_RT
#undef NEW_RT
@@ -47,8 +47,12 @@ static double RT (ulperr) (RT (float) got, const struct RT (ret) * p, int r,
if (RT(asuint) (got) == RT(asuint) (want))
return 0.0;
if (isnan (got) && isnan (want))
- /* Ignore sign of NaN. */
+ /* Ignore sign of NaN, and signalling-ness for MPFR. */
+# if USE_MPFR
+ return 0;
+# else
return RT (issignaling) (got) == RT (issignaling) (want) ? 0 : INFINITY;
+# endif
if (signbit (got) != signbit (want))
{
/* Fall through to ULP calculation if ignoring sign of zero and at
@@ -80,7 +84,7 @@ static double RT (ulperr) (RT (float) got, const struct RT (ret) * p, int r,
// TODO: incorrect when got vs want cross a powof2 boundary
/* error = got > want
? got - want - tail ulp - 0.5 ulp
- : got - want - tail ulp + 0.5 ulp; */
+ : got - want - tail ulp + 0.5 ulp. */
d = got - want;
e = d > 0 ? -p->tail - 0.5 : -p->tail + 0.5;
}
@@ -108,32 +112,34 @@ static int RT(isok_nofenv) (RT(float) ygot, RT(float) ywant)
}
#endif
-static inline void T(call_fenv) (const struct fun *f, struct T(args) a, int r,
- RT(float) * y, int *ex)
+static inline void T (call_fenv) (const struct fun *f, struct T (args) a,
+ int r, RT (float) * y, int *ex,
+ const struct conf *conf)
{
if (r != FE_TONEAREST)
fesetround (r);
feclearexcept (FE_ALL_EXCEPT);
- *y = T(call) (f, a);
+ *y = T (call) (f, a, conf);
*ex = fetestexcept (FE_ALL_EXCEPT);
if (r != FE_TONEAREST)
fesetround (FE_TONEAREST);
}
-static inline void T(call_nofenv) (const struct fun *f, struct T(args) a,
- int r, RT(float) * y, int *ex)
+static inline void T (call_nofenv) (const struct fun *f, struct T (args) a,
+ int r, RT (float) * y, int *ex,
+ const struct conf *conf)
{
if (r != FE_TONEAREST)
fesetround (r);
- *y = T(call) (f, a);
+ *y = T (call) (f, a, conf);
*ex = 0;
if (r != FE_TONEAREST)
fesetround (FE_TONEAREST);
}
-static inline int T(call_long_fenv) (const struct fun *f, struct T(args) a,
- int r, struct RT(ret) * p,
- RT(float) ygot, int exgot)
+static inline int T (call_long_fenv) (const struct fun *f, struct T (args) a,
+ int r, struct RT (ret) * p,
+ RT (float) ygot, int exgot)
{
if (r != FE_TONEAREST)
fesetround (r);
@@ -269,6 +275,7 @@ static int T(cmp) (const struct fun *f, struct gen *gen,
int r = conf->r;
int use_mpfr = conf->mpfr;
int fenv = conf->fenv;
+
for (;;)
{
struct RT(ret) want;
@@ -279,15 +286,15 @@ static int T(cmp) (const struct fun *f, struct gen *gen,
RT(float) ygot2;
int fail = 0;
if (fenv)
- T(call_fenv) (f, a, r, &ygot, &exgot);
+ T (call_fenv) (f, a, r, &ygot, &exgot, conf);
else
- T(call_nofenv) (f, a, r, &ygot, &exgot);
+ T (call_nofenv) (f, a, r, &ygot, &exgot, conf);
if (f->twice) {
secondcall = 1;
if (fenv)
- T(call_fenv) (f, a, r, &ygot2, &exgot2);
+ T (call_fenv) (f, a, r, &ygot2, &exgot2, conf);
else
- T(call_nofenv) (f, a, r, &ygot2, &exgot2);
+ T (call_nofenv) (f, a, r, &ygot2, &exgot2, conf);
secondcall = 0;
if (RT(asuint) (ygot) != RT(asuint) (ygot2))
{