aboutsummaryrefslogtreecommitdiff
path: root/math/test
diff options
context:
space:
mode:
Diffstat (limited to 'math/test')
-rw-r--r--math/test/mathbench.c229
-rw-r--r--math/test/mathbench_funcs.h141
-rw-r--r--math/test/mathbench_wrappers.h302
-rw-r--r--math/test/mathtest.c12
-rw-r--r--math/test/rtest/dotest.c45
-rwxr-xr-xmath/test/runulp.sh311
-rw-r--r--math/test/test_defs.h31
-rw-r--r--math/test/testcases/directed/acos.tst17
-rw-r--r--math/test/testcases/directed/acosf.tst21
-rw-r--r--math/test/testcases/directed/acosh.tst19
-rw-r--r--math/test/testcases/directed/acoshf.tst19
-rw-r--r--math/test/testcases/directed/asin.tst24
-rw-r--r--math/test/testcases/directed/asinf.tst24
-rw-r--r--math/test/testcases/directed/asinh.tst18
-rw-r--r--math/test/testcases/directed/asinhf.tst18
-rw-r--r--math/test/testcases/directed/atan.tst22
-rw-r--r--math/test/testcases/directed/atan2.tst110
-rw-r--r--math/test/testcases/directed/atan2f.tst121
-rw-r--r--math/test/testcases/directed/atanf.tst22
-rw-r--r--math/test/testcases/directed/atanh.tst22
-rw-r--r--math/test/testcases/directed/atanhf.tst23
-rw-r--r--math/test/testcases/directed/cbrtf.tst29
-rw-r--r--math/test/testcases/directed/cosh.tst15
-rw-r--r--math/test/testcases/directed/coshf.tst15
-rw-r--r--math/test/testcases/directed/erfc.tst23
-rw-r--r--math/test/testcases/directed/erfcf.tst14
-rw-r--r--math/test/testcases/directed/expm1.tst21
-rw-r--r--math/test/testcases/directed/expm1f.tst57
-rw-r--r--math/test/testcases/directed/log10.tst16
-rw-r--r--math/test/testcases/directed/log10f.tst69
-rw-r--r--math/test/testcases/directed/log1p.tst22
-rw-r--r--math/test/testcases/directed/log1pf.tst130
-rw-r--r--math/test/testcases/directed/sinh.tst21
-rw-r--r--math/test/testcases/directed/sinhf.tst21
-rw-r--r--math/test/testcases/directed/tanf.tst25
-rw-r--r--math/test/testcases/directed/tanh.tst18
-rw-r--r--math/test/testcases/directed/tanhf.tst20
-rw-r--r--math/test/trigpi_references.h106
-rw-r--r--math/test/ulp.c328
-rw-r--r--math/test/ulp.h41
-rw-r--r--math/test/ulp_funcs.h119
-rw-r--r--math/test/ulp_wrappers.h418
42 files changed, 2446 insertions, 633 deletions
diff --git a/math/test/mathbench.c b/math/test/mathbench.c
index ed7e89bb7710..653c58fbc484 100644
--- a/math/test/mathbench.c
+++ b/math/test/mathbench.c
@@ -1,10 +1,23 @@
/*
* Microbenchmark for math functions.
*
- * Copyright (c) 2018-2023, Arm Limited.
+ * Copyright (c) 2018-2024, Arm Limited.
* SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
*/
+#if WANT_SVE_TESTS
+# if __aarch64__ && __linux__
+# ifdef __clang__
+# pragma clang attribute push(__attribute__((target("sve"))), \
+ apply_to = any(function))
+# else
+# pragma GCC target("+sve")
+# endif
+# else
+# error "SVE not supported - please disable WANT_SVE_TESTS"
+# endif
+#endif
+
#undef _GNU_SOURCE
#define _GNU_SOURCE 1
#include <stdint.h>
@@ -29,94 +42,6 @@ static float Af[N];
static long measurecount = MEASURE;
static long itercount = ITER;
-#ifdef __vpcs
-#include <arm_neon.h>
-typedef float64x2_t v_double;
-
-#define v_double_len() 2
-
-static inline v_double
-v_double_load (const double *p)
-{
- return (v_double){p[0], p[1]};
-}
-
-static inline v_double
-v_double_dup (double x)
-{
- return (v_double){x, x};
-}
-
-typedef float32x4_t v_float;
-
-#define v_float_len() 4
-
-static inline v_float
-v_float_load (const float *p)
-{
- return (v_float){p[0], p[1], p[2], p[3]};
-}
-
-static inline v_float
-v_float_dup (float x)
-{
- return (v_float){x, x, x, x};
-}
-#else
-/* dummy definitions to make things compile. */
-typedef double v_double;
-typedef float v_float;
-#define v_double_len(x) 1
-#define v_double_load(x) (x)[0]
-#define v_double_dup(x) (x)
-#define v_float_len(x) 1
-#define v_float_load(x) (x)[0]
-#define v_float_dup(x) (x)
-
-#endif
-
-#if WANT_SVE_MATH
-#include <arm_sve.h>
-typedef svbool_t sv_bool;
-typedef svfloat64_t sv_double;
-
-#define sv_double_len() svcntd()
-
-static inline sv_double
-sv_double_load (const double *p)
-{
- svbool_t pg = svptrue_b64();
- return svld1(pg, p);
-}
-
-static inline sv_double
-sv_double_dup (double x)
-{
- return svdup_n_f64(x);
-}
-
-typedef svfloat32_t sv_float;
-
-#define sv_float_len() svcntw()
-
-static inline sv_float
-sv_float_load (const float *p)
-{
- svbool_t pg = svptrue_b32();
- return svld1(pg, p);
-}
-
-static inline sv_float
-sv_float_dup (float x)
-{
- return svdup_n_f32(x);
-}
-#else
-/* dummy definitions to make things compile. */
-#define sv_double_len(x) 1
-#define sv_float_len(x) 1
-#endif
-
static double
dummy (double x)
{
@@ -128,28 +53,28 @@ dummyf (float x)
{
return x;
}
-#ifdef __vpcs
-__vpcs static v_double
-__vn_dummy (v_double x)
+#if __aarch64__ && __linux__
+__vpcs static float64x2_t
+__vn_dummy (float64x2_t x)
{
return x;
}
-__vpcs static v_float
-__vn_dummyf (v_float x)
+__vpcs static float32x4_t
+__vn_dummyf (float32x4_t x)
{
return x;
}
#endif
-#if WANT_SVE_MATH
-static sv_double
-__sv_dummy (sv_double x, sv_bool pg)
+#if WANT_SVE_TESTS
+static svfloat64_t
+__sv_dummy (svfloat64_t x, svbool_t pg)
{
return x;
}
-static sv_float
-__sv_dummyf (sv_float x, sv_bool pg)
+static svfloat32_t
+__sv_dummyf (svfloat32_t x, svbool_t pg)
{
return x;
}
@@ -169,16 +94,17 @@ static const struct fun
{
double (*d) (double);
float (*f) (float);
-#ifdef __vpcs
- __vpcs v_double (*vnd) (v_double);
- __vpcs v_float (*vnf) (v_float);
+#if __aarch64__ && __linux__
+ __vpcs float64x2_t (*vnd) (float64x2_t);
+ __vpcs float32x4_t (*vnf) (float32x4_t);
#endif
-#if WANT_SVE_MATH
- sv_double (*svd) (sv_double, sv_bool);
- sv_float (*svf) (sv_float, sv_bool);
+#if WANT_SVE_TESTS
+ svfloat64_t (*svd) (svfloat64_t, svbool_t);
+ svfloat32_t (*svf) (svfloat32_t, svbool_t);
#endif
} fun;
} funtab[] = {
+// clang-format off
#define D(func, lo, hi) {#func, 'd', 0, lo, hi, {.d = func}},
#define F(func, lo, hi) {#func, 'f', 0, lo, hi, {.f = func}},
#define VND(func, lo, hi) {#func, 'd', 'n', lo, hi, {.vnd = func}},
@@ -187,11 +113,11 @@ static const struct fun
#define SVF(func, lo, hi) {#func, 'f', 's', lo, hi, {.svf = func}},
D (dummy, 1.0, 2.0)
F (dummyf, 1.0, 2.0)
-#ifdef __vpcs
+#if __aarch64__ && __linux__
VND (__vn_dummy, 1.0, 2.0)
VNF (__vn_dummyf, 1.0, 2.0)
#endif
-#if WANT_SVE_MATH
+#if WANT_SVE_TESTS
SVD (__sv_dummy, 1.0, 2.0)
SVF (__sv_dummyf, 1.0, 2.0)
#endif
@@ -203,6 +129,7 @@ SVF (__sv_dummyf, 1.0, 2.0)
#undef VND
#undef SVF
#undef SVD
+ // clang-format on
};
static void
@@ -301,75 +228,77 @@ runf_latency (float f (float))
prev = f (Af[i] + prev * z);
}
-#ifdef __vpcs
+#if __aarch64__ && __linux__
static void
-run_vn_thruput (__vpcs v_double f (v_double))
+run_vn_thruput (__vpcs float64x2_t f (float64x2_t))
{
- for (int i = 0; i < N; i += v_double_len ())
- f (v_double_load (A+i));
+ for (int i = 0; i < N; i += 2)
+ f (vld1q_f64 (A + i));
}
static void
-runf_vn_thruput (__vpcs v_float f (v_float))
+runf_vn_thruput (__vpcs float32x4_t f (float32x4_t))
{
- for (int i = 0; i < N; i += v_float_len ())
- f (v_float_load (Af+i));
+ for (int i = 0; i < N; i += 4)
+ f (vld1q_f32 (Af + i));
}
static void
-run_vn_latency (__vpcs v_double f (v_double))
+run_vn_latency (__vpcs float64x2_t f (float64x2_t))
{
volatile uint64x2_t vsel = (uint64x2_t) { 0, 0 };
uint64x2_t sel = vsel;
- v_double prev = v_double_dup (0);
- for (int i = 0; i < N; i += v_double_len ())
- prev = f (vbslq_f64 (sel, prev, v_double_load (A+i)));
+ float64x2_t prev = vdupq_n_f64 (0);
+ for (int i = 0; i < N; i += 2)
+ prev = f (vbslq_f64 (sel, prev, vld1q_f64 (A + i)));
}
static void
-runf_vn_latency (__vpcs v_float f (v_float))
+runf_vn_latency (__vpcs float32x4_t f (float32x4_t))
{
volatile uint32x4_t vsel = (uint32x4_t) { 0, 0, 0, 0 };
uint32x4_t sel = vsel;
- v_float prev = v_float_dup (0);
- for (int i = 0; i < N; i += v_float_len ())
- prev = f (vbslq_f32 (sel, prev, v_float_load (Af+i)));
+ float32x4_t prev = vdupq_n_f32 (0);
+ for (int i = 0; i < N; i += 4)
+ prev = f (vbslq_f32 (sel, prev, vld1q_f32 (Af + i)));
}
#endif
-#if WANT_SVE_MATH
+#if WANT_SVE_TESTS
static void
-run_sv_thruput (sv_double f (sv_double, sv_bool))
+run_sv_thruput (svfloat64_t f (svfloat64_t, svbool_t))
{
- for (int i = 0; i < N; i += sv_double_len ())
- f (sv_double_load (A+i), svptrue_b64 ());
+ for (int i = 0; i < N; i += svcntd ())
+ f (svld1_f64 (svptrue_b64 (), A + i), svptrue_b64 ());
}
static void
-runf_sv_thruput (sv_float f (sv_float, sv_bool))
+runf_sv_thruput (svfloat32_t f (svfloat32_t, svbool_t))
{
- for (int i = 0; i < N; i += sv_float_len ())
- f (sv_float_load (Af+i), svptrue_b32 ());
+ for (int i = 0; i < N; i += svcntw ())
+ f (svld1_f32 (svptrue_b32 (), Af + i), svptrue_b32 ());
}
static void
-run_sv_latency (sv_double f (sv_double, sv_bool))
+run_sv_latency (svfloat64_t f (svfloat64_t, svbool_t))
{
- volatile sv_bool vsel = svptrue_b64 ();
- sv_bool sel = vsel;
- sv_double prev = sv_double_dup (0);
- for (int i = 0; i < N; i += sv_double_len ())
- prev = f (svsel_f64 (sel, sv_double_load (A+i), prev), svptrue_b64 ());
+ volatile svbool_t vsel = svptrue_b64 ();
+ svbool_t sel = vsel;
+ svfloat64_t prev = svdup_f64 (0);
+ for (int i = 0; i < N; i += svcntd ())
+ prev = f (svsel_f64 (sel, svld1_f64 (svptrue_b64 (), A + i), prev),
+ svptrue_b64 ());
}
static void
-runf_sv_latency (sv_float f (sv_float, sv_bool))
+runf_sv_latency (svfloat32_t f (svfloat32_t, svbool_t))
{
- volatile sv_bool vsel = svptrue_b32 ();
- sv_bool sel = vsel;
- sv_float prev = sv_float_dup (0);
- for (int i = 0; i < N; i += sv_float_len ())
- prev = f (svsel_f32 (sel, sv_float_load (Af+i), prev), svptrue_b32 ());
+ volatile svbool_t vsel = svptrue_b32 ();
+ svbool_t sel = vsel;
+ svfloat32_t prev = svdup_f32 (0);
+ for (int i = 0; i < N; i += svcntw ())
+ prev = f (svsel_f32 (sel, svld1_f32 (svptrue_b32 (), Af + i), prev),
+ svptrue_b32 ());
}
#endif
@@ -377,7 +306,11 @@ static uint64_t
tic (void)
{
struct timespec ts;
+#if defined(_MSC_VER)
+ if (!timespec_get (&ts, TIME_UTC))
+#else
if (clock_gettime (CLOCK_REALTIME, &ts))
+#endif
abort ();
return ts.tv_sec * 1000000000ULL + ts.tv_nsec;
}
@@ -405,9 +338,11 @@ bench1 (const struct fun *f, int type, double lo, double hi)
int vlen = 1;
if (f->vec == 'n')
- vlen = f->prec == 'd' ? v_double_len() : v_float_len();
+ vlen = f->prec == 'd' ? 2 : 4;
+#if WANT_SVE_TESTS
else if (f->vec == 's')
- vlen = f->prec == 'd' ? sv_double_len() : sv_float_len();
+ vlen = f->prec == 'd' ? svcntd () : svcntw ();
+#endif
if (f->prec == 'd' && type == 't' && f->vec == 0)
TIMEIT (run_thruput, f->fun.d);
@@ -417,7 +352,7 @@ bench1 (const struct fun *f, int type, double lo, double hi)
TIMEIT (runf_thruput, f->fun.f);
else if (f->prec == 'f' && type == 'l' && f->vec == 0)
TIMEIT (runf_latency, f->fun.f);
-#ifdef __vpcs
+#if __aarch64__ && __linux__
else if (f->prec == 'd' && type == 't' && f->vec == 'n')
TIMEIT (run_vn_thruput, f->fun.vnd);
else if (f->prec == 'd' && type == 'l' && f->vec == 'n')
@@ -427,7 +362,7 @@ bench1 (const struct fun *f, int type, double lo, double hi)
else if (f->prec == 'f' && type == 'l' && f->vec == 'n')
TIMEIT (runf_vn_latency, f->fun.vnf);
#endif
-#if WANT_SVE_MATH
+#if WANT_SVE_TESTS
else if (f->prec == 'd' && type == 't' && f->vec == 's')
TIMEIT (run_sv_thruput, f->fun.svd);
else if (f->prec == 'd' && type == 'l' && f->vec == 's')
@@ -640,3 +575,7 @@ main (int argc, char *argv[])
}
return 0;
}
+
+#if __aarch64__ && __linux__ && WANT_SVE_TESTS && defined(__clang__)
+# pragma clang attribute pop
+#endif
diff --git a/math/test/mathbench_funcs.h b/math/test/mathbench_funcs.h
index 84c4e68650ac..261ab02f55c3 100644
--- a/math/test/mathbench_funcs.h
+++ b/math/test/mathbench_funcs.h
@@ -1,27 +1,13 @@
/*
* Function entries for mathbench.
*
- * Copyright (c) 2022-2023, Arm Limited.
+ * Copyright (c) 2022-2024, Arm Limited.
* SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
*/
/* clang-format off */
-D (exp, -9.9, 9.9)
-D (exp, 0.5, 1.0)
-D (exp10, -9.9, 9.9)
-D (exp2, -9.9, 9.9)
-D (log, 0.01, 11.1)
-D (log, 0.999, 1.001)
-D (log2, 0.01, 11.1)
-D (log2, 0.999, 1.001)
{"pow", 'd', 0, 0.01, 11.1, {.d = xypow}},
D (xpow, 0.01, 11.1)
D (ypow, -9.9, 9.9)
-D (erf, -6.0, 6.0)
-
-F (expf, -9.9, 9.9)
-F (exp2f, -9.9, 9.9)
-F (logf, 0.01, 11.1)
-F (log2f, 0.01, 11.1)
{"powf", 'f', 0, 0.01, 11.1, {.f = xypowf}},
F (xpowf, 0.01, 11.1)
F (ypowf, -9.9, 9.9)
@@ -31,32 +17,105 @@ F (ypowf, -9.9, 9.9)
{"sincosf", 'f', 0, 3.3, 33.3, {.f = sincosf_wrap}},
{"sincosf", 'f', 0, 100, 1000, {.f = sincosf_wrap}},
{"sincosf", 'f', 0, 1e6, 1e32, {.f = sincosf_wrap}},
-F (sinf, 0.1, 0.7)
-F (sinf, 0.8, 3.1)
-F (sinf, -3.1, 3.1)
-F (sinf, 3.3, 33.3)
-F (sinf, 100, 1000)
-F (sinf, 1e6, 1e32)
-F (cosf, 0.1, 0.7)
-F (cosf, 0.8, 3.1)
-F (cosf, -3.1, 3.1)
-F (cosf, 3.3, 33.3)
-F (cosf, 100, 1000)
-F (cosf, 1e6, 1e32)
-F (erff, -4.0, 4.0)
-#ifdef __vpcs
-VND (_ZGVnN2v_exp, -9.9, 9.9)
-VND (_ZGVnN2v_log, 0.01, 11.1)
-{"_ZGVnN2vv_pow", 'd', 'n', 0.01, 11.1, {.vnd = xy_Z_pow}},
-VND (_ZGVnN2v_sin, -3.1, 3.1)
-VND (_ZGVnN2v_cos, -3.1, 3.1)
-VNF (_ZGVnN4v_expf, -9.9, 9.9)
+#if WANT_TRIGPI_TESTS
+F (arm_math_cospif, -0.9, 0.9)
+D (arm_math_cospi, -0.9, 0.9)
+F (arm_math_sinpif, -0.9, 0.9)
+D (arm_math_sinpi, -0.9, 0.9)
+F (arm_math_tanpif, -0.9, 0.9)
+D (arm_math_tanpi, -0.9, 0.9)
+{"sincospif", 'f', 0, -0.9, 0.9, {.f = sincospif_wrap}},
+{"sincospi", 'd', 0, -0.9, 0.9, {.d = sincospi_wrap}},
+#endif
+#if WANT_EXPERIMENTAL_MATH
+D (arm_math_erf, -6.0, 6.0)
+F (arm_math_erff, -4.0, 4.0)
+{"atan2f", 'f', 0, -10.0, 10.0, {.f = atan2f_wrap}},
+{"atan2", 'd', 0, -10.0, 10.0, {.d = atan2_wrap}},
+{"powi", 'd', 0, 0.01, 11.1, {.d = powi_wrap}},
+#endif
+#if __aarch64__ && __linux__
+{"_ZGVnN4vv_atan2f", 'f', 'n', -10.0, 10.0, {.vnf = _Z_atan2f_wrap}},
+{"_ZGVnN2vv_atan2", 'd', 'n', -10.0, 10.0, {.vnd = _Z_atan2_wrap}},
+{"_ZGVnN4vv_hypotf", 'f', 'n', -10.0, 10.0, {.vnf = _Z_hypotf_wrap}},
+{"_ZGVnN2vv_hypot", 'd', 'n', -10.0, 10.0, {.vnd = _Z_hypot_wrap}},
+{"_ZGVnN2vv_pow", 'd', 'n', -10.0, 10.0, {.vnd = xy_Z_pow}},
+{"x_ZGVnN2vv_pow", 'd', 'n', -10.0, 10.0, {.vnd = x_Z_pow}},
+{"y_ZGVnN2vv_pow", 'd', 'n', -10.0, 10.0, {.vnd = y_Z_pow}},
+{"_ZGVnN4vv_powf", 'f', 'n', 0.01, 11.1, {.vnf = xy_Z_powf}},
+{"x_ZGVnN4vv_powf", 'f', 'n', 0.01, 11.1, {.vnf = x_Z_powf}},
+{"y_ZGVnN4vv_powf", 'f', 'n', -10.0, 10.0, {.vnf = y_Z_powf}},
+{"_ZGVnN4vl4_modff", 'f', 'n', -10.0, 10.0, {.vnf = _Z_modff_wrap}},
+{"_ZGVnN2vl8_modf", 'd', 'n', -10.0, 10.0, {.vnd = _Z_modf_wrap}},
+{"_ZGVnN4vl4l4_sincosf", 'f', 'n', -3.1, 3.1, {.vnf = _Z_sincosf_wrap}},
+{"_ZGVnN2vl8l8_sincos", 'd', 'n', -3.1, 3.1, {.vnd = _Z_sincos_wrap}},
+{"_ZGVnN4v_cexpif", 'f', 'n', -3.1, 3.1, {.vnf = _Z_cexpif_wrap}},
+{"_ZGVnN2v_cexpi", 'd', 'n', -3.1, 3.1, {.vnd = _Z_cexpi_wrap}},
VNF (_ZGVnN4v_expf_1u, -9.9, 9.9)
-VNF (_ZGVnN4v_exp2f, -9.9, 9.9)
VNF (_ZGVnN4v_exp2f_1u, -9.9, 9.9)
-VNF (_ZGVnN4v_logf, 0.01, 11.1)
-{"_ZGVnN4vv_powf", 'f', 'n', 0.01, 11.1, {.vnf = xy_Z_powf}},
-VNF (_ZGVnN4v_sinf, -3.1, 3.1)
-VNF (_ZGVnN4v_cosf, -3.1, 3.1)
+# if WANT_TRIGPI_TESTS
+VNF (_ZGVnN4v_cospif, -0.9, 0.9)
+VND (_ZGVnN2v_cospi, -0.9, 0.9)
+VNF (_ZGVnN4v_sinpif, -0.9, 0.9)
+VND (_ZGVnN2v_sinpi, -0.9, 0.9)
+VNF (_ZGVnN4v_tanpif, -0.9, 0.9)
+VND (_ZGVnN2v_tanpi, -0.9, 0.9)
+{"_ZGVnN4vl4l4_sincospif", 'f', 'n', -0.9, 0.9, {.vnf = _Z_sincospif_wrap}},
+{"_ZGVnN2vl8l8_sincospi", 'd', 'n', -0.9, 0.9, {.vnd = _Z_sincospi_wrap}},
+# endif
+#endif
+
+#if WANT_SVE_TESTS
+{ "_ZGVsMxvv_atan2f", 'f', 's', -10.0, 10.0, { .svf = _Z_sv_atan2f_wrap } },
+{ "_ZGVsMxvv_atan2", 'd', 's', -10.0, 10.0, { .svd = _Z_sv_atan2_wrap } },
+{ "_ZGVsMxvv_hypotf", 'f', 's', -10.0, 10.0, { .svf = _Z_sv_hypotf_wrap } },
+{ "_ZGVsMxvv_hypot", 'd', 's', -10.0, 10.0, { .svd = _Z_sv_hypot_wrap } },
+{"_ZGVsMxvv_powf", 'f', 's', -10.0, 10.0, {.svf = xy_Z_sv_powf}},
+{"x_ZGVsMxvv_powf", 'f', 's', -10.0, 10.0, {.svf = x_Z_sv_powf}},
+{"y_ZGVsMxvv_powf", 'f', 's', -10.0, 10.0, {.svf = y_Z_sv_powf}},
+{"_ZGVsMxvv_pow", 'd', 's', -10.0, 10.0, {.svd = xy_Z_sv_pow}},
+{"x_ZGVsMxvv_pow", 'd', 's', -10.0, 10.0, {.svd = x_Z_sv_pow}},
+{"y_ZGVsMxvv_pow", 'd', 's', -10.0, 10.0, {.svd = y_Z_sv_pow}},
+{"_ZGVsMxvl4_modff", 'f', 's', -10.0, 10.0, {.svf = _Z_sv_modff_wrap}},
+{"_ZGVsMxvl8_modf", 'd', 's', -10.0, 10.0, {.svd = _Z_sv_modf_wrap}},
+{"_ZGVsMxvl4l4_sincosf", 'f', 's', -3.1, 3.1, {.svf = _Z_sv_sincosf_wrap}},
+{"_ZGVsMxvl8l8_sincos", 'd', 's', -3.1, 3.1, {.svd = _Z_sv_sincos_wrap}},
+{"_ZGVsMxv_cexpif", 'f', 's', -3.1, 3.1, {.svf = _Z_sv_cexpif_wrap}},
+{"_ZGVsMxv_cexpi", 'd', 's', -3.1, 3.1, {.svd = _Z_sv_cexpi_wrap}},
+# if WANT_TRIGPI_TESTS
+SVF (_ZGVsMxv_cospif, -0.9, 0.9)
+SVD (_ZGVsMxv_cospi, -0.9, 0.9)
+SVF (_ZGVsMxv_sinpif, -0.9, 0.9)
+SVD (_ZGVsMxv_sinpi, -0.9, 0.9)
+SVF (_ZGVsMxv_tanpif, -0.9, 0.9)
+SVD (_ZGVsMxv_tanpi, -0.9, 0.9)
+{"_ZGVsMxvl4l4_sincospif", 'f', 's', -0.9, 0.9, {.svf = _Z_sv_sincospif_wrap}},
+{"_ZGVsMxvl8l8_sincospi", 'd', 's', -0.9, 0.9, {.svd = _Z_sv_sincospi_wrap}},
+# endif
+# if WANT_EXPERIMENTAL_MATH
+{"_ZGVsMxvv_powi", 'f', 's', -10.0, 10.0, {.svf = _Z_sv_powi_wrap}},
+{"_ZGVsMxvv_powk", 'd', 's', -10.0, 10.0, {.svd = _Z_sv_powk_wrap}},
+# endif
#endif
- /* clang-format on */
+ /* clang-format on */
+
+#define _ZSF1(fun, a, b) F (fun##f, a, b)
+#define _ZSD1(f, a, b) D (f, a, b)
+
+#define _ZVF1(fun, a, b) VNF (_ZGVnN4v_##fun##f, a, b)
+#define _ZVD1(f, a, b) VND (_ZGVnN2v_##f, a, b)
+
+#define _ZSVF1(fun, a, b) SVF (_ZGVsMxv_##fun##f, a, b)
+#define _ZSVD1(f, a, b) SVD (_ZGVsMxv_##f, a, b)
+
+/* No auto-generated wrappers for binary functions - they have be
+ manually defined in mathbench_wrappers.h. We have to define silent
+ macros for them anyway as they will be emitted by TEST_SIG. */
+#define _ZSF2(...)
+#define _ZSD2(...)
+#define _ZVF2(...)
+#define _ZVD2(...)
+#define _ZSVF2(...)
+#define _ZSVD2(...)
+
+#include "test/mathbench_funcs_gen.h"
diff --git a/math/test/mathbench_wrappers.h b/math/test/mathbench_wrappers.h
index 062b9db56de5..32dcee36530a 100644
--- a/math/test/mathbench_wrappers.h
+++ b/math/test/mathbench_wrappers.h
@@ -1,24 +1,314 @@
/*
* Function wrappers for mathbench.
*
- * Copyright (c) 2022-2023, Arm Limited.
+ * Copyright (c) 2022-2024, Arm Limited.
* SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
*/
-#ifdef __vpcs
+#if WANT_EXPERIMENTAL_MATH
+static double
+atan2_wrap (double x)
+{
+ return atan2 (5.0, x);
+}
+
+static float
+atan2f_wrap (float x)
+{
+ return atan2f (5.0f, x);
+}
+
+static double
+powi_wrap (double x)
+{
+ return __builtin_powi (x, (int) round (x));
+}
+#endif /* WANT_EXPERIMENTAL_MATH. */
+
+#if __aarch64__ && __linux__
+
+__vpcs static float32x4_t
+_Z_sincospif_wrap (float32x4_t x)
+{
+ float s[4], c[4];
+ _ZGVnN4vl4l4_sincospif (x, s, c);
+ return vld1q_f32 (s) + vld1q_f32 (c);
+}
+
+__vpcs static float64x2_t
+_Z_sincospi_wrap (float64x2_t x)
+{
+ double s[2], c[2];
+ _ZGVnN2vl8l8_sincospi (x, s, c);
+ return vld1q_f64 (s) + vld1q_f64 (c);
+}
-__vpcs static v_float
-xy_Z_powf (v_float x)
+__vpcs static float64x2_t
+_Z_atan2_wrap (float64x2_t x)
+{
+ return _ZGVnN2vv_atan2 (vdupq_n_f64 (5.0), x);
+}
+
+__vpcs static float32x4_t
+_Z_atan2f_wrap (float32x4_t x)
+{
+ return _ZGVnN4vv_atan2f (vdupq_n_f32 (5.0f), x);
+}
+
+__vpcs static float32x4_t
+_Z_hypotf_wrap (float32x4_t x)
+{
+ return _ZGVnN4vv_hypotf (vdupq_n_f32 (5.0f), x);
+}
+
+__vpcs static float64x2_t
+_Z_hypot_wrap (float64x2_t x)
+{
+ return _ZGVnN2vv_hypot (vdupq_n_f64 (5.0), x);
+}
+
+__vpcs static float32x4_t
+xy_Z_powf (float32x4_t x)
{
return _ZGVnN4vv_powf (x, x);
}
-__vpcs static v_double
-xy_Z_pow (v_double x)
+__vpcs static float32x4_t
+x_Z_powf (float32x4_t x)
+{
+ return _ZGVnN4vv_powf (x, vdupq_n_f32 (23.4));
+}
+
+__vpcs static float32x4_t
+y_Z_powf (float32x4_t x)
+{
+ return _ZGVnN4vv_powf (vdupq_n_f32 (2.34), x);
+}
+
+__vpcs static float64x2_t
+xy_Z_pow (float64x2_t x)
{
return _ZGVnN2vv_pow (x, x);
}
+__vpcs static float64x2_t
+x_Z_pow (float64x2_t x)
+{
+ return _ZGVnN2vv_pow (x, vdupq_n_f64 (23.4));
+}
+
+__vpcs static float64x2_t
+y_Z_pow (float64x2_t x)
+{
+ return _ZGVnN2vv_pow (vdupq_n_f64 (2.34), x);
+}
+
+__vpcs static float32x4_t
+_Z_modff_wrap (float32x4_t x)
+{
+ float y[4];
+ float32x4_t ret = _ZGVnN4vl4_modff (x, y);
+ return ret + vld1q_f32 (y);
+}
+
+__vpcs static float64x2_t
+_Z_modf_wrap (float64x2_t x)
+{
+ double y[2];
+ float64x2_t ret = _ZGVnN2vl8_modf (x, y);
+ return ret + vld1q_f64 (y);
+}
+
+__vpcs static float32x4_t
+_Z_sincosf_wrap (float32x4_t x)
+{
+ float s[4], c[4];
+ _ZGVnN4vl4l4_sincosf (x, s, c);
+ return vld1q_f32 (s) + vld1q_f32 (c);
+}
+
+__vpcs static float32x4_t
+_Z_cexpif_wrap (float32x4_t x)
+{
+ float32x4x2_t sc = _ZGVnN4v_cexpif (x);
+ return sc.val[0] + sc.val[1];
+}
+
+__vpcs static float64x2_t
+_Z_sincos_wrap (float64x2_t x)
+{
+ double s[2], c[2];
+ _ZGVnN2vl8l8_sincos (x, s, c);
+ return vld1q_f64 (s) + vld1q_f64 (c);
+}
+
+__vpcs static float64x2_t
+_Z_cexpi_wrap (float64x2_t x)
+{
+ float64x2x2_t sc = _ZGVnN2v_cexpi (x);
+ return sc.val[0] + sc.val[1];
+}
+
+#endif
+
+#if WANT_SVE_TESTS
+
+static svfloat32_t
+_Z_sv_atan2f_wrap (svfloat32_t x, svbool_t pg)
+{
+ return _ZGVsMxvv_atan2f (x, svdup_f32 (5.0f), pg);
+}
+
+static svfloat64_t
+_Z_sv_atan2_wrap (svfloat64_t x, svbool_t pg)
+{
+ return _ZGVsMxvv_atan2 (x, svdup_f64 (5.0), pg);
+}
+
+static svfloat32_t
+_Z_sv_hypotf_wrap (svfloat32_t x, svbool_t pg)
+{
+ return _ZGVsMxvv_hypotf (x, svdup_f32 (5.0), pg);
+}
+
+static svfloat64_t
+_Z_sv_hypot_wrap (svfloat64_t x, svbool_t pg)
+{
+ return _ZGVsMxvv_hypot (x, svdup_f64 (5.0), pg);
+}
+
+static svfloat32_t
+xy_Z_sv_powf (svfloat32_t x, svbool_t pg)
+{
+ return _ZGVsMxvv_powf (x, x, pg);
+}
+
+static svfloat32_t
+x_Z_sv_powf (svfloat32_t x, svbool_t pg)
+{
+ return _ZGVsMxvv_powf (x, svdup_f32 (23.4f), pg);
+}
+
+static svfloat32_t
+y_Z_sv_powf (svfloat32_t x, svbool_t pg)
+{
+ return _ZGVsMxvv_powf (svdup_f32 (2.34f), x, pg);
+}
+
+static svfloat64_t
+xy_Z_sv_pow (svfloat64_t x, svbool_t pg)
+{
+ return _ZGVsMxvv_pow (x, x, pg);
+}
+
+static svfloat64_t
+x_Z_sv_pow (svfloat64_t x, svbool_t pg)
+{
+ return _ZGVsMxvv_pow (x, svdup_f64 (23.4), pg);
+}
+
+static svfloat64_t
+y_Z_sv_pow (svfloat64_t x, svbool_t pg)
+{
+ return _ZGVsMxvv_pow (svdup_f64 (2.34), x, pg);
+}
+
+static svfloat32_t
+_Z_sv_sincospif_wrap (svfloat32_t x, svbool_t pg)
+{
+ float s[svcntw ()], c[svcntw ()];
+ _ZGVsMxvl4l4_sincospif (x, s, c, pg);
+ return svadd_x (pg, svld1 (pg, s), svld1 (pg, c));
+}
+
+static svfloat64_t
+_Z_sv_sincospi_wrap (svfloat64_t x, svbool_t pg)
+{
+ double s[svcntd ()], c[svcntd ()];
+ _ZGVsMxvl8l8_sincospi (x, s, c, pg);
+ return svadd_x (pg, svld1 (pg, s), svld1 (pg, c));
+}
+
+static svfloat32_t
+_Z_sv_modff_wrap (svfloat32_t x, svbool_t pg)
+{
+ float i[svcntw ()];
+ svfloat32_t r = _ZGVsMxvl4_modff (x, i, pg);
+ return svadd_x (pg, r, svld1 (pg, i));
+}
+
+static svfloat64_t
+_Z_sv_modf_wrap (svfloat64_t x, svbool_t pg)
+{
+ double i[svcntd ()];
+ svfloat64_t r = _ZGVsMxvl8_modf (x, i, pg);
+ return svadd_x (pg, r, svld1 (pg, i));
+}
+
+static svfloat32_t
+_Z_sv_sincosf_wrap (svfloat32_t x, svbool_t pg)
+{
+ float s[svcntw ()], c[svcntw ()];
+ _ZGVsMxvl4l4_sincosf (x, s, c, pg);
+ return svadd_x (pg, svld1 (pg, s), svld1 (pg, s));
+}
+
+static svfloat32_t
+_Z_sv_cexpif_wrap (svfloat32_t x, svbool_t pg)
+{
+ svfloat32x2_t sc = _ZGVsMxv_cexpif (x, pg);
+ return svadd_x (pg, svget2 (sc, 0), svget2 (sc, 1));
+}
+
+static svfloat64_t
+_Z_sv_sincos_wrap (svfloat64_t x, svbool_t pg)
+{
+ double s[svcntd ()], c[svcntd ()];
+ _ZGVsMxvl8l8_sincos (x, s, c, pg);
+ return svadd_x (pg, svld1 (pg, s), svld1 (pg, s));
+}
+
+static svfloat64_t
+_Z_sv_cexpi_wrap (svfloat64_t x, svbool_t pg)
+{
+ svfloat64x2_t sc = _ZGVsMxv_cexpi (x, pg);
+ return svadd_x (pg, svget2 (sc, 0), svget2 (sc, 1));
+}
+
+# if WANT_EXPERIMENTAL_MATH
+
+static svfloat32_t
+_Z_sv_powi_wrap (svfloat32_t x, svbool_t pg)
+{
+ return _ZGVsMxvv_powi (x, svcvt_s32_f32_x (pg, x), pg);
+}
+
+static svfloat64_t
+_Z_sv_powk_wrap (svfloat64_t x, svbool_t pg)
+{
+ return _ZGVsMxvv_powk (x, svcvt_s64_f64_x (pg, x), pg);
+}
+
+# endif
+
+#endif
+
+#if __aarch64__
+static float
+sincospif_wrap (float x)
+{
+ float s, c;
+ arm_math_sincospif (x, &s, &c);
+ return s + c;
+}
+
+static double
+sincospi_wrap (double x)
+{
+ double s, c;
+ arm_math_sincospi (x, &s, &c);
+ return s + c;
+}
#endif
static double
diff --git a/math/test/mathtest.c b/math/test/mathtest.c
index 834233fdde9d..6e81f0d7b634 100644
--- a/math/test/mathtest.c
+++ b/math/test/mathtest.c
@@ -1,10 +1,12 @@
/*
* mathtest.c - test rig for mathlib
*
- * Copyright (c) 1998-2023, Arm Limited.
+ * Copyright (c) 1998-2024, Arm Limited.
* SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
*/
+/* clang-format off */
+#define _GNU_SOURCE
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
@@ -196,11 +198,9 @@ int is_complex_rettype(int rettype) {
#define TFUNCARM(arg,ret,name,tolerance) { t_func, arg, ret, (void*)& ARM_PREFIX(name), m_none, tolerance, #name }
#define MFUNC(arg,ret,name,tolerance) { t_macro, arg, ret, NULL, m_##name, tolerance, #name }
-#ifndef PL
/* sincosf wrappers for easier testing. */
static float sincosf_sinf(float x) { float s,c; sincosf(x, &s, &c); return s; }
static float sincosf_cosf(float x) { float s,c; sincosf(x, &s, &c); return c; }
-#endif
test_func tfuncs[] = {
/* trigonometric */
@@ -220,10 +220,9 @@ test_func tfuncs[] = {
TFUNCARM(at_s,rt_s, tanf, 4*ULPUNIT),
TFUNCARM(at_s,rt_s, sinf, 3*ULPUNIT/4),
TFUNCARM(at_s,rt_s, cosf, 3*ULPUNIT/4),
-#ifndef PL
TFUNCARM(at_s,rt_s, sincosf_sinf, 3*ULPUNIT/4),
TFUNCARM(at_s,rt_s, sincosf_cosf, 3*ULPUNIT/4),
-#endif
+
/* hyperbolic */
TFUNC(at_d, rt_d, atanh, 4*ULPUNIT),
TFUNC(at_d, rt_d, asinh, 4*ULPUNIT),
@@ -254,7 +253,9 @@ test_func tfuncs[] = {
TFUNCARM(at_s,rt_s, expf, 3*ULPUNIT/4),
TFUNCARM(at_s,rt_s, exp2f, 3*ULPUNIT/4),
TFUNC(at_s,rt_s, expm1f, ULPUNIT),
+#if WANT_EXP10_TESTS
TFUNC(at_d,rt_d, exp10, ULPUNIT),
+#endif
/* power */
TFUNC(at_d2,rt_d, pow, 3*ULPUNIT/4),
@@ -1707,3 +1708,4 @@ void undef_func() {
failed++;
puts("ERROR: undefined function called");
}
+/* clang-format on */
diff --git a/math/test/rtest/dotest.c b/math/test/rtest/dotest.c
index 5b3e9b4f18e4..dd8ceb068141 100644
--- a/math/test/rtest/dotest.c
+++ b/math/test/rtest/dotest.c
@@ -1,7 +1,7 @@
/*
* dotest.c - actually generate mathlib test cases
*
- * Copyright (c) 1999-2019, Arm Limited.
+ * Copyright (c) 1999-2024, Arm Limited.
* SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
*/
@@ -18,6 +18,35 @@
#define MPFR_PREC 96 /* good enough for float or double + a few extra bits */
+#if MPFR_VERSION < MPFR_VERSION_NUM(4, 2, 0)
+int
+mpfr_tanpi (mpfr_t ret, const mpfr_t arg, mpfr_rnd_t rnd)
+{
+ MPFR_DECL_INIT (frd, MPFR_PREC);
+ mpfr_const_pi (frd, GMP_RNDN);
+ mpfr_mul (frd, frd, arg, GMP_RNDN);
+ return mpfr_tan (ret, frd, GMP_RNDN);
+}
+
+int
+mpfr_sinpi (mpfr_t ret, const mpfr_t arg, mpfr_rnd_t rnd)
+{
+ MPFR_DECL_INIT (frd, MPFR_PREC);
+ mpfr_const_pi (frd, GMP_RNDN);
+ mpfr_mul (frd, frd, arg, GMP_RNDN);
+ return mpfr_sin (ret, frd, GMP_RNDN);
+}
+
+int
+mpfr_cospi (mpfr_t ret, const mpfr_t arg, mpfr_rnd_t rnd)
+{
+ MPFR_DECL_INIT (frd, MPFR_PREC);
+ mpfr_const_pi (frd, GMP_RNDN);
+ mpfr_mul (frd, frd, arg, GMP_RNDN);
+ return mpfr_cos (ret, frd, GMP_RNDN);
+}
+#endif
+
extern int lib_fo, lib_no_arith, ntests;
/*
@@ -454,6 +483,7 @@ void universal_wrapper(wrapperctx *ctx)
}
}
+/* clang-format off */
Testable functions[] = {
/*
* Trig functions: sin, cos, tan. We test the core function
@@ -479,6 +509,18 @@ Testable functions[] = {
cases_uniform_float, 0x39800000, 0x41800000},
{"sincosf_cosf", (funcptr)mpfr_cos, args1f, {NULL},
cases_uniform_float, 0x39800000, 0x41800000},
+ {"sinpi", (funcptr)mpfr_sinpi, args1, {NULL},
+ cases_uniform, 0x3e400000, 0x40300000},
+ {"sinpif", (funcptr)mpfr_sinpi, args1f, {NULL},
+ cases_uniform_float, 0x39800000, 0x41800000},
+ {"cospi", (funcptr)mpfr_cospi, args1, {NULL},
+ cases_uniform, 0x3e400000, 0x40300000},
+ {"cospif", (funcptr)mpfr_cospi, args1f, {NULL},
+ cases_uniform_float, 0x39800000, 0x41800000},
+ {"tanpi", (funcptr)mpfr_tanpi, args1, {NULL},
+ cases_uniform, 0x3e400000, 0x40300000},
+ {"tanpif", (funcptr)mpfr_tanpi, args1f, {NULL},
+ cases_uniform_float, 0x39800000, 0x41800000},
/*
* Inverse trig: asin, acos. Between 1 and -1, of course. acos
* goes down to 2^-54, asin to 2^-27.
@@ -708,6 +750,7 @@ Testable functions[] = {
{"tgammaf", (funcptr)mpfr_gamma, args1f, {NULL}, cases_uniform_float, 0x2f800000, 0x43000000},
{"tgamma", (funcptr)mpfr_gamma, args1, {NULL}, cases_uniform, 0x3c000000, 0x40800000},
};
+/* clang-format on */
const int nfunctions = ( sizeof(functions)/sizeof(*functions) );
diff --git a/math/test/runulp.sh b/math/test/runulp.sh
index e2e03e3ae761..672908f355c4 100755
--- a/math/test/runulp.sh
+++ b/math/test/runulp.sh
@@ -2,7 +2,7 @@
# ULP error check script.
#
-# Copyright (c) 2019-2023, Arm Limited.
+# Copyright (c) 2019-2024, Arm Limited.
# SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
#set -x
@@ -20,260 +20,83 @@ FAIL=0
PASS=0
t() {
- [ $r = "n" ] && Lt=$L || Lt=$Ldir
- $emu ./ulp -r $r -e $Lt $flags "$@" && PASS=$((PASS+1)) || FAIL=$((FAIL+1))
+ # First argument: routine name
+ routine=$1; shift
+ # Second and third argument: lo and hi bounds
+ # Extra processing needed for bivariate routines
+ IFS=',' read -ra LO <<< "$1"; shift
+ IFS=',' read -ra HI <<< "$1"; shift
+ ITV="${LO[0]} ${HI[0]}"
+ for i in "${!LO[@]}"; do
+ [[ "$i" -eq "0" ]] || ITV="$ITV x ${LO[$i]} ${HI[$i]}"
+ done
+ # Fourth argument: number of test points
+ n=$1; shift
+ # Any remaining arguments forwards directly to ulp tool
+ extra_flags="$@"
+
+ # Read ULP limits, fenv expectation and control values from autogenerated files
+ limits_file=$LIMITS
+ [ $r == "n" ] || limits_file=${limits_file}_nn
+ L=$(grep "^$routine " $limits_file | awk '{print $2}')
+ [ -n "$L" ] || { echo ERROR: Could not determine ULP limit for $routine in $limits_file && false; }
+ cvals=($(grep "^$routine " $CVALS | awk '{print $2}'))
+
+ if grep -q "^$routine$" $DISABLE_FENV; then extra_flags="$extra_flags -f"; fi
+ # Emulate a do-while loop to loop over cvals, but still execute once if it is empty
+ while : ; do
+ # Empty string if we are at the end of cvals array
+ c_arg=""
+ [ -z "${cvals[0]:-}" ] || c_arg="-c ${cvals[0]}"
+ $emu ./ulp -e $L $flags $extra_flags -r $r $c_arg $routine $ITV $n && PASS=$((PASS+1)) || FAIL=$((FAIL+1))
+ # Shift cvals by 1, and break if it is now empty
+ cvals=("${cvals[@]:1}")
+ [ -n "${cvals[0]:-}" ] || break
+ done
+
+ # Run ULP tool
+
}
check() {
- $emu ./ulp -f -q "$@" >/dev/null
+ $emu ./ulp -f -q "$@"
}
-Ldir=0.5
+if [[ $WANT_EXPERIMENTAL_MATH -eq 1 ]] && [[ $WANT_SVE_TESTS -eq 1 ]] && [[ $USE_MPFR -eq 0 ]]; then
+ # No guarantees about powi accuracy, so regression-test for exactness
+ # w.r.t. the custom reference impl in ulp_wrappers.h
+ if [ -z "$FUNC" ] || [ "$FUNC" == "_ZGVsMxvv_powi" ]; then
+ check -q -f -e 0 _ZGVsMxvv_powi 0 inf x 0 1000 100000
+ check -q -f -e 0 _ZGVsMxvv_powi -0 -inf x 0 1000 100000
+ check -q -f -e 0 _ZGVsMxvv_powi 0 inf x -0 -1000 100000
+ check -q -f -e 0 _ZGVsMxvv_powi -0 -inf x -0 -1000 100000
+ fi
+ if [ -z "$FUNC" ] || [ "$FUNC" == "_ZGVsMxvv_powk" ]; then
+ check -q -f -e 0 _ZGVsMxvv_powk 0 inf x 0 1000 100000
+ check -q -f -e 0 _ZGVsMxvv_powk -0 -inf x 0 1000 100000
+ check -q -f -e 0 _ZGVsMxvv_powk 0 inf x -0 -1000 100000
+ check -q -f -e 0 _ZGVsMxvv_powk -0 -inf x -0 -1000 100000
+ fi
+fi
+
+# Test generic routines in all rounding modes
for r in $rmodes
do
-L=0.01
-t exp 0 0xffff000000000000 10000
-t exp 0x1p-6 0x1p6 40000
-t exp -0x1p-6 -0x1p6 40000
-t exp 633.3 733.3 10000
-t exp -633.3 -777.3 10000
-
-L=0.01
-t exp2 0 0xffff000000000000 10000
-t exp2 0x1p-6 0x1p6 40000
-t exp2 -0x1p-6 -0x1p6 40000
-t exp2 633.3 733.3 10000
-t exp2 -633.3 -777.3 10000
-
-L=0.02
-t log 0 0xffff000000000000 10000
-t log 0x1p-4 0x1p4 40000
-t log 0 inf 40000
-
-L=0.05
-t log2 0 0xffff000000000000 10000
-t log2 0x1p-4 0x1p4 40000
-t log2 0 inf 40000
-
-L=0.05
-t pow 0.5 2.0 x 0 inf 20000
-t pow -0.5 -2.0 x 0 inf 20000
-t pow 0.5 2.0 x -0 -inf 20000
-t pow -0.5 -2.0 x -0 -inf 20000
-t pow 0.5 2.0 x 0x1p-10 0x1p10 40000
-t pow 0.5 2.0 x -0x1p-10 -0x1p10 40000
-t pow 0 inf x 0.5 2.0 80000
-t pow 0 inf x -0.5 -2.0 80000
-t pow 0x1.fp-1 0x1.08p0 x 0x1p8 0x1p17 80000
-t pow 0x1.fp-1 0x1.08p0 x -0x1p8 -0x1p17 80000
-t pow 0 0x1p-1000 x 0 1.0 50000
-t pow 0x1p1000 inf x 0 1.0 50000
-t pow 0x1.ffffffffffff0p-1 0x1.0000000000008p0 x 0x1p60 0x1p68 50000
-t pow 0x1.ffffffffff000p-1 0x1p0 x 0x1p50 0x1p52 50000
-t pow -0x1.ffffffffff000p-1 -0x1p0 x 0x1p50 0x1p52 50000
-
-L=0.02
-t exp10 0 0x1p-47 5000
-t exp10 -0 -0x1p-47 5000
-t exp10 0x1p-47 1 50000
-t exp10 -0x1p-47 -1 50000
-t exp10 1 0x1.34413509f79ffp8 50000
-t exp10 -1 -0x1.434e6420f4374p8 50000
-t exp10 0x1.34413509f79ffp8 inf 5000
-t exp10 -0x1.434e6420f4374p8 -inf 5000
-
-L=1.0
-Ldir=0.9
-t erf 0 0xffff000000000000 10000
-t erf 0x1p-1022 0x1p-26 40000
-t erf -0x1p-1022 -0x1p-26 40000
-t erf 0x1p-26 0x1p3 40000
-t erf -0x1p-26 -0x1p3 40000
-t erf 0 inf 40000
-Ldir=0.5
-
-L=0.01
-t expf 0 0xffff0000 10000
-t expf 0x1p-14 0x1p8 50000
-t expf -0x1p-14 -0x1p8 50000
-
-L=0.01
-t exp2f 0 0xffff0000 10000
-t exp2f 0x1p-14 0x1p8 50000
-t exp2f -0x1p-14 -0x1p8 50000
-
-L=0.32
-t logf 0 0xffff0000 10000
-t logf 0x1p-4 0x1p4 50000
-t logf 0 inf 50000
-
-L=0.26
-t log2f 0 0xffff0000 10000
-t log2f 0x1p-4 0x1p4 50000
-t log2f 0 inf 50000
-
-L=0.06
-t sinf 0 0xffff0000 10000
-t sinf 0x1p-14 0x1p54 50000
-t sinf -0x1p-14 -0x1p54 50000
-
-L=0.06
-t cosf 0 0xffff0000 10000
-t cosf 0x1p-14 0x1p54 50000
-t cosf -0x1p-14 -0x1p54 50000
-
-L=0.06
-t sincosf_sinf 0 0xffff0000 10000
-t sincosf_sinf 0x1p-14 0x1p54 50000
-t sincosf_sinf -0x1p-14 -0x1p54 50000
-
-L=0.06
-t sincosf_cosf 0 0xffff0000 10000
-t sincosf_cosf 0x1p-14 0x1p54 50000
-t sincosf_cosf -0x1p-14 -0x1p54 50000
-
-L=0.4
-t powf 0x1p-1 0x1p1 x 0x1p-7 0x1p7 50000
-t powf 0x1p-1 0x1p1 x -0x1p-7 -0x1p7 50000
-t powf 0x1p-70 0x1p70 x 0x1p-1 0x1p1 50000
-t powf 0x1p-70 0x1p70 x -0x1p-1 -0x1p1 50000
-t powf 0x1.ep-1 0x1.1p0 x 0x1p8 0x1p14 50000
-t powf 0x1.ep-1 0x1.1p0 x -0x1p8 -0x1p14 50000
-
-L=0.6
-Ldir=0.9
-t erff 0 0xffff0000 10000
-t erff 0x1p-127 0x1p-26 40000
-t erff -0x1p-127 -0x1p-26 40000
-t erff 0x1p-26 0x1p3 40000
-t erff -0x1p-26 -0x1p3 40000
-t erff 0 inf 40000
-Ldir=0.5
-
+ while read F LO HI N
+ do
+ [[ -z $F ]] || t $F $LO $HI $N
+ done << EOF
+$(grep "\b$FUNC\b" $GEN_ITVS)
+EOF
done
-# vector functions
-
-Ldir=0.5
-r='n'
-flags="${ULPFLAGS:--q}"
-
-range_exp='
- 0 0xffff000000000000 10000
- 0x1p-6 0x1p6 400000
- -0x1p-6 -0x1p6 400000
- 633.3 733.3 10000
- -633.3 -777.3 10000
-'
-
-range_log='
- 0 0xffff000000000000 10000
- 0x1p-4 0x1p4 400000
- 0 inf 400000
-'
-
-range_pow='
- 0x1p-1 0x1p1 x 0x1p-10 0x1p10 50000
- 0x1p-1 0x1p1 x -0x1p-10 -0x1p10 50000
- 0x1p-500 0x1p500 x 0x1p-1 0x1p1 50000
- 0x1p-500 0x1p500 x -0x1p-1 -0x1p1 50000
- 0x1.ep-1 0x1.1p0 x 0x1p8 0x1p16 50000
- 0x1.ep-1 0x1.1p0 x -0x1p8 -0x1p16 50000
-'
-
-range_sin='
- 0 0x1p23 500000
- -0 -0x1p23 500000
- 0x1p23 inf 10000
- -0x1p23 -inf 10000
-'
-range_cos="$range_sin"
-
-range_expf='
- 0 0xffff0000 10000
- 0x1p-14 0x1p8 500000
- -0x1p-14 -0x1p8 500000
-'
-
-range_expf_1u="$range_expf"
-range_exp2f="$range_expf"
-range_exp2f_1u="$range_expf"
-
-range_logf='
- 0 0xffff0000 10000
- 0x1p-4 0x1p4 500000
-'
-
-range_sinf='
- 0 0x1p20 500000
- -0 -0x1p20 500000
- 0x1p20 inf 10000
- -0x1p20 -inf 10000
-'
-range_cosf="$range_sinf"
-
-range_powf='
- 0x1p-1 0x1p1 x 0x1p-7 0x1p7 50000
- 0x1p-1 0x1p1 x -0x1p-7 -0x1p7 50000
- 0x1p-70 0x1p70 x 0x1p-1 0x1p1 50000
- 0x1p-70 0x1p70 x -0x1p-1 -0x1p1 50000
- 0x1.ep-1 0x1.1p0 x 0x1p8 0x1p14 50000
- 0x1.ep-1 0x1.1p0 x -0x1p8 -0x1p14 50000
-'
-
-# error limits
-L_exp=1.9
-L_log=1.2
-L_pow=0.05
-L_sin=3.0
-L_cos=3.0
-L_expf=1.49
-L_expf_1u=0.4
-L_exp2f=1.49
-L_exp2f_1u=0.4
-L_logf=2.9
-L_sinf=1.4
-L_cosf=1.4
-L_powf=2.1
-
-while read G F D
+# Only test arch-specific routines in round-to-nearest, with sign of zero ignored (-z flag)
+r=n
+while read F LO HI N
do
- case "$G" in \#*) continue ;; esac
- eval range="\${range_$G}"
- eval L="\${L_$G}"
- while read X
- do
- [ -n "$X" ] || continue
- case "$X" in \#*) continue ;; esac
- disable_fenv=""
- if [ -z "$WANT_SIMD_EXCEPT" ] || [ $WANT_SIMD_EXCEPT -eq 0 ]; then
- # If library was built with SIMD exceptions
- # disabled, disable fenv checking in ulp
- # tool. Otherwise, fenv checking may still be
- # disabled by adding -f to the end of the run
- # line.
- disable_fenv="-f"
- fi
- t $D $disable_fenv $F $X
- done << EOF
-$range
-
-EOF
+ [[ -z $F ]] || t $F $LO $HI $N -z
done << EOF
-# group symbol run
-exp _ZGVnN2v_exp
-log _ZGVnN2v_log
-pow _ZGVnN2vv_pow -f
-sin _ZGVnN2v_sin -z
-cos _ZGVnN2v_cos
-expf _ZGVnN4v_expf
-expf_1u _ZGVnN4v_expf_1u -f
-exp2f _ZGVnN4v_exp2f
-exp2f_1u _ZGVnN4v_exp2f_1u -f
-logf _ZGVnN4v_logf
-sinf _ZGVnN4v_sinf -z
-cosf _ZGVnN4v_cosf
-powf _ZGVnN4vv_powf -f
+$(grep "\b$FUNC\b" $ARCH_ITVS)
EOF
[ 0 -eq $FAIL ] || {
diff --git a/math/test/test_defs.h b/math/test/test_defs.h
new file mode 100644
index 000000000000..d0656c9e1d84
--- /dev/null
+++ b/math/test/test_defs.h
@@ -0,0 +1,31 @@
+/*
+ * Helper macros for emitting various details about routines for consumption by
+ * runulp.sh.
+ *
+ * Copyright (c) 2024, Arm Limited.
+ * SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception.
+ */
+
+#define TEST_ULP(f, l) TEST_ULP f l
+#define TEST_ULP_NONNEAREST(f, l) TEST_ULP_NONNEAREST f l
+
+/* Emit routine name if e == 0 and f is expected to correctly trigger fenv
+ exceptions. e allows declaration to be emitted conditionally on
+ WANT_SIMD_EXCEPT - defer expansion by one pass to allow those flags to be
+ expanded properly. */
+#define TEST_DISABLE_FENV(f) TEST_DISABLE_FENV f
+#define TEST_DISABLE_FENV_IF_NOT(f, e) TEST_DISABLE_FENV_IF_NOT_ (f, e)
+#define TEST_DISABLE_FENV_IF_NOT_(f, e) TEST_DISABLE_FENV_IF_NOT_##e (f)
+#define TEST_DISABLE_FENV_IF_NOT_0(f) TEST_DISABLE_FENV (f)
+#define TEST_DISABLE_FENV_IF_NOT_1(f)
+
+#define TEST_INTERVAL(f, lo, hi, n) TEST_INTERVAL f lo hi n
+#define TEST_SYM_INTERVAL(f, lo, hi, n) \
+ TEST_INTERVAL (f, lo, hi, n) \
+ TEST_INTERVAL (f, -lo, -hi, n)
+// clang-format off
+#define TEST_INTERVAL2(f, xlo, xhi, ylo, yhi, n) \
+ TEST_INTERVAL f xlo,ylo xhi,yhi n
+// clang-format on
+
+#define TEST_CONTROL_VALUE(f, c) TEST_CONTROL_VALUE f c
diff --git a/math/test/testcases/directed/acos.tst b/math/test/testcases/directed/acos.tst
new file mode 100644
index 000000000000..7889e62f4459
--- /dev/null
+++ b/math/test/testcases/directed/acos.tst
@@ -0,0 +1,17 @@
+; acos.tst
+;
+; Copyright (c) 2009-2024, Arm Limited.
+; SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
+
+func=acos op1=7ff80000.00000001 result=7ff80000.00000001 errno=0
+func=acos op1=fff80000.00000001 result=7ff80000.00000001 errno=0
+func=acos op1=7ff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=acos op1=fff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=acos op1=7ff00000.00000000 result=7ff80000.00000001 errno=EDOM status=i
+func=acos op1=fff00000.00000000 result=7ff80000.00000001 errno=EDOM status=i
+func=acos op1=00000000.00000000 result=3ff921fb.54442d18.469 errno=0
+func=acos op1=80000000.00000000 result=3ff921fb.54442d18.469 errno=0
+func=acos op1=3ff00000.00000000 result=00000000.00000000 errno=0
+func=acos op1=bff00000.00000000 result=400921fb.54442d18.469 errno=0
+func=acos op1=3ff00000.00000001 result=7ff80000.00000001 errno=EDOM status=i
+func=acos op1=bff00000.00000001 result=7ff80000.00000001 errno=EDOM status=i
diff --git a/math/test/testcases/directed/acosf.tst b/math/test/testcases/directed/acosf.tst
new file mode 100644
index 000000000000..0c2165967abb
--- /dev/null
+++ b/math/test/testcases/directed/acosf.tst
@@ -0,0 +1,21 @@
+; acosf.tst
+;
+; Copyright (c) 2009-2024, Arm Limited.
+; SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
+
+func=acosf op1=7fc00001 result=7fc00001 errno=0
+func=acosf op1=ffc00001 result=7fc00001 errno=0
+func=acosf op1=7f800001 result=7fc00001 errno=0 status=i
+func=acosf op1=ff800001 result=7fc00001 errno=0 status=i
+func=acosf op1=7f800000 result=7fc00001 errno=EDOM status=i
+func=acosf op1=ff800000 result=7fc00001 errno=EDOM status=i
+func=acosf op1=00000000 result=3fc90fda.a22 errno=0
+func=acosf op1=80000000 result=3fc90fda.a22 errno=0
+func=acosf op1=3f800000 result=00000000 errno=0
+func=acosf op1=bf800000 result=40490fda.a22 errno=0
+func=acosf op1=3f800001 result=7fc00001 errno=EDOM status=i
+func=acosf op1=bf800001 result=7fc00001 errno=EDOM status=i
+func=acosf op1=33000000 result=3fc90fda.622 error=0
+func=acosf op1=30000000 result=3fc90fda.a12 error=0
+func=acosf op1=2d000000 result=3fc90fda.a21 error=0
+func=acosf op1=2a000000 result=3fc90fda.a22 error=0
diff --git a/math/test/testcases/directed/acosh.tst b/math/test/testcases/directed/acosh.tst
new file mode 100644
index 000000000000..b78d64bb8ea7
--- /dev/null
+++ b/math/test/testcases/directed/acosh.tst
@@ -0,0 +1,19 @@
+; acosh.tst
+;
+; Copyright (c) 2009-2024, Arm Limited.
+; SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
+
+func=acosh op1=7ff80000.00000001 result=7ff80000.00000001 errno=0
+func=acosh op1=fff80000.00000001 result=7ff80000.00000001 errno=0
+func=acosh op1=7ff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=acosh op1=fff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=acosh op1=7ff00000.00000000 result=7ff00000.00000000 errno=0
+func=acosh op1=3ff00000.00000000 result=00000000.00000000 errno=0
+func=acosh op1=3fefffff.ffffffff result=7ff80000.00000001 errno=EDOM status=i
+func=acosh op1=00000000.00000000 result=7ff80000.00000001 errno=EDOM status=i
+func=acosh op1=80000000.00000000 result=7ff80000.00000001 errno=EDOM status=i
+func=acosh op1=bfefffff.ffffffff result=7ff80000.00000001 errno=EDOM status=i
+func=acosh op1=bff00000.00000000 result=7ff80000.00000001 errno=EDOM status=i
+func=acosh op1=bff00000.00000001 result=7ff80000.00000001 errno=EDOM status=i
+func=acosh op1=fff00000.00000000 result=7ff80000.00000001 errno=EDOM status=i
+func=acosh op1=7fe01ac0.7f03a83e result=40862e50.541778f1.8cc error=0
diff --git a/math/test/testcases/directed/acoshf.tst b/math/test/testcases/directed/acoshf.tst
new file mode 100644
index 000000000000..9eec2caf014d
--- /dev/null
+++ b/math/test/testcases/directed/acoshf.tst
@@ -0,0 +1,19 @@
+; acoshf.tst
+;
+; Copyright (c) 2009-2024, Arm Limited.
+; SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
+
+func=acoshf op1=7fc00001 result=7fc00001 errno=0
+func=acoshf op1=ffc00001 result=7fc00001 errno=0
+func=acoshf op1=7f800001 result=7fc00001 errno=0 status=i
+func=acoshf op1=ff800001 result=7fc00001 errno=0 status=i
+func=acoshf op1=7f800000 result=7f800000 errno=0
+func=acoshf op1=3f800000 result=00000000 errno=0
+func=acoshf op1=3f7fffff result=7fc00001 errno=EDOM status=i
+func=acoshf op1=00000000 result=7fc00001 errno=EDOM status=i
+func=acoshf op1=80000000 result=7fc00001 errno=EDOM status=i
+func=acoshf op1=bf7fffff result=7fc00001 errno=EDOM status=i
+func=acoshf op1=bf800000 result=7fc00001 errno=EDOM status=i
+func=acoshf op1=bf800001 result=7fc00001 errno=EDOM status=i
+func=acoshf op1=ff800000 result=7fc00001 errno=EDOM status=i
+func=acoshf op1=7f767efe result=42b2c19d.83e error=0
diff --git a/math/test/testcases/directed/asin.tst b/math/test/testcases/directed/asin.tst
new file mode 100644
index 000000000000..7b916f3624c0
--- /dev/null
+++ b/math/test/testcases/directed/asin.tst
@@ -0,0 +1,24 @@
+; asin.tst
+;
+; Copyright (c) 2009-2024, Arm Limited.
+; SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
+
+func=asin op1=7ff80000.00000001 result=7ff80000.00000001 errno=0
+func=asin op1=fff80000.00000001 result=7ff80000.00000001 errno=0
+func=asin op1=7ff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=asin op1=fff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=asin op1=7ff00000.00000000 result=7ff80000.00000001 errno=EDOM status=i
+func=asin op1=fff00000.00000000 result=7ff80000.00000001 errno=EDOM status=i
+func=asin op1=00000000.00000000 result=00000000.00000000 errno=0
+func=asin op1=80000000.00000000 result=80000000.00000000 errno=0
+; Inconsistent behavior was detected for the following 2 cases.
+; No exception is raised with certain versions of glibc. Functions
+; approximated by x near zero may not generate/implement flops and
+; thus may not raise exceptions.
+func=asin op1=00000000.00000001 result=00000000.00000001 errno=0 maybestatus=ux
+func=asin op1=80000000.00000001 result=80000000.00000001 errno=0 maybestatus=ux
+
+func=asin op1=3ff00000.00000000 result=3ff921fb.54442d18.469 errno=0
+func=asin op1=bff00000.00000000 result=bff921fb.54442d18.469 errno=0
+func=asin op1=3ff00000.00000001 result=7ff80000.00000001 errno=EDOM status=i
+func=asin op1=bff00000.00000001 result=7ff80000.00000001 errno=EDOM status=i
diff --git a/math/test/testcases/directed/asinf.tst b/math/test/testcases/directed/asinf.tst
new file mode 100644
index 000000000000..d5830b99b620
--- /dev/null
+++ b/math/test/testcases/directed/asinf.tst
@@ -0,0 +1,24 @@
+; asinf.tst
+;
+; Copyright (c) 2009-2024, Arm Limited.
+; SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
+
+func=asinf op1=7fc00001 result=7fc00001 errno=0
+func=asinf op1=ffc00001 result=7fc00001 errno=0
+func=asinf op1=7f800001 result=7fc00001 errno=0 status=i
+func=asinf op1=ff800001 result=7fc00001 errno=0 status=i
+func=asinf op1=7f800000 result=7fc00001 errno=EDOM status=i
+func=asinf op1=ff800000 result=7fc00001 errno=EDOM status=i
+func=asinf op1=00000000 result=00000000 errno=0
+func=asinf op1=80000000 result=80000000 errno=0
+; Inconsistent behavior was detected for the following 2 cases.
+; No exception is raised with certain versions of glibc. Functions
+; approximated by x near zero may not generate/implement flops and
+; thus may not raise exceptions.
+func=asinf op1=00000001 result=00000001 errno=0 maybestatus=ux
+func=asinf op1=80000001 result=80000001 errno=0 maybestatus=ux
+
+func=asinf op1=3f800000 result=3fc90fda.a22 errno=0
+func=asinf op1=bf800000 result=bfc90fda.a22 errno=0
+func=asinf op1=3f800001 result=7fc00001 errno=EDOM status=i
+func=asinf op1=bf800001 result=7fc00001 errno=EDOM status=i
diff --git a/math/test/testcases/directed/asinh.tst b/math/test/testcases/directed/asinh.tst
new file mode 100644
index 000000000000..9b250a14f50c
--- /dev/null
+++ b/math/test/testcases/directed/asinh.tst
@@ -0,0 +1,18 @@
+; asinh.tst
+;
+; Copyright (c) 2022-2024, Arm Limited.
+; SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
+
+func=asinh op1=7ff80000.00000001 result=7ff80000.00000001 errno=0
+func=asinh op1=fff80000.00000001 result=7ff80000.00000001 errno=0
+func=asinh op1=7ff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=asinh op1=fff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=asinh op1=7ff00000.00000000 result=7ff00000.00000000 errno=0
+func=asinh op1=fff00000.00000000 result=fff00000.00000000 errno=0
+func=asinh op1=00000000.00000000 result=00000000.00000000 errno=0
+func=asinh op1=80000000.00000000 result=80000000.00000000 errno=0
+; No exception is raised with certain versions of glibc. Functions
+; approximated by x near zero may not generate/implement flops and
+; thus may not raise exceptions.
+func=asinh op1=00000000.00000001 result=00000000.00000001 errno=0 maybestatus=ux
+func=asinh op1=80000000.00000001 result=80000000.00000001 errno=0 maybestatus=ux
diff --git a/math/test/testcases/directed/asinhf.tst b/math/test/testcases/directed/asinhf.tst
new file mode 100644
index 000000000000..f2410e09b03e
--- /dev/null
+++ b/math/test/testcases/directed/asinhf.tst
@@ -0,0 +1,18 @@
+; asinhf.tst
+;
+; Copyright (c) 2007-2024, Arm Limited.
+; SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
+
+func=asinhf op1=7fc00001 result=7fc00001 errno=0
+func=asinhf op1=ffc00001 result=7fc00001 errno=0
+func=asinhf op1=7f800001 result=7fc00001 errno=0 status=i
+func=asinhf op1=ff800001 result=7fc00001 errno=0 status=i
+func=asinhf op1=7f800000 result=7f800000 errno=0
+func=asinhf op1=ff800000 result=ff800000 errno=0
+func=asinhf op1=00000000 result=00000000 errno=0
+func=asinhf op1=80000000 result=80000000 errno=0
+; No exception is raised on certain machines (different version of glibc)
+; Same issue encountered with other function similar to x close to 0
+; Could be due to function so boring no flop is involved in some implementations
+func=asinhf op1=00000001 result=00000001 errno=0 maybestatus=ux
+func=asinhf op1=80000001 result=80000001 errno=0 maybestatus=ux
diff --git a/math/test/testcases/directed/atan.tst b/math/test/testcases/directed/atan.tst
new file mode 100644
index 000000000000..d29b13245cd5
--- /dev/null
+++ b/math/test/testcases/directed/atan.tst
@@ -0,0 +1,22 @@
+; atan.tst
+;
+; Copyright (c) 1999-2024, Arm Limited.
+; SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
+
+func=atan op1=7ff80000.00000001 result=7ff80000.00000001 errno=0
+func=atan op1=fff80000.00000001 result=7ff80000.00000001 errno=0
+func=atan op1=7ff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=atan op1=fff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=atan op1=7ff00000.00000000 result=3ff921fb.54442d18.469 errno=0
+func=atan op1=fff00000.00000000 result=bff921fb.54442d18.469 errno=0
+func=atan op1=00000000.00000000 result=00000000.00000000 errno=0
+func=atan op1=80000000.00000000 result=80000000.00000000 errno=0
+; Inconsistent behavior was detected for the following 2 cases.
+; No exception is raised with certain versions of glibc. Functions
+; approximated by x near zero may not generate/implement flops and
+; thus may not raise exceptions.
+func=atan op1=00000000.00000001 result=00000000.00000001 errno=0 maybestatus=ux
+func=atan op1=80000000.00000001 result=80000000.00000001 errno=0 maybestatus=ux
+
+func=atan op1=3ff00000.00000000 result=3fe921fb.54442d18.469 errno=0
+func=atan op1=bff00000.00000000 result=bfe921fb.54442d18.469 errno=0
diff --git a/math/test/testcases/directed/atan2.tst b/math/test/testcases/directed/atan2.tst
new file mode 100644
index 000000000000..3e34e7641f28
--- /dev/null
+++ b/math/test/testcases/directed/atan2.tst
@@ -0,0 +1,110 @@
+; atan2.tst
+;
+; Copyright (c) 1999-2024, Arm Limited.
+; SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
+
+func=atan2 op1=7ff00000.00000001 op2=7ff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=atan2 op1=7ff00000.00000001 op2=fff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=atan2 op1=7ff00000.00000001 op2=7ff00000.00000000 result=7ff80000.00000001 errno=0 status=i
+func=atan2 op1=7ff00000.00000001 op2=fff00000.00000000 result=7ff80000.00000001 errno=0 status=i
+func=atan2 op1=7ff00000.00000001 op2=00000000.00000000 result=7ff80000.00000001 errno=0 status=i
+func=atan2 op1=7ff00000.00000001 op2=80000000.00000000 result=7ff80000.00000001 errno=0 status=i
+func=atan2 op1=7ff00000.00000001 op2=3ff00000.00000000 result=7ff80000.00000001 errno=0 status=i
+func=atan2 op1=7ff00000.00000001 op2=bff00000.00000000 result=7ff80000.00000001 errno=0 status=i
+func=atan2 op1=fff00000.00000001 op2=7ff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=atan2 op1=fff00000.00000001 op2=fff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=atan2 op1=fff00000.00000001 op2=7ff00000.00000000 result=7ff80000.00000001 errno=0 status=i
+func=atan2 op1=fff00000.00000001 op2=fff00000.00000000 result=7ff80000.00000001 errno=0 status=i
+func=atan2 op1=fff00000.00000001 op2=00000000.00000000 result=7ff80000.00000001 errno=0 status=i
+func=atan2 op1=fff00000.00000001 op2=80000000.00000000 result=7ff80000.00000001 errno=0 status=i
+func=atan2 op1=fff00000.00000001 op2=3ff00000.00000000 result=7ff80000.00000001 errno=0 status=i
+func=atan2 op1=fff00000.00000001 op2=bff00000.00000000 result=7ff80000.00000001 errno=0 status=i
+func=atan2 op1=7ff80000.00000001 op2=7ff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=atan2 op1=7ff80000.00000001 op2=fff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=atan2 op1=7ff80000.00000001 op2=7ff80000.00000001 result=7ff80000.00000001 errno=0
+func=atan2 op1=7ff80000.00000001 op2=fff80000.00000001 result=7ff80000.00000001 errno=0
+func=atan2 op1=7ff80000.00000001 op2=7ff00000.00000000 result=7ff80000.00000001 errno=0
+func=atan2 op1=7ff80000.00000001 op2=fff00000.00000000 result=7ff80000.00000001 errno=0
+func=atan2 op1=7ff80000.00000001 op2=00000000.00000000 result=7ff80000.00000001 errno=0
+func=atan2 op1=7ff80000.00000001 op2=80000000.00000000 result=7ff80000.00000001 errno=0
+func=atan2 op1=7ff80000.00000001 op2=3ff00000.00000000 result=7ff80000.00000001 errno=0
+func=atan2 op1=7ff80000.00000001 op2=bff00000.00000000 result=7ff80000.00000001 errno=0
+func=atan2 op1=fff80000.00000001 op2=7ff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=atan2 op1=fff80000.00000001 op2=fff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=atan2 op1=fff80000.00000001 op2=7ff80000.00000001 result=7ff80000.00000001 errno=0
+func=atan2 op1=fff80000.00000001 op2=fff80000.00000001 result=7ff80000.00000001 errno=0
+func=atan2 op1=fff80000.00000001 op2=7ff00000.00000000 result=7ff80000.00000001 errno=0
+func=atan2 op1=fff80000.00000001 op2=fff00000.00000000 result=7ff80000.00000001 errno=0
+func=atan2 op1=fff80000.00000001 op2=00000000.00000000 result=7ff80000.00000001 errno=0
+func=atan2 op1=fff80000.00000001 op2=80000000.00000000 result=7ff80000.00000001 errno=0
+func=atan2 op1=fff80000.00000001 op2=3ff00000.00000000 result=7ff80000.00000001 errno=0
+func=atan2 op1=fff80000.00000001 op2=bff00000.00000000 result=7ff80000.00000001 errno=0
+func=atan2 op1=7ff00000.00000000 op2=7ff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=atan2 op1=7ff00000.00000000 op2=fff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=atan2 op1=7ff00000.00000000 op2=7ff80000.00000001 result=7ff80000.00000001 errno=0
+func=atan2 op1=7ff00000.00000000 op2=fff80000.00000001 result=7ff80000.00000001 errno=0
+func=atan2 op1=7ff00000.00000000 op2=7ff00000.00000000 result=3fe921fb.54442d18.469 errno=0
+func=atan2 op1=7ff00000.00000000 op2=fff00000.00000000 result=4002d97c.7f3321d2.34f errno=0
+func=atan2 op1=7ff00000.00000000 op2=00000000.00000000 result=3ff921fb.54442d18.469 errno=0
+func=atan2 op1=7ff00000.00000000 op2=80000000.00000000 result=3ff921fb.54442d18.469 errno=0
+func=atan2 op1=7ff00000.00000000 op2=3ff00000.00000000 result=3ff921fb.54442d18.469 errno=0
+func=atan2 op1=7ff00000.00000000 op2=bff00000.00000000 result=3ff921fb.54442d18.469 errno=0
+func=atan2 op1=fff00000.00000000 op2=7ff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=atan2 op1=fff00000.00000000 op2=fff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=atan2 op1=fff00000.00000000 op2=7ff80000.00000001 result=7ff80000.00000001 errno=0
+func=atan2 op1=fff00000.00000000 op2=fff80000.00000001 result=7ff80000.00000001 errno=0
+func=atan2 op1=fff00000.00000000 op2=7ff00000.00000000 result=bfe921fb.54442d18.469 errno=0
+func=atan2 op1=fff00000.00000000 op2=fff00000.00000000 result=c002d97c.7f3321d2.34f errno=0
+func=atan2 op1=fff00000.00000000 op2=00000000.00000000 result=bff921fb.54442d18.469 errno=0
+func=atan2 op1=fff00000.00000000 op2=80000000.00000000 result=bff921fb.54442d18.469 errno=0
+func=atan2 op1=fff00000.00000000 op2=3ff00000.00000000 result=bff921fb.54442d18.469 errno=0
+func=atan2 op1=fff00000.00000000 op2=bff00000.00000000 result=bff921fb.54442d18.469 errno=0
+func=atan2 op1=00000000.00000000 op2=7ff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=atan2 op1=00000000.00000000 op2=fff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=atan2 op1=00000000.00000000 op2=7ff80000.00000001 result=7ff80000.00000001 errno=0
+func=atan2 op1=00000000.00000000 op2=fff80000.00000001 result=7ff80000.00000001 errno=0
+func=atan2 op1=00000000.00000000 op2=7ff00000.00000000 result=00000000.00000000 errno=0
+func=atan2 op1=00000000.00000000 op2=fff00000.00000000 result=400921fb.54442d18.469 errno=0
+func=atan2 op1=00000000.00000000 op2=00000000.00000000 result=00000000.00000000 errno=0
+func=atan2 op1=00000000.00000000 op2=80000000.00000000 result=400921fb.54442d18.469 errno=0
+func=atan2 op1=00000000.00000000 op2=3ff00000.00000000 result=00000000.00000000 errno=0
+func=atan2 op1=00000000.00000000 op2=bff00000.00000000 result=400921fb.54442d18.469 errno=0
+; No exception is raised on certain machines (different version of glibc)
+; Same issue encountered with other function similar to x close to 0
+; Could be due to function so boring no flop is involved in some implementations
+func=atan2 op1=00000000.00000001 op2=3ff00000.00000000 result=00000000.00000001 errno=0 maybestatus=ux
+func=atan2 op1=80000000.00000000 op2=7ff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=atan2 op1=80000000.00000000 op2=fff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=atan2 op1=80000000.00000000 op2=7ff80000.00000001 result=7ff80000.00000001 errno=0
+func=atan2 op1=80000000.00000000 op2=fff80000.00000001 result=7ff80000.00000001 errno=0
+func=atan2 op1=80000000.00000000 op2=7ff00000.00000000 result=80000000.00000000 errno=0
+func=atan2 op1=80000000.00000000 op2=fff00000.00000000 result=c00921fb.54442d18.469 errno=0
+func=atan2 op1=80000000.00000000 op2=00000000.00000000 result=80000000.00000000 errno=0
+func=atan2 op1=80000000.00000000 op2=80000000.00000000 result=c00921fb.54442d18.469 errno=0
+func=atan2 op1=80000000.00000000 op2=3ff00000.00000000 result=80000000.00000000 errno=0
+func=atan2 op1=80000000.00000000 op2=bff00000.00000000 result=c00921fb.54442d18.469 errno=0
+; No exception is raised on certain machines (different version of glibc)
+; Same issue encountered with other function similar to x close to 0
+; Could be due to function so boring no flop is involved in some implementations
+func=atan2 op1=80000000.00000001 op2=3ff00000.00000000 result=80000000.00000001 errno=0 maybestatus=ux
+func=atan2 op1=3ff00000.00000000 op2=7ff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=atan2 op1=3ff00000.00000000 op2=fff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=atan2 op1=3ff00000.00000000 op2=7ff80000.00000001 result=7ff80000.00000001 errno=0
+func=atan2 op1=3ff00000.00000000 op2=fff80000.00000001 result=7ff80000.00000001 errno=0
+func=atan2 op1=3ff00000.00000000 op2=7ff00000.00000000 result=00000000.00000000 errno=0
+func=atan2 op1=3ff00000.00000000 op2=fff00000.00000000 result=400921fb.54442d18.469 errno=0
+func=atan2 op1=3ff00000.00000000 op2=00000000.00000000 result=3ff921fb.54442d18.469 errno=0
+func=atan2 op1=3ff00000.00000000 op2=80000000.00000000 result=3ff921fb.54442d18.469 errno=0
+func=atan2 op1=3ff00000.00000000 op2=3ff00000.00000000 result=3fe921fb.54442d18.469 errno=0
+func=atan2 op1=3ff00000.00000000 op2=bff00000.00000000 result=4002d97c.7f3321d2.34f errno=0
+func=atan2 op1=bff00000.00000000 op2=7ff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=atan2 op1=bff00000.00000000 op2=fff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=atan2 op1=bff00000.00000000 op2=7ff80000.00000001 result=7ff80000.00000001 errno=0
+func=atan2 op1=bff00000.00000000 op2=fff80000.00000001 result=7ff80000.00000001 errno=0
+func=atan2 op1=bff00000.00000000 op2=7ff00000.00000000 result=80000000.00000000 errno=0
+func=atan2 op1=bff00000.00000000 op2=fff00000.00000000 result=c00921fb.54442d18.469 errno=0
+func=atan2 op1=bff00000.00000000 op2=00000000.00000000 result=bff921fb.54442d18.469 errno=0
+func=atan2 op1=bff00000.00000000 op2=80000000.00000000 result=bff921fb.54442d18.469 errno=0
+func=atan2 op1=bff00000.00000000 op2=3ff00000.00000000 result=bfe921fb.54442d18.469 errno=0
+func=atan2 op1=bff00000.00000000 op2=bff00000.00000000 result=c002d97c.7f3321d2.34f errno=0
+func=atan2 op1=3ff00000.00000000 op2=3ff00000.00000000 result=3fe921fb.54442d18 errno=0
diff --git a/math/test/testcases/directed/atan2f.tst b/math/test/testcases/directed/atan2f.tst
new file mode 100644
index 000000000000..e637fe0eba24
--- /dev/null
+++ b/math/test/testcases/directed/atan2f.tst
@@ -0,0 +1,121 @@
+; atan2f.tst
+;
+; Copyright (c) 1999-2024, Arm Limited.
+; SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
+
+func=atan2f op1=7f800001 op2=7f800001 result=7fc00001 errno=0 status=i
+func=atan2f op1=7f800001 op2=ff800001 result=7fc00001 errno=0 status=i
+func=atan2f op1=7f800001 op2=7fc00001 result=7fc00001 errno=0 status=i
+func=atan2f op1=7f800001 op2=ffc00001 result=7fc00001 errno=0 status=i
+func=atan2f op1=7f800001 op2=7f800000 result=7fc00001 errno=0 status=i
+func=atan2f op1=7f800001 op2=ff800000 result=7fc00001 errno=0 status=i
+func=atan2f op1=7f800001 op2=00000000 result=7fc00001 errno=0 status=i
+func=atan2f op1=7f800001 op2=80000000 result=7fc00001 errno=0 status=i
+func=atan2f op1=7f800001 op2=3f800000 result=7fc00001 errno=0 status=i
+func=atan2f op1=7f800001 op2=bf800000 result=7fc00001 errno=0 status=i
+func=atan2f op1=ff800001 op2=7f800001 result=7fc00001 errno=0 status=i
+func=atan2f op1=ff800001 op2=ff800001 result=7fc00001 errno=0 status=i
+func=atan2f op1=ff800001 op2=7fc00001 result=7fc00001 errno=0 status=i
+func=atan2f op1=ff800001 op2=ffc00001 result=7fc00001 errno=0 status=i
+func=atan2f op1=ff800001 op2=7f800000 result=7fc00001 errno=0 status=i
+func=atan2f op1=ff800001 op2=ff800000 result=7fc00001 errno=0 status=i
+func=atan2f op1=ff800001 op2=00000000 result=7fc00001 errno=0 status=i
+func=atan2f op1=ff800001 op2=80000000 result=7fc00001 errno=0 status=i
+func=atan2f op1=ff800001 op2=3f800000 result=7fc00001 errno=0 status=i
+func=atan2f op1=ff800001 op2=bf800000 result=7fc00001 errno=0 status=i
+func=atan2f op1=7fc00001 op2=7f800001 result=7fc00001 errno=0 status=i
+func=atan2f op1=7fc00001 op2=ff800001 result=7fc00001 errno=0 status=i
+func=atan2f op1=7fc00001 op2=7fc00001 result=7fc00001 errno=0
+func=atan2f op1=7fc00001 op2=ffc00001 result=7fc00001 errno=0
+func=atan2f op1=7fc00001 op2=7f800000 result=7fc00001 errno=0
+func=atan2f op1=7fc00001 op2=ff800000 result=7fc00001 errno=0
+func=atan2f op1=7fc00001 op2=00000000 result=7fc00001 errno=0
+func=atan2f op1=7fc00001 op2=80000000 result=7fc00001 errno=0
+func=atan2f op1=7fc00001 op2=3f800000 result=7fc00001 errno=0
+func=atan2f op1=7fc00001 op2=bf800000 result=7fc00001 errno=0
+func=atan2f op1=ffc00001 op2=7f800001 result=7fc00001 errno=0 status=i
+func=atan2f op1=ffc00001 op2=ff800001 result=7fc00001 errno=0 status=i
+func=atan2f op1=ffc00001 op2=7fc00001 result=ffc00001 errno=0
+func=atan2f op1=ffc00001 op2=ffc00001 result=ffc00001 errno=0
+func=atan2f op1=ffc00001 op2=7f800000 result=ffc00001 errno=0
+func=atan2f op1=ffc00001 op2=ff800000 result=ffc00001 errno=0
+func=atan2f op1=ffc00001 op2=00000000 result=ffc00001 errno=0
+func=atan2f op1=ffc00001 op2=80000000 result=ffc00001 errno=0
+func=atan2f op1=ffc00001 op2=3f800000 result=ffc00001 errno=0
+func=atan2f op1=ffc00001 op2=bf800000 result=ffc00001 errno=0
+func=atan2f op1=7f800000 op2=7f800001 result=7fc00001 errno=0 status=i
+func=atan2f op1=7f800000 op2=ff800001 result=7fc00001 errno=0 status=i
+func=atan2f op1=7f800000 op2=7fc00001 result=7fc00001 errno=0
+func=atan2f op1=7f800000 op2=ffc00001 result=7fc00001 errno=0
+func=atan2f op1=7f800000 op2=7f800000 result=3f490fda.a22 errno=0
+func=atan2f op1=7f800000 op2=ff800000 result=4016cbe3.f99 errno=0
+func=atan2f op1=7f800000 op2=00000000 result=3fc90fda.a22 errno=0
+func=atan2f op1=7f800000 op2=80000000 result=3fc90fda.a22 errno=0
+func=atan2f op1=7f800000 op2=3f800000 result=3fc90fda.a22 errno=0
+func=atan2f op1=7f800000 op2=bf800000 result=3fc90fda.a22 errno=0
+func=atan2f op1=ff800000 op2=7f800001 result=7fc00001 errno=0 status=i
+func=atan2f op1=ff800000 op2=ff800001 result=7fc00001 errno=0 status=i
+func=atan2f op1=ff800000 op2=7fc00001 result=7fc00001 errno=0
+func=atan2f op1=ff800000 op2=ffc00001 result=ffc00001 errno=0
+func=atan2f op1=ff800000 op2=7f800000 result=bf490fda.a22 errno=0
+func=atan2f op1=ff800000 op2=ff800000 result=c016cbe3.f99 errno=0
+func=atan2f op1=ff800000 op2=00000000 result=bfc90fda.a22 errno=0
+func=atan2f op1=ff800000 op2=80000000 result=bfc90fda.a22 errno=0
+func=atan2f op1=ff800000 op2=3f800000 result=bfc90fda.a22 errno=0
+func=atan2f op1=ff800000 op2=bf800000 result=bfc90fda.a22 errno=0
+func=atan2f op1=00000000 op2=7f800001 result=7fc00001 errno=0 status=i
+func=atan2f op1=00000000 op2=ff800001 result=7fc00001 errno=0 status=i
+func=atan2f op1=00000000 op2=7fc00001 result=7fc00001 errno=0
+func=atan2f op1=00000000 op2=ffc00001 result=ffc00001 errno=0
+func=atan2f op1=00000000 op2=7f800000 result=00000000 errno=0
+func=atan2f op1=00000000 op2=ff800000 result=40490fda.a22 errno=0
+func=atan2f op1=00000000 op2=00000000 result=00000000 errno=0
+func=atan2f op1=00000000 op2=80000000 result=40490fda.a22 errno=0
+func=atan2f op1=00000000 op2=3f800000 result=00000000 errno=0
+func=atan2f op1=00000000 op2=bf800000 result=40490fda.a22 errno=0
+; No exception is raised on certain machines (different version of glibc)
+; Same issue encountered with other function similar to x close to 0
+; Could be due to function so boring no flop is involved in some implementations
+func=atan2f op1=00000001 op2=3f800000 result=00000001 errno=0 maybestatus=ux
+
+func=atan2f op1=80000000 op2=7f800001 result=7fc00001 errno=0 status=i
+func=atan2f op1=80000000 op2=ff800001 result=7fc00001 errno=0 status=i
+func=atan2f op1=80000000 op2=7fc00001 result=7fc00001 errno=0
+func=atan2f op1=80000000 op2=ffc00001 result=ffc00001 errno=0
+func=atan2f op1=80000000 op2=7f800000 result=80000000 errno=0
+func=atan2f op1=80000000 op2=ff800000 result=c0490fda.a22 errno=0
+func=atan2f op1=80000000 op2=00000000 result=80000000 errno=0
+func=atan2f op1=80000000 op2=80000000 result=c0490fda.a22 errno=0
+func=atan2f op1=80000000 op2=3f800000 result=80000000 errno=0
+func=atan2f op1=80000000 op2=bf800000 result=c0490fda.a22 errno=0
+; No exception is raised on certain machines (different version of glibc)
+; Same issue encountered with other function similar to x close to 0
+; Could be due to function so boring no flop is involved in some implementations
+func=atan2f op1=80000001 op2=3f800000 result=80000001 errno=0 maybestatus=ux
+
+func=atan2f op1=3f800000 op2=7f800001 result=7fc00001 errno=0 status=i
+func=atan2f op1=3f800000 op2=ff800001 result=7fc00001 errno=0 status=i
+func=atan2f op1=3f800000 op2=7fc00001 result=7fc00001 errno=0
+func=atan2f op1=3f800000 op2=ffc00001 result=ffc00001 errno=0
+func=atan2f op1=3f800000 op2=7f800000 result=00000000 errno=0
+func=atan2f op1=3f800000 op2=ff800000 result=40490fda.a22 errno=0
+func=atan2f op1=3f800000 op2=00000000 result=3fc90fda.a22 errno=0
+func=atan2f op1=3f800000 op2=80000000 result=3fc90fda.a22 errno=0
+func=atan2f op1=3f800000 op2=3f800000 result=3f490fda.a22 errno=0
+func=atan2f op1=3f800000 op2=bf800000 result=4016cbe3.f99 errno=0
+func=atan2f op1=bf800000 op2=7f800001 result=7fc00001 errno=0 status=i
+func=atan2f op1=bf800000 op2=ff800001 result=7fc00001 errno=0 status=i
+func=atan2f op1=bf800000 op2=7fc00001 result=7fc00001 errno=0
+func=atan2f op1=bf800000 op2=ffc00001 result=ffc00001 errno=0
+func=atan2f op1=bf800000 op2=7f800000 result=80000000 errno=0
+func=atan2f op1=bf800000 op2=ff800000 result=c0490fda.a22 errno=0
+func=atan2f op1=bf800000 op2=00000000 result=bfc90fda.a22 errno=0
+func=atan2f op1=bf800000 op2=80000000 result=bfc90fda.a22 errno=0
+func=atan2f op1=bf800000 op2=3f800000 result=bf490fda.a22 errno=0
+func=atan2f op1=bf800000 op2=bf800000 result=c016cbe3.f99 errno=0
+func=atan2f op1=8005f16d op2=002bb601 result=be0a60a5.d88 error=0
+func=atan2f op1=80818ec8 op2=80ba5db9 result=c0222eda.f42 error=0
+
+func=atan2f op1=ff7fffff op2=ff7fffff result=c016cbe3.f99 errno=0
+func=atan2f op1=bfc00001 op2=7f7fffff result=80300000.700 errno=0 status=u
+func=atan2f op1=80800001 op2=40000000 result=80400000.800 errno=0 status=u
diff --git a/math/test/testcases/directed/atanf.tst b/math/test/testcases/directed/atanf.tst
new file mode 100644
index 000000000000..8739ea89c3a2
--- /dev/null
+++ b/math/test/testcases/directed/atanf.tst
@@ -0,0 +1,22 @@
+; atanf.tst
+;
+; Copyright (c) 2007-2024, Arm Limited.
+; SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
+
+func=atanf op1=7fc00001 result=7fc00001 errno=0
+func=atanf op1=ffc00001 result=7fc00001 errno=0
+func=atanf op1=7f800001 result=7fc00001 errno=0 status=i
+func=atanf op1=ff800001 result=7fc00001 errno=0 status=i
+func=atanf op1=7f800000 result=3fc90fda.a22 errno=0
+func=atanf op1=ff800000 result=bfc90fda.a22 errno=0
+func=atanf op1=00000000 result=00000000 errno=0
+func=atanf op1=80000000 result=80000000 errno=0
+; Inconsistent behavior was detected for the following 2 cases.
+; No exception is raised with certain versions of glibc. Functions
+; approximated by x near zero may not generate/implement flops and
+; thus may not raise exceptions.
+func=atanf op1=00000001 result=00000001 errno=0 maybestatus=ux
+func=atanf op1=80000001 result=80000001 errno=0 maybestatus=ux
+
+func=atanf op1=3f800000 result=3f490fda.a22 errno=0
+func=atanf op1=bf800000 result=bf490fda.a22 errno=0
diff --git a/math/test/testcases/directed/atanh.tst b/math/test/testcases/directed/atanh.tst
new file mode 100644
index 000000000000..7ba297e5046c
--- /dev/null
+++ b/math/test/testcases/directed/atanh.tst
@@ -0,0 +1,22 @@
+; atanh.tst
+;
+; Copyright (c) 2009-2024, Arm Limited.
+; SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
+
+func=atanh op1=7ff80000.00000001 result=7ff80000.00000001 errno=0
+func=atanh op1=fff80000.00000001 result=7ff80000.00000001 errno=0
+func=atanh op1=7ff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=atanh op1=fff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=atanh op1=7ff00000.00000000 result=7ff80000.00000001 errno=EDOM status=i
+func=atanh op1=fff00000.00000000 result=7ff80000.00000001 errno=EDOM status=i
+func=atanh op1=3ff00000.00000001 result=7ff80000.00000001 errno=EDOM status=i
+func=atanh op1=bff00000.00000001 result=7ff80000.00000001 errno=EDOM status=i
+func=atanh op1=3ff00000.00000000 result=7ff00000.00000000 errno=ERANGE status=z
+func=atanh op1=bff00000.00000000 result=fff00000.00000000 errno=ERANGE status=z
+func=atanh op1=00000000.00000000 result=00000000.00000000 errno=0
+func=atanh op1=80000000.00000000 result=80000000.00000000 errno=0
+; No exception is raised with certain versions of glibc. Functions
+; approximated by x near zero may not generate/implement flops and
+; thus may not raise exceptions.
+func=atanh op1=00000000.00000001 result=00000000.00000001 errno=0 maybestatus=ux
+func=atanh op1=80000000.00000001 result=80000000.00000001 errno=0 maybestatus=ux
diff --git a/math/test/testcases/directed/atanhf.tst b/math/test/testcases/directed/atanhf.tst
new file mode 100644
index 000000000000..010012831b3c
--- /dev/null
+++ b/math/test/testcases/directed/atanhf.tst
@@ -0,0 +1,23 @@
+; atanhf.tst
+;
+; Copyright (c) 2009-2024, Arm Limited.
+; SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
+
+func=atanhf op1=7fc00001 result=7fc00001 errno=0
+func=atanhf op1=ffc00001 result=7fc00001 errno=0
+func=atanhf op1=7f800001 result=7fc00001 errno=0 status=i
+func=atanhf op1=ff800001 result=7fc00001 errno=0 status=i
+func=atanhf op1=7f800000 result=7fc00001 errno=EDOM status=i
+func=atanhf op1=ff800000 result=7fc00001 errno=EDOM status=i
+func=atanhf op1=3f800001 result=7fc00001 errno=EDOM status=i
+func=atanhf op1=bf800001 result=7fc00001 errno=EDOM status=i
+func=atanhf op1=3f800000 result=7f800000 errno=ERANGE status=z
+func=atanhf op1=bf800000 result=ff800000 errno=ERANGE status=z
+func=atanhf op1=00000000 result=00000000 errno=0
+func=atanhf op1=80000000 result=80000000 errno=0
+
+; No exception is raised with certain versions of glibc. Functions
+; approximated by x near zero may not generate/implement flops and
+; thus may not raise exceptions.
+func=atanhf op1=00000001 result=00000001 errno=0 maybestatus=ux
+func=atanhf op1=80000001 result=80000001 errno=0 maybestatus=ux
diff --git a/math/test/testcases/directed/cbrtf.tst b/math/test/testcases/directed/cbrtf.tst
new file mode 100644
index 000000000000..98942580c7a7
--- /dev/null
+++ b/math/test/testcases/directed/cbrtf.tst
@@ -0,0 +1,29 @@
+; cbrtf.tst
+;
+; Copyright (c) 2009-2024, Arm Limited.
+; SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
+
+func=cbrtf op1=7f800000 result=7f800000 errno=0
+func=cbrtf op1=ff800000 result=ff800000 errno=0
+func=cbrtf op1=7f800001 result=7fc00001 errno=0 status=i
+func=cbrtf op1=7fc00001 result=7fc00001 errno=0
+func=cbrtf op1=00000000 result=00000000 errno=0
+func=cbrtf op1=00000001 result=26a14517.cc7 errno=0
+func=cbrtf op1=00000002 result=26cb2ff5.29f errno=0
+func=cbrtf op1=00000003 result=26e89768.579 errno=0
+func=cbrtf op1=00000004 result=27000000.000 errno=0
+func=cbrtf op1=00400000 result=2a4b2ff5.29f errno=0
+func=cbrtf op1=00800000 result=2a800000.000 errno=0
+func=cbrtf op1=3f800000 result=3f800000.000 errno=0
+func=cbrtf op1=40000000 result=3fa14517.cc7 errno=0
+func=cbrtf op1=7f7fffff result=54cb2ff4.e63 errno=0
+func=cbrtf op1=80000000 result=80000000 errno=0
+func=cbrtf op1=80000001 result=a6a14517.cc7 errno=0
+func=cbrtf op1=80000002 result=a6cb2ff5.29f errno=0
+func=cbrtf op1=80000003 result=a6e89768.579 errno=0
+func=cbrtf op1=80000004 result=a7000000.000 errno=0
+func=cbrtf op1=80400000 result=aa4b2ff5.29f errno=0
+func=cbrtf op1=80800000 result=aa800000.000 errno=0
+func=cbrtf op1=bf800000 result=bf800000.000 errno=0
+func=cbrtf op1=c0000000 result=bfa14517.cc7 errno=0
+func=cbrtf op1=ff7fffff result=d4cb2ff4.e63 errno=0
diff --git a/math/test/testcases/directed/cosh.tst b/math/test/testcases/directed/cosh.tst
new file mode 100644
index 000000000000..4dc6fe4846dc
--- /dev/null
+++ b/math/test/testcases/directed/cosh.tst
@@ -0,0 +1,15 @@
+; cosh.tst
+;
+; Copyright (c) 1999-2024, Arm Limited.
+; SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
+
+func=cosh op1=7ff80000.00000001 result=7ff80000.00000001 errno=0
+func=cosh op1=fff80000.00000001 result=7ff80000.00000001 errno=0
+func=cosh op1=7ff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=cosh op1=fff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=cosh op1=7ff00000.00000000 result=7ff00000.00000000 errno=0
+func=cosh op1=7fefffff.ffffffff result=7ff00000.00000000 errno=ERANGE status=ox
+func=cosh op1=fff00000.00000000 result=7ff00000.00000000 errno=0
+func=cosh op1=ffefffff.ffffffff result=7ff00000.00000000 errno=ERANGE status=ox
+func=cosh op1=00000000.00000000 result=3ff00000.00000000 errno=0
+func=cosh op1=80000000.00000000 result=3ff00000.00000000 errno=0
diff --git a/math/test/testcases/directed/coshf.tst b/math/test/testcases/directed/coshf.tst
new file mode 100644
index 000000000000..d224baf486a5
--- /dev/null
+++ b/math/test/testcases/directed/coshf.tst
@@ -0,0 +1,15 @@
+; coshf.tst
+;
+; Copyright (c) 2007-2024, Arm Limited.
+; SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
+
+func=coshf op1=7fc00001 result=7fc00001 errno=0
+func=coshf op1=ffc00001 result=7fc00001 errno=0
+func=coshf op1=7f800001 result=7fc00001 errno=0 status=i
+func=coshf op1=ff800001 result=7fc00001 errno=0 status=i
+func=coshf op1=7f800000 result=7f800000 errno=0
+func=coshf op1=7f7fffff result=7f800000 errno=ERANGE status=ox
+func=coshf op1=ff800000 result=7f800000 errno=0
+func=coshf op1=ff7fffff result=7f800000 errno=ERANGE status=ox
+func=coshf op1=00000000 result=3f800000 errno=0
+func=coshf op1=80000000 result=3f800000 errno=0
diff --git a/math/test/testcases/directed/erfc.tst b/math/test/testcases/directed/erfc.tst
new file mode 100644
index 000000000000..249e7343eac2
--- /dev/null
+++ b/math/test/testcases/directed/erfc.tst
@@ -0,0 +1,23 @@
+; erfc.tst - Directed test cases for erfc
+;
+; Copyright (c) 2022-2024, Arm Limited.
+; SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
+
+func=erfc op1=7ff80000.00000001 result=7ff80000.00000001 errno=0
+func=erfc op1=fff80000.00000001 result=7ff80000.00000001 errno=0
+func=erfc op1=7ff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=erfc op1=fff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=erfc op1=7ff00000.00000000 result=00000000.00000000 errno=0
+func=erfc op1=7fefffff.ffffffff result=00000000.00000000 errno=ERANGE status=ux
+; We deliberately turned off errno setting in erf, as standard simply
+; state that errno `may` be set to ERANGE in case of underflow.
+; As a result the following condition on errno cannot be satisfied.
+;
+; func=erfc op1=403b44af.48b01531 result=00000000.00000000 errno=ERANGE status=ux
+;
+func=erfc op1=c03b44af.48b01531 result=40000000.00000000 errno=0
+func=erfc op1=403bffff.ffffffff result=00000000.00000000 errno=ERANGE status=ux
+func=erfc op1=c03bffff.ffffffff result=40000000.00000000 errno=0
+func=erfc op1=fff00000.00000000 result=40000000.00000000 errno=0
+func=erfc op1=00000000.00000000 result=3ff00000.00000000 errno=0
+func=erfc op1=80000000.00000000 result=3ff00000.00000000 errno=0
diff --git a/math/test/testcases/directed/erfcf.tst b/math/test/testcases/directed/erfcf.tst
new file mode 100644
index 000000000000..22a1a8f236d8
--- /dev/null
+++ b/math/test/testcases/directed/erfcf.tst
@@ -0,0 +1,14 @@
+; erfcf.tst - Directed test cases for erfcf
+;
+; Copyright (c) 2007-2024, Arm Limited.
+; SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
+
+func=erfcf op1=7fc00001 result=7fc00001 errno=0
+func=erfcf op1=ffc00001 result=7fc00001 errno=0
+func=erfcf op1=7f800001 result=7fc00001 errno=0 status=i
+func=erfcf op1=ff800001 result=7fc00001 errno=0 status=i
+func=erfcf op1=7f800000 result=00000000 errno=0
+func=erfcf op1=7f7fffff result=00000000 errno=ERANGE status=ux
+func=erfcf op1=ff800000 result=40000000 errno=0
+func=erfcf op1=00000000 result=3f800000 errno=0
+func=erfcf op1=80000000 result=3f800000 errno=0
diff --git a/math/test/testcases/directed/expm1.tst b/math/test/testcases/directed/expm1.tst
new file mode 100644
index 000000000000..3d58c6b3f161
--- /dev/null
+++ b/math/test/testcases/directed/expm1.tst
@@ -0,0 +1,21 @@
+; expm1.tst
+;
+; Copyright (c) 2009-2024, Arm Limited.
+; SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
+
+func=expm1 op1=7ff80000.00000001 result=7ff80000.00000001 errno=0
+func=expm1 op1=fff80000.00000001 result=7ff80000.00000001 errno=0
+func=expm1 op1=7ff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=expm1 op1=fff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=expm1 op1=7ff00000.00000000 result=7ff00000.00000000 errno=0
+func=expm1 op1=7fefffff.ffffffff result=7ff00000.00000000 errno=ERANGE status=ox
+func=expm1 op1=fff00000.00000000 result=bff00000.00000000 errno=0
+func=expm1 op1=ffefffff.ffffffff result=bff00000.00000000 errno=0
+func=expm1 op1=00000000.00000000 result=00000000.00000000 errno=0
+func=expm1 op1=80000000.00000000 result=80000000.00000000 errno=0
+; Inconsistent behavior was detected for the following 2 cases.
+; No exception is raised with certain versions of glibc. Functions
+; approximated by x near zero may not generate/implement flops and
+; thus may not raise exceptions.
+func=expm1 op1=00000000.00000001 result=00000000.00000001 errno=0 maybestatus=ux
+func=expm1 op1=80000000.00000001 result=80000000.00000001 errno=0 maybestatus=ux
diff --git a/math/test/testcases/directed/expm1f.tst b/math/test/testcases/directed/expm1f.tst
new file mode 100644
index 000000000000..44a15d679870
--- /dev/null
+++ b/math/test/testcases/directed/expm1f.tst
@@ -0,0 +1,57 @@
+; expm1f.tst
+;
+; Copyright (c) 2009-2024, Arm Limited.
+; SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
+
+func=expm1f op1=7fc00001 result=7fc00001 errno=0
+func=expm1f op1=ffc00001 result=7fc00001 errno=0
+func=expm1f op1=7f800001 result=7fc00001 errno=0 status=i
+func=expm1f op1=ff800001 result=7fc00001 errno=0 status=i
+func=expm1f op1=7f800000 result=7f800000 errno=0
+func=expm1f op1=7f7fffff result=7f800000 errno=ERANGE status=ox
+func=expm1f op1=ff800000 result=bf800000 errno=0
+func=expm1f op1=ff7fffff result=bf800000 errno=0
+func=expm1f op1=00000000 result=00000000 errno=0
+func=expm1f op1=80000000 result=80000000 errno=0
+
+; No exception is raised with certain versions of glibc. Functions
+; approximated by x near zero may not generate/implement flops and
+; thus may not raise exceptions.
+
+func=expm1f op1=00000001 result=00000001 errno=0 maybestatus=ux
+func=expm1f op1=80000001 result=80000001 errno=0 maybestatus=ux
+
+func=expm1f op1=42b145c0 result=7f6ac2dd.9b8 errno=0
+
+; Check both sides of the over/underflow thresholds in the code.
+func=expm1f op1=c2000000 result=bf7fffff.fff error=0
+func=expm1f op1=c2000001 result=bf7fffff.fff error=0
+func=expm1f op1=43000000 result=7f800000 error=overflow
+func=expm1f op1=43000001 result=7f800000 error=overflow
+func=expm1f op1=c2a80000 result=bf800000.000 error=0
+func=expm1f op1=c2a80001 result=bf800000.000 error=0
+
+; Check values for which exp goes denormal. expm1f should not report
+; spurious overflow.
+func=expm1f op1=c2b00f34 result=bf800000.000 error=0
+func=expm1f op1=c2ce8ed0 result=bf800000.000 error=0
+func=expm1f op1=c2dc6bba result=bf800000.000 error=0
+
+; Regression tests for significance loss when the two components of
+; the result have opposite sign but similar magnitude
+func=expm1f op1=be8516c1 result=be6a652b.0dc error=0
+func=expm1f op1=be851714 result=be6a65ab.0e5 error=0
+func=expm1f op1=be851cc7 result=be6a6e75.111 error=0
+func=expm1f op1=be851d1a result=be6a6ef5.102 error=0
+func=expm1f op1=be851d6d result=be6a6f75.0f2 error=0
+func=expm1f op1=be852065 result=be6a7409.0e4 error=0
+func=expm1f op1=be8520b8 result=be6a7489.0c7 error=0
+func=expm1f op1=be85210b result=be6a7509.0a8 error=0
+func=expm1f op1=be855401 result=be6ac39b.0d5 error=0
+func=expm1f op1=be933307 result=be7fdbf0.d8d error=0
+func=expm1f op1=be92ed6b result=be7f737a.d81 error=0
+func=expm1f op1=be933b90 result=be7fe8be.d76 error=0
+func=expm1f op1=3eb11364 result=3ed38deb.0c0 error=0
+func=expm1f op1=3f28e830 result=3f6f344b.0da error=0
+func=expm1f op1=3eb1578f result=3ed3ee47.13b error=0
+func=expm1f op1=3f50176a result=3fa08e36.fea error=0
diff --git a/math/test/testcases/directed/log10.tst b/math/test/testcases/directed/log10.tst
new file mode 100644
index 000000000000..3ff252013498
--- /dev/null
+++ b/math/test/testcases/directed/log10.tst
@@ -0,0 +1,16 @@
+; log10.tst
+;
+; Copyright (c) 2007-2024, Arm Limited.
+; SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
+
+func=log10 op1=7ff80000.00000001 result=7ff80000.00000001 errno=0
+func=log10 op1=fff80000.00000001 result=7ff80000.00000001 errno=0
+func=log10 op1=7ff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=log10 op1=fff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=log10 op1=fff02000.00000000 result=7ff80000.00000001 errno=0 status=i
+func=log10 op1=7ff00000.00000000 result=7ff00000.00000000 errno=0
+func=log10 op1=3ff00000.00000000 result=00000000.00000000 errno=0
+func=log10 op1=fff00000.00000000 result=7ff80000.00000001 errno=EDOM status=i
+func=log10 op1=00000000.00000000 result=fff00000.00000000 errno=ERANGE status=z
+func=log10 op1=80000000.00000000 result=fff00000.00000000 errno=ERANGE status=z
+func=log10 op1=80000000.00000001 result=7ff80000.00000001 errno=EDOM status=i
diff --git a/math/test/testcases/directed/log10f.tst b/math/test/testcases/directed/log10f.tst
new file mode 100644
index 000000000000..5c83e3f5e9b4
--- /dev/null
+++ b/math/test/testcases/directed/log10f.tst
@@ -0,0 +1,69 @@
+; log10f.tst
+;
+; Copyright (c) 2007-2024, Arm Limited.
+; SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
+
+func=log10f op1=7fc00001 result=7fc00001 errno=0
+func=log10f op1=ffc00001 result=7fc00001 errno=0
+func=log10f op1=7f800001 result=7fc00001 errno=0 status=i
+func=log10f op1=ff800001 result=7fc00001 errno=0 status=i
+func=log10f op1=ff810000 result=7fc00001 errno=0 status=i
+func=log10f op1=7f800000 result=7f800000 errno=0
+func=log10f op1=3f800000 result=00000000 errno=0
+func=log10f op1=ff800000 result=7fc00001 errno=EDOM status=i
+func=log10f op1=00000000 result=ff800000 errno=ERANGE status=z
+func=log10f op1=80000000 result=ff800000 errno=ERANGE status=z
+func=log10f op1=80000001 result=7fc00001 errno=EDOM status=i
+
+; Directed tests for the special-case handling of log10 of things
+; very near 1
+func=log10f op1=3f81a618 result=3bb62472.b92 error=0
+func=log10f op1=3f876783 result=3cc811f4.26c error=0
+func=log10f op1=3f816af8 result=3b9cc4c7.057 error=0
+func=log10f op1=3f7bed7d result=bbe432cb.e23 error=0
+func=log10f op1=3f803ece result=3a59ff3a.a84 error=0
+func=log10f op1=3f80089f result=38ef9728.aa6 error=0
+func=log10f op1=3f86ab72 result=3cb4b711.457 error=0
+func=log10f op1=3f780854 result=bc60f953.904 error=0
+func=log10f op1=3f7c6d76 result=bbc7fd01.01c error=0
+func=log10f op1=3f85dff6 result=3c9fa76f.81f error=0
+func=log10f op1=3f7b87f4 result=bbfa9edc.be4 error=0
+func=log10f op1=3f81c710 result=3bc4457b.745 error=0
+func=log10f op1=3f80946d result=3b00a140.c06 error=0
+func=log10f op1=3f7e87ea result=bb23cd70.828 error=0
+func=log10f op1=3f811437 result=3b6ee960.b40 error=0
+func=log10f op1=3f858dcf result=3c971d9b.2ea error=0
+func=log10f op1=3f7f61a3 result=ba89b814.4e0 error=0
+func=log10f op1=3f82d642 result=3c1bfb8d.517 error=0
+func=log10f op1=3f80f3bc result=3b52ebe8.c75 error=0
+func=log10f op1=3f85eff9 result=3ca150d9.7e8 error=0
+func=log10f op1=3f843eb8 result=3c68263f.771 error=0
+func=log10f op1=3f78e691 result=bc481cf4.50a error=0
+func=log10f op1=3f87c56f result=3cd1b268.5e6 error=0
+func=log10f op1=3f83b711 result=3c4b94c5.918 error=0
+func=log10f op1=3f823b2b result=3bf5eb02.e2a error=0
+func=log10f op1=3f7f2c4e result=bab82c80.519 error=0
+func=log10f op1=3f83fc92 result=3c5a3ba1.543 error=0
+func=log10f op1=3f793956 result=bc3ee04e.03c error=0
+func=log10f op1=3f839ba5 result=3c45caca.92a error=0
+func=log10f op1=3f862f30 result=3ca7de76.16f error=0
+func=log10f op1=3f832a20 result=3c2dc6e9.afd error=0
+func=log10f op1=3f810296 result=3b5fb92a.429 error=0
+func=log10f op1=3f7e58c9 result=bb38655a.0a4 error=0
+func=log10f op1=3f8362e7 result=3c39cc65.d15 error=0
+func=log10f op1=3f7fdb85 result=b97d9016.40b error=0
+func=log10f op1=3f84484e result=3c6a29f2.f74 error=0
+func=log10f op1=3f861862 result=3ca5819e.f2d error=0
+func=log10f op1=3f7c027b result=bbdf912d.440 error=0
+func=log10f op1=3f867803 result=3caf6744.34d error=0
+func=log10f op1=3f789a89 result=bc509bce.458 error=0
+func=log10f op1=3f8361d9 result=3c399347.379 error=0
+func=log10f op1=3f7d3ac3 result=bb9ad93a.93d error=0
+func=log10f op1=3f7ee241 result=baf8bd12.a62 error=0
+func=log10f op1=3f83a1fd result=3c4721bd.0a4 error=0
+func=log10f op1=3f840da3 result=3c5dd375.675 error=0
+func=log10f op1=3f79c2fe result=bc2f8a60.8c5 error=0
+func=log10f op1=3f854a93 result=3c901cc9.add error=0
+func=log10f op1=3f87a50a result=3cce6125.cd6 error=0
+func=log10f op1=3f818bf5 result=3baaee68.a55 error=0
+func=log10f op1=3f830a44 result=3c2705c4.d87 error=0
diff --git a/math/test/testcases/directed/log1p.tst b/math/test/testcases/directed/log1p.tst
new file mode 100644
index 000000000000..109413a79e96
--- /dev/null
+++ b/math/test/testcases/directed/log1p.tst
@@ -0,0 +1,22 @@
+; log1p.tst
+;
+; Copyright (c) 2009-2024, Arm Limited.
+; SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
+
+func=log1p op1=7ff80000.00000001 result=7ff80000.00000001 errno=0
+func=log1p op1=fff80000.00000001 result=7ff80000.00000001 errno=0
+func=log1p op1=7ff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=log1p op1=fff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=log1p op1=fff02000.00000000 result=7ff80000.00000001 errno=0 status=i
+func=log1p op1=7ff00000.00000000 result=7ff00000.00000000 errno=0
+; Cases 6, 9 , 10, 11, 12 fail with certain versions of GLIBC and not others.
+; The main reason seems to be the handling of errno and exceptions.
+
+func=log1p op1=00000000.00000000 result=00000000.00000000 errno=0
+func=log1p op1=80000000.00000000 result=80000000.00000000 errno=0
+
+; No exception is raised with certain versions of glibc. Functions
+; approximated by x near zero may not generate/implement flops and
+; thus may not raise exceptions.
+func=log1p op1=00000000.00000001 result=00000000.00000001 errno=0 maybestatus=ux
+func=log1p op1=80000000.00000001 result=80000000.00000001 errno=0 maybestatus=ux
diff --git a/math/test/testcases/directed/log1pf.tst b/math/test/testcases/directed/log1pf.tst
new file mode 100644
index 000000000000..9655b9473612
--- /dev/null
+++ b/math/test/testcases/directed/log1pf.tst
@@ -0,0 +1,130 @@
+; log1pf.tst
+;
+; Copyright (c) 2009-2024, Arm Limited.
+; SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
+
+func=log1pf op1=7fc00001 result=7fc00001 errno=0
+func=log1pf op1=ffc00001 result=7fc00001 errno=0
+func=log1pf op1=7f800001 result=7fc00001 errno=0 status=i
+func=log1pf op1=ff800001 result=7fc00001 errno=0 status=i
+func=log1pf op1=ff810000 result=7fc00001 errno=0 status=i
+func=log1pf op1=7f800000 result=7f800000 errno=0
+
+; Cases 6, 9 , 10, 11, 12 fail with certain versions of GLIBC and not others.
+; The main reason seems to be the handling of errno and exceptions.
+
+func=log1pf op1=00000000 result=00000000 errno=0
+func=log1pf op1=80000000 result=80000000 errno=0
+
+; No exception is raised with certain versions of glibc. Functions
+; approximated by x near zero may not generate/implement flops and
+; thus may not raise exceptions.
+func=log1pf op1=00000001 result=00000001 errno=0 maybestatus=ux
+func=log1pf op1=80000001 result=80000001 errno=0 maybestatus=ux
+
+func=log1pf op1=3f1e91ee result=3ef6d127.fdb errno=0
+func=log1pf op1=3f201046 result=3ef8a881.fba errno=0
+func=log1pf op1=3f21b916 result=3efab23b.f9f errno=0
+func=log1pf op1=3f21bde6 result=3efab821.fee errno=0
+func=log1pf op1=3f22a5ee result=3efbd435.ff2 errno=0
+func=log1pf op1=3f231b56 result=3efc63b7.e26 errno=0
+func=log1pf op1=3f23ce96 result=3efd3e83.fc8 errno=0
+func=log1pf op1=3eee18c6 result=3ec38576.02e errno=0
+func=log1pf op1=3eee2f41 result=3ec394ce.057 errno=0
+func=log1pf op1=3eee770d result=3ec3c5cc.00c errno=0
+func=log1pf op1=3eee7fed result=3ec3cbda.065 errno=0
+func=log1pf op1=3eee8fb2 result=3ec3d69c.008 errno=0
+func=log1pf op1=3eeeb8eb result=3ec3f2ba.061 errno=0
+func=log1pf op1=3eeeccfd result=3ec4006a.01d errno=0
+func=log1pf op1=3eeef5f0 result=3ec41c56.020 errno=0
+func=log1pf op1=3eeeff12 result=3ec42290.00c errno=0
+func=log1pf op1=3eef05cf result=3ec42728.052 errno=0
+func=log1pf op1=3eef13d3 result=3ec430b6.00e errno=0
+func=log1pf op1=3eef2e70 result=3ec442da.04a errno=0
+func=log1pf op1=3eef3fbf result=3ec44ea6.055 errno=0
+func=log1pf op1=3eef3feb result=3ec44ec4.021 errno=0
+func=log1pf op1=3eef4399 result=3ec45146.011 errno=0
+func=log1pf op1=3eef452e result=3ec4525a.049 errno=0
+func=log1pf op1=3eef4ea9 result=3ec458d0.020 errno=0
+func=log1pf op1=3eef7365 result=3ec471d8.05e errno=0
+func=log1pf op1=3eefa38f result=3ec492a8.003 errno=0
+func=log1pf op1=3eefb1f1 result=3ec49c74.015 errno=0
+func=log1pf op1=3eefb334 result=3ec49d50.023 errno=0
+func=log1pf op1=3eefb3c1 result=3ec49db0.0bf errno=0
+func=log1pf op1=3eefb591 result=3ec49eec.15d errno=0
+func=log1pf op1=3eefd736 result=3ec4b5d6.02d errno=0
+func=log1pf op1=3eefd797 result=3ec4b618.114 errno=0
+func=log1pf op1=3eefee5d result=3ec4c59a.071 errno=0
+func=log1pf op1=3eeffff4 result=3ec4d194.0a7 errno=0
+func=log1pf op1=3ef00cd1 result=3ec4da56.025 errno=0
+func=log1pf op1=3ef0163a result=3ec4e0be.07a errno=0
+func=log1pf op1=3ef01e89 result=3ec4e666.007 errno=0
+func=log1pf op1=3ef02004 result=3ec4e768.00a errno=0
+func=log1pf op1=3ef02c40 result=3ec4efbc.017 errno=0
+func=log1pf op1=3ef05b50 result=3ec50fc4.031 errno=0
+func=log1pf op1=3ef05bb1 result=3ec51006.05f errno=0
+func=log1pf op1=3ef0651b result=3ec5166e.0d9 errno=0
+func=log1pf op1=3ef06609 result=3ec51710.02a errno=0
+func=log1pf op1=3ef0666a result=3ec51752.049 errno=0
+func=log1pf op1=3ef0791e result=3ec5240c.0a8 errno=0
+func=log1pf op1=3ef07d46 result=3ec526e0.00e errno=0
+func=log1pf op1=3ef091fd result=3ec534f8.03c errno=0
+func=log1pf op1=3ef09602 result=3ec537b4.128 errno=0
+func=log1pf op1=3ef09848 result=3ec53940.044 errno=0
+func=log1pf op1=3ef0a04f result=3ec53eb6.07d errno=0
+func=log1pf op1=3ef0ab6a result=3ec54644.062 errno=0
+func=log1pf op1=3ef0ae49 result=3ec54838.002 errno=0
+func=log1pf op1=3ef0c1b8 result=3ec55570.000 errno=0
+func=log1pf op1=3ef0ca06 result=3ec55b16.00d errno=0
+func=log1pf op1=3ef0cc29 result=3ec55c8a.095 errno=0
+func=log1pf op1=3ef0d228 result=3ec5609e.04f errno=0
+func=log1pf op1=3ef0d8c0 result=3ec5651a.05e errno=0
+func=log1pf op1=3ef0dc0c result=3ec56758.029 errno=0
+func=log1pf op1=3ef0e0e8 result=3ec56aa6.02e errno=0
+func=log1pf op1=3ef0e502 result=3ec56d70.102 errno=0
+func=log1pf op1=3ef0e754 result=3ec56f04.017 errno=0
+func=log1pf op1=3ef0efe9 result=3ec574da.01c errno=0
+func=log1pf op1=3ef0f309 result=3ec576fa.016 errno=0
+func=log1pf op1=3ef0f499 result=3ec5780a.005 errno=0
+func=log1pf op1=3ef0f6c2 result=3ec57982.083 errno=0
+func=log1pf op1=3ef0f852 result=3ec57a92.05d errno=0
+func=log1pf op1=3ef0f9e2 result=3ec57ba2.02e errno=0
+func=log1pf op1=3ef119ee result=3ec5916c.024 errno=0
+func=log1pf op1=3ef11edf result=3ec594c8.03d errno=0
+func=log1pf op1=3ef128c4 result=3ec59b82.001 errno=0
+func=log1pf op1=3ef12ac1 result=3ec59cdc.04b errno=0
+func=log1pf op1=3ef12fea result=3ec5a05e.045 errno=0
+func=log1pf op1=3ef131e7 result=3ec5a1b8.05a errno=0
+func=log1pf op1=3ef134e1 result=3ec5a3be.00e errno=0
+func=log1pf op1=3ef1397a result=3ec5a6de.127 errno=0
+func=log1pf op1=3ef13ade result=3ec5a7d0.0f6 errno=0
+func=log1pf op1=3ef13c0d result=3ec5a89e.054 errno=0
+func=log1pf op1=3ef13d71 result=3ec5a990.016 errno=0
+func=log1pf op1=3ef14074 result=3ec5ab9c.12c errno=0
+func=log1pf op1=3ef146a0 result=3ec5afce.035 errno=0
+func=log1pf op1=3ef14a39 result=3ec5b240.024 errno=0
+func=log1pf op1=3ef14d39 result=3ec5b44a.00c errno=0
+func=log1pf op1=3ef152a3 result=3ec5b7f8.04d errno=0
+func=log1pf op1=3ef170a1 result=3ec5cc5a.021 errno=0
+func=log1pf op1=3ef17855 result=3ec5d196.0dc errno=0
+func=log1pf op1=3ef17ece result=3ec5d5fc.010 errno=0
+func=log1pf op1=3ef1810c result=3ec5d782.08e errno=0
+func=log1pf op1=3ef18da9 result=3ec5e014.0ae errno=0
+func=log1pf op1=3ef19054 result=3ec5e1e4.1a2 errno=0
+func=log1pf op1=3ef190ea result=3ec5e24a.048 errno=0
+func=log1pf op1=3ef1a739 result=3ec5f172.0d8 errno=0
+func=log1pf op1=3ef1a83c result=3ec5f222.018 errno=0
+func=log1pf op1=3ef1bbcc result=3ec5ff6c.09d errno=0
+func=log1pf op1=3ef1bd3c result=3ec60066.03a errno=0
+func=log1pf op1=3ef1d6ee result=3ec611da.056 errno=0
+func=log1pf op1=3ef1de36 result=3ec616cc.01b errno=0
+func=log1pf op1=3ef1e623 result=3ec61c2e.008 errno=0
+func=log1pf op1=3ef1e9b1 result=3ec61e98.029 errno=0
+func=log1pf op1=3ef1ee19 result=3ec62196.0d8 errno=0
+func=log1pf op1=3ef1f13a result=3ec623b6.039 errno=0
+func=log1pf op1=3ef1f1a7 result=3ec62400.091 errno=0
+func=log1pf op1=3ef1f214 result=3ec6244a.0e8 errno=0
+func=log1pf op1=3ef206e1 result=3ec6326a.09b errno=0
+func=log1pf op1=3ef21245 result=3ec63a26.012 errno=0
+func=log1pf op1=3ef217fd result=3ec63e08.048 errno=0
+func=log1pf op1=3ef2186a result=3ec63e52.063 errno=0
diff --git a/math/test/testcases/directed/sinh.tst b/math/test/testcases/directed/sinh.tst
new file mode 100644
index 000000000000..ab0d84b84d9e
--- /dev/null
+++ b/math/test/testcases/directed/sinh.tst
@@ -0,0 +1,21 @@
+; sinh.tst
+;
+; Copyright (c) 1999-2024, Arm Limited.
+; SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
+
+func=sinh op1=7ff80000.00000001 result=7ff80000.00000001 errno=0
+func=sinh op1=fff80000.00000001 result=7ff80000.00000001 errno=0
+func=sinh op1=7ff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=sinh op1=fff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=sinh op1=7ff00000.00000000 result=7ff00000.00000000 errno=0
+func=sinh op1=7fefffff.ffffffff result=7ff00000.00000000 errno=ERANGE status=ox
+func=sinh op1=fff00000.00000000 result=fff00000.00000000 errno=0
+func=sinh op1=ffefffff.ffffffff result=fff00000.00000000 errno=ERANGE status=ox
+func=sinh op1=00000000.00000000 result=00000000.00000000 errno=0
+func=sinh op1=80000000.00000000 result=80000000.00000000 errno=0
+
+; No exception is raised with certain versions of glibc. Functions
+; approximated by x near zero may not generate/implement flops and
+; thus may not raise exceptions.
+func=sinh op1=00000000.00000001 result=00000000.00000001 errno=0 maybestatus=ux
+func=sinh op1=80000000.00000001 result=80000000.00000001 errno=0 maybestatus=ux
diff --git a/math/test/testcases/directed/sinhf.tst b/math/test/testcases/directed/sinhf.tst
new file mode 100644
index 000000000000..d9269c0fa405
--- /dev/null
+++ b/math/test/testcases/directed/sinhf.tst
@@ -0,0 +1,21 @@
+; sinhf.tst
+;
+; Copyright (c) 2009-2024, Arm Limited.
+; SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
+
+func=sinhf op1=7fc00001 result=7fc00001 errno=0
+func=sinhf op1=ffc00001 result=7fc00001 errno=0
+func=sinhf op1=7f800001 result=7fc00001 errno=0 status=i
+func=sinhf op1=ff800001 result=7fc00001 errno=0 status=i
+func=sinhf op1=7f800000 result=7f800000 errno=0
+func=sinhf op1=7f7fffff result=7f800000 errno=ERANGE status=ox
+func=sinhf op1=ff800000 result=ff800000 errno=0
+func=sinhf op1=ff7fffff result=ff800000 errno=ERANGE status=ox
+func=sinhf op1=00000000 result=00000000 errno=0
+func=sinhf op1=80000000 result=80000000 errno=0
+
+; No exception is raised with certain versions of glibc. Functions
+; approximated by x near zero may not generate/implement flops and
+; thus may not raise exceptions.
+func=sinhf op1=00000001 result=00000001 errno=0 maybestatus=ux
+func=sinhf op1=80000001 result=80000001 errno=0 maybestatus=ux
diff --git a/math/test/testcases/directed/tanf.tst b/math/test/testcases/directed/tanf.tst
new file mode 100644
index 000000000000..e38142df6e3c
--- /dev/null
+++ b/math/test/testcases/directed/tanf.tst
@@ -0,0 +1,25 @@
+; tanf.tst
+;
+; Copyright (c) 2022-2024, Arm Limited.
+; SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
+
+func=tanf op1=7fc00001 result=7fc00001 errno=0
+func=tanf op1=ffc00001 result=7fc00001 errno=0
+func=tanf op1=7f800001 result=7fc00001 errno=0 status=i
+func=tanf op1=ff800001 result=7fc00001 errno=0 status=i
+func=tanf op1=7f800000 result=7fc00001 errno=EDOM status=i
+func=tanf op1=ff800000 result=7fc00001 errno=EDOM status=i
+func=tanf op1=00000000 result=00000000 errno=0
+func=tanf op1=80000000 result=80000000 errno=0
+; SDCOMP-26094: check tanf in the cases for which the range reducer
+; returns values furthest beyond its nominal upper bound of pi/4.
+func=tanf op1=46427f1b result=3f80396d.599 error=0
+func=tanf op1=4647e568 result=3f8039a6.c9f error=0
+func=tanf op1=46428bac result=3f803a03.148 error=0
+func=tanf op1=4647f1f9 result=3f803a3c.852 error=0
+func=tanf op1=4647fe8a result=3f803ad2.410 error=0
+func=tanf op1=45d8d7f1 result=bf800669.901 error=0
+func=tanf op1=45d371a4 result=bf800686.3cd error=0
+func=tanf op1=45ce0b57 result=bf8006a2.e9a error=0
+func=tanf op1=45d35882 result=bf80071b.bc4 error=0
+func=tanf op1=45cdf235 result=bf800738.693 error=0
diff --git a/math/test/testcases/directed/tanh.tst b/math/test/testcases/directed/tanh.tst
new file mode 100644
index 000000000000..e842063c0ef7
--- /dev/null
+++ b/math/test/testcases/directed/tanh.tst
@@ -0,0 +1,18 @@
+; tanh.tst
+;
+; Copyright (c) 1999-2024, Arm Limited.
+; SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
+
+func=tanh op1=7ff80000.00000001 result=7ff80000.00000001 errno=0
+func=tanh op1=fff80000.00000001 result=7ff80000.00000001 errno=0
+func=tanh op1=7ff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=tanh op1=fff00000.00000001 result=7ff80000.00000001 errno=0 status=i
+func=tanh op1=7ff00000.00000000 result=3ff00000.00000000 errno=0
+func=tanh op1=fff00000.00000000 result=bff00000.00000000 errno=0
+func=tanh op1=00000000.00000000 result=00000000.00000000 errno=0
+func=tanh op1=80000000.00000000 result=80000000.00000000 errno=0
+; No exception is raised with certain versions of glibc. Functions
+; approximated by x near zero may not generate/implement flops and
+; thus may not raise exceptions.
+func=tanh op1=00000000.00000001 result=00000000.00000001 errno=0 maybestatus=ux
+func=tanh op1=80000000.00000001 result=80000000.00000001 errno=0 maybestatus=ux
diff --git a/math/test/testcases/directed/tanhf.tst b/math/test/testcases/directed/tanhf.tst
new file mode 100644
index 000000000000..412aa12b3621
--- /dev/null
+++ b/math/test/testcases/directed/tanhf.tst
@@ -0,0 +1,20 @@
+; tanhf.tst
+;
+; Copyright (c) 2007-2024, Arm Limited.
+; SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
+
+func=tanhf op1=7fc00001 result=7fc00001 errno=0
+func=tanhf op1=ffc00001 result=7fc00001 errno=0
+func=tanhf op1=7f800001 result=7fc00001 errno=0 status=i
+func=tanhf op1=ff800001 result=7fc00001 errno=0 status=i
+func=tanhf op1=7f800000 result=3f800000 errno=0
+func=tanhf op1=ff800000 result=bf800000 errno=0
+func=tanhf op1=00000000 result=00000000 errno=0
+func=tanhf op1=80000000 result=80000000 errno=0
+; No exception is raised with certain versions of glibc. Functions
+; approximated by x near zero may not generate/implement flops and
+; thus may not raise exceptions.
+; func=tanhf op1=00000001 result=00000001 errno=0 maybestatus=ux
+; func=tanhf op1=80000001 result=80000001 errno=0 maybestatus=ux
+func=tanhf op1=00000001 result=00000001 errno=0 maybestatus=ux
+func=tanhf op1=80000001 result=80000001 errno=0 maybestatus=ux
diff --git a/math/test/trigpi_references.h b/math/test/trigpi_references.h
new file mode 100644
index 000000000000..3dc5a3173436
--- /dev/null
+++ b/math/test/trigpi_references.h
@@ -0,0 +1,106 @@
+/*
+ * Extended precision scalar reference functions for trigpi.
+ *
+ * Copyright (c) 2023-2024, Arm Limited.
+ * SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
+ */
+
+#include "math_config.h"
+
+#ifndef M_PIl
+# define M_PIl 3.141592653589793238462643383279502884l
+#endif
+
+long double
+arm_math_sinpil (long double x)
+{
+ /* sin(inf) should return nan, as defined by C23. */
+ if (isinf (x))
+ return __math_invalid (x);
+
+ long double ax = fabsl (x);
+
+ /* Return 0 for all values above 2^64 to prevent
+ overflow when casting to uint64_t. */
+ if (ax >= 0x1p64)
+ return x < 0 ? -0.0l : 0.0l;
+
+ /* All integer cases should return 0, with unchanged sign for zero. */
+ if (x == 0.0l)
+ return x;
+ if (ax == (uint64_t) ax)
+ return x < 0 ? -0.0l : 0.0l;
+
+ return sinl (x * M_PIl);
+}
+
+long double
+arm_math_cospil (long double x)
+{
+ /* cos(inf) should return nan, as defined by C23. */
+ if (isinf (x))
+ return __math_invalid (x);
+
+ long double ax = fabsl (x);
+
+ if (ax >= 0x1p64)
+ return 1;
+
+ uint64_t m = (uint64_t) ax;
+
+ /* Integer values of cospi(x) should return +/-1.
+ The sign depends on if x is odd or even. */
+ if (m == ax)
+ return (m & 1) ? -1 : 1;
+
+ /* Values of Integer + 0.5 should always return 0. */
+ if (ax - 0.5 == m || ax + 0.5 == m)
+ return 0;
+
+ return cosl (ax * M_PIl);
+}
+
+long double
+arm_math_tanpil (long double x)
+{
+ /* inf and x = n + 0.5 for any integral n should return nan. */
+ if (fabsl (x) >= 0x1p54l)
+ {
+ if (isinf (x))
+ return __math_invalid (x);
+ return x < 0 ? -0.0l : 0.0l;
+ }
+
+ long double i = roundl (x);
+ long double f = x - i;
+ int64_t m = (int64_t) i;
+
+ if (x == 0)
+ {
+ return x;
+ }
+ else if (x == i)
+ {
+ if (x < 0)
+ {
+ return m & 1 ? 0.0l : -0.0l;
+ }
+ else
+ {
+ return m & 1 ? -0.0l : 0.0l;
+ }
+ }
+ else if (fabsl (f) == 0.5l)
+ {
+ if (x < 0)
+ {
+ return m & 1 ? -1.0l / 0.0l : 1.0l / 0.0l;
+ }
+ else
+ {
+ return m & 1 ? 1.0l / 0.0l : -1.0l / 0.0l;
+ }
+ }
+
+ return tanl (f * M_PIl);
+}
diff --git a/math/test/ulp.c b/math/test/ulp.c
index 5ff29972e50e..0a75fe264630 100644
--- a/math/test/ulp.c
+++ b/math/test/ulp.c
@@ -1,10 +1,23 @@
/*
* ULP error checking tool for math functions.
*
- * Copyright (c) 2019-2023, Arm Limited.
+ * Copyright (c) 2019-2024, Arm Limited.
* SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
*/
+#if WANT_SVE_TESTS
+# if __aarch64__ && __linux__
+# ifdef __clang__
+# pragma clang attribute push(__attribute__((target("sve"))), \
+ apply_to = any(function))
+# else
+# pragma GCC target("+sve")
+# endif
+# else
+# error "SVE not supported - please disable WANT_SVE_TESTS"
+# endif
+#endif
+
#define _GNU_SOURCE
#include <ctype.h>
#include <fenv.h>
@@ -16,6 +29,8 @@
#include <string.h>
#include "mathlib.h"
+#include "trigpi_references.h"
+
/* Don't depend on mpfr by default. */
#ifndef USE_MPFR
# define USE_MPFR 0
@@ -24,50 +39,6 @@
# include <mpfr.h>
#endif
-static inline uint64_t
-asuint64 (double f)
-{
- union
- {
- double f;
- uint64_t i;
- } u = {f};
- return u.i;
-}
-
-static inline double
-asdouble (uint64_t i)
-{
- union
- {
- uint64_t i;
- double f;
- } u = {i};
- return u.f;
-}
-
-static inline uint32_t
-asuint (float f)
-{
- union
- {
- float f;
- uint32_t i;
- } u = {f};
- return u.i;
-}
-
-static inline float
-asfloat (uint32_t i)
-{
- union
- {
- uint32_t i;
- float f;
- } u = {i};
- return u.f;
-}
-
static uint64_t seed = 0x0123456789abcdef;
static uint64_t
rand64 (void)
@@ -198,68 +169,96 @@ next_d2 (void *g)
return (struct args_d2){asdouble (x), asdouble (x2)};
}
-struct conf
-{
- int r;
- int rc;
- int quiet;
- int mpfr;
- int fenv;
- unsigned long long n;
- double softlim;
- double errlim;
- int ignore_zero_sign;
-};
-
/* A bit of a hack: call vector functions twice with the same
input in lane 0 but a different value in other lanes: once
with an in-range value and then with a special case value. */
static int secondcall;
/* Wrappers for vector functions. */
-#ifdef __vpcs
-typedef __f32x4_t v_float;
-typedef __f64x2_t v_double;
+#if __aarch64__ && __linux__
/* First element of fv and dv may be changed by -c argument. */
static float fv[2] = {1.0f, -INFINITY};
static double dv[2] = {1.0, -INFINITY};
-static inline v_float argf(float x) { return (v_float){x,x,x,fv[secondcall]}; }
-static inline v_double argd(double x) { return (v_double){x,dv[secondcall]}; }
-#if WANT_SVE_MATH
+static inline float32x4_t
+argf (float x)
+{
+ return (float32x4_t){ x, x, x, fv[secondcall] };
+}
+static inline float64x2_t
+argd (double x)
+{
+ return (float64x2_t){ x, dv[secondcall] };
+}
+#if WANT_SVE_TESTS
#include <arm_sve.h>
-typedef __SVFloat32_t sv_float;
-typedef __SVFloat64_t sv_double;
-
-static inline sv_float svargf(float x) {
- int n = svcntw();
- float base[n];
- for (int i=0; i<n; i++)
- base[i] = (float)x;
- base[n-1] = (float) fv[secondcall];
- return svld1(svptrue_b32(), base);
-}
-static inline sv_double svargd(double x) {
- int n = svcntd();
- double base[n];
- for (int i=0; i<n; i++)
- base[i] = x;
- base[n-1] = dv[secondcall];
- return svld1(svptrue_b64(), base);
-}
-static inline float svretf(sv_float vec) {
- int n = svcntw();
- float res[n];
- svst1(svptrue_b32(), res, vec);
- return res[0];
-}
-static inline double svretd(sv_double vec) {
- int n = svcntd();
- double res[n];
- svst1(svptrue_b64(), res, vec);
- return res[0];
+
+static inline svfloat32_t
+svargf (float x)
+{
+ int n = svcntw ();
+ float base[n];
+ for (int i = 0; i < n; i++)
+ base[i] = (float) x;
+ base[n - 1] = (float) fv[secondcall];
+ return svld1 (svptrue_b32 (), base);
+}
+static inline svfloat64_t
+svargd (double x)
+{
+ int n = svcntd ();
+ double base[n];
+ for (int i = 0; i < n; i++)
+ base[i] = x;
+ base[n - 1] = dv[secondcall];
+ return svld1 (svptrue_b64 (), base);
+}
+static inline float
+svretf (svfloat32_t vec, svbool_t pg)
+{
+ return svlastb_f32 (svpfirst (pg, svpfalse ()), vec);
}
+static inline double
+svretd (svfloat64_t vec, svbool_t pg)
+{
+ return svlastb_f64 (svpfirst (pg, svpfalse ()), vec);
+}
+
+static inline svbool_t
+parse_pg (uint64_t p, int is_single)
+{
+ if (is_single)
+ {
+ uint32_t tmp[svcntw ()];
+ for (unsigned i = 0; i < svcntw (); i++)
+ tmp[i] = (p >> i) & 1;
+ return svcmpne (svptrue_b32 (), svld1 (svptrue_b32 (), tmp), 0);
+ }
+ else
+ {
+ uint64_t tmp[svcntd ()];
+ for (unsigned i = 0; i < svcntd (); i++)
+ tmp[i] = (p >> i) & 1;
+ return svcmpne (svptrue_b64 (), svld1 (svptrue_b64 (), tmp), 0);
+ }
+}
+# endif
#endif
+
+struct conf
+{
+ int r;
+ int rc;
+ int quiet;
+ int mpfr;
+ int fenv;
+ unsigned long long n;
+ double softlim;
+ double errlim;
+ int ignore_zero_sign;
+#if WANT_SVE_TESTS
+ svbool_t *pg;
#endif
+};
#include "test/ulp_wrappers.h"
@@ -269,12 +268,19 @@ struct fun
int arity;
int singleprec;
int twice;
+ int is_predicated;
union
{
float (*f1) (float);
float (*f2) (float, float);
double (*d1) (double);
double (*d2) (double, double);
+#if WANT_SVE_TESTS
+ float (*f1_pred) (svbool_t, float);
+ float (*f2_pred) (svbool_t, float, float);
+ double (*d1_pred) (svbool_t, double);
+ double (*d2_pred) (svbool_t, double, double);
+#endif
} fun;
union
{
@@ -294,44 +300,33 @@ struct fun
#endif
};
+// clang-format off
static const struct fun fun[] = {
#if USE_MPFR
-# define F(x, x_wrap, x_long, x_mpfr, a, s, t, twice) \
- {#x, a, s, twice, {.t = x_wrap}, {.t = x_long}, {.t = x_mpfr}},
+# define F(x, x_wrap, x_long, x_mpfr, a, s, t, twice) \
+ { #x, a, s, twice, 0, { .t = x_wrap }, { .t = x_long }, { .t = x_mpfr } },
+# define SVF(x, x_wrap, x_long, x_mpfr, a, s, t, twice) \
+ { #x, a, s, twice, 1, { .t##_pred = x_wrap }, { .t = x_long }, { .t = x_mpfr } },
#else
-# define F(x, x_wrap, x_long, x_mpfr, a, s, t, twice) \
- {#x, a, s, twice, {.t = x_wrap}, {.t = x_long}},
+# define F(x, x_wrap, x_long, x_mpfr, a, s, t, twice) \
+ { #x, a, s, twice, 0, { .t = x_wrap }, { .t = x_long } },
+# define SVF(x, x_wrap, x_long, x_mpfr, a, s, t, twice) \
+ { #x, a, s, twice, 1, { .t##_pred = x_wrap }, { .t = x_long } },
#endif
#define F1(x) F (x##f, x##f, x, mpfr_##x, 1, 1, f1, 0)
#define F2(x) F (x##f, x##f, x, mpfr_##x, 2, 1, f2, 0)
#define D1(x) F (x, x, x##l, mpfr_##x, 1, 0, d1, 0)
#define D2(x) F (x, x, x##l, mpfr_##x, 2, 0, d2, 0)
/* Neon routines. */
-#define VF1(x) F (__v_##x##f, v_##x##f, x, mpfr_##x, 1, 1, f1, 0)
-#define VF2(x) F (__v_##x##f, v_##x##f, x, mpfr_##x, 2, 1, f2, 0)
-#define VD1(x) F (__v_##x, v_##x, x##l, mpfr_##x, 1, 0, d1, 0)
-#define VD2(x) F (__v_##x, v_##x, x##l, mpfr_##x, 2, 0, d2, 0)
-#define VNF1(x) F (__vn_##x##f, vn_##x##f, x, mpfr_##x, 1, 1, f1, 0)
-#define VNF2(x) F (__vn_##x##f, vn_##x##f, x, mpfr_##x, 2, 1, f2, 0)
-#define VND1(x) F (__vn_##x, vn_##x, x##l, mpfr_##x, 1, 0, d1, 0)
-#define VND2(x) F (__vn_##x, vn_##x, x##l, mpfr_##x, 2, 0, d2, 0)
-#define ZVF1(x) F (_ZGVnN4v_##x##f, Z_##x##f, x, mpfr_##x, 1, 1, f1, 0)
-#define ZVF2(x) F (_ZGVnN4vv_##x##f, Z_##x##f, x, mpfr_##x, 2, 1, f2, 0)
-#define ZVD1(x) F (_ZGVnN2v_##x, Z_##x, x##l, mpfr_##x, 1, 0, d1, 0)
-#define ZVD2(x) F (_ZGVnN2vv_##x, Z_##x, x##l, mpfr_##x, 2, 0, d2, 0)
-#define ZVNF1(x) VNF1 (x) ZVF1 (x)
-#define ZVNF2(x) VNF2 (x) ZVF2 (x)
-#define ZVND1(x) VND1 (x) ZVD1 (x)
-#define ZVND2(x) VND2 (x) ZVD2 (x)
+#define ZVNF1(x) F (_ZGVnN4v_##x##f, Z_##x##f, x, mpfr_##x, 1, 1, f1, 0)
+#define ZVNF2(x) F (_ZGVnN4vv_##x##f, Z_##x##f, x, mpfr_##x, 2, 1, f2, 0)
+#define ZVND1(x) F (_ZGVnN2v_##x, Z_##x, x##l, mpfr_##x, 1, 0, d1, 0)
+#define ZVND2(x) F (_ZGVnN2vv_##x, Z_##x, x##l, mpfr_##x, 2, 0, d2, 0)
/* SVE routines. */
-#define SVF1(x) F (__sv_##x##f, sv_##x##f, x, mpfr_##x, 1, 1, f1, 0)
-#define SVF2(x) F (__sv_##x##f, sv_##x##f, x, mpfr_##x, 2, 1, f2, 0)
-#define SVD1(x) F (__sv_##x, sv_##x, x##l, mpfr_##x, 1, 0, d1, 0)
-#define SVD2(x) F (__sv_##x, sv_##x, x##l, mpfr_##x, 2, 0, d2, 0)
-#define ZSVF1(x) F (_ZGVsMxv_##x##f, Z_sv_##x##f, x, mpfr_##x, 1, 1, f1, 0)
-#define ZSVF2(x) F (_ZGVsMxvv_##x##f, Z_sv_##x##f, x, mpfr_##x, 2, 1, f2, 0)
-#define ZSVD1(x) F (_ZGVsMxv_##x, Z_sv_##x, x##l, mpfr_##x, 1, 0, d1, 0)
-#define ZSVD2(x) F (_ZGVsMxvv_##x, Z_sv_##x, x##l, mpfr_##x, 2, 0, d2, 0)
+#define ZSVF1(x) SVF (_ZGVsMxv_##x##f, Z_sv_##x##f, x, mpfr_##x, 1, 1, f1, 0)
+#define ZSVF2(x) SVF (_ZGVsMxvv_##x##f, Z_sv_##x##f, x, mpfr_##x, 2, 1, f2, 0)
+#define ZSVD1(x) SVF (_ZGVsMxv_##x, Z_sv_##x, x##l, mpfr_##x, 1, 0, d1, 0)
+#define ZSVD2(x) SVF (_ZGVsMxvv_##x, Z_sv_##x, x##l, mpfr_##x, 2, 0, d2, 0)
#include "test/ulp_funcs.h"
@@ -340,11 +335,13 @@ static const struct fun fun[] = {
#undef F2
#undef D1
#undef D2
-#undef SVF1
-#undef SVF2
-#undef SVD1
-#undef SVD2
- {0}};
+#undef ZSVF1
+#undef ZSVF2
+#undef ZSVD1
+#undef ZSVD2
+ { 0 }
+};
+// clang-format on
/* Boilerplate for generic calls. */
@@ -365,24 +362,40 @@ ulpscale_d (double x)
return e - 0x3ff - 52;
}
static inline float
-call_f1 (const struct fun *f, struct args_f1 a)
+call_f1 (const struct fun *f, struct args_f1 a, const struct conf *conf)
{
+#if WANT_SVE_TESTS
+ if (f->is_predicated)
+ return f->fun.f1_pred (*conf->pg, a.x);
+#endif
return f->fun.f1 (a.x);
}
static inline float
-call_f2 (const struct fun *f, struct args_f2 a)
+call_f2 (const struct fun *f, struct args_f2 a, const struct conf *conf)
{
+#if WANT_SVE_TESTS
+ if (f->is_predicated)
+ return f->fun.f2_pred (*conf->pg, a.x, a.x2);
+#endif
return f->fun.f2 (a.x, a.x2);
}
static inline double
-call_d1 (const struct fun *f, struct args_d1 a)
+call_d1 (const struct fun *f, struct args_d1 a, const struct conf *conf)
{
+#if WANT_SVE_TESTS
+ if (f->is_predicated)
+ return f->fun.d1_pred (*conf->pg, a.x);
+#endif
return f->fun.d1 (a.x);
}
static inline double
-call_d2 (const struct fun *f, struct args_d2 a)
+call_d2 (const struct fun *f, struct args_d2 a, const struct conf *conf)
{
+#if WANT_SVE_TESTS
+ if (f->is_predicated)
+ return f->fun.d2_pred (*conf->pg, a.x, a.x2);
+#endif
return f->fun.d2 (a.x, a.x2);
}
static inline double
@@ -595,6 +608,11 @@ usage (void)
" This should be different from tested input in other lanes, and non-special \n"
" (i.e. should not trigger fenv exceptions). Default is 1.");
#endif
+#if WANT_SVE_TESTS
+ puts ("-p: integer input for controlling predicate passed to SVE function. "
+ "If bit N is set, lane N is activated (bits past the vector length "
+ "are ignored). Default is UINT64_MAX (ptrue).");
+#endif
puts ("-z: ignore sign of 0.");
puts ("Supported func:");
for (const struct fun *f = fun; f->name; f++)
@@ -633,9 +651,21 @@ getnum (const char *s, int singleprec)
sign = singleprec ? 1ULL << 31 : 1ULL << 63;
s++;
}
+
+ /* Sentinel value for failed parse. */
+ char *should_not_be_s = NULL;
+
/* 0xXXXX is treated as bit representation, '-' flips the sign bit. */
if (s[0] == '0' && tolower (s[1]) == 'x' && strchr (s, 'p') == 0)
- return sign ^ strtoull (s, 0, 0);
+ {
+ uint64_t out = sign ^ strtoull (s, &should_not_be_s, 0);
+ if (should_not_be_s == s)
+ {
+ printf ("ERROR: Could not parse '%s'\n", s);
+ exit (1);
+ }
+ return out;
+ }
// /* SNaN, QNaN, NaN, Inf. */
// for (i=0; s[i] && i < sizeof buf; i++)
// buf[i] = tolower(s[i]);
@@ -647,8 +677,16 @@ getnum (const char *s, int singleprec)
// if (strcmp(buf, "inf") == 0 || strcmp(buf, "infinity") == 0)
// return sign | (singleprec ? 0x7f800000 : 0x7ff0000000000000);
/* Otherwise assume it's a floating-point literal. */
- return sign
- | (singleprec ? asuint (strtof (s, 0)) : asuint64 (strtod (s, 0)));
+ uint64_t out = sign
+ | (singleprec ? asuint (strtof (s, &should_not_be_s))
+ : asuint64 (strtod (s, &should_not_be_s)));
+ if (should_not_be_s == s)
+ {
+ printf ("ERROR: Could not parse '%s'\n", s);
+ exit (1);
+ }
+
+ return out;
}
static void
@@ -720,6 +758,9 @@ main (int argc, char *argv[])
conf.softlim = 0;
conf.errlim = INFINITY;
conf.ignore_zero_sign = 0;
+#if WANT_SVE_TESTS
+ uint64_t pg_int = UINT64_MAX;
+#endif
for (;;)
{
argc--;
@@ -767,7 +808,7 @@ main (int argc, char *argv[])
case 'z':
conf.ignore_zero_sign = 1;
break;
-#ifdef __vpcs
+#if __aarch64__ && __linux__
case 'c':
argc--;
argv++;
@@ -775,6 +816,13 @@ main (int argc, char *argv[])
dv[0] = strtod(argv[0], 0);
break;
#endif
+#if WANT_SVE_TESTS
+ case 'p':
+ argc--;
+ argv++;
+ pg_int = strtoull (argv[0], 0, 0);
+ break;
+#endif
default:
usage ();
}
@@ -806,7 +854,7 @@ main (int argc, char *argv[])
if (strncmp (argv[0], "_ZGVnN", 6) == 0)
exit (0);
#endif
-#if !WANT_SVE_MATH
+#if !WANT_SVE_TESTS
if (strncmp (argv[0], "_ZGVsMxv", 8) == 0)
exit (0);
#endif
@@ -824,5 +872,13 @@ main (int argc, char *argv[])
argv++;
parsegen (&gen, argc, argv, f);
conf.n = gen.cnt;
+#if WANT_SVE_TESTS
+ svbool_t pg = parse_pg (pg_int, f->singleprec);
+ conf.pg = &pg;
+#endif
return cmp (f, &gen, &conf);
}
+
+#if __aarch64__ && __linux__ && WANT_SVE_TESTS && defined(__clang__)
+# pragma clang attribute pop
+#endif
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))
{
diff --git a/math/test/ulp_funcs.h b/math/test/ulp_funcs.h
index 84f7927d3935..b58a68ff275b 100644
--- a/math/test/ulp_funcs.h
+++ b/math/test/ulp_funcs.h
@@ -1,40 +1,109 @@
/*
* Function entries for ulp.
*
- * Copyright (c) 2022-2023, Arm Limited.
+ * Copyright (c) 2022-2024, Arm Limited.
* SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
*/
/* clang-format off */
- F1 (sin)
- F1 (cos)
F (sincosf_sinf, sincosf_sinf, sincos_sin, sincos_mpfr_sin, 1, 1, f1, 0)
F (sincosf_cosf, sincosf_cosf, sincos_cos, sincos_mpfr_cos, 1, 1, f1, 0)
- F1 (exp)
- F1 (exp2)
- F1 (log)
- F1 (log2)
F2 (pow)
- F1 (erf)
- D1 (exp)
- D1 (exp10)
- D1 (exp2)
- D1 (log)
- D1 (log2)
D2 (pow)
- D1 (erf)
-#ifdef __vpcs
- F (_ZGVnN4v_sinf, Z_sinf, sin, mpfr_sin, 1, 1, f1, 1)
- F (_ZGVnN4v_cosf, Z_cosf, cos, mpfr_cos, 1, 1, f1, 1)
+#if __aarch64__ && __linux__
F (_ZGVnN4v_expf_1u, Z_expf_1u, exp, mpfr_exp, 1, 1, f1, 1)
- F (_ZGVnN4v_expf, Z_expf, exp, mpfr_exp, 1, 1, f1, 1)
F (_ZGVnN4v_exp2f_1u, Z_exp2f_1u, exp2, mpfr_exp2, 1, 1, f1, 1)
- F (_ZGVnN4v_exp2f, Z_exp2f, exp2, mpfr_exp2, 1, 1, f1, 1)
- F (_ZGVnN4v_logf, Z_logf, log, mpfr_log, 1, 1, f1, 1)
F (_ZGVnN4vv_powf, Z_powf, pow, mpfr_pow, 2, 1, f2, 1)
- F (_ZGVnN2v_sin, Z_sin, sinl, mpfr_sin, 1, 0, d1, 1)
- F (_ZGVnN2v_cos, Z_cos, cosl, mpfr_cos, 1, 0, d1, 1)
- F (_ZGVnN2v_exp, Z_exp, expl, mpfr_exp, 1, 0, d1, 1)
- F (_ZGVnN2v_log, Z_log, logl, mpfr_log, 1, 0, d1, 1)
F (_ZGVnN2vv_pow, Z_pow, powl, mpfr_pow, 2, 0, d2, 1)
+ F (_ZGVnN4v_sincosf_sin, v_sincosf_sin, sin, mpfr_sin, 1, 1, f1, 0)
+ F (_ZGVnN4v_sincosf_cos, v_sincosf_cos, cos, mpfr_cos, 1, 1, f1, 0)
+ F (_ZGVnN4v_cexpif_sin, v_cexpif_sin, sin, mpfr_sin, 1, 1, f1, 0)
+ F (_ZGVnN4v_cexpif_cos, v_cexpif_cos, cos, mpfr_cos, 1, 1, f1, 0)
+ F (_ZGVnN4vl4_modff_frac, v_modff_frac, modf_frac, modf_mpfr_frac, 1, 1, f1, 0)
+ F (_ZGVnN4vl4_modff_int, v_modff_int, modf_int, modf_mpfr_int, 1, 1, f1, 0)
+ F (_ZGVnN2v_sincos_sin, v_sincos_sin, sinl, mpfr_sin, 1, 0, d1, 0)
+ F (_ZGVnN2v_sincos_cos, v_sincos_cos, cosl, mpfr_cos, 1, 0, d1, 0)
+ F (_ZGVnN2v_cexpi_sin, v_cexpi_sin, sinl, mpfr_sin, 1, 0, d1, 0)
+ F (_ZGVnN2v_cexpi_cos, v_cexpi_cos, cosl, mpfr_cos, 1, 0, d1, 0)
+ F (_ZGVnN2vl8_modf_frac, v_modf_frac, modfl_frac, modf_mpfr_frac, 1, 0, d1, 0)
+ F (_ZGVnN2vl8_modf_int, v_modf_int, modfl_int, modf_mpfr_int, 1, 0, d1, 0)
#endif
-/* clang-format on */
+
+#if WANT_SVE_TESTS
+SVF (_ZGVsMxv_sincosf_sin, sv_sincosf_sin, sin, mpfr_sin, 1, 1, f1, 0)
+SVF (_ZGVsMxv_sincosf_cos, sv_sincosf_cos, cos, mpfr_cos, 1, 1, f1, 0)
+SVF (_ZGVsMxv_cexpif_sin, sv_cexpif_sin, sin, mpfr_sin, 1, 1, f1, 0)
+SVF (_ZGVsMxv_cexpif_cos, sv_cexpif_cos, cos, mpfr_cos, 1, 1, f1, 0)
+SVF (_ZGVsMxvl4_modff_frac, sv_modff_frac, modf_frac, modf_mpfr_frac, 1, 1, f1, 0)
+SVF (_ZGVsMxvl4_modff_int, sv_modff_int, modf_int, modf_mpfr_int, 1, 1, f1, 0)
+SVF (_ZGVsMxv_sincos_sin, sv_sincos_sin, sinl, mpfr_sin, 1, 0, d1, 0)
+SVF (_ZGVsMxv_sincos_cos, sv_sincos_cos, cosl, mpfr_cos, 1, 0, d1, 0)
+SVF (_ZGVsMxv_cexpi_sin, sv_cexpi_sin, sinl, mpfr_sin, 1, 0, d1, 0)
+SVF (_ZGVsMxv_cexpi_cos, sv_cexpi_cos, cosl, mpfr_cos, 1, 0, d1, 0)
+SVF (_ZGVsMxvl8_modf_frac, sv_modf_frac, modfl_frac, modf_mpfr_frac, 1, 0, d1, 0)
+SVF (_ZGVsMxvl8_modf_int, sv_modf_int, modfl_int, modf_mpfr_int, 1, 0, d1, 0)
+#endif
+
+#if WANT_EXPERIMENTAL_MATH
+ F (arm_math_erff, arm_math_erff, erf, mpfr_erf, 1, 1, f1, 0)
+ F (arm_math_erf, arm_math_erf, erfl, mpfr_erf, 1, 0, d1, 0)
+#endif
+
+#if WANT_TRIGPI_TESTS
+ F (arm_math_cospif, arm_math_cospif, arm_math_cospi, mpfr_cospi, 1, 1, f1, 0)
+ F (arm_math_cospi, arm_math_cospi, arm_math_cospil, mpfr_cospi, 1, 0, d1, 0)
+ F (arm_math_sinpif, arm_math_sinpif, arm_math_sinpi, mpfr_sinpi, 1, 1, f1, 0)
+ F (arm_math_sinpi, arm_math_sinpi, arm_math_sinpil, mpfr_sinpi, 1, 0, d1, 0)
+ F (arm_math_tanpif, arm_math_tanpif, arm_math_tanpi, mpfr_tanpi, 1, 1, f1, 0)
+ F (arm_math_tanpi, arm_math_tanpi, arm_math_tanpil, mpfr_tanpi, 1, 0, d1, 0)
+ F (arm_math_sincospif_sin, arm_math_sincospif_sin, arm_math_sinpi, mpfr_sinpi, 1, 1, f1, 0)
+ F (arm_math_sincospif_cos, arm_math_sincospif_cos, arm_math_cospi, mpfr_cospi, 1, 1, f1, 0)
+ F (arm_math_sincospi_sin, arm_math_sincospi_sin, arm_math_sinpil, mpfr_sinpi, 1, 0, d1, 0)
+ F (arm_math_sincospi_cos, arm_math_sincospi_cos, arm_math_cospil, mpfr_cospi, 1, 0, d1, 0)
+# if __aarch64__ && __linux__
+ F (_ZGVnN4v_cospif, Z_cospif, arm_math_cospi, mpfr_cospi, 1, 1, f1, 0)
+ F (_ZGVnN2v_cospi, Z_cospi, arm_math_cospil, mpfr_cospi, 1, 0, d1, 0)
+ F (_ZGVnN4v_sinpif, Z_sinpif, arm_math_sinpi, mpfr_sinpi, 1, 1, f1, 0)
+ F (_ZGVnN2v_sinpi, Z_sinpi, arm_math_sinpil, mpfr_sinpi, 1, 0, d1, 0)
+ F (_ZGVnN4v_tanpif, Z_tanpif, arm_math_tanpi, mpfr_tanpi, 1, 1, f1, 0)
+ F (_ZGVnN2v_tanpi, Z_tanpi, arm_math_tanpil, mpfr_tanpi, 1, 0, d1, 0)
+ F (_ZGVnN4v_sincospif_sin, v_sincospif_sin, arm_math_sinpi, mpfr_sinpi, 1, 1, f1, 0)
+ F (_ZGVnN4v_sincospif_cos, v_sincospif_cos, arm_math_cospi, mpfr_cospi, 1, 1, f1, 0)
+ F (_ZGVnN2v_sincospi_sin, v_sincospi_sin, arm_math_sinpil, mpfr_sinpi, 1, 0, d1, 0)
+ F (_ZGVnN2v_sincospi_cos, v_sincospi_cos, arm_math_cospil, mpfr_cospi, 1, 0, d1, 0)
+# endif
+# if WANT_SVE_TESTS
+ SVF (_ZGVsMxv_cospif, Z_sv_cospif, arm_math_cospi, mpfr_cospi, 1, 1, f1, 0)
+ SVF (_ZGVsMxv_cospi, Z_sv_cospi, arm_math_cospil, mpfr_cospi, 1, 0, d1, 0)
+ SVF (_ZGVsMxv_sinpif, Z_sv_sinpif, arm_math_sinpi, mpfr_sinpi, 1, 1, f1, 0)
+ SVF (_ZGVsMxv_sinpi, Z_sv_sinpi, arm_math_sinpil, mpfr_sinpi, 1, 0, d1, 0)
+ SVF (_ZGVsMxv_tanpif, Z_sv_tanpif, arm_math_tanpi, mpfr_tanpi, 1, 1, f1, 0)
+ SVF (_ZGVsMxv_tanpi, Z_sv_tanpi, arm_math_tanpil, mpfr_tanpi, 1, 0, d1, 0)
+ SVF (_ZGVsMxvl4l4_sincospif_sin, sv_sincospif_sin, arm_math_sinpi, mpfr_sinpi, 1, 1, f1, 0)
+ SVF (_ZGVsMxvl4l4_sincospif_cos, sv_sincospif_cos, arm_math_cospi, mpfr_cospi, 1, 1, f1, 0)
+ SVF (_ZGVsMxvl8l8_sincospi_sin, sv_sincospi_sin, arm_math_sinpil, mpfr_sinpi, 1, 0, d1, 0)
+ SVF (_ZGVsMxvl8l8_sincospi_cos, sv_sincospi_cos, arm_math_cospil, mpfr_cospi, 1, 0, d1, 0)
+# if WANT_EXPERIMENTAL_MATH
+SVF (_ZGVsMxvv_powk, Z_sv_powk, ref_powi, mpfr_powi, 2, 0, d2, 0)
+SVF (_ZGVsMxvv_powi, Z_sv_powi, ref_powif, mpfr_powi, 2, 1, f2, 0)
+# endif
+# endif
+#endif
+
+ /* clang-format on */
+
+#define _ZSF1(f) F1 (f)
+#define _ZSF2(f) F2 (f)
+#define _ZSD1(f) D1 (f)
+#define _ZSD2(f) D2 (f)
+
+#define _ZVF1(f) ZVNF1 (f)
+#define _ZVD1(f) ZVND1 (f)
+#define _ZVF2(f) ZVNF2 (f)
+#define _ZVD2(f) ZVND2 (f)
+
+#define _ZSVF1(f) ZSVF1 (f)
+#define _ZSVF2(f) ZSVF2 (f)
+#define _ZSVD1(f) ZSVD1 (f)
+#define _ZSVD2(f) ZSVD2 (f)
+
+#include "test/ulp_funcs_gen.h"
diff --git a/math/test/ulp_wrappers.h b/math/test/ulp_wrappers.h
index 60dc3d6dd652..33e1e75f23ab 100644
--- a/math/test/ulp_wrappers.h
+++ b/math/test/ulp_wrappers.h
@@ -1,12 +1,18 @@
/*
* Function wrappers for ulp.
*
- * Copyright (c) 2022-2023, Arm Limited.
+ * Copyright (c) 2022-2024, Arm Limited.
* SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
*/
/* clang-format off */
+#if __aarch64__ && __linux__
+#include <arm_neon.h>
+#endif
+
+#include <stdbool.h>
+
/* Wrappers for sincos. */
static float sincosf_sinf(float x) {(void)cosf(x); return sinf(x);}
static float sincosf_cosf(float x) {(void)sinf(x); return cosf(x);}
@@ -15,23 +21,409 @@ static double sincos_cos(double x) {(void)sin(x); return cos(x);}
#if USE_MPFR
static int sincos_mpfr_sin(mpfr_t y, const mpfr_t x, mpfr_rnd_t r) { mpfr_cos(y,x,r); return mpfr_sin(y,x,r); }
static int sincos_mpfr_cos(mpfr_t y, const mpfr_t x, mpfr_rnd_t r) { mpfr_sin(y,x,r); return mpfr_cos(y,x,r); }
+static int modf_mpfr_frac(mpfr_t f, const mpfr_t x, mpfr_rnd_t r) { MPFR_DECL_INIT(i, 80); return mpfr_modf(i,f,x,r); }
+static int modf_mpfr_int(mpfr_t i, const mpfr_t x, mpfr_rnd_t r) { MPFR_DECL_INIT(f, 80); return mpfr_modf(i,f,x,r); }
+# if MPFR_VERSION < MPFR_VERSION_NUM(4, 2, 0)
+static int mpfr_tanpi (mpfr_t ret, const mpfr_t arg, mpfr_rnd_t rnd) {
+ MPFR_DECL_INIT (frd, 1080);
+ mpfr_const_pi (frd, GMP_RNDN);
+ mpfr_mul (frd, frd, arg, GMP_RNDN);
+ return mpfr_tan (ret, frd, GMP_RNDN);
+}
+static int mpfr_sinpi (mpfr_t ret, const mpfr_t arg, mpfr_rnd_t rnd) {
+ MPFR_DECL_INIT (frd, 1080);
+ mpfr_const_pi (frd, GMP_RNDN);
+ mpfr_mul (frd, frd, arg, GMP_RNDN);
+ return mpfr_sin (ret, frd, GMP_RNDN);
+}
+
+static int mpfr_cospi (mpfr_t ret, const mpfr_t arg, mpfr_rnd_t rnd) {
+ MPFR_DECL_INIT (frd, 1080);
+ mpfr_const_pi (frd, GMP_RNDN);
+ mpfr_mul (frd, frd, arg, GMP_RNDN);
+ return mpfr_cos (ret, frd, GMP_RNDN);
+}
+# endif
+# if WANT_EXPERIMENTAL_MATH
+static int wrap_mpfr_powi(mpfr_t ret, const mpfr_t x, const mpfr_t y, mpfr_rnd_t rnd) {
+ mpfr_t y2;
+ mpfr_init(y2);
+ mpfr_trunc(y2, y);
+ return mpfr_pow(ret, x, y2, rnd);
+}
+# endif
#endif
+float modff_frac(float x) { float i; return modff(x, &i); }
+float modff_int(float x) { float i; modff(x, &i); return i; }
+double modf_frac(double x) { double i; return modf(x, &i); }
+double modf_int(double x) { double i; modf(x, &i); return i; }
+long double modfl_frac(long double x) { long double i; return modfl(x, &i); }
+long double modfl_int(long double x) { long double i; modfl(x, &i); return i; }
+
/* Wrappers for vector functions. */
-#ifdef __vpcs
-static float Z_sinf(float x) { return _ZGVnN4v_sinf(argf(x))[0]; }
-static float Z_cosf(float x) { return _ZGVnN4v_cosf(argf(x))[0]; }
+#if __aarch64__ && __linux__
static float Z_expf_1u(float x) { return _ZGVnN4v_expf_1u(argf(x))[0]; }
-static float Z_expf(float x) { return _ZGVnN4v_expf(argf(x))[0]; }
static float Z_exp2f_1u(float x) { return _ZGVnN4v_exp2f_1u(argf(x))[0]; }
-static float Z_exp2f(float x) { return _ZGVnN4v_exp2f(argf(x))[0]; }
-static float Z_logf(float x) { return _ZGVnN4v_logf(argf(x))[0]; }
-static float Z_powf(float x, float y) { return _ZGVnN4vv_powf(argf(x),argf(y))[0]; }
-static double Z_sin(double x) { return _ZGVnN2v_sin(argd(x))[0]; }
-static double Z_cos(double x) { return _ZGVnN2v_cos(argd(x))[0]; }
-static double Z_exp(double x) { return _ZGVnN2v_exp(argd(x))[0]; }
-static double Z_log(double x) { return _ZGVnN2v_log(argd(x))[0]; }
-static double Z_pow(double x, double y) { return _ZGVnN2vv_pow(argd(x),argd(y))[0]; }
#endif
/* clang-format on */
+
+/* No wrappers for scalar routines, but TEST_SIG will emit them. */
+#define ZSNF1_WRAP(func)
+#define ZSNF2_WRAP(func)
+#define ZSND1_WRAP(func)
+#define ZSND2_WRAP(func)
+
+#define ZVNF1_WRAP(func) \
+ static float Z_##func##f (float x) \
+ { \
+ return _ZGVnN4v_##func##f (argf (x))[0]; \
+ }
+#define ZVNF2_WRAP(func) \
+ static float Z_##func##f (float x, float y) \
+ { \
+ return _ZGVnN4vv_##func##f (argf (x), argf (y))[0]; \
+ }
+#define ZVND1_WRAP(func) \
+ static double Z_##func (double x) { return _ZGVnN2v_##func (argd (x))[0]; }
+#define ZVND2_WRAP(func) \
+ static double Z_##func (double x, double y) \
+ { \
+ return _ZGVnN2vv_##func (argd (x), argd (y))[0]; \
+ }
+
+#if WANT_TRIGPI_TESTS
+float
+arm_math_sincospif_sin (float x)
+{
+ float s, c;
+ arm_math_sincospif (x, &s, &c);
+ return s;
+}
+float
+arm_math_sincospif_cos (float x)
+{
+ float s, c;
+ arm_math_sincospif (x, &s, &c);
+ return c;
+}
+double
+arm_math_sincospi_sin (double x)
+{
+ double s, c;
+ arm_math_sincospi (x, &s, &c);
+ return s;
+}
+double
+arm_math_sincospi_cos (double x)
+{
+ double s, c;
+ arm_math_sincospi (x, &s, &c);
+ return c;
+}
+#endif
+
+#if __aarch64__ && __linux__
+
+# if WANT_TRIGPI_TESTS
+ZVNF1_WRAP (cospi)
+ZVND1_WRAP (cospi)
+ZVNF1_WRAP (sinpi)
+ZVND1_WRAP (sinpi)
+ZVNF1_WRAP (tanpi)
+ZVND1_WRAP (tanpi)
+
+double
+v_sincospi_sin (double x)
+{
+ double s[2], c[2];
+ _ZGVnN2vl8l8_sincospi (vdupq_n_f64 (x), s, c);
+ return s[0];
+}
+double
+v_sincospi_cos (double x)
+{
+ double s[2], c[2];
+ _ZGVnN2vl8l8_sincospi (vdupq_n_f64 (x), s, c);
+ return c[0];
+}
+float
+v_sincospif_sin (float x)
+{
+ float s[4], c[4];
+ _ZGVnN4vl4l4_sincospif (vdupq_n_f32 (x), s, c);
+ return s[0];
+}
+float
+v_sincospif_cos (float x)
+{
+ float s[4], c[4];
+ _ZGVnN4vl4l4_sincospif (vdupq_n_f32 (x), s, c);
+ return c[0];
+}
+# endif // WANT_TRIGPI_TESTS
+
+float
+v_sincosf_sin (float x)
+{
+ float s[4], c[4];
+ _ZGVnN4vl4l4_sincosf (vdupq_n_f32 (x), s, c);
+ return s[0];
+}
+float
+v_sincosf_cos (float x)
+{
+ float s[4], c[4];
+ _ZGVnN4vl4l4_sincosf (vdupq_n_f32 (x), s, c);
+ return c[0];
+}
+float
+v_cexpif_sin (float x)
+{
+ return _ZGVnN4v_cexpif (vdupq_n_f32 (x)).val[0][0];
+}
+float
+v_cexpif_cos (float x)
+{
+ return _ZGVnN4v_cexpif (vdupq_n_f32 (x)).val[1][0];
+}
+float
+v_modff_frac (float x)
+{
+ float y[4];
+ return _ZGVnN4vl4_modff (vdupq_n_f32 (x), y)[0];
+}
+float
+v_modff_int (float x)
+{
+ float y[4];
+ _ZGVnN4vl4_modff (vdupq_n_f32 (x), y);
+ return y[0];
+}
+double
+v_sincos_sin (double x)
+{
+ double s[2], c[2];
+ _ZGVnN2vl8l8_sincos (vdupq_n_f64 (x), s, c);
+ return s[0];
+}
+double
+v_sincos_cos (double x)
+{
+ double s[2], c[2];
+ _ZGVnN2vl8l8_sincos (vdupq_n_f64 (x), s, c);
+ return c[0];
+}
+double
+v_cexpi_sin (double x)
+{
+ return _ZGVnN2v_cexpi (vdupq_n_f64 (x)).val[0][0];
+}
+double
+v_cexpi_cos (double x)
+{
+ return _ZGVnN2v_cexpi (vdupq_n_f64 (x)).val[1][0];
+}
+double
+v_modf_frac (double x)
+{
+ double y[2];
+ return _ZGVnN2vl8_modf (vdupq_n_f64 (x), y)[0];
+}
+double
+v_modf_int (double x)
+{
+ double y[2];
+ _ZGVnN2vl8_modf (vdupq_n_f64 (x), y);
+ return y[0];
+}
+#endif // __aarch64__ && __linux__
+
+#if WANT_SVE_TESTS
+# define ZSVNF1_WRAP(func) \
+ static float Z_sv_##func##f (svbool_t pg, float x) \
+ { \
+ return svretf (_ZGVsMxv_##func##f (svargf (x), pg), pg); \
+ }
+# define ZSVNF2_WRAP(func) \
+ static float Z_sv_##func##f (svbool_t pg, float x, float y) \
+ { \
+ return svretf (_ZGVsMxvv_##func##f (svargf (x), svargf (y), pg), pg); \
+ }
+# define ZSVND1_WRAP(func) \
+ static double Z_sv_##func (svbool_t pg, double x) \
+ { \
+ return svretd (_ZGVsMxv_##func (svargd (x), pg), pg); \
+ }
+# define ZSVND2_WRAP(func) \
+ static double Z_sv_##func (svbool_t pg, double x, double y) \
+ { \
+ return svretd (_ZGVsMxvv_##func (svargd (x), svargd (y), pg), pg); \
+ }
+
+# if WANT_TRIGPI_TESTS
+ZSVNF1_WRAP (cospi)
+ZSVND1_WRAP (cospi)
+ZSVNF1_WRAP (sinpi)
+ZSVND1_WRAP (sinpi)
+ZSVNF1_WRAP (tanpi)
+ZSVND1_WRAP (tanpi)
+double
+sv_sincospi_sin (svbool_t pg, double x)
+{
+ double s[svcntd ()], c[svcntd ()];
+ _ZGVsMxvl8l8_sincospi (svdup_f64 (x), s, c, pg);
+ return svretd (svld1 (pg, s), pg);
+}
+double
+sv_sincospi_cos (svbool_t pg, double x)
+{
+ double s[svcntd ()], c[svcntd ()];
+ _ZGVsMxvl8l8_sincospi (svdup_f64 (x), s, c, pg);
+ return svretd (svld1 (pg, c), pg);
+}
+float
+sv_sincospif_sin (svbool_t pg, float x)
+{
+ float s[svcntw ()], c[svcntw ()];
+ _ZGVsMxvl4l4_sincospif (svdup_f32 (x), s, c, pg);
+ return svretf (svld1 (pg, s), pg);
+}
+float
+sv_sincospif_cos (svbool_t pg, float x)
+{
+ float s[svcntw ()], c[svcntw ()];
+ _ZGVsMxvl4l4_sincospif (svdup_f32 (x), s, c, pg);
+ return svretf (svld1 (pg, c), pg);
+}
+# endif // WANT_TRIGPI_TESTS
+
+float
+sv_sincosf_sin (svbool_t pg, float x)
+{
+ float s[svcntw ()], c[svcntw ()];
+ _ZGVsMxvl4l4_sincosf (svdup_f32 (x), s, c, pg);
+ return svretf (svld1 (pg, s), pg);
+}
+float
+sv_sincosf_cos (svbool_t pg, float x)
+{
+ float s[svcntw ()], c[svcntw ()];
+ _ZGVsMxvl4l4_sincosf (svdup_f32 (x), s, c, pg);
+ return svretf (svld1 (pg, c), pg);
+}
+float
+sv_cexpif_sin (svbool_t pg, float x)
+{
+ return svretf (svget2 (_ZGVsMxv_cexpif (svdup_f32 (x), pg), 0), pg);
+}
+float
+sv_cexpif_cos (svbool_t pg, float x)
+{
+ return svretf (svget2 (_ZGVsMxv_cexpif (svdup_f32 (x), pg), 1), pg);
+}
+float
+sv_modff_frac (svbool_t pg, float x)
+{
+ float i[svcntw ()];
+ return svretf (_ZGVsMxvl4_modff (svdup_f32 (x), i, pg), pg);
+}
+float
+sv_modff_int (svbool_t pg, float x)
+{
+ float i[svcntw ()];
+ _ZGVsMxvl4_modff (svdup_f32 (x), i, pg);
+ return svretf (svld1 (pg, i), pg);
+}
+double
+sv_sincos_sin (svbool_t pg, double x)
+{
+ double s[svcntd ()], c[svcntd ()];
+ _ZGVsMxvl8l8_sincos (svdup_f64 (x), s, c, pg);
+ return svretd (svld1 (pg, s), pg);
+}
+double
+sv_sincos_cos (svbool_t pg, double x)
+{
+ double s[svcntd ()], c[svcntd ()];
+ _ZGVsMxvl8l8_sincos (svdup_f64 (x), s, c, pg);
+ return svretd (svld1 (pg, c), pg);
+}
+double
+sv_cexpi_sin (svbool_t pg, double x)
+{
+ return svretd (svget2 (_ZGVsMxv_cexpi (svdup_f64 (x), pg), 0), pg);
+}
+double
+sv_cexpi_cos (svbool_t pg, double x)
+{
+ return svretd (svget2 (_ZGVsMxv_cexpi (svdup_f64 (x), pg), 1), pg);
+}
+double
+sv_modf_frac (svbool_t pg, double x)
+{
+ double i[svcntd ()];
+ return svretd (_ZGVsMxvl8_modf (svdup_f64 (x), i, pg), pg);
+}
+double
+sv_modf_int (svbool_t pg, double x)
+{
+ double i[svcntd ()];
+ _ZGVsMxvl8_modf (svdup_f64 (x), i, pg);
+ return svretd (svld1 (pg, i), pg);
+}
+
+# if WANT_EXPERIMENTAL_MATH
+
+/* Our implementations of powi/powk are too imprecise to verify
+ against any established pow implementation. Instead we have the
+ following simple implementation, against which it is enough to
+ maintain bitwise reproducibility. Note the test framework expects
+ the reference impl to be of higher precision than the function
+ under test. For instance this means that the reference for
+ double-precision powi will be passed a long double, so to check
+ bitwise reproducibility we have to cast it back down to
+ double. This is fine since a round-trip to higher precision and
+ back down is correctly rounded. */
+# define DECL_POW_INT_REF(NAME, DBL_T, FLT_T, INT_T) \
+ static DBL_T __attribute__ ((unused)) NAME (DBL_T in_val, DBL_T y) \
+ { \
+ INT_T n = (INT_T) round (y); \
+ FLT_T acc = 1.0; \
+ bool want_recip = n < 0; \
+ n = n < 0 ? -n : n; \
+ \
+ for (FLT_T c = in_val; n; c *= c, n >>= 1) \
+ { \
+ if (n & 0x1) \
+ { \
+ acc *= c; \
+ } \
+ } \
+ if (want_recip) \
+ { \
+ acc = 1.0 / acc; \
+ } \
+ return acc; \
+ }
+
+DECL_POW_INT_REF (ref_powif, double, float, int)
+DECL_POW_INT_REF (ref_powi, long double, double, int)
+static float
+Z_sv_powi (svbool_t pg, float x, float y)
+{
+ return svretf (_ZGVsMxvv_powi (svargf (x), svdup_s32 ((int) round (y)), pg),
+ pg);
+}
+static double
+Z_sv_powk (svbool_t pg, double x, double y)
+{
+ return svretd (_ZGVsMxvv_powk (svargd (x), svdup_s64 ((long) round (y)), pg),
+ pg);
+}
+
+# endif // WANT_EXPERIMENTAL_MATH
+#endif // WANT_SVE_TESTS
+
+#include "test/ulp_wrappers_gen.h"