131914882SAlex Richardson /* 231914882SAlex Richardson * ULP error checking tool for math functions. 331914882SAlex Richardson * 4*f3087befSAndrew Turner * Copyright (c) 2019-2024, Arm Limited. 5072a4ba8SAndrew Turner * SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception 631914882SAlex Richardson */ 731914882SAlex Richardson 8*f3087befSAndrew Turner #if WANT_SVE_TESTS 9*f3087befSAndrew Turner # if __aarch64__ && __linux__ 10*f3087befSAndrew Turner # ifdef __clang__ 11*f3087befSAndrew Turner # pragma clang attribute push(__attribute__((target("sve"))), \ 12*f3087befSAndrew Turner apply_to = any(function)) 13*f3087befSAndrew Turner # else 14*f3087befSAndrew Turner # pragma GCC target("+sve") 15*f3087befSAndrew Turner # endif 16*f3087befSAndrew Turner # else 17*f3087befSAndrew Turner # error "SVE not supported - please disable WANT_SVE_TESTS" 18*f3087befSAndrew Turner # endif 19*f3087befSAndrew Turner #endif 20*f3087befSAndrew Turner 215a02ffc3SAndrew Turner #define _GNU_SOURCE 2231914882SAlex Richardson #include <ctype.h> 2331914882SAlex Richardson #include <fenv.h> 2431914882SAlex Richardson #include <float.h> 2531914882SAlex Richardson #include <math.h> 2631914882SAlex Richardson #include <stdint.h> 2731914882SAlex Richardson #include <stdio.h> 2831914882SAlex Richardson #include <stdlib.h> 2931914882SAlex Richardson #include <string.h> 3031914882SAlex Richardson #include "mathlib.h" 3131914882SAlex Richardson 32*f3087befSAndrew Turner #include "trigpi_references.h" 33*f3087befSAndrew Turner 3431914882SAlex Richardson /* Don't depend on mpfr by default. */ 3531914882SAlex Richardson #ifndef USE_MPFR 3631914882SAlex Richardson # define USE_MPFR 0 3731914882SAlex Richardson #endif 3831914882SAlex Richardson #if USE_MPFR 3931914882SAlex Richardson # include <mpfr.h> 4031914882SAlex Richardson #endif 4131914882SAlex Richardson 4231914882SAlex Richardson static uint64_t seed = 0x0123456789abcdef; 4331914882SAlex Richardson static uint64_t 4431914882SAlex Richardson rand64 (void) 4531914882SAlex Richardson { 4631914882SAlex Richardson seed = 6364136223846793005ull * seed + 1; 4731914882SAlex Richardson return seed ^ (seed >> 32); 4831914882SAlex Richardson } 4931914882SAlex Richardson 5031914882SAlex Richardson /* Uniform random in [0,n]. */ 5131914882SAlex Richardson static uint64_t 5231914882SAlex Richardson randn (uint64_t n) 5331914882SAlex Richardson { 5431914882SAlex Richardson uint64_t r, m; 5531914882SAlex Richardson 5631914882SAlex Richardson if (n == 0) 5731914882SAlex Richardson return 0; 5831914882SAlex Richardson n++; 5931914882SAlex Richardson if (n == 0) 6031914882SAlex Richardson return rand64 (); 6131914882SAlex Richardson for (;;) 6231914882SAlex Richardson { 6331914882SAlex Richardson r = rand64 (); 6431914882SAlex Richardson m = r % n; 6531914882SAlex Richardson if (r - m <= -n) 6631914882SAlex Richardson return m; 6731914882SAlex Richardson } 6831914882SAlex Richardson } 6931914882SAlex Richardson 7031914882SAlex Richardson struct gen 7131914882SAlex Richardson { 7231914882SAlex Richardson uint64_t start; 7331914882SAlex Richardson uint64_t len; 7431914882SAlex Richardson uint64_t start2; 7531914882SAlex Richardson uint64_t len2; 7631914882SAlex Richardson uint64_t off; 7731914882SAlex Richardson uint64_t step; 7831914882SAlex Richardson uint64_t cnt; 7931914882SAlex Richardson }; 8031914882SAlex Richardson 8131914882SAlex Richardson struct args_f1 8231914882SAlex Richardson { 8331914882SAlex Richardson float x; 8431914882SAlex Richardson }; 8531914882SAlex Richardson 8631914882SAlex Richardson struct args_f2 8731914882SAlex Richardson { 8831914882SAlex Richardson float x; 8931914882SAlex Richardson float x2; 9031914882SAlex Richardson }; 9131914882SAlex Richardson 9231914882SAlex Richardson struct args_d1 9331914882SAlex Richardson { 9431914882SAlex Richardson double x; 9531914882SAlex Richardson }; 9631914882SAlex Richardson 9731914882SAlex Richardson struct args_d2 9831914882SAlex Richardson { 9931914882SAlex Richardson double x; 10031914882SAlex Richardson double x2; 10131914882SAlex Richardson }; 10231914882SAlex Richardson 10331914882SAlex Richardson /* result = y + tail*2^ulpexp. */ 10431914882SAlex Richardson struct ret_f 10531914882SAlex Richardson { 10631914882SAlex Richardson float y; 10731914882SAlex Richardson double tail; 10831914882SAlex Richardson int ulpexp; 10931914882SAlex Richardson int ex; 11031914882SAlex Richardson int ex_may; 11131914882SAlex Richardson }; 11231914882SAlex Richardson 11331914882SAlex Richardson struct ret_d 11431914882SAlex Richardson { 11531914882SAlex Richardson double y; 11631914882SAlex Richardson double tail; 11731914882SAlex Richardson int ulpexp; 11831914882SAlex Richardson int ex; 11931914882SAlex Richardson int ex_may; 12031914882SAlex Richardson }; 12131914882SAlex Richardson 12231914882SAlex Richardson static inline uint64_t 12331914882SAlex Richardson next1 (struct gen *g) 12431914882SAlex Richardson { 12531914882SAlex Richardson /* For single argument use randomized incremental steps, 12631914882SAlex Richardson that produce dense sampling without collisions and allow 12731914882SAlex Richardson testing all inputs in a range. */ 12831914882SAlex Richardson uint64_t r = g->start + g->off; 12931914882SAlex Richardson g->off += g->step + randn (g->step / 2); 13031914882SAlex Richardson if (g->off > g->len) 13131914882SAlex Richardson g->off -= g->len; /* hack. */ 13231914882SAlex Richardson return r; 13331914882SAlex Richardson } 13431914882SAlex Richardson 13531914882SAlex Richardson static inline uint64_t 13631914882SAlex Richardson next2 (uint64_t *x2, struct gen *g) 13731914882SAlex Richardson { 13831914882SAlex Richardson /* For two arguments use uniform random sampling. */ 13931914882SAlex Richardson uint64_t r = g->start + randn (g->len); 14031914882SAlex Richardson *x2 = g->start2 + randn (g->len2); 14131914882SAlex Richardson return r; 14231914882SAlex Richardson } 14331914882SAlex Richardson 14431914882SAlex Richardson static struct args_f1 14531914882SAlex Richardson next_f1 (void *g) 14631914882SAlex Richardson { 14731914882SAlex Richardson return (struct args_f1){asfloat (next1 (g))}; 14831914882SAlex Richardson } 14931914882SAlex Richardson 15031914882SAlex Richardson static struct args_f2 15131914882SAlex Richardson next_f2 (void *g) 15231914882SAlex Richardson { 15331914882SAlex Richardson uint64_t x2; 15431914882SAlex Richardson uint64_t x = next2 (&x2, g); 15531914882SAlex Richardson return (struct args_f2){asfloat (x), asfloat (x2)}; 15631914882SAlex Richardson } 15731914882SAlex Richardson 15831914882SAlex Richardson static struct args_d1 15931914882SAlex Richardson next_d1 (void *g) 16031914882SAlex Richardson { 16131914882SAlex Richardson return (struct args_d1){asdouble (next1 (g))}; 16231914882SAlex Richardson } 16331914882SAlex Richardson 16431914882SAlex Richardson static struct args_d2 16531914882SAlex Richardson next_d2 (void *g) 16631914882SAlex Richardson { 16731914882SAlex Richardson uint64_t x2; 16831914882SAlex Richardson uint64_t x = next2 (&x2, g); 16931914882SAlex Richardson return (struct args_d2){asdouble (x), asdouble (x2)}; 17031914882SAlex Richardson } 17131914882SAlex Richardson 172*f3087befSAndrew Turner /* A bit of a hack: call vector functions twice with the same 173*f3087befSAndrew Turner input in lane 0 but a different value in other lanes: once 174*f3087befSAndrew Turner with an in-range value and then with a special case value. */ 175*f3087befSAndrew Turner static int secondcall; 176*f3087befSAndrew Turner 177*f3087befSAndrew Turner /* Wrappers for vector functions. */ 178*f3087befSAndrew Turner #if __aarch64__ && __linux__ 179*f3087befSAndrew Turner /* First element of fv and dv may be changed by -c argument. */ 180*f3087befSAndrew Turner static float fv[2] = {1.0f, -INFINITY}; 181*f3087befSAndrew Turner static double dv[2] = {1.0, -INFINITY}; 182*f3087befSAndrew Turner static inline float32x4_t 183*f3087befSAndrew Turner argf (float x) 184*f3087befSAndrew Turner { 185*f3087befSAndrew Turner return (float32x4_t){ x, x, x, fv[secondcall] }; 186*f3087befSAndrew Turner } 187*f3087befSAndrew Turner static inline float64x2_t 188*f3087befSAndrew Turner argd (double x) 189*f3087befSAndrew Turner { 190*f3087befSAndrew Turner return (float64x2_t){ x, dv[secondcall] }; 191*f3087befSAndrew Turner } 192*f3087befSAndrew Turner #if WANT_SVE_TESTS 193*f3087befSAndrew Turner #include <arm_sve.h> 194*f3087befSAndrew Turner 195*f3087befSAndrew Turner static inline svfloat32_t 196*f3087befSAndrew Turner svargf (float x) 197*f3087befSAndrew Turner { 198*f3087befSAndrew Turner int n = svcntw (); 199*f3087befSAndrew Turner float base[n]; 200*f3087befSAndrew Turner for (int i = 0; i < n; i++) 201*f3087befSAndrew Turner base[i] = (float) x; 202*f3087befSAndrew Turner base[n - 1] = (float) fv[secondcall]; 203*f3087befSAndrew Turner return svld1 (svptrue_b32 (), base); 204*f3087befSAndrew Turner } 205*f3087befSAndrew Turner static inline svfloat64_t 206*f3087befSAndrew Turner svargd (double x) 207*f3087befSAndrew Turner { 208*f3087befSAndrew Turner int n = svcntd (); 209*f3087befSAndrew Turner double base[n]; 210*f3087befSAndrew Turner for (int i = 0; i < n; i++) 211*f3087befSAndrew Turner base[i] = x; 212*f3087befSAndrew Turner base[n - 1] = dv[secondcall]; 213*f3087befSAndrew Turner return svld1 (svptrue_b64 (), base); 214*f3087befSAndrew Turner } 215*f3087befSAndrew Turner static inline float 216*f3087befSAndrew Turner svretf (svfloat32_t vec, svbool_t pg) 217*f3087befSAndrew Turner { 218*f3087befSAndrew Turner return svlastb_f32 (svpfirst (pg, svpfalse ()), vec); 219*f3087befSAndrew Turner } 220*f3087befSAndrew Turner static inline double 221*f3087befSAndrew Turner svretd (svfloat64_t vec, svbool_t pg) 222*f3087befSAndrew Turner { 223*f3087befSAndrew Turner return svlastb_f64 (svpfirst (pg, svpfalse ()), vec); 224*f3087befSAndrew Turner } 225*f3087befSAndrew Turner 226*f3087befSAndrew Turner static inline svbool_t 227*f3087befSAndrew Turner parse_pg (uint64_t p, int is_single) 228*f3087befSAndrew Turner { 229*f3087befSAndrew Turner if (is_single) 230*f3087befSAndrew Turner { 231*f3087befSAndrew Turner uint32_t tmp[svcntw ()]; 232*f3087befSAndrew Turner for (unsigned i = 0; i < svcntw (); i++) 233*f3087befSAndrew Turner tmp[i] = (p >> i) & 1; 234*f3087befSAndrew Turner return svcmpne (svptrue_b32 (), svld1 (svptrue_b32 (), tmp), 0); 235*f3087befSAndrew Turner } 236*f3087befSAndrew Turner else 237*f3087befSAndrew Turner { 238*f3087befSAndrew Turner uint64_t tmp[svcntd ()]; 239*f3087befSAndrew Turner for (unsigned i = 0; i < svcntd (); i++) 240*f3087befSAndrew Turner tmp[i] = (p >> i) & 1; 241*f3087befSAndrew Turner return svcmpne (svptrue_b64 (), svld1 (svptrue_b64 (), tmp), 0); 242*f3087befSAndrew Turner } 243*f3087befSAndrew Turner } 244*f3087befSAndrew Turner # endif 245*f3087befSAndrew Turner #endif 246*f3087befSAndrew Turner 24731914882SAlex Richardson struct conf 24831914882SAlex Richardson { 24931914882SAlex Richardson int r; 25031914882SAlex Richardson int rc; 25131914882SAlex Richardson int quiet; 25231914882SAlex Richardson int mpfr; 25331914882SAlex Richardson int fenv; 25431914882SAlex Richardson unsigned long long n; 25531914882SAlex Richardson double softlim; 25631914882SAlex Richardson double errlim; 2575a02ffc3SAndrew Turner int ignore_zero_sign; 258*f3087befSAndrew Turner #if WANT_SVE_TESTS 259*f3087befSAndrew Turner svbool_t *pg; 260*f3087befSAndrew Turner #endif 26131914882SAlex Richardson }; 26231914882SAlex Richardson 263072a4ba8SAndrew Turner #include "test/ulp_wrappers.h" 264072a4ba8SAndrew Turner 26531914882SAlex Richardson struct fun 26631914882SAlex Richardson { 26731914882SAlex Richardson const char *name; 26831914882SAlex Richardson int arity; 26931914882SAlex Richardson int singleprec; 27031914882SAlex Richardson int twice; 271*f3087befSAndrew Turner int is_predicated; 27231914882SAlex Richardson union 27331914882SAlex Richardson { 27431914882SAlex Richardson float (*f1) (float); 27531914882SAlex Richardson float (*f2) (float, float); 27631914882SAlex Richardson double (*d1) (double); 27731914882SAlex Richardson double (*d2) (double, double); 278*f3087befSAndrew Turner #if WANT_SVE_TESTS 279*f3087befSAndrew Turner float (*f1_pred) (svbool_t, float); 280*f3087befSAndrew Turner float (*f2_pred) (svbool_t, float, float); 281*f3087befSAndrew Turner double (*d1_pred) (svbool_t, double); 282*f3087befSAndrew Turner double (*d2_pred) (svbool_t, double, double); 283*f3087befSAndrew Turner #endif 28431914882SAlex Richardson } fun; 28531914882SAlex Richardson union 28631914882SAlex Richardson { 28731914882SAlex Richardson double (*f1) (double); 28831914882SAlex Richardson double (*f2) (double, double); 28931914882SAlex Richardson long double (*d1) (long double); 29031914882SAlex Richardson long double (*d2) (long double, long double); 29131914882SAlex Richardson } fun_long; 29231914882SAlex Richardson #if USE_MPFR 29331914882SAlex Richardson union 29431914882SAlex Richardson { 29531914882SAlex Richardson int (*f1) (mpfr_t, const mpfr_t, mpfr_rnd_t); 29631914882SAlex Richardson int (*f2) (mpfr_t, const mpfr_t, const mpfr_t, mpfr_rnd_t); 29731914882SAlex Richardson int (*d1) (mpfr_t, const mpfr_t, mpfr_rnd_t); 29831914882SAlex Richardson int (*d2) (mpfr_t, const mpfr_t, const mpfr_t, mpfr_rnd_t); 29931914882SAlex Richardson } fun_mpfr; 30031914882SAlex Richardson #endif 30131914882SAlex Richardson }; 30231914882SAlex Richardson 303*f3087befSAndrew Turner // clang-format off 30431914882SAlex Richardson static const struct fun fun[] = { 30531914882SAlex Richardson #if USE_MPFR 30631914882SAlex Richardson # define F(x, x_wrap, x_long, x_mpfr, a, s, t, twice) \ 307*f3087befSAndrew Turner { #x, a, s, twice, 0, { .t = x_wrap }, { .t = x_long }, { .t = x_mpfr } }, 308*f3087befSAndrew Turner # define SVF(x, x_wrap, x_long, x_mpfr, a, s, t, twice) \ 309*f3087befSAndrew Turner { #x, a, s, twice, 1, { .t##_pred = x_wrap }, { .t = x_long }, { .t = x_mpfr } }, 31031914882SAlex Richardson #else 31131914882SAlex Richardson # define F(x, x_wrap, x_long, x_mpfr, a, s, t, twice) \ 312*f3087befSAndrew Turner { #x, a, s, twice, 0, { .t = x_wrap }, { .t = x_long } }, 313*f3087befSAndrew Turner # define SVF(x, x_wrap, x_long, x_mpfr, a, s, t, twice) \ 314*f3087befSAndrew Turner { #x, a, s, twice, 1, { .t##_pred = x_wrap }, { .t = x_long } }, 31531914882SAlex Richardson #endif 31631914882SAlex Richardson #define F1(x) F (x##f, x##f, x, mpfr_##x, 1, 1, f1, 0) 31731914882SAlex Richardson #define F2(x) F (x##f, x##f, x, mpfr_##x, 2, 1, f2, 0) 31831914882SAlex Richardson #define D1(x) F (x, x, x##l, mpfr_##x, 1, 0, d1, 0) 31931914882SAlex Richardson #define D2(x) F (x, x, x##l, mpfr_##x, 2, 0, d2, 0) 320072a4ba8SAndrew Turner /* Neon routines. */ 321*f3087befSAndrew Turner #define ZVNF1(x) F (_ZGVnN4v_##x##f, Z_##x##f, x, mpfr_##x, 1, 1, f1, 0) 322*f3087befSAndrew Turner #define ZVNF2(x) F (_ZGVnN4vv_##x##f, Z_##x##f, x, mpfr_##x, 2, 1, f2, 0) 323*f3087befSAndrew Turner #define ZVND1(x) F (_ZGVnN2v_##x, Z_##x, x##l, mpfr_##x, 1, 0, d1, 0) 324*f3087befSAndrew Turner #define ZVND2(x) F (_ZGVnN2vv_##x, Z_##x, x##l, mpfr_##x, 2, 0, d2, 0) 325072a4ba8SAndrew Turner /* SVE routines. */ 326*f3087befSAndrew Turner #define ZSVF1(x) SVF (_ZGVsMxv_##x##f, Z_sv_##x##f, x, mpfr_##x, 1, 1, f1, 0) 327*f3087befSAndrew Turner #define ZSVF2(x) SVF (_ZGVsMxvv_##x##f, Z_sv_##x##f, x, mpfr_##x, 2, 1, f2, 0) 328*f3087befSAndrew Turner #define ZSVD1(x) SVF (_ZGVsMxv_##x, Z_sv_##x, x##l, mpfr_##x, 1, 0, d1, 0) 329*f3087befSAndrew Turner #define ZSVD2(x) SVF (_ZGVsMxvv_##x, Z_sv_##x, x##l, mpfr_##x, 2, 0, d2, 0) 330072a4ba8SAndrew Turner 331072a4ba8SAndrew Turner #include "test/ulp_funcs.h" 332072a4ba8SAndrew Turner 33331914882SAlex Richardson #undef F 33431914882SAlex Richardson #undef F1 33531914882SAlex Richardson #undef F2 33631914882SAlex Richardson #undef D1 33731914882SAlex Richardson #undef D2 338*f3087befSAndrew Turner #undef ZSVF1 339*f3087befSAndrew Turner #undef ZSVF2 340*f3087befSAndrew Turner #undef ZSVD1 341*f3087befSAndrew Turner #undef ZSVD2 342*f3087befSAndrew Turner { 0 } 343*f3087befSAndrew Turner }; 344*f3087befSAndrew Turner // clang-format on 34531914882SAlex Richardson 34631914882SAlex Richardson /* Boilerplate for generic calls. */ 34731914882SAlex Richardson 34831914882SAlex Richardson static inline int 34931914882SAlex Richardson ulpscale_f (float x) 35031914882SAlex Richardson { 35131914882SAlex Richardson int e = asuint (x) >> 23 & 0xff; 35231914882SAlex Richardson if (!e) 35331914882SAlex Richardson e++; 35431914882SAlex Richardson return e - 0x7f - 23; 35531914882SAlex Richardson } 35631914882SAlex Richardson static inline int 35731914882SAlex Richardson ulpscale_d (double x) 35831914882SAlex Richardson { 35931914882SAlex Richardson int e = asuint64 (x) >> 52 & 0x7ff; 36031914882SAlex Richardson if (!e) 36131914882SAlex Richardson e++; 36231914882SAlex Richardson return e - 0x3ff - 52; 36331914882SAlex Richardson } 36431914882SAlex Richardson static inline float 365*f3087befSAndrew Turner call_f1 (const struct fun *f, struct args_f1 a, const struct conf *conf) 36631914882SAlex Richardson { 367*f3087befSAndrew Turner #if WANT_SVE_TESTS 368*f3087befSAndrew Turner if (f->is_predicated) 369*f3087befSAndrew Turner return f->fun.f1_pred (*conf->pg, a.x); 370*f3087befSAndrew Turner #endif 37131914882SAlex Richardson return f->fun.f1 (a.x); 37231914882SAlex Richardson } 37331914882SAlex Richardson static inline float 374*f3087befSAndrew Turner call_f2 (const struct fun *f, struct args_f2 a, const struct conf *conf) 37531914882SAlex Richardson { 376*f3087befSAndrew Turner #if WANT_SVE_TESTS 377*f3087befSAndrew Turner if (f->is_predicated) 378*f3087befSAndrew Turner return f->fun.f2_pred (*conf->pg, a.x, a.x2); 379*f3087befSAndrew Turner #endif 38031914882SAlex Richardson return f->fun.f2 (a.x, a.x2); 38131914882SAlex Richardson } 38231914882SAlex Richardson 38331914882SAlex Richardson static inline double 384*f3087befSAndrew Turner call_d1 (const struct fun *f, struct args_d1 a, const struct conf *conf) 38531914882SAlex Richardson { 386*f3087befSAndrew Turner #if WANT_SVE_TESTS 387*f3087befSAndrew Turner if (f->is_predicated) 388*f3087befSAndrew Turner return f->fun.d1_pred (*conf->pg, a.x); 389*f3087befSAndrew Turner #endif 39031914882SAlex Richardson return f->fun.d1 (a.x); 39131914882SAlex Richardson } 39231914882SAlex Richardson static inline double 393*f3087befSAndrew Turner call_d2 (const struct fun *f, struct args_d2 a, const struct conf *conf) 39431914882SAlex Richardson { 395*f3087befSAndrew Turner #if WANT_SVE_TESTS 396*f3087befSAndrew Turner if (f->is_predicated) 397*f3087befSAndrew Turner return f->fun.d2_pred (*conf->pg, a.x, a.x2); 398*f3087befSAndrew Turner #endif 39931914882SAlex Richardson return f->fun.d2 (a.x, a.x2); 40031914882SAlex Richardson } 40131914882SAlex Richardson static inline double 40231914882SAlex Richardson call_long_f1 (const struct fun *f, struct args_f1 a) 40331914882SAlex Richardson { 40431914882SAlex Richardson return f->fun_long.f1 (a.x); 40531914882SAlex Richardson } 40631914882SAlex Richardson static inline double 40731914882SAlex Richardson call_long_f2 (const struct fun *f, struct args_f2 a) 40831914882SAlex Richardson { 40931914882SAlex Richardson return f->fun_long.f2 (a.x, a.x2); 41031914882SAlex Richardson } 41131914882SAlex Richardson static inline long double 41231914882SAlex Richardson call_long_d1 (const struct fun *f, struct args_d1 a) 41331914882SAlex Richardson { 41431914882SAlex Richardson return f->fun_long.d1 (a.x); 41531914882SAlex Richardson } 41631914882SAlex Richardson static inline long double 41731914882SAlex Richardson call_long_d2 (const struct fun *f, struct args_d2 a) 41831914882SAlex Richardson { 41931914882SAlex Richardson return f->fun_long.d2 (a.x, a.x2); 42031914882SAlex Richardson } 42131914882SAlex Richardson static inline void 42231914882SAlex Richardson printcall_f1 (const struct fun *f, struct args_f1 a) 42331914882SAlex Richardson { 42431914882SAlex Richardson printf ("%s(%a)", f->name, a.x); 42531914882SAlex Richardson } 42631914882SAlex Richardson static inline void 42731914882SAlex Richardson printcall_f2 (const struct fun *f, struct args_f2 a) 42831914882SAlex Richardson { 42931914882SAlex Richardson printf ("%s(%a, %a)", f->name, a.x, a.x2); 43031914882SAlex Richardson } 43131914882SAlex Richardson static inline void 43231914882SAlex Richardson printcall_d1 (const struct fun *f, struct args_d1 a) 43331914882SAlex Richardson { 43431914882SAlex Richardson printf ("%s(%a)", f->name, a.x); 43531914882SAlex Richardson } 43631914882SAlex Richardson static inline void 43731914882SAlex Richardson printcall_d2 (const struct fun *f, struct args_d2 a) 43831914882SAlex Richardson { 43931914882SAlex Richardson printf ("%s(%a, %a)", f->name, a.x, a.x2); 44031914882SAlex Richardson } 44131914882SAlex Richardson static inline void 44231914882SAlex Richardson printgen_f1 (const struct fun *f, struct gen *gen) 44331914882SAlex Richardson { 44431914882SAlex Richardson printf ("%s in [%a;%a]", f->name, asfloat (gen->start), 44531914882SAlex Richardson asfloat (gen->start + gen->len)); 44631914882SAlex Richardson } 44731914882SAlex Richardson static inline void 44831914882SAlex Richardson printgen_f2 (const struct fun *f, struct gen *gen) 44931914882SAlex Richardson { 45031914882SAlex Richardson printf ("%s in [%a;%a] x [%a;%a]", f->name, asfloat (gen->start), 45131914882SAlex Richardson asfloat (gen->start + gen->len), asfloat (gen->start2), 45231914882SAlex Richardson asfloat (gen->start2 + gen->len2)); 45331914882SAlex Richardson } 45431914882SAlex Richardson static inline void 45531914882SAlex Richardson printgen_d1 (const struct fun *f, struct gen *gen) 45631914882SAlex Richardson { 45731914882SAlex Richardson printf ("%s in [%a;%a]", f->name, asdouble (gen->start), 45831914882SAlex Richardson asdouble (gen->start + gen->len)); 45931914882SAlex Richardson } 46031914882SAlex Richardson static inline void 46131914882SAlex Richardson printgen_d2 (const struct fun *f, struct gen *gen) 46231914882SAlex Richardson { 46331914882SAlex Richardson printf ("%s in [%a;%a] x [%a;%a]", f->name, asdouble (gen->start), 46431914882SAlex Richardson asdouble (gen->start + gen->len), asdouble (gen->start2), 46531914882SAlex Richardson asdouble (gen->start2 + gen->len2)); 46631914882SAlex Richardson } 46731914882SAlex Richardson 46831914882SAlex Richardson #define reduce_f1(a, f, op) (f (a.x)) 46931914882SAlex Richardson #define reduce_f2(a, f, op) (f (a.x) op f (a.x2)) 47031914882SAlex Richardson #define reduce_d1(a, f, op) (f (a.x)) 47131914882SAlex Richardson #define reduce_d2(a, f, op) (f (a.x) op f (a.x2)) 47231914882SAlex Richardson 47331914882SAlex Richardson #ifndef IEEE_754_2008_SNAN 47431914882SAlex Richardson # define IEEE_754_2008_SNAN 1 47531914882SAlex Richardson #endif 47631914882SAlex Richardson static inline int 47731914882SAlex Richardson issignaling_f (float x) 47831914882SAlex Richardson { 47931914882SAlex Richardson uint32_t ix = asuint (x); 48031914882SAlex Richardson if (!IEEE_754_2008_SNAN) 48131914882SAlex Richardson return (ix & 0x7fc00000) == 0x7fc00000; 48231914882SAlex Richardson return 2 * (ix ^ 0x00400000) > 2u * 0x7fc00000; 48331914882SAlex Richardson } 48431914882SAlex Richardson static inline int 48531914882SAlex Richardson issignaling_d (double x) 48631914882SAlex Richardson { 48731914882SAlex Richardson uint64_t ix = asuint64 (x); 48831914882SAlex Richardson if (!IEEE_754_2008_SNAN) 48931914882SAlex Richardson return (ix & 0x7ff8000000000000) == 0x7ff8000000000000; 49031914882SAlex Richardson return 2 * (ix ^ 0x0008000000000000) > 2 * 0x7ff8000000000000ULL; 49131914882SAlex Richardson } 49231914882SAlex Richardson 49331914882SAlex Richardson #if USE_MPFR 49431914882SAlex Richardson static mpfr_rnd_t 49531914882SAlex Richardson rmap (int r) 49631914882SAlex Richardson { 49731914882SAlex Richardson switch (r) 49831914882SAlex Richardson { 49931914882SAlex Richardson case FE_TONEAREST: 50031914882SAlex Richardson return MPFR_RNDN; 50131914882SAlex Richardson case FE_TOWARDZERO: 50231914882SAlex Richardson return MPFR_RNDZ; 50331914882SAlex Richardson case FE_UPWARD: 50431914882SAlex Richardson return MPFR_RNDU; 50531914882SAlex Richardson case FE_DOWNWARD: 50631914882SAlex Richardson return MPFR_RNDD; 50731914882SAlex Richardson } 50831914882SAlex Richardson return -1; 50931914882SAlex Richardson } 51031914882SAlex Richardson 51131914882SAlex Richardson #define prec_mpfr_f 50 51231914882SAlex Richardson #define prec_mpfr_d 80 51331914882SAlex Richardson #define prec_f 24 51431914882SAlex Richardson #define prec_d 53 51531914882SAlex Richardson #define emin_f -148 51631914882SAlex Richardson #define emin_d -1073 51731914882SAlex Richardson #define emax_f 128 51831914882SAlex Richardson #define emax_d 1024 51931914882SAlex Richardson static inline int 52031914882SAlex Richardson call_mpfr_f1 (mpfr_t y, const struct fun *f, struct args_f1 a, mpfr_rnd_t r) 52131914882SAlex Richardson { 52231914882SAlex Richardson MPFR_DECL_INIT (x, prec_f); 52331914882SAlex Richardson mpfr_set_flt (x, a.x, MPFR_RNDN); 52431914882SAlex Richardson return f->fun_mpfr.f1 (y, x, r); 52531914882SAlex Richardson } 52631914882SAlex Richardson static inline int 52731914882SAlex Richardson call_mpfr_f2 (mpfr_t y, const struct fun *f, struct args_f2 a, mpfr_rnd_t r) 52831914882SAlex Richardson { 52931914882SAlex Richardson MPFR_DECL_INIT (x, prec_f); 53031914882SAlex Richardson MPFR_DECL_INIT (x2, prec_f); 53131914882SAlex Richardson mpfr_set_flt (x, a.x, MPFR_RNDN); 53231914882SAlex Richardson mpfr_set_flt (x2, a.x2, MPFR_RNDN); 53331914882SAlex Richardson return f->fun_mpfr.f2 (y, x, x2, r); 53431914882SAlex Richardson } 53531914882SAlex Richardson static inline int 53631914882SAlex Richardson call_mpfr_d1 (mpfr_t y, const struct fun *f, struct args_d1 a, mpfr_rnd_t r) 53731914882SAlex Richardson { 53831914882SAlex Richardson MPFR_DECL_INIT (x, prec_d); 53931914882SAlex Richardson mpfr_set_d (x, a.x, MPFR_RNDN); 54031914882SAlex Richardson return f->fun_mpfr.d1 (y, x, r); 54131914882SAlex Richardson } 54231914882SAlex Richardson static inline int 54331914882SAlex Richardson call_mpfr_d2 (mpfr_t y, const struct fun *f, struct args_d2 a, mpfr_rnd_t r) 54431914882SAlex Richardson { 54531914882SAlex Richardson MPFR_DECL_INIT (x, prec_d); 54631914882SAlex Richardson MPFR_DECL_INIT (x2, prec_d); 54731914882SAlex Richardson mpfr_set_d (x, a.x, MPFR_RNDN); 54831914882SAlex Richardson mpfr_set_d (x2, a.x2, MPFR_RNDN); 54931914882SAlex Richardson return f->fun_mpfr.d2 (y, x, x2, r); 55031914882SAlex Richardson } 55131914882SAlex Richardson #endif 55231914882SAlex Richardson 55331914882SAlex Richardson #define float_f float 55431914882SAlex Richardson #define double_f double 55531914882SAlex Richardson #define copysign_f copysignf 55631914882SAlex Richardson #define nextafter_f nextafterf 55731914882SAlex Richardson #define fabs_f fabsf 55831914882SAlex Richardson #define asuint_f asuint 55931914882SAlex Richardson #define asfloat_f asfloat 56031914882SAlex Richardson #define scalbn_f scalbnf 56131914882SAlex Richardson #define lscalbn_f scalbn 56231914882SAlex Richardson #define halfinf_f 0x1p127f 56331914882SAlex Richardson #define min_normal_f 0x1p-126f 56431914882SAlex Richardson 56531914882SAlex Richardson #define float_d double 56631914882SAlex Richardson #define double_d long double 56731914882SAlex Richardson #define copysign_d copysign 56831914882SAlex Richardson #define nextafter_d nextafter 56931914882SAlex Richardson #define fabs_d fabs 57031914882SAlex Richardson #define asuint_d asuint64 57131914882SAlex Richardson #define asfloat_d asdouble 57231914882SAlex Richardson #define scalbn_d scalbn 57331914882SAlex Richardson #define lscalbn_d scalbnl 57431914882SAlex Richardson #define halfinf_d 0x1p1023 57531914882SAlex Richardson #define min_normal_d 0x1p-1022 57631914882SAlex Richardson 57731914882SAlex Richardson #define NEW_RT 57831914882SAlex Richardson #define RT(x) x##_f 57931914882SAlex Richardson #define T(x) x##_f1 58031914882SAlex Richardson #include "ulp.h" 58131914882SAlex Richardson #undef T 58231914882SAlex Richardson #define T(x) x##_f2 58331914882SAlex Richardson #include "ulp.h" 58431914882SAlex Richardson #undef T 58531914882SAlex Richardson #undef RT 58631914882SAlex Richardson 58731914882SAlex Richardson #define NEW_RT 58831914882SAlex Richardson #define RT(x) x##_d 58931914882SAlex Richardson #define T(x) x##_d1 59031914882SAlex Richardson #include "ulp.h" 59131914882SAlex Richardson #undef T 59231914882SAlex Richardson #define T(x) x##_d2 59331914882SAlex Richardson #include "ulp.h" 59431914882SAlex Richardson #undef T 59531914882SAlex Richardson #undef RT 59631914882SAlex Richardson 59731914882SAlex Richardson static void 59831914882SAlex Richardson usage (void) 59931914882SAlex Richardson { 6005a02ffc3SAndrew Turner puts ("./ulp [-q] [-m] [-f] [-r {n|u|d|z}] [-l soft-ulplimit] [-e ulplimit] func " 60131914882SAlex Richardson "lo [hi [x lo2 hi2] [count]]"); 60231914882SAlex Richardson puts ("Compares func against a higher precision implementation in [lo; hi]."); 60331914882SAlex Richardson puts ("-q: quiet."); 60431914882SAlex Richardson puts ("-m: use mpfr even if faster method is available."); 6055a02ffc3SAndrew Turner puts ("-f: disable fenv exceptions testing."); 6065a02ffc3SAndrew Turner #ifdef ___vpcs 607072a4ba8SAndrew Turner puts ("-c: neutral 'control value' to test behaviour when one lane can affect another. \n" 608072a4ba8SAndrew Turner " This should be different from tested input in other lanes, and non-special \n" 609072a4ba8SAndrew Turner " (i.e. should not trigger fenv exceptions). Default is 1."); 610072a4ba8SAndrew Turner #endif 611*f3087befSAndrew Turner #if WANT_SVE_TESTS 612*f3087befSAndrew Turner puts ("-p: integer input for controlling predicate passed to SVE function. " 613*f3087befSAndrew Turner "If bit N is set, lane N is activated (bits past the vector length " 614*f3087befSAndrew Turner "are ignored). Default is UINT64_MAX (ptrue)."); 615*f3087befSAndrew Turner #endif 6165a02ffc3SAndrew Turner puts ("-z: ignore sign of 0."); 61731914882SAlex Richardson puts ("Supported func:"); 61831914882SAlex Richardson for (const struct fun *f = fun; f->name; f++) 61931914882SAlex Richardson printf ("\t%s\n", f->name); 62031914882SAlex Richardson exit (1); 62131914882SAlex Richardson } 62231914882SAlex Richardson 62331914882SAlex Richardson static int 62431914882SAlex Richardson cmp (const struct fun *f, struct gen *gen, const struct conf *conf) 62531914882SAlex Richardson { 62631914882SAlex Richardson int r = 1; 62731914882SAlex Richardson if (f->arity == 1 && f->singleprec) 62831914882SAlex Richardson r = cmp_f1 (f, gen, conf); 62931914882SAlex Richardson else if (f->arity == 2 && f->singleprec) 63031914882SAlex Richardson r = cmp_f2 (f, gen, conf); 63131914882SAlex Richardson else if (f->arity == 1 && !f->singleprec) 63231914882SAlex Richardson r = cmp_d1 (f, gen, conf); 63331914882SAlex Richardson else if (f->arity == 2 && !f->singleprec) 63431914882SAlex Richardson r = cmp_d2 (f, gen, conf); 63531914882SAlex Richardson else 63631914882SAlex Richardson usage (); 63731914882SAlex Richardson return r; 63831914882SAlex Richardson } 63931914882SAlex Richardson 64031914882SAlex Richardson static uint64_t 64131914882SAlex Richardson getnum (const char *s, int singleprec) 64231914882SAlex Richardson { 64331914882SAlex Richardson // int i; 64431914882SAlex Richardson uint64_t sign = 0; 64531914882SAlex Richardson // char buf[12]; 64631914882SAlex Richardson 64731914882SAlex Richardson if (s[0] == '+') 64831914882SAlex Richardson s++; 64931914882SAlex Richardson else if (s[0] == '-') 65031914882SAlex Richardson { 65131914882SAlex Richardson sign = singleprec ? 1ULL << 31 : 1ULL << 63; 65231914882SAlex Richardson s++; 65331914882SAlex Richardson } 654*f3087befSAndrew Turner 655*f3087befSAndrew Turner /* Sentinel value for failed parse. */ 656*f3087befSAndrew Turner char *should_not_be_s = NULL; 657*f3087befSAndrew Turner 65831914882SAlex Richardson /* 0xXXXX is treated as bit representation, '-' flips the sign bit. */ 65931914882SAlex Richardson if (s[0] == '0' && tolower (s[1]) == 'x' && strchr (s, 'p') == 0) 660*f3087befSAndrew Turner { 661*f3087befSAndrew Turner uint64_t out = sign ^ strtoull (s, &should_not_be_s, 0); 662*f3087befSAndrew Turner if (should_not_be_s == s) 663*f3087befSAndrew Turner { 664*f3087befSAndrew Turner printf ("ERROR: Could not parse '%s'\n", s); 665*f3087befSAndrew Turner exit (1); 666*f3087befSAndrew Turner } 667*f3087befSAndrew Turner return out; 668*f3087befSAndrew Turner } 66931914882SAlex Richardson // /* SNaN, QNaN, NaN, Inf. */ 67031914882SAlex Richardson // for (i=0; s[i] && i < sizeof buf; i++) 67131914882SAlex Richardson // buf[i] = tolower(s[i]); 67231914882SAlex Richardson // buf[i] = 0; 67331914882SAlex Richardson // if (strcmp(buf, "snan") == 0) 67431914882SAlex Richardson // return sign | (singleprec ? 0x7fa00000 : 0x7ff4000000000000); 67531914882SAlex Richardson // if (strcmp(buf, "qnan") == 0 || strcmp(buf, "nan") == 0) 67631914882SAlex Richardson // return sign | (singleprec ? 0x7fc00000 : 0x7ff8000000000000); 67731914882SAlex Richardson // if (strcmp(buf, "inf") == 0 || strcmp(buf, "infinity") == 0) 67831914882SAlex Richardson // return sign | (singleprec ? 0x7f800000 : 0x7ff0000000000000); 67931914882SAlex Richardson /* Otherwise assume it's a floating-point literal. */ 680*f3087befSAndrew Turner uint64_t out = sign 681*f3087befSAndrew Turner | (singleprec ? asuint (strtof (s, &should_not_be_s)) 682*f3087befSAndrew Turner : asuint64 (strtod (s, &should_not_be_s))); 683*f3087befSAndrew Turner if (should_not_be_s == s) 684*f3087befSAndrew Turner { 685*f3087befSAndrew Turner printf ("ERROR: Could not parse '%s'\n", s); 686*f3087befSAndrew Turner exit (1); 687*f3087befSAndrew Turner } 688*f3087befSAndrew Turner 689*f3087befSAndrew Turner return out; 69031914882SAlex Richardson } 69131914882SAlex Richardson 69231914882SAlex Richardson static void 69331914882SAlex Richardson parsegen (struct gen *g, int argc, char *argv[], const struct fun *f) 69431914882SAlex Richardson { 69531914882SAlex Richardson int singleprec = f->singleprec; 69631914882SAlex Richardson int arity = f->arity; 69731914882SAlex Richardson uint64_t a, b, a2, b2, n; 69831914882SAlex Richardson if (argc < 1) 69931914882SAlex Richardson usage (); 70031914882SAlex Richardson b = a = getnum (argv[0], singleprec); 70131914882SAlex Richardson n = 0; 70231914882SAlex Richardson if (argc > 1 && strcmp (argv[1], "x") == 0) 70331914882SAlex Richardson { 70431914882SAlex Richardson argc -= 2; 70531914882SAlex Richardson argv += 2; 70631914882SAlex Richardson } 70731914882SAlex Richardson else if (argc > 1) 70831914882SAlex Richardson { 70931914882SAlex Richardson b = getnum (argv[1], singleprec); 71031914882SAlex Richardson if (argc > 2 && strcmp (argv[2], "x") == 0) 71131914882SAlex Richardson { 71231914882SAlex Richardson argc -= 3; 71331914882SAlex Richardson argv += 3; 71431914882SAlex Richardson } 71531914882SAlex Richardson } 71631914882SAlex Richardson b2 = a2 = getnum (argv[0], singleprec); 71731914882SAlex Richardson if (argc > 1) 71831914882SAlex Richardson b2 = getnum (argv[1], singleprec); 71931914882SAlex Richardson if (argc > 2) 72031914882SAlex Richardson n = strtoull (argv[2], 0, 0); 72131914882SAlex Richardson if (argc > 3) 72231914882SAlex Richardson usage (); 72331914882SAlex Richardson //printf("ab %lx %lx ab2 %lx %lx n %lu\n", a, b, a2, b2, n); 72431914882SAlex Richardson if (arity == 1) 72531914882SAlex Richardson { 72631914882SAlex Richardson g->start = a; 72731914882SAlex Richardson g->len = b - a; 72831914882SAlex Richardson if (n - 1 > b - a) 72931914882SAlex Richardson n = b - a + 1; 73031914882SAlex Richardson g->off = 0; 73131914882SAlex Richardson g->step = n ? (g->len + 1) / n : 1; 73231914882SAlex Richardson g->start2 = g->len2 = 0; 73331914882SAlex Richardson g->cnt = n; 73431914882SAlex Richardson } 73531914882SAlex Richardson else if (arity == 2) 73631914882SAlex Richardson { 73731914882SAlex Richardson g->start = a; 73831914882SAlex Richardson g->len = b - a; 73931914882SAlex Richardson g->off = g->step = 0; 74031914882SAlex Richardson g->start2 = a2; 74131914882SAlex Richardson g->len2 = b2 - a2; 74231914882SAlex Richardson g->cnt = n; 74331914882SAlex Richardson } 74431914882SAlex Richardson else 74531914882SAlex Richardson usage (); 74631914882SAlex Richardson } 74731914882SAlex Richardson 74831914882SAlex Richardson int 74931914882SAlex Richardson main (int argc, char *argv[]) 75031914882SAlex Richardson { 75131914882SAlex Richardson const struct fun *f; 75231914882SAlex Richardson struct gen gen; 75331914882SAlex Richardson struct conf conf; 75431914882SAlex Richardson conf.rc = 'n'; 75531914882SAlex Richardson conf.quiet = 0; 75631914882SAlex Richardson conf.mpfr = 0; 75731914882SAlex Richardson conf.fenv = 1; 75831914882SAlex Richardson conf.softlim = 0; 75931914882SAlex Richardson conf.errlim = INFINITY; 7605a02ffc3SAndrew Turner conf.ignore_zero_sign = 0; 761*f3087befSAndrew Turner #if WANT_SVE_TESTS 762*f3087befSAndrew Turner uint64_t pg_int = UINT64_MAX; 763*f3087befSAndrew Turner #endif 76431914882SAlex Richardson for (;;) 76531914882SAlex Richardson { 76631914882SAlex Richardson argc--; 76731914882SAlex Richardson argv++; 76831914882SAlex Richardson if (argc < 1) 76931914882SAlex Richardson usage (); 77031914882SAlex Richardson if (argv[0][0] != '-') 77131914882SAlex Richardson break; 77231914882SAlex Richardson switch (argv[0][1]) 77331914882SAlex Richardson { 77431914882SAlex Richardson case 'e': 77531914882SAlex Richardson argc--; 77631914882SAlex Richardson argv++; 77731914882SAlex Richardson if (argc < 1) 77831914882SAlex Richardson usage (); 77931914882SAlex Richardson conf.errlim = strtod (argv[0], 0); 78031914882SAlex Richardson break; 78131914882SAlex Richardson case 'f': 78231914882SAlex Richardson conf.fenv = 0; 78331914882SAlex Richardson break; 78431914882SAlex Richardson case 'l': 78531914882SAlex Richardson argc--; 78631914882SAlex Richardson argv++; 78731914882SAlex Richardson if (argc < 1) 78831914882SAlex Richardson usage (); 78931914882SAlex Richardson conf.softlim = strtod (argv[0], 0); 79031914882SAlex Richardson break; 79131914882SAlex Richardson case 'm': 79231914882SAlex Richardson conf.mpfr = 1; 79331914882SAlex Richardson break; 79431914882SAlex Richardson case 'q': 79531914882SAlex Richardson conf.quiet = 1; 79631914882SAlex Richardson break; 79731914882SAlex Richardson case 'r': 79831914882SAlex Richardson conf.rc = argv[0][2]; 79931914882SAlex Richardson if (!conf.rc) 80031914882SAlex Richardson { 80131914882SAlex Richardson argc--; 80231914882SAlex Richardson argv++; 8035a02ffc3SAndrew Turner if (argc < 1 || argv[0][1] != '\0') 80431914882SAlex Richardson usage (); 80531914882SAlex Richardson conf.rc = argv[0][0]; 80631914882SAlex Richardson } 80731914882SAlex Richardson break; 8085a02ffc3SAndrew Turner case 'z': 8095a02ffc3SAndrew Turner conf.ignore_zero_sign = 1; 8105a02ffc3SAndrew Turner break; 811*f3087befSAndrew Turner #if __aarch64__ && __linux__ 812072a4ba8SAndrew Turner case 'c': 813072a4ba8SAndrew Turner argc--; 814072a4ba8SAndrew Turner argv++; 815072a4ba8SAndrew Turner fv[0] = strtof(argv[0], 0); 816072a4ba8SAndrew Turner dv[0] = strtod(argv[0], 0); 817072a4ba8SAndrew Turner break; 818072a4ba8SAndrew Turner #endif 819*f3087befSAndrew Turner #if WANT_SVE_TESTS 820*f3087befSAndrew Turner case 'p': 821*f3087befSAndrew Turner argc--; 822*f3087befSAndrew Turner argv++; 823*f3087befSAndrew Turner pg_int = strtoull (argv[0], 0, 0); 824*f3087befSAndrew Turner break; 825*f3087befSAndrew Turner #endif 82631914882SAlex Richardson default: 82731914882SAlex Richardson usage (); 82831914882SAlex Richardson } 82931914882SAlex Richardson } 83031914882SAlex Richardson switch (conf.rc) 83131914882SAlex Richardson { 83231914882SAlex Richardson case 'n': 83331914882SAlex Richardson conf.r = FE_TONEAREST; 83431914882SAlex Richardson break; 83531914882SAlex Richardson case 'u': 83631914882SAlex Richardson conf.r = FE_UPWARD; 83731914882SAlex Richardson break; 83831914882SAlex Richardson case 'd': 83931914882SAlex Richardson conf.r = FE_DOWNWARD; 84031914882SAlex Richardson break; 84131914882SAlex Richardson case 'z': 84231914882SAlex Richardson conf.r = FE_TOWARDZERO; 84331914882SAlex Richardson break; 84431914882SAlex Richardson default: 84531914882SAlex Richardson usage (); 84631914882SAlex Richardson } 84731914882SAlex Richardson for (f = fun; f->name; f++) 84831914882SAlex Richardson if (strcmp (argv[0], f->name) == 0) 84931914882SAlex Richardson break; 85031914882SAlex Richardson if (!f->name) 8515a02ffc3SAndrew Turner { 8525a02ffc3SAndrew Turner #ifndef __vpcs 8535a02ffc3SAndrew Turner /* Ignore vector math functions if vector math is not supported. */ 8545a02ffc3SAndrew Turner if (strncmp (argv[0], "_ZGVnN", 6) == 0) 8555a02ffc3SAndrew Turner exit (0); 8565a02ffc3SAndrew Turner #endif 857*f3087befSAndrew Turner #if !WANT_SVE_TESTS 8585a02ffc3SAndrew Turner if (strncmp (argv[0], "_ZGVsMxv", 8) == 0) 8595a02ffc3SAndrew Turner exit (0); 8605a02ffc3SAndrew Turner #endif 8615a02ffc3SAndrew Turner printf ("math function %s not supported\n", argv[0]); 8625a02ffc3SAndrew Turner exit (1); 8635a02ffc3SAndrew Turner } 86431914882SAlex Richardson if (!f->singleprec && LDBL_MANT_DIG == DBL_MANT_DIG) 86531914882SAlex Richardson conf.mpfr = 1; /* Use mpfr if long double has no extra precision. */ 86631914882SAlex Richardson if (!USE_MPFR && conf.mpfr) 86731914882SAlex Richardson { 86831914882SAlex Richardson puts ("mpfr is not available."); 86931914882SAlex Richardson return 0; 87031914882SAlex Richardson } 87131914882SAlex Richardson argc--; 87231914882SAlex Richardson argv++; 87331914882SAlex Richardson parsegen (&gen, argc, argv, f); 87431914882SAlex Richardson conf.n = gen.cnt; 875*f3087befSAndrew Turner #if WANT_SVE_TESTS 876*f3087befSAndrew Turner svbool_t pg = parse_pg (pg_int, f->singleprec); 877*f3087befSAndrew Turner conf.pg = &pg; 878*f3087befSAndrew Turner #endif 87931914882SAlex Richardson return cmp (f, &gen, &conf); 88031914882SAlex Richardson } 881*f3087befSAndrew Turner 882*f3087befSAndrew Turner #if __aarch64__ && __linux__ && WANT_SVE_TESTS && defined(__clang__) 883*f3087befSAndrew Turner # pragma clang attribute pop 884*f3087befSAndrew Turner #endif 885