1*0928368fSKristof Beyls /*
2*0928368fSKristof Beyls * ULP error checking tool for math functions.
3*0928368fSKristof Beyls *
4*0928368fSKristof Beyls * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5*0928368fSKristof Beyls * See https://llvm.org/LICENSE.txt for license information.
6*0928368fSKristof Beyls * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7*0928368fSKristof Beyls */
8*0928368fSKristof Beyls
9*0928368fSKristof Beyls #include <ctype.h>
10*0928368fSKristof Beyls #include <fenv.h>
11*0928368fSKristof Beyls #include <float.h>
12*0928368fSKristof Beyls #include <math.h>
13*0928368fSKristof Beyls #include <stdint.h>
14*0928368fSKristof Beyls #include <stdio.h>
15*0928368fSKristof Beyls #include <stdlib.h>
16*0928368fSKristof Beyls #include <string.h>
17*0928368fSKristof Beyls #include "mathlib.h"
18*0928368fSKristof Beyls
19*0928368fSKristof Beyls /* Don't depend on mpfr by default. */
20*0928368fSKristof Beyls #ifndef USE_MPFR
21*0928368fSKristof Beyls # define USE_MPFR 0
22*0928368fSKristof Beyls #endif
23*0928368fSKristof Beyls #if USE_MPFR
24*0928368fSKristof Beyls # include <mpfr.h>
25*0928368fSKristof Beyls #endif
26*0928368fSKristof Beyls
27*0928368fSKristof Beyls #ifndef WANT_VMATH
28*0928368fSKristof Beyls /* Enable the build of vector math code. */
29*0928368fSKristof Beyls # define WANT_VMATH 1
30*0928368fSKristof Beyls #endif
31*0928368fSKristof Beyls
32*0928368fSKristof Beyls static inline uint64_t
asuint64(double f)33*0928368fSKristof Beyls asuint64 (double f)
34*0928368fSKristof Beyls {
35*0928368fSKristof Beyls union
36*0928368fSKristof Beyls {
37*0928368fSKristof Beyls double f;
38*0928368fSKristof Beyls uint64_t i;
39*0928368fSKristof Beyls } u = {f};
40*0928368fSKristof Beyls return u.i;
41*0928368fSKristof Beyls }
42*0928368fSKristof Beyls
43*0928368fSKristof Beyls static inline double
asdouble(uint64_t i)44*0928368fSKristof Beyls asdouble (uint64_t i)
45*0928368fSKristof Beyls {
46*0928368fSKristof Beyls union
47*0928368fSKristof Beyls {
48*0928368fSKristof Beyls uint64_t i;
49*0928368fSKristof Beyls double f;
50*0928368fSKristof Beyls } u = {i};
51*0928368fSKristof Beyls return u.f;
52*0928368fSKristof Beyls }
53*0928368fSKristof Beyls
54*0928368fSKristof Beyls static inline uint32_t
asuint(float f)55*0928368fSKristof Beyls asuint (float f)
56*0928368fSKristof Beyls {
57*0928368fSKristof Beyls union
58*0928368fSKristof Beyls {
59*0928368fSKristof Beyls float f;
60*0928368fSKristof Beyls uint32_t i;
61*0928368fSKristof Beyls } u = {f};
62*0928368fSKristof Beyls return u.i;
63*0928368fSKristof Beyls }
64*0928368fSKristof Beyls
65*0928368fSKristof Beyls static inline float
asfloat(uint32_t i)66*0928368fSKristof Beyls asfloat (uint32_t i)
67*0928368fSKristof Beyls {
68*0928368fSKristof Beyls union
69*0928368fSKristof Beyls {
70*0928368fSKristof Beyls uint32_t i;
71*0928368fSKristof Beyls float f;
72*0928368fSKristof Beyls } u = {i};
73*0928368fSKristof Beyls return u.f;
74*0928368fSKristof Beyls }
75*0928368fSKristof Beyls
76*0928368fSKristof Beyls static uint64_t seed = 0x0123456789abcdef;
77*0928368fSKristof Beyls static uint64_t
rand64(void)78*0928368fSKristof Beyls rand64 (void)
79*0928368fSKristof Beyls {
80*0928368fSKristof Beyls seed = 6364136223846793005ull * seed + 1;
81*0928368fSKristof Beyls return seed ^ (seed >> 32);
82*0928368fSKristof Beyls }
83*0928368fSKristof Beyls
84*0928368fSKristof Beyls /* Uniform random in [0,n]. */
85*0928368fSKristof Beyls static uint64_t
randn(uint64_t n)86*0928368fSKristof Beyls randn (uint64_t n)
87*0928368fSKristof Beyls {
88*0928368fSKristof Beyls uint64_t r, m;
89*0928368fSKristof Beyls
90*0928368fSKristof Beyls if (n == 0)
91*0928368fSKristof Beyls return 0;
92*0928368fSKristof Beyls n++;
93*0928368fSKristof Beyls if (n == 0)
94*0928368fSKristof Beyls return rand64 ();
95*0928368fSKristof Beyls for (;;)
96*0928368fSKristof Beyls {
97*0928368fSKristof Beyls r = rand64 ();
98*0928368fSKristof Beyls m = r % n;
99*0928368fSKristof Beyls if (r - m <= -n)
100*0928368fSKristof Beyls return m;
101*0928368fSKristof Beyls }
102*0928368fSKristof Beyls }
103*0928368fSKristof Beyls
104*0928368fSKristof Beyls struct gen
105*0928368fSKristof Beyls {
106*0928368fSKristof Beyls uint64_t start;
107*0928368fSKristof Beyls uint64_t len;
108*0928368fSKristof Beyls uint64_t start2;
109*0928368fSKristof Beyls uint64_t len2;
110*0928368fSKristof Beyls uint64_t off;
111*0928368fSKristof Beyls uint64_t step;
112*0928368fSKristof Beyls uint64_t cnt;
113*0928368fSKristof Beyls };
114*0928368fSKristof Beyls
115*0928368fSKristof Beyls struct args_f1
116*0928368fSKristof Beyls {
117*0928368fSKristof Beyls float x;
118*0928368fSKristof Beyls };
119*0928368fSKristof Beyls
120*0928368fSKristof Beyls struct args_f2
121*0928368fSKristof Beyls {
122*0928368fSKristof Beyls float x;
123*0928368fSKristof Beyls float x2;
124*0928368fSKristof Beyls };
125*0928368fSKristof Beyls
126*0928368fSKristof Beyls struct args_d1
127*0928368fSKristof Beyls {
128*0928368fSKristof Beyls double x;
129*0928368fSKristof Beyls };
130*0928368fSKristof Beyls
131*0928368fSKristof Beyls struct args_d2
132*0928368fSKristof Beyls {
133*0928368fSKristof Beyls double x;
134*0928368fSKristof Beyls double x2;
135*0928368fSKristof Beyls };
136*0928368fSKristof Beyls
137*0928368fSKristof Beyls /* result = y + tail*2^ulpexp. */
138*0928368fSKristof Beyls struct ret_f
139*0928368fSKristof Beyls {
140*0928368fSKristof Beyls float y;
141*0928368fSKristof Beyls double tail;
142*0928368fSKristof Beyls int ulpexp;
143*0928368fSKristof Beyls int ex;
144*0928368fSKristof Beyls int ex_may;
145*0928368fSKristof Beyls };
146*0928368fSKristof Beyls
147*0928368fSKristof Beyls struct ret_d
148*0928368fSKristof Beyls {
149*0928368fSKristof Beyls double y;
150*0928368fSKristof Beyls double tail;
151*0928368fSKristof Beyls int ulpexp;
152*0928368fSKristof Beyls int ex;
153*0928368fSKristof Beyls int ex_may;
154*0928368fSKristof Beyls };
155*0928368fSKristof Beyls
156*0928368fSKristof Beyls static inline uint64_t
next1(struct gen * g)157*0928368fSKristof Beyls next1 (struct gen *g)
158*0928368fSKristof Beyls {
159*0928368fSKristof Beyls /* For single argument use randomized incremental steps,
160*0928368fSKristof Beyls that produce dense sampling without collisions and allow
161*0928368fSKristof Beyls testing all inputs in a range. */
162*0928368fSKristof Beyls uint64_t r = g->start + g->off;
163*0928368fSKristof Beyls g->off += g->step + randn (g->step / 2);
164*0928368fSKristof Beyls if (g->off > g->len)
165*0928368fSKristof Beyls g->off -= g->len; /* hack. */
166*0928368fSKristof Beyls return r;
167*0928368fSKristof Beyls }
168*0928368fSKristof Beyls
169*0928368fSKristof Beyls static inline uint64_t
next2(uint64_t * x2,struct gen * g)170*0928368fSKristof Beyls next2 (uint64_t *x2, struct gen *g)
171*0928368fSKristof Beyls {
172*0928368fSKristof Beyls /* For two arguments use uniform random sampling. */
173*0928368fSKristof Beyls uint64_t r = g->start + randn (g->len);
174*0928368fSKristof Beyls *x2 = g->start2 + randn (g->len2);
175*0928368fSKristof Beyls return r;
176*0928368fSKristof Beyls }
177*0928368fSKristof Beyls
178*0928368fSKristof Beyls static struct args_f1
next_f1(void * g)179*0928368fSKristof Beyls next_f1 (void *g)
180*0928368fSKristof Beyls {
181*0928368fSKristof Beyls return (struct args_f1){asfloat (next1 (g))};
182*0928368fSKristof Beyls }
183*0928368fSKristof Beyls
184*0928368fSKristof Beyls static struct args_f2
next_f2(void * g)185*0928368fSKristof Beyls next_f2 (void *g)
186*0928368fSKristof Beyls {
187*0928368fSKristof Beyls uint64_t x2;
188*0928368fSKristof Beyls uint64_t x = next2 (&x2, g);
189*0928368fSKristof Beyls return (struct args_f2){asfloat (x), asfloat (x2)};
190*0928368fSKristof Beyls }
191*0928368fSKristof Beyls
192*0928368fSKristof Beyls static struct args_d1
next_d1(void * g)193*0928368fSKristof Beyls next_d1 (void *g)
194*0928368fSKristof Beyls {
195*0928368fSKristof Beyls return (struct args_d1){asdouble (next1 (g))};
196*0928368fSKristof Beyls }
197*0928368fSKristof Beyls
198*0928368fSKristof Beyls static struct args_d2
next_d2(void * g)199*0928368fSKristof Beyls next_d2 (void *g)
200*0928368fSKristof Beyls {
201*0928368fSKristof Beyls uint64_t x2;
202*0928368fSKristof Beyls uint64_t x = next2 (&x2, g);
203*0928368fSKristof Beyls return (struct args_d2){asdouble (x), asdouble (x2)};
204*0928368fSKristof Beyls }
205*0928368fSKristof Beyls
206*0928368fSKristof Beyls struct conf
207*0928368fSKristof Beyls {
208*0928368fSKristof Beyls int r;
209*0928368fSKristof Beyls int rc;
210*0928368fSKristof Beyls int quiet;
211*0928368fSKristof Beyls int mpfr;
212*0928368fSKristof Beyls int fenv;
213*0928368fSKristof Beyls unsigned long long n;
214*0928368fSKristof Beyls double softlim;
215*0928368fSKristof Beyls double errlim;
216*0928368fSKristof Beyls };
217*0928368fSKristof Beyls
218*0928368fSKristof Beyls /* Wrappers for sincos. */
sincosf_sinf(float x)219*0928368fSKristof Beyls static float sincosf_sinf(float x) {(void)cosf(x); return sinf(x);}
sincosf_cosf(float x)220*0928368fSKristof Beyls static float sincosf_cosf(float x) {(void)sinf(x); return cosf(x);}
sincos_sin(double x)221*0928368fSKristof Beyls static double sincos_sin(double x) {(void)cos(x); return sin(x);}
sincos_cos(double x)222*0928368fSKristof Beyls static double sincos_cos(double x) {(void)sin(x); return cos(x);}
223*0928368fSKristof Beyls #if USE_MPFR
sincos_mpfr_sin(mpfr_t y,const mpfr_t x,mpfr_rnd_t r)224*0928368fSKristof Beyls 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); }
sincos_mpfr_cos(mpfr_t y,const mpfr_t x,mpfr_rnd_t r)225*0928368fSKristof Beyls 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); }
226*0928368fSKristof Beyls #endif
227*0928368fSKristof Beyls
228*0928368fSKristof Beyls /* A bit of a hack: call vector functions twice with the same
229*0928368fSKristof Beyls input in lane 0 but a different value in other lanes: once
230*0928368fSKristof Beyls with an in-range value and then with a special case value. */
231*0928368fSKristof Beyls static int secondcall;
232*0928368fSKristof Beyls
233*0928368fSKristof Beyls /* Wrappers for vector functions. */
234*0928368fSKristof Beyls #if __aarch64__ && WANT_VMATH
235*0928368fSKristof Beyls typedef __f32x4_t v_float;
236*0928368fSKristof Beyls typedef __f64x2_t v_double;
237*0928368fSKristof Beyls static const float fv[2] = {1.0f, -INFINITY};
238*0928368fSKristof Beyls static const double dv[2] = {1.0, -INFINITY};
argf(float x)239*0928368fSKristof Beyls static inline v_float argf(float x) { return (v_float){x,x,x,fv[secondcall]}; }
argd(double x)240*0928368fSKristof Beyls static inline v_double argd(double x) { return (v_double){x,dv[secondcall]}; }
241*0928368fSKristof Beyls
v_sinf(float x)242*0928368fSKristof Beyls static float v_sinf(float x) { return __v_sinf(argf(x))[0]; }
v_cosf(float x)243*0928368fSKristof Beyls static float v_cosf(float x) { return __v_cosf(argf(x))[0]; }
v_expf_1u(float x)244*0928368fSKristof Beyls static float v_expf_1u(float x) { return __v_expf_1u(argf(x))[0]; }
v_expf(float x)245*0928368fSKristof Beyls static float v_expf(float x) { return __v_expf(argf(x))[0]; }
v_exp2f_1u(float x)246*0928368fSKristof Beyls static float v_exp2f_1u(float x) { return __v_exp2f_1u(argf(x))[0]; }
v_exp2f(float x)247*0928368fSKristof Beyls static float v_exp2f(float x) { return __v_exp2f(argf(x))[0]; }
v_logf(float x)248*0928368fSKristof Beyls static float v_logf(float x) { return __v_logf(argf(x))[0]; }
v_powf(float x,float y)249*0928368fSKristof Beyls static float v_powf(float x, float y) { return __v_powf(argf(x),argf(y))[0]; }
v_sin(double x)250*0928368fSKristof Beyls static double v_sin(double x) { return __v_sin(argd(x))[0]; }
v_cos(double x)251*0928368fSKristof Beyls static double v_cos(double x) { return __v_cos(argd(x))[0]; }
v_exp(double x)252*0928368fSKristof Beyls static double v_exp(double x) { return __v_exp(argd(x))[0]; }
v_log(double x)253*0928368fSKristof Beyls static double v_log(double x) { return __v_log(argd(x))[0]; }
v_pow(double x,double y)254*0928368fSKristof Beyls static double v_pow(double x, double y) { return __v_pow(argd(x),argd(y))[0]; }
255*0928368fSKristof Beyls #ifdef __vpcs
vn_sinf(float x)256*0928368fSKristof Beyls static float vn_sinf(float x) { return __vn_sinf(argf(x))[0]; }
vn_cosf(float x)257*0928368fSKristof Beyls static float vn_cosf(float x) { return __vn_cosf(argf(x))[0]; }
vn_expf_1u(float x)258*0928368fSKristof Beyls static float vn_expf_1u(float x) { return __vn_expf_1u(argf(x))[0]; }
vn_expf(float x)259*0928368fSKristof Beyls static float vn_expf(float x) { return __vn_expf(argf(x))[0]; }
vn_exp2f_1u(float x)260*0928368fSKristof Beyls static float vn_exp2f_1u(float x) { return __vn_exp2f_1u(argf(x))[0]; }
vn_exp2f(float x)261*0928368fSKristof Beyls static float vn_exp2f(float x) { return __vn_exp2f(argf(x))[0]; }
vn_logf(float x)262*0928368fSKristof Beyls static float vn_logf(float x) { return __vn_logf(argf(x))[0]; }
vn_powf(float x,float y)263*0928368fSKristof Beyls static float vn_powf(float x, float y) { return __vn_powf(argf(x),argf(y))[0]; }
vn_sin(double x)264*0928368fSKristof Beyls static double vn_sin(double x) { return __vn_sin(argd(x))[0]; }
vn_cos(double x)265*0928368fSKristof Beyls static double vn_cos(double x) { return __vn_cos(argd(x))[0]; }
vn_exp(double x)266*0928368fSKristof Beyls static double vn_exp(double x) { return __vn_exp(argd(x))[0]; }
vn_log(double x)267*0928368fSKristof Beyls static double vn_log(double x) { return __vn_log(argd(x))[0]; }
vn_pow(double x,double y)268*0928368fSKristof Beyls static double vn_pow(double x, double y) { return __vn_pow(argd(x),argd(y))[0]; }
Z_sinf(float x)269*0928368fSKristof Beyls static float Z_sinf(float x) { return _ZGVnN4v_sinf(argf(x))[0]; }
Z_cosf(float x)270*0928368fSKristof Beyls static float Z_cosf(float x) { return _ZGVnN4v_cosf(argf(x))[0]; }
Z_expf(float x)271*0928368fSKristof Beyls static float Z_expf(float x) { return _ZGVnN4v_expf(argf(x))[0]; }
Z_exp2f(float x)272*0928368fSKristof Beyls static float Z_exp2f(float x) { return _ZGVnN4v_exp2f(argf(x))[0]; }
Z_logf(float x)273*0928368fSKristof Beyls static float Z_logf(float x) { return _ZGVnN4v_logf(argf(x))[0]; }
Z_powf(float x,float y)274*0928368fSKristof Beyls static float Z_powf(float x, float y) { return _ZGVnN4vv_powf(argf(x),argf(y))[0]; }
Z_sin(double x)275*0928368fSKristof Beyls static double Z_sin(double x) { return _ZGVnN2v_sin(argd(x))[0]; }
Z_cos(double x)276*0928368fSKristof Beyls static double Z_cos(double x) { return _ZGVnN2v_cos(argd(x))[0]; }
Z_exp(double x)277*0928368fSKristof Beyls static double Z_exp(double x) { return _ZGVnN2v_exp(argd(x))[0]; }
Z_log(double x)278*0928368fSKristof Beyls static double Z_log(double x) { return _ZGVnN2v_log(argd(x))[0]; }
Z_pow(double x,double y)279*0928368fSKristof Beyls static double Z_pow(double x, double y) { return _ZGVnN2vv_pow(argd(x),argd(y))[0]; }
280*0928368fSKristof Beyls #endif
281*0928368fSKristof Beyls #endif
282*0928368fSKristof Beyls
283*0928368fSKristof Beyls struct fun
284*0928368fSKristof Beyls {
285*0928368fSKristof Beyls const char *name;
286*0928368fSKristof Beyls int arity;
287*0928368fSKristof Beyls int singleprec;
288*0928368fSKristof Beyls int twice;
289*0928368fSKristof Beyls union
290*0928368fSKristof Beyls {
291*0928368fSKristof Beyls float (*f1) (float);
292*0928368fSKristof Beyls float (*f2) (float, float);
293*0928368fSKristof Beyls double (*d1) (double);
294*0928368fSKristof Beyls double (*d2) (double, double);
295*0928368fSKristof Beyls } fun;
296*0928368fSKristof Beyls union
297*0928368fSKristof Beyls {
298*0928368fSKristof Beyls double (*f1) (double);
299*0928368fSKristof Beyls double (*f2) (double, double);
300*0928368fSKristof Beyls long double (*d1) (long double);
301*0928368fSKristof Beyls long double (*d2) (long double, long double);
302*0928368fSKristof Beyls } fun_long;
303*0928368fSKristof Beyls #if USE_MPFR
304*0928368fSKristof Beyls union
305*0928368fSKristof Beyls {
306*0928368fSKristof Beyls int (*f1) (mpfr_t, const mpfr_t, mpfr_rnd_t);
307*0928368fSKristof Beyls int (*f2) (mpfr_t, const mpfr_t, const mpfr_t, mpfr_rnd_t);
308*0928368fSKristof Beyls int (*d1) (mpfr_t, const mpfr_t, mpfr_rnd_t);
309*0928368fSKristof Beyls int (*d2) (mpfr_t, const mpfr_t, const mpfr_t, mpfr_rnd_t);
310*0928368fSKristof Beyls } fun_mpfr;
311*0928368fSKristof Beyls #endif
312*0928368fSKristof Beyls };
313*0928368fSKristof Beyls
314*0928368fSKristof Beyls static const struct fun fun[] = {
315*0928368fSKristof Beyls #if USE_MPFR
316*0928368fSKristof Beyls # define F(x, x_wrap, x_long, x_mpfr, a, s, t, twice) \
317*0928368fSKristof Beyls {#x, a, s, twice, {.t = x_wrap}, {.t = x_long}, {.t = x_mpfr}},
318*0928368fSKristof Beyls #else
319*0928368fSKristof Beyls # define F(x, x_wrap, x_long, x_mpfr, a, s, t, twice) \
320*0928368fSKristof Beyls {#x, a, s, twice, {.t = x_wrap}, {.t = x_long}},
321*0928368fSKristof Beyls #endif
322*0928368fSKristof Beyls #define F1(x) F (x##f, x##f, x, mpfr_##x, 1, 1, f1, 0)
323*0928368fSKristof Beyls #define F2(x) F (x##f, x##f, x, mpfr_##x, 2, 1, f2, 0)
324*0928368fSKristof Beyls #define D1(x) F (x, x, x##l, mpfr_##x, 1, 0, d1, 0)
325*0928368fSKristof Beyls #define D2(x) F (x, x, x##l, mpfr_##x, 2, 0, d2, 0)
326*0928368fSKristof Beyls F1 (sin)
327*0928368fSKristof Beyls F1 (cos)
328*0928368fSKristof Beyls F (sincosf_sinf, sincosf_sinf, sincos_sin, sincos_mpfr_sin, 1, 1, f1, 0)
329*0928368fSKristof Beyls F (sincosf_cosf, sincosf_cosf, sincos_cos, sincos_mpfr_cos, 1, 1, f1, 0)
330*0928368fSKristof Beyls F1 (exp)
331*0928368fSKristof Beyls F1 (exp2)
332*0928368fSKristof Beyls F1 (log)
333*0928368fSKristof Beyls F1 (log2)
334*0928368fSKristof Beyls F2 (pow)
335*0928368fSKristof Beyls D1 (exp)
336*0928368fSKristof Beyls D1 (exp2)
337*0928368fSKristof Beyls D1 (log)
338*0928368fSKristof Beyls D1 (log2)
339*0928368fSKristof Beyls D2 (pow)
340*0928368fSKristof Beyls #if WANT_VMATH
341*0928368fSKristof Beyls F (__s_sinf, __s_sinf, sin, mpfr_sin, 1, 1, f1, 0)
342*0928368fSKristof Beyls F (__s_cosf, __s_cosf, cos, mpfr_cos, 1, 1, f1, 0)
343*0928368fSKristof Beyls F (__s_expf_1u, __s_expf_1u, exp, mpfr_exp, 1, 1, f1, 0)
344*0928368fSKristof Beyls F (__s_expf, __s_expf, exp, mpfr_exp, 1, 1, f1, 0)
345*0928368fSKristof Beyls F (__s_exp2f_1u, __s_exp2f_1u, exp2, mpfr_exp2, 1, 1, f1, 0)
346*0928368fSKristof Beyls F (__s_exp2f, __s_exp2f, exp2, mpfr_exp2, 1, 1, f1, 0)
347*0928368fSKristof Beyls F (__s_powf, __s_powf, pow, mpfr_pow, 2, 1, f2, 0)
348*0928368fSKristof Beyls F (__s_logf, __s_logf, log, mpfr_log, 1, 1, f1, 0)
349*0928368fSKristof Beyls F (__s_sin, __s_sin, sinl, mpfr_sin, 1, 0, d1, 0)
350*0928368fSKristof Beyls F (__s_cos, __s_cos, cosl, mpfr_cos, 1, 0, d1, 0)
351*0928368fSKristof Beyls F (__s_exp, __s_exp, expl, mpfr_exp, 1, 0, d1, 0)
352*0928368fSKristof Beyls F (__s_log, __s_log, logl, mpfr_log, 1, 0, d1, 0)
353*0928368fSKristof Beyls F (__s_pow, __s_pow, powl, mpfr_pow, 2, 0, d2, 0)
354*0928368fSKristof Beyls #if __aarch64__
355*0928368fSKristof Beyls F (__v_sinf, v_sinf, sin, mpfr_sin, 1, 1, f1, 1)
356*0928368fSKristof Beyls F (__v_cosf, v_cosf, cos, mpfr_cos, 1, 1, f1, 1)
357*0928368fSKristof Beyls F (__v_expf_1u, v_expf_1u, exp, mpfr_exp, 1, 1, f1, 1)
358*0928368fSKristof Beyls F (__v_expf, v_expf, exp, mpfr_exp, 1, 1, f1, 1)
359*0928368fSKristof Beyls F (__v_exp2f_1u, v_exp2f_1u, exp2, mpfr_exp2, 1, 1, f1, 1)
360*0928368fSKristof Beyls F (__v_exp2f, v_exp2f, exp2, mpfr_exp2, 1, 1, f1, 1)
361*0928368fSKristof Beyls F (__v_logf, v_logf, log, mpfr_log, 1, 1, f1, 1)
362*0928368fSKristof Beyls F (__v_powf, v_powf, pow, mpfr_pow, 2, 1, f2, 1)
363*0928368fSKristof Beyls F (__v_sin, v_sin, sinl, mpfr_sin, 1, 0, d1, 1)
364*0928368fSKristof Beyls F (__v_cos, v_cos, cosl, mpfr_cos, 1, 0, d1, 1)
365*0928368fSKristof Beyls F (__v_exp, v_exp, expl, mpfr_exp, 1, 0, d1, 1)
366*0928368fSKristof Beyls F (__v_log, v_log, logl, mpfr_log, 1, 0, d1, 1)
367*0928368fSKristof Beyls F (__v_pow, v_pow, powl, mpfr_pow, 2, 0, d2, 1)
368*0928368fSKristof Beyls #ifdef __vpcs
369*0928368fSKristof Beyls F (__vn_sinf, vn_sinf, sin, mpfr_sin, 1, 1, f1, 1)
370*0928368fSKristof Beyls F (__vn_cosf, vn_cosf, cos, mpfr_cos, 1, 1, f1, 1)
371*0928368fSKristof Beyls F (__vn_expf_1u, vn_expf_1u, exp, mpfr_exp, 1, 1, f1, 1)
372*0928368fSKristof Beyls F (__vn_expf, vn_expf, exp, mpfr_exp, 1, 1, f1, 1)
373*0928368fSKristof Beyls F (__vn_exp2f_1u, vn_exp2f_1u, exp2, mpfr_exp2, 1, 1, f1, 1)
374*0928368fSKristof Beyls F (__vn_exp2f, vn_exp2f, exp2, mpfr_exp2, 1, 1, f1, 1)
375*0928368fSKristof Beyls F (__vn_logf, vn_logf, log, mpfr_log, 1, 1, f1, 1)
376*0928368fSKristof Beyls F (__vn_powf, vn_powf, pow, mpfr_pow, 2, 1, f2, 1)
377*0928368fSKristof Beyls F (__vn_sin, vn_sin, sinl, mpfr_sin, 1, 0, d1, 1)
378*0928368fSKristof Beyls F (__vn_cos, vn_cos, cosl, mpfr_cos, 1, 0, d1, 1)
379*0928368fSKristof Beyls F (__vn_exp, vn_exp, expl, mpfr_exp, 1, 0, d1, 1)
380*0928368fSKristof Beyls F (__vn_log, vn_log, logl, mpfr_log, 1, 0, d1, 1)
381*0928368fSKristof Beyls F (__vn_pow, vn_pow, powl, mpfr_pow, 2, 0, d2, 1)
382*0928368fSKristof Beyls F (_ZGVnN4v_sinf, Z_sinf, sin, mpfr_sin, 1, 1, f1, 1)
383*0928368fSKristof Beyls F (_ZGVnN4v_cosf, Z_cosf, cos, mpfr_cos, 1, 1, f1, 1)
384*0928368fSKristof Beyls F (_ZGVnN4v_expf, Z_expf, exp, mpfr_exp, 1, 1, f1, 1)
385*0928368fSKristof Beyls F (_ZGVnN4v_exp2f, Z_exp2f, exp2, mpfr_exp2, 1, 1, f1, 1)
386*0928368fSKristof Beyls F (_ZGVnN4v_logf, Z_logf, log, mpfr_log, 1, 1, f1, 1)
387*0928368fSKristof Beyls F (_ZGVnN4vv_powf, Z_powf, pow, mpfr_pow, 2, 1, f2, 1)
388*0928368fSKristof Beyls F (_ZGVnN2v_sin, Z_sin, sinl, mpfr_sin, 1, 0, d1, 1)
389*0928368fSKristof Beyls F (_ZGVnN2v_cos, Z_cos, cosl, mpfr_cos, 1, 0, d1, 1)
390*0928368fSKristof Beyls F (_ZGVnN2v_exp, Z_exp, expl, mpfr_exp, 1, 0, d1, 1)
391*0928368fSKristof Beyls F (_ZGVnN2v_log, Z_log, logl, mpfr_log, 1, 0, d1, 1)
392*0928368fSKristof Beyls F (_ZGVnN2vv_pow, Z_pow, powl, mpfr_pow, 2, 0, d2, 1)
393*0928368fSKristof Beyls #endif
394*0928368fSKristof Beyls #endif
395*0928368fSKristof Beyls #endif
396*0928368fSKristof Beyls #undef F
397*0928368fSKristof Beyls #undef F1
398*0928368fSKristof Beyls #undef F2
399*0928368fSKristof Beyls #undef D1
400*0928368fSKristof Beyls #undef D2
401*0928368fSKristof Beyls {0}};
402*0928368fSKristof Beyls
403*0928368fSKristof Beyls /* Boilerplate for generic calls. */
404*0928368fSKristof Beyls
405*0928368fSKristof Beyls static inline int
ulpscale_f(float x)406*0928368fSKristof Beyls ulpscale_f (float x)
407*0928368fSKristof Beyls {
408*0928368fSKristof Beyls int e = asuint (x) >> 23 & 0xff;
409*0928368fSKristof Beyls if (!e)
410*0928368fSKristof Beyls e++;
411*0928368fSKristof Beyls return e - 0x7f - 23;
412*0928368fSKristof Beyls }
413*0928368fSKristof Beyls static inline int
ulpscale_d(double x)414*0928368fSKristof Beyls ulpscale_d (double x)
415*0928368fSKristof Beyls {
416*0928368fSKristof Beyls int e = asuint64 (x) >> 52 & 0x7ff;
417*0928368fSKristof Beyls if (!e)
418*0928368fSKristof Beyls e++;
419*0928368fSKristof Beyls return e - 0x3ff - 52;
420*0928368fSKristof Beyls }
421*0928368fSKristof Beyls static inline float
call_f1(const struct fun * f,struct args_f1 a)422*0928368fSKristof Beyls call_f1 (const struct fun *f, struct args_f1 a)
423*0928368fSKristof Beyls {
424*0928368fSKristof Beyls return f->fun.f1 (a.x);
425*0928368fSKristof Beyls }
426*0928368fSKristof Beyls static inline float
call_f2(const struct fun * f,struct args_f2 a)427*0928368fSKristof Beyls call_f2 (const struct fun *f, struct args_f2 a)
428*0928368fSKristof Beyls {
429*0928368fSKristof Beyls return f->fun.f2 (a.x, a.x2);
430*0928368fSKristof Beyls }
431*0928368fSKristof Beyls
432*0928368fSKristof Beyls static inline double
call_d1(const struct fun * f,struct args_d1 a)433*0928368fSKristof Beyls call_d1 (const struct fun *f, struct args_d1 a)
434*0928368fSKristof Beyls {
435*0928368fSKristof Beyls return f->fun.d1 (a.x);
436*0928368fSKristof Beyls }
437*0928368fSKristof Beyls static inline double
call_d2(const struct fun * f,struct args_d2 a)438*0928368fSKristof Beyls call_d2 (const struct fun *f, struct args_d2 a)
439*0928368fSKristof Beyls {
440*0928368fSKristof Beyls return f->fun.d2 (a.x, a.x2);
441*0928368fSKristof Beyls }
442*0928368fSKristof Beyls static inline double
call_long_f1(const struct fun * f,struct args_f1 a)443*0928368fSKristof Beyls call_long_f1 (const struct fun *f, struct args_f1 a)
444*0928368fSKristof Beyls {
445*0928368fSKristof Beyls return f->fun_long.f1 (a.x);
446*0928368fSKristof Beyls }
447*0928368fSKristof Beyls static inline double
call_long_f2(const struct fun * f,struct args_f2 a)448*0928368fSKristof Beyls call_long_f2 (const struct fun *f, struct args_f2 a)
449*0928368fSKristof Beyls {
450*0928368fSKristof Beyls return f->fun_long.f2 (a.x, a.x2);
451*0928368fSKristof Beyls }
452*0928368fSKristof Beyls static inline long double
call_long_d1(const struct fun * f,struct args_d1 a)453*0928368fSKristof Beyls call_long_d1 (const struct fun *f, struct args_d1 a)
454*0928368fSKristof Beyls {
455*0928368fSKristof Beyls return f->fun_long.d1 (a.x);
456*0928368fSKristof Beyls }
457*0928368fSKristof Beyls static inline long double
call_long_d2(const struct fun * f,struct args_d2 a)458*0928368fSKristof Beyls call_long_d2 (const struct fun *f, struct args_d2 a)
459*0928368fSKristof Beyls {
460*0928368fSKristof Beyls return f->fun_long.d2 (a.x, a.x2);
461*0928368fSKristof Beyls }
462*0928368fSKristof Beyls static inline void
printcall_f1(const struct fun * f,struct args_f1 a)463*0928368fSKristof Beyls printcall_f1 (const struct fun *f, struct args_f1 a)
464*0928368fSKristof Beyls {
465*0928368fSKristof Beyls printf ("%s(%a)", f->name, a.x);
466*0928368fSKristof Beyls }
467*0928368fSKristof Beyls static inline void
printcall_f2(const struct fun * f,struct args_f2 a)468*0928368fSKristof Beyls printcall_f2 (const struct fun *f, struct args_f2 a)
469*0928368fSKristof Beyls {
470*0928368fSKristof Beyls printf ("%s(%a, %a)", f->name, a.x, a.x2);
471*0928368fSKristof Beyls }
472*0928368fSKristof Beyls static inline void
printcall_d1(const struct fun * f,struct args_d1 a)473*0928368fSKristof Beyls printcall_d1 (const struct fun *f, struct args_d1 a)
474*0928368fSKristof Beyls {
475*0928368fSKristof Beyls printf ("%s(%a)", f->name, a.x);
476*0928368fSKristof Beyls }
477*0928368fSKristof Beyls static inline void
printcall_d2(const struct fun * f,struct args_d2 a)478*0928368fSKristof Beyls printcall_d2 (const struct fun *f, struct args_d2 a)
479*0928368fSKristof Beyls {
480*0928368fSKristof Beyls printf ("%s(%a, %a)", f->name, a.x, a.x2);
481*0928368fSKristof Beyls }
482*0928368fSKristof Beyls static inline void
printgen_f1(const struct fun * f,struct gen * gen)483*0928368fSKristof Beyls printgen_f1 (const struct fun *f, struct gen *gen)
484*0928368fSKristof Beyls {
485*0928368fSKristof Beyls printf ("%s in [%a;%a]", f->name, asfloat (gen->start),
486*0928368fSKristof Beyls asfloat (gen->start + gen->len));
487*0928368fSKristof Beyls }
488*0928368fSKristof Beyls static inline void
printgen_f2(const struct fun * f,struct gen * gen)489*0928368fSKristof Beyls printgen_f2 (const struct fun *f, struct gen *gen)
490*0928368fSKristof Beyls {
491*0928368fSKristof Beyls printf ("%s in [%a;%a] x [%a;%a]", f->name, asfloat (gen->start),
492*0928368fSKristof Beyls asfloat (gen->start + gen->len), asfloat (gen->start2),
493*0928368fSKristof Beyls asfloat (gen->start2 + gen->len2));
494*0928368fSKristof Beyls }
495*0928368fSKristof Beyls static inline void
printgen_d1(const struct fun * f,struct gen * gen)496*0928368fSKristof Beyls printgen_d1 (const struct fun *f, struct gen *gen)
497*0928368fSKristof Beyls {
498*0928368fSKristof Beyls printf ("%s in [%a;%a]", f->name, asdouble (gen->start),
499*0928368fSKristof Beyls asdouble (gen->start + gen->len));
500*0928368fSKristof Beyls }
501*0928368fSKristof Beyls static inline void
printgen_d2(const struct fun * f,struct gen * gen)502*0928368fSKristof Beyls printgen_d2 (const struct fun *f, struct gen *gen)
503*0928368fSKristof Beyls {
504*0928368fSKristof Beyls printf ("%s in [%a;%a] x [%a;%a]", f->name, asdouble (gen->start),
505*0928368fSKristof Beyls asdouble (gen->start + gen->len), asdouble (gen->start2),
506*0928368fSKristof Beyls asdouble (gen->start2 + gen->len2));
507*0928368fSKristof Beyls }
508*0928368fSKristof Beyls
509*0928368fSKristof Beyls #define reduce_f1(a, f, op) (f (a.x))
510*0928368fSKristof Beyls #define reduce_f2(a, f, op) (f (a.x) op f (a.x2))
511*0928368fSKristof Beyls #define reduce_d1(a, f, op) (f (a.x))
512*0928368fSKristof Beyls #define reduce_d2(a, f, op) (f (a.x) op f (a.x2))
513*0928368fSKristof Beyls
514*0928368fSKristof Beyls #ifndef IEEE_754_2008_SNAN
515*0928368fSKristof Beyls # define IEEE_754_2008_SNAN 1
516*0928368fSKristof Beyls #endif
517*0928368fSKristof Beyls static inline int
issignaling_f(float x)518*0928368fSKristof Beyls issignaling_f (float x)
519*0928368fSKristof Beyls {
520*0928368fSKristof Beyls uint32_t ix = asuint (x);
521*0928368fSKristof Beyls if (!IEEE_754_2008_SNAN)
522*0928368fSKristof Beyls return (ix & 0x7fc00000) == 0x7fc00000;
523*0928368fSKristof Beyls return 2 * (ix ^ 0x00400000) > 2u * 0x7fc00000;
524*0928368fSKristof Beyls }
525*0928368fSKristof Beyls static inline int
issignaling_d(double x)526*0928368fSKristof Beyls issignaling_d (double x)
527*0928368fSKristof Beyls {
528*0928368fSKristof Beyls uint64_t ix = asuint64 (x);
529*0928368fSKristof Beyls if (!IEEE_754_2008_SNAN)
530*0928368fSKristof Beyls return (ix & 0x7ff8000000000000) == 0x7ff8000000000000;
531*0928368fSKristof Beyls return 2 * (ix ^ 0x0008000000000000) > 2 * 0x7ff8000000000000ULL;
532*0928368fSKristof Beyls }
533*0928368fSKristof Beyls
534*0928368fSKristof Beyls #if USE_MPFR
535*0928368fSKristof Beyls static mpfr_rnd_t
rmap(int r)536*0928368fSKristof Beyls rmap (int r)
537*0928368fSKristof Beyls {
538*0928368fSKristof Beyls switch (r)
539*0928368fSKristof Beyls {
540*0928368fSKristof Beyls case FE_TONEAREST:
541*0928368fSKristof Beyls return MPFR_RNDN;
542*0928368fSKristof Beyls case FE_TOWARDZERO:
543*0928368fSKristof Beyls return MPFR_RNDZ;
544*0928368fSKristof Beyls case FE_UPWARD:
545*0928368fSKristof Beyls return MPFR_RNDU;
546*0928368fSKristof Beyls case FE_DOWNWARD:
547*0928368fSKristof Beyls return MPFR_RNDD;
548*0928368fSKristof Beyls }
549*0928368fSKristof Beyls return -1;
550*0928368fSKristof Beyls }
551*0928368fSKristof Beyls
552*0928368fSKristof Beyls #define prec_mpfr_f 50
553*0928368fSKristof Beyls #define prec_mpfr_d 80
554*0928368fSKristof Beyls #define prec_f 24
555*0928368fSKristof Beyls #define prec_d 53
556*0928368fSKristof Beyls #define emin_f -148
557*0928368fSKristof Beyls #define emin_d -1073
558*0928368fSKristof Beyls #define emax_f 128
559*0928368fSKristof Beyls #define emax_d 1024
560*0928368fSKristof Beyls static inline int
call_mpfr_f1(mpfr_t y,const struct fun * f,struct args_f1 a,mpfr_rnd_t r)561*0928368fSKristof Beyls call_mpfr_f1 (mpfr_t y, const struct fun *f, struct args_f1 a, mpfr_rnd_t r)
562*0928368fSKristof Beyls {
563*0928368fSKristof Beyls MPFR_DECL_INIT (x, prec_f);
564*0928368fSKristof Beyls mpfr_set_flt (x, a.x, MPFR_RNDN);
565*0928368fSKristof Beyls return f->fun_mpfr.f1 (y, x, r);
566*0928368fSKristof Beyls }
567*0928368fSKristof Beyls static inline int
call_mpfr_f2(mpfr_t y,const struct fun * f,struct args_f2 a,mpfr_rnd_t r)568*0928368fSKristof Beyls call_mpfr_f2 (mpfr_t y, const struct fun *f, struct args_f2 a, mpfr_rnd_t r)
569*0928368fSKristof Beyls {
570*0928368fSKristof Beyls MPFR_DECL_INIT (x, prec_f);
571*0928368fSKristof Beyls MPFR_DECL_INIT (x2, prec_f);
572*0928368fSKristof Beyls mpfr_set_flt (x, a.x, MPFR_RNDN);
573*0928368fSKristof Beyls mpfr_set_flt (x2, a.x2, MPFR_RNDN);
574*0928368fSKristof Beyls return f->fun_mpfr.f2 (y, x, x2, r);
575*0928368fSKristof Beyls }
576*0928368fSKristof Beyls static inline int
call_mpfr_d1(mpfr_t y,const struct fun * f,struct args_d1 a,mpfr_rnd_t r)577*0928368fSKristof Beyls call_mpfr_d1 (mpfr_t y, const struct fun *f, struct args_d1 a, mpfr_rnd_t r)
578*0928368fSKristof Beyls {
579*0928368fSKristof Beyls MPFR_DECL_INIT (x, prec_d);
580*0928368fSKristof Beyls mpfr_set_d (x, a.x, MPFR_RNDN);
581*0928368fSKristof Beyls return f->fun_mpfr.d1 (y, x, r);
582*0928368fSKristof Beyls }
583*0928368fSKristof Beyls static inline int
call_mpfr_d2(mpfr_t y,const struct fun * f,struct args_d2 a,mpfr_rnd_t r)584*0928368fSKristof Beyls call_mpfr_d2 (mpfr_t y, const struct fun *f, struct args_d2 a, mpfr_rnd_t r)
585*0928368fSKristof Beyls {
586*0928368fSKristof Beyls MPFR_DECL_INIT (x, prec_d);
587*0928368fSKristof Beyls MPFR_DECL_INIT (x2, prec_d);
588*0928368fSKristof Beyls mpfr_set_d (x, a.x, MPFR_RNDN);
589*0928368fSKristof Beyls mpfr_set_d (x2, a.x2, MPFR_RNDN);
590*0928368fSKristof Beyls return f->fun_mpfr.d2 (y, x, x2, r);
591*0928368fSKristof Beyls }
592*0928368fSKristof Beyls #endif
593*0928368fSKristof Beyls
594*0928368fSKristof Beyls #define float_f float
595*0928368fSKristof Beyls #define double_f double
596*0928368fSKristof Beyls #define copysign_f copysignf
597*0928368fSKristof Beyls #define nextafter_f nextafterf
598*0928368fSKristof Beyls #define fabs_f fabsf
599*0928368fSKristof Beyls #define asuint_f asuint
600*0928368fSKristof Beyls #define asfloat_f asfloat
601*0928368fSKristof Beyls #define scalbn_f scalbnf
602*0928368fSKristof Beyls #define lscalbn_f scalbn
603*0928368fSKristof Beyls #define halfinf_f 0x1p127f
604*0928368fSKristof Beyls #define min_normal_f 0x1p-126f
605*0928368fSKristof Beyls
606*0928368fSKristof Beyls #define float_d double
607*0928368fSKristof Beyls #define double_d long double
608*0928368fSKristof Beyls #define copysign_d copysign
609*0928368fSKristof Beyls #define nextafter_d nextafter
610*0928368fSKristof Beyls #define fabs_d fabs
611*0928368fSKristof Beyls #define asuint_d asuint64
612*0928368fSKristof Beyls #define asfloat_d asdouble
613*0928368fSKristof Beyls #define scalbn_d scalbn
614*0928368fSKristof Beyls #define lscalbn_d scalbnl
615*0928368fSKristof Beyls #define halfinf_d 0x1p1023
616*0928368fSKristof Beyls #define min_normal_d 0x1p-1022
617*0928368fSKristof Beyls
618*0928368fSKristof Beyls #define NEW_RT
619*0928368fSKristof Beyls #define RT(x) x##_f
620*0928368fSKristof Beyls #define T(x) x##_f1
621*0928368fSKristof Beyls #include "ulp.h"
622*0928368fSKristof Beyls #undef T
623*0928368fSKristof Beyls #define T(x) x##_f2
624*0928368fSKristof Beyls #include "ulp.h"
625*0928368fSKristof Beyls #undef T
626*0928368fSKristof Beyls #undef RT
627*0928368fSKristof Beyls
628*0928368fSKristof Beyls #define NEW_RT
629*0928368fSKristof Beyls #define RT(x) x##_d
630*0928368fSKristof Beyls #define T(x) x##_d1
631*0928368fSKristof Beyls #include "ulp.h"
632*0928368fSKristof Beyls #undef T
633*0928368fSKristof Beyls #define T(x) x##_d2
634*0928368fSKristof Beyls #include "ulp.h"
635*0928368fSKristof Beyls #undef T
636*0928368fSKristof Beyls #undef RT
637*0928368fSKristof Beyls
638*0928368fSKristof Beyls static void
usage(void)639*0928368fSKristof Beyls usage (void)
640*0928368fSKristof Beyls {
641*0928368fSKristof Beyls puts ("./ulp [-q] [-m] [-f] [-r nudz] [-l soft-ulplimit] [-e ulplimit] func "
642*0928368fSKristof Beyls "lo [hi [x lo2 hi2] [count]]");
643*0928368fSKristof Beyls puts ("Compares func against a higher precision implementation in [lo; hi].");
644*0928368fSKristof Beyls puts ("-q: quiet.");
645*0928368fSKristof Beyls puts ("-m: use mpfr even if faster method is available.");
646*0928368fSKristof Beyls puts ("-f: disable fenv testing (rounding modes and exceptions).");
647*0928368fSKristof Beyls puts ("Supported func:");
648*0928368fSKristof Beyls for (const struct fun *f = fun; f->name; f++)
649*0928368fSKristof Beyls printf ("\t%s\n", f->name);
650*0928368fSKristof Beyls exit (1);
651*0928368fSKristof Beyls }
652*0928368fSKristof Beyls
653*0928368fSKristof Beyls static int
cmp(const struct fun * f,struct gen * gen,const struct conf * conf)654*0928368fSKristof Beyls cmp (const struct fun *f, struct gen *gen, const struct conf *conf)
655*0928368fSKristof Beyls {
656*0928368fSKristof Beyls int r = 1;
657*0928368fSKristof Beyls if (f->arity == 1 && f->singleprec)
658*0928368fSKristof Beyls r = cmp_f1 (f, gen, conf);
659*0928368fSKristof Beyls else if (f->arity == 2 && f->singleprec)
660*0928368fSKristof Beyls r = cmp_f2 (f, gen, conf);
661*0928368fSKristof Beyls else if (f->arity == 1 && !f->singleprec)
662*0928368fSKristof Beyls r = cmp_d1 (f, gen, conf);
663*0928368fSKristof Beyls else if (f->arity == 2 && !f->singleprec)
664*0928368fSKristof Beyls r = cmp_d2 (f, gen, conf);
665*0928368fSKristof Beyls else
666*0928368fSKristof Beyls usage ();
667*0928368fSKristof Beyls return r;
668*0928368fSKristof Beyls }
669*0928368fSKristof Beyls
670*0928368fSKristof Beyls static uint64_t
getnum(const char * s,int singleprec)671*0928368fSKristof Beyls getnum (const char *s, int singleprec)
672*0928368fSKristof Beyls {
673*0928368fSKristof Beyls // int i;
674*0928368fSKristof Beyls uint64_t sign = 0;
675*0928368fSKristof Beyls // char buf[12];
676*0928368fSKristof Beyls
677*0928368fSKristof Beyls if (s[0] == '+')
678*0928368fSKristof Beyls s++;
679*0928368fSKristof Beyls else if (s[0] == '-')
680*0928368fSKristof Beyls {
681*0928368fSKristof Beyls sign = singleprec ? 1ULL << 31 : 1ULL << 63;
682*0928368fSKristof Beyls s++;
683*0928368fSKristof Beyls }
684*0928368fSKristof Beyls /* 0xXXXX is treated as bit representation, '-' flips the sign bit. */
685*0928368fSKristof Beyls if (s[0] == '0' && tolower (s[1]) == 'x' && strchr (s, 'p') == 0)
686*0928368fSKristof Beyls return sign ^ strtoull (s, 0, 0);
687*0928368fSKristof Beyls // /* SNaN, QNaN, NaN, Inf. */
688*0928368fSKristof Beyls // for (i=0; s[i] && i < sizeof buf; i++)
689*0928368fSKristof Beyls // buf[i] = tolower(s[i]);
690*0928368fSKristof Beyls // buf[i] = 0;
691*0928368fSKristof Beyls // if (strcmp(buf, "snan") == 0)
692*0928368fSKristof Beyls // return sign | (singleprec ? 0x7fa00000 : 0x7ff4000000000000);
693*0928368fSKristof Beyls // if (strcmp(buf, "qnan") == 0 || strcmp(buf, "nan") == 0)
694*0928368fSKristof Beyls // return sign | (singleprec ? 0x7fc00000 : 0x7ff8000000000000);
695*0928368fSKristof Beyls // if (strcmp(buf, "inf") == 0 || strcmp(buf, "infinity") == 0)
696*0928368fSKristof Beyls // return sign | (singleprec ? 0x7f800000 : 0x7ff0000000000000);
697*0928368fSKristof Beyls /* Otherwise assume it's a floating-point literal. */
698*0928368fSKristof Beyls return sign
699*0928368fSKristof Beyls | (singleprec ? asuint (strtof (s, 0)) : asuint64 (strtod (s, 0)));
700*0928368fSKristof Beyls }
701*0928368fSKristof Beyls
702*0928368fSKristof Beyls static void
parsegen(struct gen * g,int argc,char * argv[],const struct fun * f)703*0928368fSKristof Beyls parsegen (struct gen *g, int argc, char *argv[], const struct fun *f)
704*0928368fSKristof Beyls {
705*0928368fSKristof Beyls int singleprec = f->singleprec;
706*0928368fSKristof Beyls int arity = f->arity;
707*0928368fSKristof Beyls uint64_t a, b, a2, b2, n;
708*0928368fSKristof Beyls if (argc < 1)
709*0928368fSKristof Beyls usage ();
710*0928368fSKristof Beyls b = a = getnum (argv[0], singleprec);
711*0928368fSKristof Beyls n = 0;
712*0928368fSKristof Beyls if (argc > 1 && strcmp (argv[1], "x") == 0)
713*0928368fSKristof Beyls {
714*0928368fSKristof Beyls argc -= 2;
715*0928368fSKristof Beyls argv += 2;
716*0928368fSKristof Beyls }
717*0928368fSKristof Beyls else if (argc > 1)
718*0928368fSKristof Beyls {
719*0928368fSKristof Beyls b = getnum (argv[1], singleprec);
720*0928368fSKristof Beyls if (argc > 2 && strcmp (argv[2], "x") == 0)
721*0928368fSKristof Beyls {
722*0928368fSKristof Beyls argc -= 3;
723*0928368fSKristof Beyls argv += 3;
724*0928368fSKristof Beyls }
725*0928368fSKristof Beyls }
726*0928368fSKristof Beyls b2 = a2 = getnum (argv[0], singleprec);
727*0928368fSKristof Beyls if (argc > 1)
728*0928368fSKristof Beyls b2 = getnum (argv[1], singleprec);
729*0928368fSKristof Beyls if (argc > 2)
730*0928368fSKristof Beyls n = strtoull (argv[2], 0, 0);
731*0928368fSKristof Beyls if (argc > 3)
732*0928368fSKristof Beyls usage ();
733*0928368fSKristof Beyls //printf("ab %lx %lx ab2 %lx %lx n %lu\n", a, b, a2, b2, n);
734*0928368fSKristof Beyls if (arity == 1)
735*0928368fSKristof Beyls {
736*0928368fSKristof Beyls g->start = a;
737*0928368fSKristof Beyls g->len = b - a;
738*0928368fSKristof Beyls if (n - 1 > b - a)
739*0928368fSKristof Beyls n = b - a + 1;
740*0928368fSKristof Beyls g->off = 0;
741*0928368fSKristof Beyls g->step = n ? (g->len + 1) / n : 1;
742*0928368fSKristof Beyls g->start2 = g->len2 = 0;
743*0928368fSKristof Beyls g->cnt = n;
744*0928368fSKristof Beyls }
745*0928368fSKristof Beyls else if (arity == 2)
746*0928368fSKristof Beyls {
747*0928368fSKristof Beyls g->start = a;
748*0928368fSKristof Beyls g->len = b - a;
749*0928368fSKristof Beyls g->off = g->step = 0;
750*0928368fSKristof Beyls g->start2 = a2;
751*0928368fSKristof Beyls g->len2 = b2 - a2;
752*0928368fSKristof Beyls g->cnt = n;
753*0928368fSKristof Beyls }
754*0928368fSKristof Beyls else
755*0928368fSKristof Beyls usage ();
756*0928368fSKristof Beyls }
757*0928368fSKristof Beyls
758*0928368fSKristof Beyls int
main(int argc,char * argv[])759*0928368fSKristof Beyls main (int argc, char *argv[])
760*0928368fSKristof Beyls {
761*0928368fSKristof Beyls const struct fun *f;
762*0928368fSKristof Beyls struct gen gen;
763*0928368fSKristof Beyls struct conf conf;
764*0928368fSKristof Beyls conf.rc = 'n';
765*0928368fSKristof Beyls conf.quiet = 0;
766*0928368fSKristof Beyls conf.mpfr = 0;
767*0928368fSKristof Beyls conf.fenv = 1;
768*0928368fSKristof Beyls conf.softlim = 0;
769*0928368fSKristof Beyls conf.errlim = INFINITY;
770*0928368fSKristof Beyls for (;;)
771*0928368fSKristof Beyls {
772*0928368fSKristof Beyls argc--;
773*0928368fSKristof Beyls argv++;
774*0928368fSKristof Beyls if (argc < 1)
775*0928368fSKristof Beyls usage ();
776*0928368fSKristof Beyls if (argv[0][0] != '-')
777*0928368fSKristof Beyls break;
778*0928368fSKristof Beyls switch (argv[0][1])
779*0928368fSKristof Beyls {
780*0928368fSKristof Beyls case 'e':
781*0928368fSKristof Beyls argc--;
782*0928368fSKristof Beyls argv++;
783*0928368fSKristof Beyls if (argc < 1)
784*0928368fSKristof Beyls usage ();
785*0928368fSKristof Beyls conf.errlim = strtod (argv[0], 0);
786*0928368fSKristof Beyls break;
787*0928368fSKristof Beyls case 'f':
788*0928368fSKristof Beyls conf.fenv = 0;
789*0928368fSKristof Beyls break;
790*0928368fSKristof Beyls case 'l':
791*0928368fSKristof Beyls argc--;
792*0928368fSKristof Beyls argv++;
793*0928368fSKristof Beyls if (argc < 1)
794*0928368fSKristof Beyls usage ();
795*0928368fSKristof Beyls conf.softlim = strtod (argv[0], 0);
796*0928368fSKristof Beyls break;
797*0928368fSKristof Beyls case 'm':
798*0928368fSKristof Beyls conf.mpfr = 1;
799*0928368fSKristof Beyls break;
800*0928368fSKristof Beyls case 'q':
801*0928368fSKristof Beyls conf.quiet = 1;
802*0928368fSKristof Beyls break;
803*0928368fSKristof Beyls case 'r':
804*0928368fSKristof Beyls conf.rc = argv[0][2];
805*0928368fSKristof Beyls if (!conf.rc)
806*0928368fSKristof Beyls {
807*0928368fSKristof Beyls argc--;
808*0928368fSKristof Beyls argv++;
809*0928368fSKristof Beyls if (argc < 1)
810*0928368fSKristof Beyls usage ();
811*0928368fSKristof Beyls conf.rc = argv[0][0];
812*0928368fSKristof Beyls }
813*0928368fSKristof Beyls break;
814*0928368fSKristof Beyls default:
815*0928368fSKristof Beyls usage ();
816*0928368fSKristof Beyls }
817*0928368fSKristof Beyls }
818*0928368fSKristof Beyls switch (conf.rc)
819*0928368fSKristof Beyls {
820*0928368fSKristof Beyls case 'n':
821*0928368fSKristof Beyls conf.r = FE_TONEAREST;
822*0928368fSKristof Beyls break;
823*0928368fSKristof Beyls case 'u':
824*0928368fSKristof Beyls conf.r = FE_UPWARD;
825*0928368fSKristof Beyls break;
826*0928368fSKristof Beyls case 'd':
827*0928368fSKristof Beyls conf.r = FE_DOWNWARD;
828*0928368fSKristof Beyls break;
829*0928368fSKristof Beyls case 'z':
830*0928368fSKristof Beyls conf.r = FE_TOWARDZERO;
831*0928368fSKristof Beyls break;
832*0928368fSKristof Beyls default:
833*0928368fSKristof Beyls usage ();
834*0928368fSKristof Beyls }
835*0928368fSKristof Beyls for (f = fun; f->name; f++)
836*0928368fSKristof Beyls if (strcmp (argv[0], f->name) == 0)
837*0928368fSKristof Beyls break;
838*0928368fSKristof Beyls if (!f->name)
839*0928368fSKristof Beyls usage ();
840*0928368fSKristof Beyls if (!f->singleprec && LDBL_MANT_DIG == DBL_MANT_DIG)
841*0928368fSKristof Beyls conf.mpfr = 1; /* Use mpfr if long double has no extra precision. */
842*0928368fSKristof Beyls if (!USE_MPFR && conf.mpfr)
843*0928368fSKristof Beyls {
844*0928368fSKristof Beyls puts ("mpfr is not available.");
845*0928368fSKristof Beyls return 0;
846*0928368fSKristof Beyls }
847*0928368fSKristof Beyls argc--;
848*0928368fSKristof Beyls argv++;
849*0928368fSKristof Beyls parsegen (&gen, argc, argv, f);
850*0928368fSKristof Beyls conf.n = gen.cnt;
851*0928368fSKristof Beyls return cmp (f, &gen, &conf);
852*0928368fSKristof Beyls }
853