1bbbf1280Sopenharmony_ci/* 2bbbf1280Sopenharmony_ci * Generic functions for ULP error estimation. 3bbbf1280Sopenharmony_ci * 4bbbf1280Sopenharmony_ci * Copyright (c) 2019, Arm Limited. 5bbbf1280Sopenharmony_ci * SPDX-License-Identifier: MIT 6bbbf1280Sopenharmony_ci */ 7bbbf1280Sopenharmony_ci 8bbbf1280Sopenharmony_ci/* For each different math function type, 9bbbf1280Sopenharmony_ci T(x) should add a different suffix to x. 10bbbf1280Sopenharmony_ci RT(x) should add a return type specific suffix to x. */ 11bbbf1280Sopenharmony_ci 12bbbf1280Sopenharmony_ci#ifdef NEW_RT 13bbbf1280Sopenharmony_ci#undef NEW_RT 14bbbf1280Sopenharmony_ci 15bbbf1280Sopenharmony_ci# if USE_MPFR 16bbbf1280Sopenharmony_cistatic int RT(ulpscale_mpfr) (mpfr_t x, int t) 17bbbf1280Sopenharmony_ci{ 18bbbf1280Sopenharmony_ci /* TODO: pow of 2 cases. */ 19bbbf1280Sopenharmony_ci if (mpfr_regular_p (x)) 20bbbf1280Sopenharmony_ci { 21bbbf1280Sopenharmony_ci mpfr_exp_t e = mpfr_get_exp (x) - RT(prec); 22bbbf1280Sopenharmony_ci if (e < RT(emin)) 23bbbf1280Sopenharmony_ci e = RT(emin) - 1; 24bbbf1280Sopenharmony_ci if (e > RT(emax) - RT(prec)) 25bbbf1280Sopenharmony_ci e = RT(emax) - RT(prec); 26bbbf1280Sopenharmony_ci return e; 27bbbf1280Sopenharmony_ci } 28bbbf1280Sopenharmony_ci if (mpfr_zero_p (x)) 29bbbf1280Sopenharmony_ci return RT(emin) - 1; 30bbbf1280Sopenharmony_ci if (mpfr_inf_p (x)) 31bbbf1280Sopenharmony_ci return RT(emax) - RT(prec); 32bbbf1280Sopenharmony_ci /* NaN. */ 33bbbf1280Sopenharmony_ci return 0; 34bbbf1280Sopenharmony_ci} 35bbbf1280Sopenharmony_ci# endif 36bbbf1280Sopenharmony_ci 37bbbf1280Sopenharmony_ci/* Difference between exact result and closest real number that 38bbbf1280Sopenharmony_ci gets rounded to got, i.e. error before rounding, for a correctly 39bbbf1280Sopenharmony_ci rounded result the difference is 0. */ 40bbbf1280Sopenharmony_cistatic double RT(ulperr) (RT(float) got, const struct RT(ret) * p, int r) 41bbbf1280Sopenharmony_ci{ 42bbbf1280Sopenharmony_ci RT(float) want = p->y; 43bbbf1280Sopenharmony_ci RT(float) d; 44bbbf1280Sopenharmony_ci double e; 45bbbf1280Sopenharmony_ci 46bbbf1280Sopenharmony_ci if (RT(asuint) (got) == RT(asuint) (want)) 47bbbf1280Sopenharmony_ci return 0.0; 48bbbf1280Sopenharmony_ci if (signbit (got) != signbit (want)) 49bbbf1280Sopenharmony_ci /* May have false positives with NaN. */ 50bbbf1280Sopenharmony_ci //return isnan(got) && isnan(want) ? 0 : INFINITY; 51bbbf1280Sopenharmony_ci return INFINITY; 52bbbf1280Sopenharmony_ci if (!isfinite (want) || !isfinite (got)) 53bbbf1280Sopenharmony_ci { 54bbbf1280Sopenharmony_ci if (isnan (got) != isnan (want)) 55bbbf1280Sopenharmony_ci return INFINITY; 56bbbf1280Sopenharmony_ci if (isnan (want)) 57bbbf1280Sopenharmony_ci return 0; 58bbbf1280Sopenharmony_ci if (isinf (got)) 59bbbf1280Sopenharmony_ci { 60bbbf1280Sopenharmony_ci got = RT(copysign) (RT(halfinf), got); 61bbbf1280Sopenharmony_ci want *= 0.5f; 62bbbf1280Sopenharmony_ci } 63bbbf1280Sopenharmony_ci if (isinf (want)) 64bbbf1280Sopenharmony_ci { 65bbbf1280Sopenharmony_ci want = RT(copysign) (RT(halfinf), want); 66bbbf1280Sopenharmony_ci got *= 0.5f; 67bbbf1280Sopenharmony_ci } 68bbbf1280Sopenharmony_ci } 69bbbf1280Sopenharmony_ci if (r == FE_TONEAREST) 70bbbf1280Sopenharmony_ci { 71bbbf1280Sopenharmony_ci // TODO: incorrect when got vs want cross a powof2 boundary 72bbbf1280Sopenharmony_ci /* error = got > want 73bbbf1280Sopenharmony_ci ? got - want - tail ulp - 0.5 ulp 74bbbf1280Sopenharmony_ci : got - want - tail ulp + 0.5 ulp; */ 75bbbf1280Sopenharmony_ci d = got - want; 76bbbf1280Sopenharmony_ci e = d > 0 ? -p->tail - 0.5 : -p->tail + 0.5; 77bbbf1280Sopenharmony_ci } 78bbbf1280Sopenharmony_ci else 79bbbf1280Sopenharmony_ci { 80bbbf1280Sopenharmony_ci if ((r == FE_DOWNWARD && got < want) || (r == FE_UPWARD && got > want) 81bbbf1280Sopenharmony_ci || (r == FE_TOWARDZERO && fabs (got) < fabs (want))) 82bbbf1280Sopenharmony_ci got = RT(nextafter) (got, want); 83bbbf1280Sopenharmony_ci d = got - want; 84bbbf1280Sopenharmony_ci e = -p->tail; 85bbbf1280Sopenharmony_ci } 86bbbf1280Sopenharmony_ci return RT(scalbn) (d, -p->ulpexp) + e; 87bbbf1280Sopenharmony_ci} 88bbbf1280Sopenharmony_ci 89bbbf1280Sopenharmony_cistatic int RT(isok) (RT(float) ygot, int exgot, RT(float) ywant, int exwant, 90bbbf1280Sopenharmony_ci int exmay) 91bbbf1280Sopenharmony_ci{ 92bbbf1280Sopenharmony_ci return RT(asuint) (ygot) == RT(asuint) (ywant) 93bbbf1280Sopenharmony_ci && ((exgot ^ exwant) & ~exmay) == 0; 94bbbf1280Sopenharmony_ci} 95bbbf1280Sopenharmony_ci 96bbbf1280Sopenharmony_cistatic int RT(isok_nofenv) (RT(float) ygot, RT(float) ywant) 97bbbf1280Sopenharmony_ci{ 98bbbf1280Sopenharmony_ci return RT(asuint) (ygot) == RT(asuint) (ywant); 99bbbf1280Sopenharmony_ci} 100bbbf1280Sopenharmony_ci#endif 101bbbf1280Sopenharmony_ci 102bbbf1280Sopenharmony_cistatic inline void T(call_fenv) (const struct fun *f, struct T(args) a, int r, 103bbbf1280Sopenharmony_ci RT(float) * y, int *ex) 104bbbf1280Sopenharmony_ci{ 105bbbf1280Sopenharmony_ci if (r != FE_TONEAREST) 106bbbf1280Sopenharmony_ci fesetround (r); 107bbbf1280Sopenharmony_ci feclearexcept (FE_ALL_EXCEPT); 108bbbf1280Sopenharmony_ci *y = T(call) (f, a); 109bbbf1280Sopenharmony_ci *ex = fetestexcept (FE_ALL_EXCEPT); 110bbbf1280Sopenharmony_ci if (r != FE_TONEAREST) 111bbbf1280Sopenharmony_ci fesetround (FE_TONEAREST); 112bbbf1280Sopenharmony_ci} 113bbbf1280Sopenharmony_ci 114bbbf1280Sopenharmony_cistatic inline void T(call_nofenv) (const struct fun *f, struct T(args) a, 115bbbf1280Sopenharmony_ci int r, RT(float) * y, int *ex) 116bbbf1280Sopenharmony_ci{ 117bbbf1280Sopenharmony_ci *y = T(call) (f, a); 118bbbf1280Sopenharmony_ci *ex = 0; 119bbbf1280Sopenharmony_ci} 120bbbf1280Sopenharmony_ci 121bbbf1280Sopenharmony_cistatic inline int T(call_long_fenv) (const struct fun *f, struct T(args) a, 122bbbf1280Sopenharmony_ci int r, struct RT(ret) * p, 123bbbf1280Sopenharmony_ci RT(float) ygot, int exgot) 124bbbf1280Sopenharmony_ci{ 125bbbf1280Sopenharmony_ci if (r != FE_TONEAREST) 126bbbf1280Sopenharmony_ci fesetround (r); 127bbbf1280Sopenharmony_ci feclearexcept (FE_ALL_EXCEPT); 128bbbf1280Sopenharmony_ci volatile struct T(args) va = a; // TODO: barrier 129bbbf1280Sopenharmony_ci a = va; 130bbbf1280Sopenharmony_ci RT(double) yl = T(call_long) (f, a); 131bbbf1280Sopenharmony_ci p->y = (RT(float)) yl; 132bbbf1280Sopenharmony_ci volatile RT(float) vy = p->y; // TODO: barrier 133bbbf1280Sopenharmony_ci (void) vy; 134bbbf1280Sopenharmony_ci p->ex = fetestexcept (FE_ALL_EXCEPT); 135bbbf1280Sopenharmony_ci if (r != FE_TONEAREST) 136bbbf1280Sopenharmony_ci fesetround (FE_TONEAREST); 137bbbf1280Sopenharmony_ci p->ex_may = FE_INEXACT; 138bbbf1280Sopenharmony_ci if (RT(isok) (ygot, exgot, p->y, p->ex, p->ex_may)) 139bbbf1280Sopenharmony_ci return 1; 140bbbf1280Sopenharmony_ci p->ulpexp = RT(ulpscale) (p->y); 141bbbf1280Sopenharmony_ci if (isinf (p->y)) 142bbbf1280Sopenharmony_ci p->tail = RT(lscalbn) (yl - (RT(double)) 2 * RT(halfinf), -p->ulpexp); 143bbbf1280Sopenharmony_ci else 144bbbf1280Sopenharmony_ci p->tail = RT(lscalbn) (yl - p->y, -p->ulpexp); 145bbbf1280Sopenharmony_ci if (RT(fabs) (p->y) < RT(min_normal)) 146bbbf1280Sopenharmony_ci { 147bbbf1280Sopenharmony_ci /* TODO: subnormal result is treated as undeflow even if it's 148bbbf1280Sopenharmony_ci exact since call_long may not raise inexact correctly. */ 149bbbf1280Sopenharmony_ci if (p->y != 0 || (p->ex & FE_INEXACT)) 150bbbf1280Sopenharmony_ci p->ex |= FE_UNDERFLOW | FE_INEXACT; 151bbbf1280Sopenharmony_ci } 152bbbf1280Sopenharmony_ci return 0; 153bbbf1280Sopenharmony_ci} 154bbbf1280Sopenharmony_cistatic inline int T(call_long_nofenv) (const struct fun *f, struct T(args) a, 155bbbf1280Sopenharmony_ci int r, struct RT(ret) * p, 156bbbf1280Sopenharmony_ci RT(float) ygot, int exgot) 157bbbf1280Sopenharmony_ci{ 158bbbf1280Sopenharmony_ci RT(double) yl = T(call_long) (f, a); 159bbbf1280Sopenharmony_ci p->y = (RT(float)) yl; 160bbbf1280Sopenharmony_ci if (RT(isok_nofenv) (ygot, p->y)) 161bbbf1280Sopenharmony_ci return 1; 162bbbf1280Sopenharmony_ci p->ulpexp = RT(ulpscale) (p->y); 163bbbf1280Sopenharmony_ci if (isinf (p->y)) 164bbbf1280Sopenharmony_ci p->tail = RT(lscalbn) (yl - (RT(double)) 2 * RT(halfinf), -p->ulpexp); 165bbbf1280Sopenharmony_ci else 166bbbf1280Sopenharmony_ci p->tail = RT(lscalbn) (yl - p->y, -p->ulpexp); 167bbbf1280Sopenharmony_ci return 0; 168bbbf1280Sopenharmony_ci} 169bbbf1280Sopenharmony_ci 170bbbf1280Sopenharmony_ci/* There are nan input args and all quiet. */ 171bbbf1280Sopenharmony_cistatic inline int T(qnanpropagation) (struct T(args) a) 172bbbf1280Sopenharmony_ci{ 173bbbf1280Sopenharmony_ci return T(reduce) (a, isnan, ||) && !T(reduce) (a, RT(issignaling), ||); 174bbbf1280Sopenharmony_ci} 175bbbf1280Sopenharmony_cistatic inline RT(float) T(sum) (struct T(args) a) 176bbbf1280Sopenharmony_ci{ 177bbbf1280Sopenharmony_ci return T(reduce) (a, , +); 178bbbf1280Sopenharmony_ci} 179bbbf1280Sopenharmony_ci 180bbbf1280Sopenharmony_ci/* returns 1 if the got result is ok. */ 181bbbf1280Sopenharmony_cistatic inline int T(call_mpfr_fix) (const struct fun *f, struct T(args) a, 182bbbf1280Sopenharmony_ci int r_fenv, struct RT(ret) * p, 183bbbf1280Sopenharmony_ci RT(float) ygot, int exgot) 184bbbf1280Sopenharmony_ci{ 185bbbf1280Sopenharmony_ci#if USE_MPFR 186bbbf1280Sopenharmony_ci int t, t2; 187bbbf1280Sopenharmony_ci mpfr_rnd_t r = rmap (r_fenv); 188bbbf1280Sopenharmony_ci MPFR_DECL_INIT(my, RT(prec_mpfr)); 189bbbf1280Sopenharmony_ci MPFR_DECL_INIT(mr, RT(prec)); 190bbbf1280Sopenharmony_ci MPFR_DECL_INIT(me, RT(prec_mpfr)); 191bbbf1280Sopenharmony_ci mpfr_clear_flags (); 192bbbf1280Sopenharmony_ci t = T(call_mpfr) (my, f, a, r); 193bbbf1280Sopenharmony_ci /* Double rounding. */ 194bbbf1280Sopenharmony_ci t2 = mpfr_set (mr, my, r); 195bbbf1280Sopenharmony_ci if (t2) 196bbbf1280Sopenharmony_ci t = t2; 197bbbf1280Sopenharmony_ci mpfr_set_emin (RT(emin)); 198bbbf1280Sopenharmony_ci mpfr_set_emax (RT(emax)); 199bbbf1280Sopenharmony_ci t = mpfr_check_range (mr, t, r); 200bbbf1280Sopenharmony_ci t = mpfr_subnormalize (mr, t, r); 201bbbf1280Sopenharmony_ci mpfr_set_emax (MPFR_EMAX_DEFAULT); 202bbbf1280Sopenharmony_ci mpfr_set_emin (MPFR_EMIN_DEFAULT); 203bbbf1280Sopenharmony_ci p->y = mpfr_get_d (mr, r); 204bbbf1280Sopenharmony_ci p->ex = t ? FE_INEXACT : 0; 205bbbf1280Sopenharmony_ci p->ex_may = FE_INEXACT; 206bbbf1280Sopenharmony_ci if (mpfr_underflow_p () && (p->ex & FE_INEXACT)) 207bbbf1280Sopenharmony_ci /* TODO: handle before and after rounding uflow cases. */ 208bbbf1280Sopenharmony_ci p->ex |= FE_UNDERFLOW; 209bbbf1280Sopenharmony_ci if (mpfr_overflow_p ()) 210bbbf1280Sopenharmony_ci p->ex |= FE_OVERFLOW | FE_INEXACT; 211bbbf1280Sopenharmony_ci if (mpfr_divby0_p ()) 212bbbf1280Sopenharmony_ci p->ex |= FE_DIVBYZERO; 213bbbf1280Sopenharmony_ci //if (mpfr_erangeflag_p ()) 214bbbf1280Sopenharmony_ci // p->ex |= FE_INVALID; 215bbbf1280Sopenharmony_ci if (!mpfr_nanflag_p () && RT(isok) (ygot, exgot, p->y, p->ex, p->ex_may)) 216bbbf1280Sopenharmony_ci return 1; 217bbbf1280Sopenharmony_ci if (mpfr_nanflag_p () && !T(qnanpropagation) (a)) 218bbbf1280Sopenharmony_ci p->ex |= FE_INVALID; 219bbbf1280Sopenharmony_ci p->ulpexp = RT(ulpscale_mpfr) (my, t); 220bbbf1280Sopenharmony_ci if (!isfinite (p->y)) 221bbbf1280Sopenharmony_ci { 222bbbf1280Sopenharmony_ci p->tail = 0; 223bbbf1280Sopenharmony_ci if (isnan (p->y)) 224bbbf1280Sopenharmony_ci { 225bbbf1280Sopenharmony_ci /* If an input was nan keep its sign. */ 226bbbf1280Sopenharmony_ci p->y = T(sum) (a); 227bbbf1280Sopenharmony_ci if (!isnan (p->y)) 228bbbf1280Sopenharmony_ci p->y = (p->y - p->y) / (p->y - p->y); 229bbbf1280Sopenharmony_ci return RT(isok) (ygot, exgot, p->y, p->ex, p->ex_may); 230bbbf1280Sopenharmony_ci } 231bbbf1280Sopenharmony_ci mpfr_set_si_2exp (mr, signbit (p->y) ? -1 : 1, 1024, MPFR_RNDN); 232bbbf1280Sopenharmony_ci if (mpfr_cmpabs (my, mr) >= 0) 233bbbf1280Sopenharmony_ci return RT(isok) (ygot, exgot, p->y, p->ex, p->ex_may); 234bbbf1280Sopenharmony_ci } 235bbbf1280Sopenharmony_ci mpfr_sub (me, my, mr, MPFR_RNDN); 236bbbf1280Sopenharmony_ci mpfr_mul_2si (me, me, -p->ulpexp, MPFR_RNDN); 237bbbf1280Sopenharmony_ci p->tail = mpfr_get_d (me, MPFR_RNDN); 238bbbf1280Sopenharmony_ci return 0; 239bbbf1280Sopenharmony_ci#else 240bbbf1280Sopenharmony_ci abort (); 241bbbf1280Sopenharmony_ci#endif 242bbbf1280Sopenharmony_ci} 243bbbf1280Sopenharmony_ci 244bbbf1280Sopenharmony_cistatic int T(cmp) (const struct fun *f, struct gen *gen, 245bbbf1280Sopenharmony_ci const struct conf *conf) 246bbbf1280Sopenharmony_ci{ 247bbbf1280Sopenharmony_ci double maxerr = 0; 248bbbf1280Sopenharmony_ci uint64_t cnt = 0; 249bbbf1280Sopenharmony_ci uint64_t cnt1 = 0; 250bbbf1280Sopenharmony_ci uint64_t cnt2 = 0; 251bbbf1280Sopenharmony_ci uint64_t cntfail = 0; 252bbbf1280Sopenharmony_ci int r = conf->r; 253bbbf1280Sopenharmony_ci int use_mpfr = conf->mpfr; 254bbbf1280Sopenharmony_ci int fenv = conf->fenv; 255bbbf1280Sopenharmony_ci for (;;) 256bbbf1280Sopenharmony_ci { 257bbbf1280Sopenharmony_ci struct RT(ret) want; 258bbbf1280Sopenharmony_ci struct T(args) a = T(next) (gen); 259bbbf1280Sopenharmony_ci int exgot; 260bbbf1280Sopenharmony_ci int exgot2; 261bbbf1280Sopenharmony_ci RT(float) ygot; 262bbbf1280Sopenharmony_ci RT(float) ygot2; 263bbbf1280Sopenharmony_ci int fail = 0; 264bbbf1280Sopenharmony_ci if (fenv) 265bbbf1280Sopenharmony_ci T(call_fenv) (f, a, r, &ygot, &exgot); 266bbbf1280Sopenharmony_ci else 267bbbf1280Sopenharmony_ci T(call_nofenv) (f, a, r, &ygot, &exgot); 268bbbf1280Sopenharmony_ci if (f->twice) { 269bbbf1280Sopenharmony_ci secondcall = 1; 270bbbf1280Sopenharmony_ci if (fenv) 271bbbf1280Sopenharmony_ci T(call_fenv) (f, a, r, &ygot2, &exgot2); 272bbbf1280Sopenharmony_ci else 273bbbf1280Sopenharmony_ci T(call_nofenv) (f, a, r, &ygot2, &exgot2); 274bbbf1280Sopenharmony_ci secondcall = 0; 275bbbf1280Sopenharmony_ci if (RT(asuint) (ygot) != RT(asuint) (ygot2)) 276bbbf1280Sopenharmony_ci { 277bbbf1280Sopenharmony_ci fail = 1; 278bbbf1280Sopenharmony_ci cntfail++; 279bbbf1280Sopenharmony_ci T(printcall) (f, a); 280bbbf1280Sopenharmony_ci printf (" got %a then %a for same input\n", ygot, ygot2); 281bbbf1280Sopenharmony_ci } 282bbbf1280Sopenharmony_ci } 283bbbf1280Sopenharmony_ci cnt++; 284bbbf1280Sopenharmony_ci int ok = use_mpfr 285bbbf1280Sopenharmony_ci ? T(call_mpfr_fix) (f, a, r, &want, ygot, exgot) 286bbbf1280Sopenharmony_ci : (fenv ? T(call_long_fenv) (f, a, r, &want, ygot, exgot) 287bbbf1280Sopenharmony_ci : T(call_long_nofenv) (f, a, r, &want, ygot, exgot)); 288bbbf1280Sopenharmony_ci if (!ok) 289bbbf1280Sopenharmony_ci { 290bbbf1280Sopenharmony_ci int print = 0; 291bbbf1280Sopenharmony_ci double err = RT(ulperr) (ygot, &want, r); 292bbbf1280Sopenharmony_ci double abserr = fabs (err); 293bbbf1280Sopenharmony_ci // TODO: count errors below accuracy limit. 294bbbf1280Sopenharmony_ci if (abserr > 0) 295bbbf1280Sopenharmony_ci cnt1++; 296bbbf1280Sopenharmony_ci if (abserr > 1) 297bbbf1280Sopenharmony_ci cnt2++; 298bbbf1280Sopenharmony_ci if (abserr > conf->errlim) 299bbbf1280Sopenharmony_ci { 300bbbf1280Sopenharmony_ci print = 1; 301bbbf1280Sopenharmony_ci if (!fail) 302bbbf1280Sopenharmony_ci { 303bbbf1280Sopenharmony_ci fail = 1; 304bbbf1280Sopenharmony_ci cntfail++; 305bbbf1280Sopenharmony_ci } 306bbbf1280Sopenharmony_ci } 307bbbf1280Sopenharmony_ci if (abserr > maxerr) 308bbbf1280Sopenharmony_ci { 309bbbf1280Sopenharmony_ci maxerr = abserr; 310bbbf1280Sopenharmony_ci if (!conf->quiet && abserr > conf->softlim) 311bbbf1280Sopenharmony_ci print = 1; 312bbbf1280Sopenharmony_ci } 313bbbf1280Sopenharmony_ci if (print) 314bbbf1280Sopenharmony_ci { 315bbbf1280Sopenharmony_ci T(printcall) (f, a); 316bbbf1280Sopenharmony_ci // TODO: inf ulp handling 317bbbf1280Sopenharmony_ci printf (" got %a want %a %+g ulp err %g\n", ygot, want.y, 318bbbf1280Sopenharmony_ci want.tail, err); 319bbbf1280Sopenharmony_ci } 320bbbf1280Sopenharmony_ci int diff = fenv ? exgot ^ want.ex : 0; 321bbbf1280Sopenharmony_ci if (fenv && (diff & ~want.ex_may)) 322bbbf1280Sopenharmony_ci { 323bbbf1280Sopenharmony_ci if (!fail) 324bbbf1280Sopenharmony_ci { 325bbbf1280Sopenharmony_ci fail = 1; 326bbbf1280Sopenharmony_ci cntfail++; 327bbbf1280Sopenharmony_ci } 328bbbf1280Sopenharmony_ci T(printcall) (f, a); 329bbbf1280Sopenharmony_ci printf (" is %a %+g ulp, got except 0x%0x", want.y, want.tail, 330bbbf1280Sopenharmony_ci exgot); 331bbbf1280Sopenharmony_ci if (diff & exgot) 332bbbf1280Sopenharmony_ci printf (" wrongly set: 0x%x", diff & exgot); 333bbbf1280Sopenharmony_ci if (diff & ~exgot) 334bbbf1280Sopenharmony_ci printf (" wrongly clear: 0x%x", diff & ~exgot); 335bbbf1280Sopenharmony_ci putchar ('\n'); 336bbbf1280Sopenharmony_ci } 337bbbf1280Sopenharmony_ci } 338bbbf1280Sopenharmony_ci if (cnt >= conf->n) 339bbbf1280Sopenharmony_ci break; 340bbbf1280Sopenharmony_ci if (!conf->quiet && cnt % 0x100000 == 0) 341bbbf1280Sopenharmony_ci printf ("progress: %6.3f%% cnt %llu cnt1 %llu cnt2 %llu cntfail %llu " 342bbbf1280Sopenharmony_ci "maxerr %g\n", 343bbbf1280Sopenharmony_ci 100.0 * cnt / conf->n, (unsigned long long) cnt, 344bbbf1280Sopenharmony_ci (unsigned long long) cnt1, (unsigned long long) cnt2, 345bbbf1280Sopenharmony_ci (unsigned long long) cntfail, maxerr); 346bbbf1280Sopenharmony_ci } 347bbbf1280Sopenharmony_ci double cc = cnt; 348bbbf1280Sopenharmony_ci if (cntfail) 349bbbf1280Sopenharmony_ci printf ("FAIL "); 350bbbf1280Sopenharmony_ci else 351bbbf1280Sopenharmony_ci printf ("PASS "); 352bbbf1280Sopenharmony_ci T(printgen) (f, gen); 353bbbf1280Sopenharmony_ci printf (" round %c errlim %g maxerr %g %s cnt %llu cnt1 %llu %g%% cnt2 %llu " 354bbbf1280Sopenharmony_ci "%g%% cntfail %llu %g%%\n", 355bbbf1280Sopenharmony_ci conf->rc, conf->errlim, 356bbbf1280Sopenharmony_ci maxerr, conf->r == FE_TONEAREST ? "+0.5" : "+1.0", 357bbbf1280Sopenharmony_ci (unsigned long long) cnt, 358bbbf1280Sopenharmony_ci (unsigned long long) cnt1, 100.0 * cnt1 / cc, 359bbbf1280Sopenharmony_ci (unsigned long long) cnt2, 100.0 * cnt2 / cc, 360bbbf1280Sopenharmony_ci (unsigned long long) cntfail, 100.0 * cntfail / cc); 361bbbf1280Sopenharmony_ci return !!cntfail; 362bbbf1280Sopenharmony_ci} 363