1bbbf1280Sopenharmony_ci/* 2bbbf1280Sopenharmony_ci * mathtest.c - test rig for mathlib 3bbbf1280Sopenharmony_ci * 4bbbf1280Sopenharmony_ci * Copyright (c) 1998-2019, Arm Limited. 5bbbf1280Sopenharmony_ci * SPDX-License-Identifier: MIT 6bbbf1280Sopenharmony_ci */ 7bbbf1280Sopenharmony_ci 8bbbf1280Sopenharmony_ci#include <assert.h> 9bbbf1280Sopenharmony_ci#include <stdio.h> 10bbbf1280Sopenharmony_ci#include <stdlib.h> 11bbbf1280Sopenharmony_ci#include <string.h> 12bbbf1280Sopenharmony_ci#include <setjmp.h> 13bbbf1280Sopenharmony_ci#include <ctype.h> 14bbbf1280Sopenharmony_ci#include <math.h> 15bbbf1280Sopenharmony_ci#include <errno.h> 16bbbf1280Sopenharmony_ci#include <limits.h> 17bbbf1280Sopenharmony_ci#include <fenv.h> 18bbbf1280Sopenharmony_ci#include "mathlib.h" 19bbbf1280Sopenharmony_ci 20bbbf1280Sopenharmony_ci#ifndef math_errhandling 21bbbf1280Sopenharmony_ci# define math_errhandling 0 22bbbf1280Sopenharmony_ci#endif 23bbbf1280Sopenharmony_ci 24bbbf1280Sopenharmony_ci#ifdef __cplusplus 25bbbf1280Sopenharmony_ci #define EXTERN_C extern "C" 26bbbf1280Sopenharmony_ci#else 27bbbf1280Sopenharmony_ci #define EXTERN_C extern 28bbbf1280Sopenharmony_ci#endif 29bbbf1280Sopenharmony_ci 30bbbf1280Sopenharmony_ci#ifndef TRUE 31bbbf1280Sopenharmony_ci#define TRUE 1 32bbbf1280Sopenharmony_ci#endif 33bbbf1280Sopenharmony_ci#ifndef FALSE 34bbbf1280Sopenharmony_ci#define FALSE 0 35bbbf1280Sopenharmony_ci#endif 36bbbf1280Sopenharmony_ci 37bbbf1280Sopenharmony_ci#ifdef IMPORT_SYMBOL 38bbbf1280Sopenharmony_ci#define STR2(x) #x 39bbbf1280Sopenharmony_ci#define STR(x) STR2(x) 40bbbf1280Sopenharmony_ci_Pragma(STR(import IMPORT_SYMBOL)) 41bbbf1280Sopenharmony_ci#endif 42bbbf1280Sopenharmony_ci 43bbbf1280Sopenharmony_ciint dmsd, dlsd; 44bbbf1280Sopenharmony_ciint quiet = 0; 45bbbf1280Sopenharmony_ciint doround = 0; 46bbbf1280Sopenharmony_ciunsigned statusmask = FE_ALL_EXCEPT; 47bbbf1280Sopenharmony_ci 48bbbf1280Sopenharmony_ci#define EXTRABITS (12) 49bbbf1280Sopenharmony_ci#define ULPUNIT (1<<EXTRABITS) 50bbbf1280Sopenharmony_ci 51bbbf1280Sopenharmony_citypedef int (*test) (void); 52bbbf1280Sopenharmony_ci 53bbbf1280Sopenharmony_ci/* 54bbbf1280Sopenharmony_ci struct to hold info about a function (which could actually be a macro) 55bbbf1280Sopenharmony_ci*/ 56bbbf1280Sopenharmony_citypedef struct { 57bbbf1280Sopenharmony_ci enum { 58bbbf1280Sopenharmony_ci t_func, t_macro 59bbbf1280Sopenharmony_ci } type; 60bbbf1280Sopenharmony_ci enum { 61bbbf1280Sopenharmony_ci at_d, at_s, /* double or single precision float */ 62bbbf1280Sopenharmony_ci at_d2, at_s2, /* same, but taking two args */ 63bbbf1280Sopenharmony_ci at_di, at_si, /* double/single and an int */ 64bbbf1280Sopenharmony_ci at_dip, at_sip, /* double/single and an int ptr */ 65bbbf1280Sopenharmony_ci at_ddp, at_ssp, /* d/s and a d/s ptr */ 66bbbf1280Sopenharmony_ci at_dc, at_sc, /* double or single precision complex */ 67bbbf1280Sopenharmony_ci at_dc2, at_sc2 /* same, but taking two args */ 68bbbf1280Sopenharmony_ci } argtype; 69bbbf1280Sopenharmony_ci enum { 70bbbf1280Sopenharmony_ci rt_d, rt_s, rt_i, /* double, single, int */ 71bbbf1280Sopenharmony_ci rt_dc, rt_sc, /* double, single precision complex */ 72bbbf1280Sopenharmony_ci rt_d2, rt_s2 /* also use res2 */ 73bbbf1280Sopenharmony_ci } rettype; 74bbbf1280Sopenharmony_ci union { 75bbbf1280Sopenharmony_ci void* ptr; 76bbbf1280Sopenharmony_ci double (*d_d_ptr)(double); 77bbbf1280Sopenharmony_ci float (*s_s_ptr)(float); 78bbbf1280Sopenharmony_ci int (*d_i_ptr)(double); 79bbbf1280Sopenharmony_ci int (*s_i_ptr)(float); 80bbbf1280Sopenharmony_ci double (*d2_d_ptr)(double, double); 81bbbf1280Sopenharmony_ci float (*s2_s_ptr)(float, float); 82bbbf1280Sopenharmony_ci double (*di_d_ptr)(double,int); 83bbbf1280Sopenharmony_ci float (*si_s_ptr)(float,int); 84bbbf1280Sopenharmony_ci double (*dip_d_ptr)(double,int*); 85bbbf1280Sopenharmony_ci float (*sip_s_ptr)(float,int*); 86bbbf1280Sopenharmony_ci double (*ddp_d_ptr)(double,double*); 87bbbf1280Sopenharmony_ci float (*ssp_s_ptr)(float,float*); 88bbbf1280Sopenharmony_ci } func; 89bbbf1280Sopenharmony_ci enum { 90bbbf1280Sopenharmony_ci m_none, 91bbbf1280Sopenharmony_ci m_isfinite, m_isfinitef, 92bbbf1280Sopenharmony_ci m_isgreater, m_isgreaterequal, 93bbbf1280Sopenharmony_ci m_isgreaterequalf, m_isgreaterf, 94bbbf1280Sopenharmony_ci m_isinf, m_isinff, 95bbbf1280Sopenharmony_ci m_isless, m_islessequal, 96bbbf1280Sopenharmony_ci m_islessequalf, m_islessf, 97bbbf1280Sopenharmony_ci m_islessgreater, m_islessgreaterf, 98bbbf1280Sopenharmony_ci m_isnan, m_isnanf, 99bbbf1280Sopenharmony_ci m_isnormal, m_isnormalf, 100bbbf1280Sopenharmony_ci m_isunordered, m_isunorderedf, 101bbbf1280Sopenharmony_ci m_fpclassify, m_fpclassifyf, 102bbbf1280Sopenharmony_ci m_signbit, m_signbitf, 103bbbf1280Sopenharmony_ci /* not actually a macro, but makes things easier */ 104bbbf1280Sopenharmony_ci m_rred, m_rredf, 105bbbf1280Sopenharmony_ci m_cadd, m_csub, m_cmul, m_cdiv, 106bbbf1280Sopenharmony_ci m_caddf, m_csubf, m_cmulf, m_cdivf 107bbbf1280Sopenharmony_ci } macro_name; /* only used if a macro/something that can't be done using func */ 108bbbf1280Sopenharmony_ci long long tolerance; 109bbbf1280Sopenharmony_ci const char* name; 110bbbf1280Sopenharmony_ci} test_func; 111bbbf1280Sopenharmony_ci 112bbbf1280Sopenharmony_ci/* used in qsort */ 113bbbf1280Sopenharmony_ciint compare_tfuncs(const void* a, const void* b) { 114bbbf1280Sopenharmony_ci return strcmp(((test_func*)a)->name, ((test_func*)b)->name); 115bbbf1280Sopenharmony_ci} 116bbbf1280Sopenharmony_ci 117bbbf1280Sopenharmony_ciint is_double_argtype(int argtype) { 118bbbf1280Sopenharmony_ci switch(argtype) { 119bbbf1280Sopenharmony_ci case at_d: 120bbbf1280Sopenharmony_ci case at_d2: 121bbbf1280Sopenharmony_ci case at_dc: 122bbbf1280Sopenharmony_ci case at_dc2: 123bbbf1280Sopenharmony_ci return 1; 124bbbf1280Sopenharmony_ci default: 125bbbf1280Sopenharmony_ci return 0; 126bbbf1280Sopenharmony_ci } 127bbbf1280Sopenharmony_ci} 128bbbf1280Sopenharmony_ci 129bbbf1280Sopenharmony_ciint is_single_argtype(int argtype) { 130bbbf1280Sopenharmony_ci switch(argtype) { 131bbbf1280Sopenharmony_ci case at_s: 132bbbf1280Sopenharmony_ci case at_s2: 133bbbf1280Sopenharmony_ci case at_sc: 134bbbf1280Sopenharmony_ci case at_sc2: 135bbbf1280Sopenharmony_ci return 1; 136bbbf1280Sopenharmony_ci default: 137bbbf1280Sopenharmony_ci return 0; 138bbbf1280Sopenharmony_ci } 139bbbf1280Sopenharmony_ci} 140bbbf1280Sopenharmony_ci 141bbbf1280Sopenharmony_ciint is_double_rettype(int rettype) { 142bbbf1280Sopenharmony_ci switch(rettype) { 143bbbf1280Sopenharmony_ci case rt_d: 144bbbf1280Sopenharmony_ci case rt_dc: 145bbbf1280Sopenharmony_ci case rt_d2: 146bbbf1280Sopenharmony_ci return 1; 147bbbf1280Sopenharmony_ci default: 148bbbf1280Sopenharmony_ci return 0; 149bbbf1280Sopenharmony_ci } 150bbbf1280Sopenharmony_ci} 151bbbf1280Sopenharmony_ci 152bbbf1280Sopenharmony_ciint is_single_rettype(int rettype) { 153bbbf1280Sopenharmony_ci switch(rettype) { 154bbbf1280Sopenharmony_ci case rt_s: 155bbbf1280Sopenharmony_ci case rt_sc: 156bbbf1280Sopenharmony_ci case rt_s2: 157bbbf1280Sopenharmony_ci return 1; 158bbbf1280Sopenharmony_ci default: 159bbbf1280Sopenharmony_ci return 0; 160bbbf1280Sopenharmony_ci } 161bbbf1280Sopenharmony_ci} 162bbbf1280Sopenharmony_ci 163bbbf1280Sopenharmony_ciint is_complex_argtype(int argtype) { 164bbbf1280Sopenharmony_ci switch(argtype) { 165bbbf1280Sopenharmony_ci case at_dc: 166bbbf1280Sopenharmony_ci case at_sc: 167bbbf1280Sopenharmony_ci case at_dc2: 168bbbf1280Sopenharmony_ci case at_sc2: 169bbbf1280Sopenharmony_ci return 1; 170bbbf1280Sopenharmony_ci default: 171bbbf1280Sopenharmony_ci return 0; 172bbbf1280Sopenharmony_ci } 173bbbf1280Sopenharmony_ci} 174bbbf1280Sopenharmony_ci 175bbbf1280Sopenharmony_ciint is_complex_rettype(int rettype) { 176bbbf1280Sopenharmony_ci switch(rettype) { 177bbbf1280Sopenharmony_ci case rt_dc: 178bbbf1280Sopenharmony_ci case rt_sc: 179bbbf1280Sopenharmony_ci return 1; 180bbbf1280Sopenharmony_ci default: 181bbbf1280Sopenharmony_ci return 0; 182bbbf1280Sopenharmony_ci } 183bbbf1280Sopenharmony_ci} 184bbbf1280Sopenharmony_ci 185bbbf1280Sopenharmony_ci/* 186bbbf1280Sopenharmony_ci * Special-case flags indicating that some functions' error 187bbbf1280Sopenharmony_ci * tolerance handling is more complicated than a fixed relative 188bbbf1280Sopenharmony_ci * error bound. 189bbbf1280Sopenharmony_ci */ 190bbbf1280Sopenharmony_ci#define ABSLOWERBOUND 0x4000000000000000LL 191bbbf1280Sopenharmony_ci#define PLUSMINUSPIO2 0x1000000000000000LL 192bbbf1280Sopenharmony_ci 193bbbf1280Sopenharmony_ci#define ARM_PREFIX(x) x 194bbbf1280Sopenharmony_ci 195bbbf1280Sopenharmony_ci#define TFUNC(arg,ret,name,tolerance) { t_func, arg, ret, (void*)&name, m_none, tolerance, #name } 196bbbf1280Sopenharmony_ci#define TFUNCARM(arg,ret,name,tolerance) { t_func, arg, ret, (void*)& ARM_PREFIX(name), m_none, tolerance, #name } 197bbbf1280Sopenharmony_ci#define MFUNC(arg,ret,name,tolerance) { t_macro, arg, ret, NULL, m_##name, tolerance, #name } 198bbbf1280Sopenharmony_ci 199bbbf1280Sopenharmony_ci/* sincosf wrappers for easier testing. */ 200bbbf1280Sopenharmony_cistatic float sincosf_sinf(float x) { float s,c; sincosf(x, &s, &c); return s; } 201bbbf1280Sopenharmony_cistatic float sincosf_cosf(float x) { float s,c; sincosf(x, &s, &c); return c; } 202bbbf1280Sopenharmony_ci 203bbbf1280Sopenharmony_citest_func tfuncs[] = { 204bbbf1280Sopenharmony_ci /* trigonometric */ 205bbbf1280Sopenharmony_ci TFUNC(at_d,rt_d, acos, 4*ULPUNIT), 206bbbf1280Sopenharmony_ci TFUNC(at_d,rt_d, asin, 4*ULPUNIT), 207bbbf1280Sopenharmony_ci TFUNC(at_d,rt_d, atan, 4*ULPUNIT), 208bbbf1280Sopenharmony_ci TFUNC(at_d2,rt_d, atan2, 4*ULPUNIT), 209bbbf1280Sopenharmony_ci 210bbbf1280Sopenharmony_ci TFUNC(at_d,rt_d, tan, 2*ULPUNIT), 211bbbf1280Sopenharmony_ci TFUNC(at_d,rt_d, sin, 2*ULPUNIT), 212bbbf1280Sopenharmony_ci TFUNC(at_d,rt_d, cos, 2*ULPUNIT), 213bbbf1280Sopenharmony_ci 214bbbf1280Sopenharmony_ci TFUNC(at_s,rt_s, acosf, 4*ULPUNIT), 215bbbf1280Sopenharmony_ci TFUNC(at_s,rt_s, asinf, 4*ULPUNIT), 216bbbf1280Sopenharmony_ci TFUNC(at_s,rt_s, atanf, 4*ULPUNIT), 217bbbf1280Sopenharmony_ci TFUNC(at_s2,rt_s, atan2f, 4*ULPUNIT), 218bbbf1280Sopenharmony_ci TFUNCARM(at_s,rt_s, tanf, 4*ULPUNIT), 219bbbf1280Sopenharmony_ci TFUNCARM(at_s,rt_s, sinf, 3*ULPUNIT/4), 220bbbf1280Sopenharmony_ci TFUNCARM(at_s,rt_s, cosf, 3*ULPUNIT/4), 221bbbf1280Sopenharmony_ci TFUNCARM(at_s,rt_s, sincosf_sinf, 3*ULPUNIT/4), 222bbbf1280Sopenharmony_ci TFUNCARM(at_s,rt_s, sincosf_cosf, 3*ULPUNIT/4), 223bbbf1280Sopenharmony_ci 224bbbf1280Sopenharmony_ci /* hyperbolic */ 225bbbf1280Sopenharmony_ci TFUNC(at_d, rt_d, atanh, 4*ULPUNIT), 226bbbf1280Sopenharmony_ci TFUNC(at_d, rt_d, asinh, 4*ULPUNIT), 227bbbf1280Sopenharmony_ci TFUNC(at_d, rt_d, acosh, 4*ULPUNIT), 228bbbf1280Sopenharmony_ci TFUNC(at_d,rt_d, tanh, 4*ULPUNIT), 229bbbf1280Sopenharmony_ci TFUNC(at_d,rt_d, sinh, 4*ULPUNIT), 230bbbf1280Sopenharmony_ci TFUNC(at_d,rt_d, cosh, 4*ULPUNIT), 231bbbf1280Sopenharmony_ci 232bbbf1280Sopenharmony_ci TFUNC(at_s, rt_s, atanhf, 4*ULPUNIT), 233bbbf1280Sopenharmony_ci TFUNC(at_s, rt_s, asinhf, 4*ULPUNIT), 234bbbf1280Sopenharmony_ci TFUNC(at_s, rt_s, acoshf, 4*ULPUNIT), 235bbbf1280Sopenharmony_ci TFUNC(at_s,rt_s, tanhf, 4*ULPUNIT), 236bbbf1280Sopenharmony_ci TFUNC(at_s,rt_s, sinhf, 4*ULPUNIT), 237bbbf1280Sopenharmony_ci TFUNC(at_s,rt_s, coshf, 4*ULPUNIT), 238bbbf1280Sopenharmony_ci 239bbbf1280Sopenharmony_ci /* exponential and logarithmic */ 240bbbf1280Sopenharmony_ci TFUNC(at_d,rt_d, log, 3*ULPUNIT/4), 241bbbf1280Sopenharmony_ci TFUNC(at_d,rt_d, log10, 3*ULPUNIT), 242bbbf1280Sopenharmony_ci TFUNC(at_d,rt_d, log2, 3*ULPUNIT/4), 243bbbf1280Sopenharmony_ci TFUNC(at_d,rt_d, log1p, 2*ULPUNIT), 244bbbf1280Sopenharmony_ci TFUNC(at_d,rt_d, exp, 3*ULPUNIT/4), 245bbbf1280Sopenharmony_ci TFUNC(at_d,rt_d, exp2, 3*ULPUNIT/4), 246bbbf1280Sopenharmony_ci TFUNC(at_d,rt_d, expm1, ULPUNIT), 247bbbf1280Sopenharmony_ci TFUNCARM(at_s,rt_s, logf, ULPUNIT), 248bbbf1280Sopenharmony_ci TFUNC(at_s,rt_s, log10f, 3*ULPUNIT), 249bbbf1280Sopenharmony_ci TFUNCARM(at_s,rt_s, log2f, ULPUNIT), 250bbbf1280Sopenharmony_ci TFUNC(at_s,rt_s, log1pf, 2*ULPUNIT), 251bbbf1280Sopenharmony_ci TFUNCARM(at_s,rt_s, expf, 3*ULPUNIT/4), 252bbbf1280Sopenharmony_ci TFUNCARM(at_s,rt_s, exp2f, 3*ULPUNIT/4), 253bbbf1280Sopenharmony_ci TFUNC(at_s,rt_s, expm1f, ULPUNIT), 254bbbf1280Sopenharmony_ci 255bbbf1280Sopenharmony_ci /* power */ 256bbbf1280Sopenharmony_ci TFUNC(at_d2,rt_d, pow, 3*ULPUNIT/4), 257bbbf1280Sopenharmony_ci TFUNC(at_d,rt_d, sqrt, ULPUNIT/2), 258bbbf1280Sopenharmony_ci TFUNC(at_d,rt_d, cbrt, 2*ULPUNIT), 259bbbf1280Sopenharmony_ci TFUNC(at_d2, rt_d, hypot, 4*ULPUNIT), 260bbbf1280Sopenharmony_ci 261bbbf1280Sopenharmony_ci TFUNCARM(at_s2,rt_s, powf, ULPUNIT), 262bbbf1280Sopenharmony_ci TFUNC(at_s,rt_s, sqrtf, ULPUNIT/2), 263bbbf1280Sopenharmony_ci TFUNC(at_s,rt_s, cbrtf, 2*ULPUNIT), 264bbbf1280Sopenharmony_ci TFUNC(at_s2, rt_s, hypotf, 4*ULPUNIT), 265bbbf1280Sopenharmony_ci 266bbbf1280Sopenharmony_ci /* error function */ 267bbbf1280Sopenharmony_ci TFUNC(at_d,rt_d, erf, 16*ULPUNIT), 268bbbf1280Sopenharmony_ci TFUNC(at_s,rt_s, erff, 16*ULPUNIT), 269bbbf1280Sopenharmony_ci TFUNC(at_d,rt_d, erfc, 16*ULPUNIT), 270bbbf1280Sopenharmony_ci TFUNC(at_s,rt_s, erfcf, 16*ULPUNIT), 271bbbf1280Sopenharmony_ci 272bbbf1280Sopenharmony_ci /* gamma functions */ 273bbbf1280Sopenharmony_ci TFUNC(at_d,rt_d, tgamma, 16*ULPUNIT), 274bbbf1280Sopenharmony_ci TFUNC(at_s,rt_s, tgammaf, 16*ULPUNIT), 275bbbf1280Sopenharmony_ci TFUNC(at_d,rt_d, lgamma, 16*ULPUNIT | ABSLOWERBOUND), 276bbbf1280Sopenharmony_ci TFUNC(at_s,rt_s, lgammaf, 16*ULPUNIT | ABSLOWERBOUND), 277bbbf1280Sopenharmony_ci 278bbbf1280Sopenharmony_ci TFUNC(at_d,rt_d, ceil, 0), 279bbbf1280Sopenharmony_ci TFUNC(at_s,rt_s, ceilf, 0), 280bbbf1280Sopenharmony_ci TFUNC(at_d2,rt_d, copysign, 0), 281bbbf1280Sopenharmony_ci TFUNC(at_s2,rt_s, copysignf, 0), 282bbbf1280Sopenharmony_ci TFUNC(at_d,rt_d, floor, 0), 283bbbf1280Sopenharmony_ci TFUNC(at_s,rt_s, floorf, 0), 284bbbf1280Sopenharmony_ci TFUNC(at_d2,rt_d, fmax, 0), 285bbbf1280Sopenharmony_ci TFUNC(at_s2,rt_s, fmaxf, 0), 286bbbf1280Sopenharmony_ci TFUNC(at_d2,rt_d, fmin, 0), 287bbbf1280Sopenharmony_ci TFUNC(at_s2,rt_s, fminf, 0), 288bbbf1280Sopenharmony_ci TFUNC(at_d2,rt_d, fmod, 0), 289bbbf1280Sopenharmony_ci TFUNC(at_s2,rt_s, fmodf, 0), 290bbbf1280Sopenharmony_ci MFUNC(at_d, rt_i, fpclassify, 0), 291bbbf1280Sopenharmony_ci MFUNC(at_s, rt_i, fpclassifyf, 0), 292bbbf1280Sopenharmony_ci TFUNC(at_dip,rt_d, frexp, 0), 293bbbf1280Sopenharmony_ci TFUNC(at_sip,rt_s, frexpf, 0), 294bbbf1280Sopenharmony_ci MFUNC(at_d, rt_i, isfinite, 0), 295bbbf1280Sopenharmony_ci MFUNC(at_s, rt_i, isfinitef, 0), 296bbbf1280Sopenharmony_ci MFUNC(at_d, rt_i, isgreater, 0), 297bbbf1280Sopenharmony_ci MFUNC(at_d, rt_i, isgreaterequal, 0), 298bbbf1280Sopenharmony_ci MFUNC(at_s, rt_i, isgreaterequalf, 0), 299bbbf1280Sopenharmony_ci MFUNC(at_s, rt_i, isgreaterf, 0), 300bbbf1280Sopenharmony_ci MFUNC(at_d, rt_i, isinf, 0), 301bbbf1280Sopenharmony_ci MFUNC(at_s, rt_i, isinff, 0), 302bbbf1280Sopenharmony_ci MFUNC(at_d, rt_i, isless, 0), 303bbbf1280Sopenharmony_ci MFUNC(at_d, rt_i, islessequal, 0), 304bbbf1280Sopenharmony_ci MFUNC(at_s, rt_i, islessequalf, 0), 305bbbf1280Sopenharmony_ci MFUNC(at_s, rt_i, islessf, 0), 306bbbf1280Sopenharmony_ci MFUNC(at_d, rt_i, islessgreater, 0), 307bbbf1280Sopenharmony_ci MFUNC(at_s, rt_i, islessgreaterf, 0), 308bbbf1280Sopenharmony_ci MFUNC(at_d, rt_i, isnan, 0), 309bbbf1280Sopenharmony_ci MFUNC(at_s, rt_i, isnanf, 0), 310bbbf1280Sopenharmony_ci MFUNC(at_d, rt_i, isnormal, 0), 311bbbf1280Sopenharmony_ci MFUNC(at_s, rt_i, isnormalf, 0), 312bbbf1280Sopenharmony_ci MFUNC(at_d, rt_i, isunordered, 0), 313bbbf1280Sopenharmony_ci MFUNC(at_s, rt_i, isunorderedf, 0), 314bbbf1280Sopenharmony_ci TFUNC(at_di,rt_d, ldexp, 0), 315bbbf1280Sopenharmony_ci TFUNC(at_si,rt_s, ldexpf, 0), 316bbbf1280Sopenharmony_ci TFUNC(at_ddp,rt_d2, modf, 0), 317bbbf1280Sopenharmony_ci TFUNC(at_ssp,rt_s2, modff, 0), 318bbbf1280Sopenharmony_ci#ifndef BIGRANGERED 319bbbf1280Sopenharmony_ci MFUNC(at_d, rt_d, rred, 2*ULPUNIT), 320bbbf1280Sopenharmony_ci#else 321bbbf1280Sopenharmony_ci MFUNC(at_d, rt_d, m_rred, ULPUNIT), 322bbbf1280Sopenharmony_ci#endif 323bbbf1280Sopenharmony_ci MFUNC(at_d, rt_i, signbit, 0), 324bbbf1280Sopenharmony_ci MFUNC(at_s, rt_i, signbitf, 0), 325bbbf1280Sopenharmony_ci}; 326bbbf1280Sopenharmony_ci 327bbbf1280Sopenharmony_ci/* 328bbbf1280Sopenharmony_ci * keywords are: func size op1 op2 result res2 errno op1r op1i op2r op2i resultr resulti 329bbbf1280Sopenharmony_ci * also we ignore: wrongresult wrongres2 wrongerrno 330bbbf1280Sopenharmony_ci * op1 equivalent to op1r, same with op2 and result 331bbbf1280Sopenharmony_ci */ 332bbbf1280Sopenharmony_ci 333bbbf1280Sopenharmony_citypedef struct { 334bbbf1280Sopenharmony_ci test_func *func; 335bbbf1280Sopenharmony_ci unsigned op1r[2]; /* real part, also used for non-complex numbers */ 336bbbf1280Sopenharmony_ci unsigned op1i[2]; /* imaginary part */ 337bbbf1280Sopenharmony_ci unsigned op2r[2]; 338bbbf1280Sopenharmony_ci unsigned op2i[2]; 339bbbf1280Sopenharmony_ci unsigned resultr[3]; 340bbbf1280Sopenharmony_ci unsigned resulti[3]; 341bbbf1280Sopenharmony_ci enum { 342bbbf1280Sopenharmony_ci rc_none, rc_zero, rc_infinity, rc_nan, rc_finite 343bbbf1280Sopenharmony_ci } resultc; /* special complex results, rc_none means use resultr and resulti as normal */ 344bbbf1280Sopenharmony_ci unsigned res2[2]; 345bbbf1280Sopenharmony_ci unsigned status; /* IEEE status return, if any */ 346bbbf1280Sopenharmony_ci unsigned maybestatus; /* for optional status, or allowance for spurious */ 347bbbf1280Sopenharmony_ci int nresult; /* number of result words */ 348bbbf1280Sopenharmony_ci int in_err, in_err_limit; 349bbbf1280Sopenharmony_ci int err; 350bbbf1280Sopenharmony_ci int maybeerr; 351bbbf1280Sopenharmony_ci int valid; 352bbbf1280Sopenharmony_ci int comment; 353bbbf1280Sopenharmony_ci int random; 354bbbf1280Sopenharmony_ci} testdetail; 355bbbf1280Sopenharmony_ci 356bbbf1280Sopenharmony_cienum { /* keywords */ 357bbbf1280Sopenharmony_ci k_errno, k_errno_in, k_error, k_func, k_maybeerror, k_maybestatus, k_op1, k_op1i, k_op1r, k_op2, k_op2i, k_op2r, 358bbbf1280Sopenharmony_ci k_random, k_res2, k_result, k_resultc, k_resulti, k_resultr, k_status, 359bbbf1280Sopenharmony_ci k_wrongres2, k_wrongresult, k_wrongstatus, k_wrongerrno 360bbbf1280Sopenharmony_ci}; 361bbbf1280Sopenharmony_cichar *keywords[] = { 362bbbf1280Sopenharmony_ci "errno", "errno_in", "error", "func", "maybeerror", "maybestatus", "op1", "op1i", "op1r", "op2", "op2i", "op2r", 363bbbf1280Sopenharmony_ci "random", "res2", "result", "resultc", "resulti", "resultr", "status", 364bbbf1280Sopenharmony_ci "wrongres2", "wrongresult", "wrongstatus", "wrongerrno" 365bbbf1280Sopenharmony_ci}; 366bbbf1280Sopenharmony_ci 367bbbf1280Sopenharmony_cienum { 368bbbf1280Sopenharmony_ci e_0, e_EDOM, e_ERANGE, 369bbbf1280Sopenharmony_ci 370bbbf1280Sopenharmony_ci /* 371bbbf1280Sopenharmony_ci * This enum makes sure that we have the right number of errnos in the 372bbbf1280Sopenharmony_ci * errno[] array 373bbbf1280Sopenharmony_ci */ 374bbbf1280Sopenharmony_ci e_number_of_errnos 375bbbf1280Sopenharmony_ci}; 376bbbf1280Sopenharmony_cichar *errnos[] = { 377bbbf1280Sopenharmony_ci "0", "EDOM", "ERANGE" 378bbbf1280Sopenharmony_ci}; 379bbbf1280Sopenharmony_ci 380bbbf1280Sopenharmony_cienum { 381bbbf1280Sopenharmony_ci e_none, e_divbyzero, e_domain, e_overflow, e_underflow 382bbbf1280Sopenharmony_ci}; 383bbbf1280Sopenharmony_cichar *errors[] = { 384bbbf1280Sopenharmony_ci "0", "divbyzero", "domain", "overflow", "underflow" 385bbbf1280Sopenharmony_ci}; 386bbbf1280Sopenharmony_ci 387bbbf1280Sopenharmony_cistatic int verbose, fo, strict; 388bbbf1280Sopenharmony_ci 389bbbf1280Sopenharmony_ci/* state toggled by random=on / random=off */ 390bbbf1280Sopenharmony_cistatic int randomstate; 391bbbf1280Sopenharmony_ci 392bbbf1280Sopenharmony_ci/* Canonify a double NaN: SNaNs all become 7FF00000.00000001 and QNaNs 393bbbf1280Sopenharmony_ci * all become 7FF80000.00000001 */ 394bbbf1280Sopenharmony_civoid canon_dNaN(unsigned a[2]) { 395bbbf1280Sopenharmony_ci if ((a[0] & 0x7FF00000) != 0x7FF00000) 396bbbf1280Sopenharmony_ci return; /* not Inf or NaN */ 397bbbf1280Sopenharmony_ci if (!(a[0] & 0xFFFFF) && !a[1]) 398bbbf1280Sopenharmony_ci return; /* Inf */ 399bbbf1280Sopenharmony_ci a[0] &= 0x7FF80000; /* canonify top word */ 400bbbf1280Sopenharmony_ci a[1] = 0x00000001; /* canonify bottom word */ 401bbbf1280Sopenharmony_ci} 402bbbf1280Sopenharmony_ci 403bbbf1280Sopenharmony_ci/* Canonify a single NaN: SNaNs all become 7F800001 and QNaNs 404bbbf1280Sopenharmony_ci * all become 7FC00001. Returns classification of the NaN. */ 405bbbf1280Sopenharmony_civoid canon_sNaN(unsigned a[1]) { 406bbbf1280Sopenharmony_ci if ((a[0] & 0x7F800000) != 0x7F800000) 407bbbf1280Sopenharmony_ci return; /* not Inf or NaN */ 408bbbf1280Sopenharmony_ci if (!(a[0] & 0x7FFFFF)) 409bbbf1280Sopenharmony_ci return; /* Inf */ 410bbbf1280Sopenharmony_ci a[0] &= 0x7FC00000; /* canonify most bits */ 411bbbf1280Sopenharmony_ci a[0] |= 0x00000001; /* canonify bottom bit */ 412bbbf1280Sopenharmony_ci} 413bbbf1280Sopenharmony_ci 414bbbf1280Sopenharmony_ci/* 415bbbf1280Sopenharmony_ci * Detect difficult operands for FO mode. 416bbbf1280Sopenharmony_ci */ 417bbbf1280Sopenharmony_ciint is_dhard(unsigned a[2]) 418bbbf1280Sopenharmony_ci{ 419bbbf1280Sopenharmony_ci if ((a[0] & 0x7FF00000) == 0x7FF00000) 420bbbf1280Sopenharmony_ci return TRUE; /* inf or NaN */ 421bbbf1280Sopenharmony_ci if ((a[0] & 0x7FF00000) == 0 && 422bbbf1280Sopenharmony_ci ((a[0] & 0x7FFFFFFF) | a[1]) != 0) 423bbbf1280Sopenharmony_ci return TRUE; /* denormal */ 424bbbf1280Sopenharmony_ci return FALSE; 425bbbf1280Sopenharmony_ci} 426bbbf1280Sopenharmony_ciint is_shard(unsigned a[1]) 427bbbf1280Sopenharmony_ci{ 428bbbf1280Sopenharmony_ci if ((a[0] & 0x7F800000) == 0x7F800000) 429bbbf1280Sopenharmony_ci return TRUE; /* inf or NaN */ 430bbbf1280Sopenharmony_ci if ((a[0] & 0x7F800000) == 0 && 431bbbf1280Sopenharmony_ci (a[0] & 0x7FFFFFFF) != 0) 432bbbf1280Sopenharmony_ci return TRUE; /* denormal */ 433bbbf1280Sopenharmony_ci return FALSE; 434bbbf1280Sopenharmony_ci} 435bbbf1280Sopenharmony_ci 436bbbf1280Sopenharmony_ci/* 437bbbf1280Sopenharmony_ci * Normalise all zeroes into +0, for FO mode. 438bbbf1280Sopenharmony_ci */ 439bbbf1280Sopenharmony_civoid dnormzero(unsigned a[2]) 440bbbf1280Sopenharmony_ci{ 441bbbf1280Sopenharmony_ci if (a[0] == 0x80000000 && a[1] == 0) 442bbbf1280Sopenharmony_ci a[0] = 0; 443bbbf1280Sopenharmony_ci} 444bbbf1280Sopenharmony_civoid snormzero(unsigned a[1]) 445bbbf1280Sopenharmony_ci{ 446bbbf1280Sopenharmony_ci if (a[0] == 0x80000000) 447bbbf1280Sopenharmony_ci a[0] = 0; 448bbbf1280Sopenharmony_ci} 449bbbf1280Sopenharmony_ci 450bbbf1280Sopenharmony_cistatic int find(char *word, char **array, int asize) { 451bbbf1280Sopenharmony_ci int i, j; 452bbbf1280Sopenharmony_ci 453bbbf1280Sopenharmony_ci asize /= sizeof(char *); 454bbbf1280Sopenharmony_ci 455bbbf1280Sopenharmony_ci i = -1; j = asize; /* strictly between i and j */ 456bbbf1280Sopenharmony_ci while (j-i > 1) { 457bbbf1280Sopenharmony_ci int k = (i+j) / 2; 458bbbf1280Sopenharmony_ci int c = strcmp(word, array[k]); 459bbbf1280Sopenharmony_ci if (c > 0) 460bbbf1280Sopenharmony_ci i = k; 461bbbf1280Sopenharmony_ci else if (c < 0) 462bbbf1280Sopenharmony_ci j = k; 463bbbf1280Sopenharmony_ci else /* found it! */ 464bbbf1280Sopenharmony_ci return k; 465bbbf1280Sopenharmony_ci } 466bbbf1280Sopenharmony_ci return -1; /* not found */ 467bbbf1280Sopenharmony_ci} 468bbbf1280Sopenharmony_ci 469bbbf1280Sopenharmony_cistatic test_func* find_testfunc(char *word) { 470bbbf1280Sopenharmony_ci int i, j, asize; 471bbbf1280Sopenharmony_ci 472bbbf1280Sopenharmony_ci asize = sizeof(tfuncs)/sizeof(test_func); 473bbbf1280Sopenharmony_ci 474bbbf1280Sopenharmony_ci i = -1; j = asize; /* strictly between i and j */ 475bbbf1280Sopenharmony_ci while (j-i > 1) { 476bbbf1280Sopenharmony_ci int k = (i+j) / 2; 477bbbf1280Sopenharmony_ci int c = strcmp(word, tfuncs[k].name); 478bbbf1280Sopenharmony_ci if (c > 0) 479bbbf1280Sopenharmony_ci i = k; 480bbbf1280Sopenharmony_ci else if (c < 0) 481bbbf1280Sopenharmony_ci j = k; 482bbbf1280Sopenharmony_ci else /* found it! */ 483bbbf1280Sopenharmony_ci return tfuncs + k; 484bbbf1280Sopenharmony_ci } 485bbbf1280Sopenharmony_ci return NULL; /* not found */ 486bbbf1280Sopenharmony_ci} 487bbbf1280Sopenharmony_ci 488bbbf1280Sopenharmony_cistatic long long calc_error(unsigned a[2], unsigned b[3], int shift, int rettype) { 489bbbf1280Sopenharmony_ci unsigned r0, r1, r2; 490bbbf1280Sopenharmony_ci int sign, carry; 491bbbf1280Sopenharmony_ci long long result; 492bbbf1280Sopenharmony_ci 493bbbf1280Sopenharmony_ci /* 494bbbf1280Sopenharmony_ci * If either number is infinite, require exact equality. If 495bbbf1280Sopenharmony_ci * either number is NaN, require that both are NaN. If either 496bbbf1280Sopenharmony_ci * of these requirements is broken, return INT_MAX. 497bbbf1280Sopenharmony_ci */ 498bbbf1280Sopenharmony_ci if (is_double_rettype(rettype)) { 499bbbf1280Sopenharmony_ci if ((a[0] & 0x7FF00000) == 0x7FF00000 || 500bbbf1280Sopenharmony_ci (b[0] & 0x7FF00000) == 0x7FF00000) { 501bbbf1280Sopenharmony_ci if (((a[0] & 0x800FFFFF) || a[1]) && 502bbbf1280Sopenharmony_ci ((b[0] & 0x800FFFFF) || b[1]) && 503bbbf1280Sopenharmony_ci (a[0] & 0x7FF00000) == 0x7FF00000 && 504bbbf1280Sopenharmony_ci (b[0] & 0x7FF00000) == 0x7FF00000) 505bbbf1280Sopenharmony_ci return 0; /* both NaN - OK */ 506bbbf1280Sopenharmony_ci if (!((a[0] & 0xFFFFF) || a[1]) && 507bbbf1280Sopenharmony_ci !((b[0] & 0xFFFFF) || b[1]) && 508bbbf1280Sopenharmony_ci a[0] == b[0]) 509bbbf1280Sopenharmony_ci return 0; /* both same sign of Inf - OK */ 510bbbf1280Sopenharmony_ci return LLONG_MAX; 511bbbf1280Sopenharmony_ci } 512bbbf1280Sopenharmony_ci } else { 513bbbf1280Sopenharmony_ci if ((a[0] & 0x7F800000) == 0x7F800000 || 514bbbf1280Sopenharmony_ci (b[0] & 0x7F800000) == 0x7F800000) { 515bbbf1280Sopenharmony_ci if ((a[0] & 0x807FFFFF) && 516bbbf1280Sopenharmony_ci (b[0] & 0x807FFFFF) && 517bbbf1280Sopenharmony_ci (a[0] & 0x7F800000) == 0x7F800000 && 518bbbf1280Sopenharmony_ci (b[0] & 0x7F800000) == 0x7F800000) 519bbbf1280Sopenharmony_ci return 0; /* both NaN - OK */ 520bbbf1280Sopenharmony_ci if (!(a[0] & 0x7FFFFF) && 521bbbf1280Sopenharmony_ci !(b[0] & 0x7FFFFF) && 522bbbf1280Sopenharmony_ci a[0] == b[0]) 523bbbf1280Sopenharmony_ci return 0; /* both same sign of Inf - OK */ 524bbbf1280Sopenharmony_ci return LLONG_MAX; 525bbbf1280Sopenharmony_ci } 526bbbf1280Sopenharmony_ci } 527bbbf1280Sopenharmony_ci 528bbbf1280Sopenharmony_ci /* 529bbbf1280Sopenharmony_ci * Both finite. Return INT_MAX if the signs differ. 530bbbf1280Sopenharmony_ci */ 531bbbf1280Sopenharmony_ci if ((a[0] ^ b[0]) & 0x80000000) 532bbbf1280Sopenharmony_ci return LLONG_MAX; 533bbbf1280Sopenharmony_ci 534bbbf1280Sopenharmony_ci /* 535bbbf1280Sopenharmony_ci * Now it's just straight multiple-word subtraction. 536bbbf1280Sopenharmony_ci */ 537bbbf1280Sopenharmony_ci if (is_double_rettype(rettype)) { 538bbbf1280Sopenharmony_ci r2 = -b[2]; carry = (r2 == 0); 539bbbf1280Sopenharmony_ci r1 = a[1] + ~b[1] + carry; carry = (r1 < a[1] || (carry && r1 == a[1])); 540bbbf1280Sopenharmony_ci r0 = a[0] + ~b[0] + carry; 541bbbf1280Sopenharmony_ci } else { 542bbbf1280Sopenharmony_ci r2 = -b[1]; carry = (r2 == 0); 543bbbf1280Sopenharmony_ci r1 = a[0] + ~b[0] + carry; carry = (r1 < a[0] || (carry && r1 == a[0])); 544bbbf1280Sopenharmony_ci r0 = ~0 + carry; 545bbbf1280Sopenharmony_ci } 546bbbf1280Sopenharmony_ci 547bbbf1280Sopenharmony_ci /* 548bbbf1280Sopenharmony_ci * Forgive larger errors in specialised cases. 549bbbf1280Sopenharmony_ci */ 550bbbf1280Sopenharmony_ci if (shift > 0) { 551bbbf1280Sopenharmony_ci if (shift > 32*3) 552bbbf1280Sopenharmony_ci return 0; /* all errors are forgiven! */ 553bbbf1280Sopenharmony_ci while (shift >= 32) { 554bbbf1280Sopenharmony_ci r2 = r1; 555bbbf1280Sopenharmony_ci r1 = r0; 556bbbf1280Sopenharmony_ci r0 = -(r0 >> 31); 557bbbf1280Sopenharmony_ci shift -= 32; 558bbbf1280Sopenharmony_ci } 559bbbf1280Sopenharmony_ci 560bbbf1280Sopenharmony_ci if (shift > 0) { 561bbbf1280Sopenharmony_ci r2 = (r2 >> shift) | (r1 << (32-shift)); 562bbbf1280Sopenharmony_ci r1 = (r1 >> shift) | (r0 << (32-shift)); 563bbbf1280Sopenharmony_ci r0 = (r0 >> shift) | ((-(r0 >> 31)) << (32-shift)); 564bbbf1280Sopenharmony_ci } 565bbbf1280Sopenharmony_ci } 566bbbf1280Sopenharmony_ci 567bbbf1280Sopenharmony_ci if (r0 & 0x80000000) { 568bbbf1280Sopenharmony_ci sign = 1; 569bbbf1280Sopenharmony_ci r2 = ~r2; carry = (r2 == 0); 570bbbf1280Sopenharmony_ci r1 = 0 + ~r1 + carry; carry = (carry && (r2 == 0)); 571bbbf1280Sopenharmony_ci r0 = 0 + ~r0 + carry; 572bbbf1280Sopenharmony_ci } else { 573bbbf1280Sopenharmony_ci sign = 0; 574bbbf1280Sopenharmony_ci } 575bbbf1280Sopenharmony_ci 576bbbf1280Sopenharmony_ci if (r0 >= (1LL<<(31-EXTRABITS))) 577bbbf1280Sopenharmony_ci return LLONG_MAX; /* many ulps out */ 578bbbf1280Sopenharmony_ci 579bbbf1280Sopenharmony_ci result = (r2 >> (32-EXTRABITS)) & (ULPUNIT-1); 580bbbf1280Sopenharmony_ci result |= r1 << EXTRABITS; 581bbbf1280Sopenharmony_ci result |= (long long)r0 << (32+EXTRABITS); 582bbbf1280Sopenharmony_ci if (sign) 583bbbf1280Sopenharmony_ci result = -result; 584bbbf1280Sopenharmony_ci return result; 585bbbf1280Sopenharmony_ci} 586bbbf1280Sopenharmony_ci 587bbbf1280Sopenharmony_ci/* special named operands */ 588bbbf1280Sopenharmony_ci 589bbbf1280Sopenharmony_citypedef struct { 590bbbf1280Sopenharmony_ci unsigned op1, op2; 591bbbf1280Sopenharmony_ci char* name; 592bbbf1280Sopenharmony_ci} special_op; 593bbbf1280Sopenharmony_ci 594bbbf1280Sopenharmony_cistatic special_op special_ops_double[] = { 595bbbf1280Sopenharmony_ci {0x00000000,0x00000000,"0"}, 596bbbf1280Sopenharmony_ci {0x3FF00000,0x00000000,"1"}, 597bbbf1280Sopenharmony_ci {0x7FF00000,0x00000000,"inf"}, 598bbbf1280Sopenharmony_ci {0x7FF80000,0x00000001,"qnan"}, 599bbbf1280Sopenharmony_ci {0x7FF00000,0x00000001,"snan"}, 600bbbf1280Sopenharmony_ci {0x3ff921fb,0x54442d18,"pi2"}, 601bbbf1280Sopenharmony_ci {0x400921fb,0x54442d18,"pi"}, 602bbbf1280Sopenharmony_ci {0x3fe921fb,0x54442d18,"pi4"}, 603bbbf1280Sopenharmony_ci {0x4002d97c,0x7f3321d2,"3pi4"}, 604bbbf1280Sopenharmony_ci}; 605bbbf1280Sopenharmony_ci 606bbbf1280Sopenharmony_cistatic special_op special_ops_float[] = { 607bbbf1280Sopenharmony_ci {0x00000000,0,"0"}, 608bbbf1280Sopenharmony_ci {0x3f800000,0,"1"}, 609bbbf1280Sopenharmony_ci {0x7f800000,0,"inf"}, 610bbbf1280Sopenharmony_ci {0x7fc00000,0,"qnan"}, 611bbbf1280Sopenharmony_ci {0x7f800001,0,"snan"}, 612bbbf1280Sopenharmony_ci {0x3fc90fdb,0,"pi2"}, 613bbbf1280Sopenharmony_ci {0x40490fdb,0,"pi"}, 614bbbf1280Sopenharmony_ci {0x3f490fdb,0,"pi4"}, 615bbbf1280Sopenharmony_ci {0x4016cbe4,0,"3pi4"}, 616bbbf1280Sopenharmony_ci}; 617bbbf1280Sopenharmony_ci 618bbbf1280Sopenharmony_ci/* 619bbbf1280Sopenharmony_ci This is what is returned by the below functions. 620bbbf1280Sopenharmony_ci We need it to handle the sign of the number 621bbbf1280Sopenharmony_ci*/ 622bbbf1280Sopenharmony_cistatic special_op tmp_op = {0,0,0}; 623bbbf1280Sopenharmony_ci 624bbbf1280Sopenharmony_cispecial_op* find_special_op_from_op(unsigned op1, unsigned op2, int is_double) { 625bbbf1280Sopenharmony_ci int i; 626bbbf1280Sopenharmony_ci special_op* sop; 627bbbf1280Sopenharmony_ci if(is_double) { 628bbbf1280Sopenharmony_ci sop = special_ops_double; 629bbbf1280Sopenharmony_ci } else { 630bbbf1280Sopenharmony_ci sop = special_ops_float; 631bbbf1280Sopenharmony_ci } 632bbbf1280Sopenharmony_ci for(i = 0; i < sizeof(special_ops_double)/sizeof(special_op); i++) { 633bbbf1280Sopenharmony_ci if(sop->op1 == (op1&0x7fffffff) && sop->op2 == op2) { 634bbbf1280Sopenharmony_ci if(tmp_op.name) free(tmp_op.name); 635bbbf1280Sopenharmony_ci tmp_op.name = malloc(strlen(sop->name)+2); 636bbbf1280Sopenharmony_ci if(op1>>31) { 637bbbf1280Sopenharmony_ci sprintf(tmp_op.name,"-%s",sop->name); 638bbbf1280Sopenharmony_ci } else { 639bbbf1280Sopenharmony_ci strcpy(tmp_op.name,sop->name); 640bbbf1280Sopenharmony_ci } 641bbbf1280Sopenharmony_ci return &tmp_op; 642bbbf1280Sopenharmony_ci } 643bbbf1280Sopenharmony_ci sop++; 644bbbf1280Sopenharmony_ci } 645bbbf1280Sopenharmony_ci return NULL; 646bbbf1280Sopenharmony_ci} 647bbbf1280Sopenharmony_ci 648bbbf1280Sopenharmony_cispecial_op* find_special_op_from_name(const char* name, int is_double) { 649bbbf1280Sopenharmony_ci int i, neg=0; 650bbbf1280Sopenharmony_ci special_op* sop; 651bbbf1280Sopenharmony_ci if(is_double) { 652bbbf1280Sopenharmony_ci sop = special_ops_double; 653bbbf1280Sopenharmony_ci } else { 654bbbf1280Sopenharmony_ci sop = special_ops_float; 655bbbf1280Sopenharmony_ci } 656bbbf1280Sopenharmony_ci if(*name=='-') { 657bbbf1280Sopenharmony_ci neg=1; 658bbbf1280Sopenharmony_ci name++; 659bbbf1280Sopenharmony_ci } else if(*name=='+') { 660bbbf1280Sopenharmony_ci name++; 661bbbf1280Sopenharmony_ci } 662bbbf1280Sopenharmony_ci for(i = 0; i < sizeof(special_ops_double)/sizeof(special_op); i++) { 663bbbf1280Sopenharmony_ci if(0 == strcmp(name,sop->name)) { 664bbbf1280Sopenharmony_ci tmp_op.op1 = sop->op1; 665bbbf1280Sopenharmony_ci if(neg) { 666bbbf1280Sopenharmony_ci tmp_op.op1 |= 0x80000000; 667bbbf1280Sopenharmony_ci } 668bbbf1280Sopenharmony_ci tmp_op.op2 = sop->op2; 669bbbf1280Sopenharmony_ci return &tmp_op; 670bbbf1280Sopenharmony_ci } 671bbbf1280Sopenharmony_ci sop++; 672bbbf1280Sopenharmony_ci } 673bbbf1280Sopenharmony_ci return NULL; 674bbbf1280Sopenharmony_ci} 675bbbf1280Sopenharmony_ci 676bbbf1280Sopenharmony_ci/* 677bbbf1280Sopenharmony_ci helper function for the below 678bbbf1280Sopenharmony_ci type=0 for single, 1 for double, 2 for no sop 679bbbf1280Sopenharmony_ci*/ 680bbbf1280Sopenharmony_ciint do_op(char* q, unsigned* op, const char* name, int num, int sop_type) { 681bbbf1280Sopenharmony_ci int i; 682bbbf1280Sopenharmony_ci int n=num; 683bbbf1280Sopenharmony_ci special_op* sop = NULL; 684bbbf1280Sopenharmony_ci for(i = 0; i < num; i++) { 685bbbf1280Sopenharmony_ci op[i] = 0; 686bbbf1280Sopenharmony_ci } 687bbbf1280Sopenharmony_ci if(sop_type<2) { 688bbbf1280Sopenharmony_ci sop = find_special_op_from_name(q,sop_type); 689bbbf1280Sopenharmony_ci } 690bbbf1280Sopenharmony_ci if(sop != NULL) { 691bbbf1280Sopenharmony_ci op[0] = sop->op1; 692bbbf1280Sopenharmony_ci op[1] = sop->op2; 693bbbf1280Sopenharmony_ci } else { 694bbbf1280Sopenharmony_ci switch(num) { 695bbbf1280Sopenharmony_ci case 1: n = sscanf(q, "%x", &op[0]); break; 696bbbf1280Sopenharmony_ci case 2: n = sscanf(q, "%x.%x", &op[0], &op[1]); break; 697bbbf1280Sopenharmony_ci case 3: n = sscanf(q, "%x.%x.%x", &op[0], &op[1], &op[2]); break; 698bbbf1280Sopenharmony_ci default: return -1; 699bbbf1280Sopenharmony_ci } 700bbbf1280Sopenharmony_ci } 701bbbf1280Sopenharmony_ci if (verbose) { 702bbbf1280Sopenharmony_ci printf("%s=",name); 703bbbf1280Sopenharmony_ci for (i = 0; (i < n); ++i) printf("%x.", op[i]); 704bbbf1280Sopenharmony_ci printf(" (n=%d)\n", n); 705bbbf1280Sopenharmony_ci } 706bbbf1280Sopenharmony_ci return n; 707bbbf1280Sopenharmony_ci} 708bbbf1280Sopenharmony_ci 709bbbf1280Sopenharmony_citestdetail parsetest(char *testbuf, testdetail oldtest) { 710bbbf1280Sopenharmony_ci char *p; /* Current part of line: Option name */ 711bbbf1280Sopenharmony_ci char *q; /* Current part of line: Option value */ 712bbbf1280Sopenharmony_ci testdetail ret; /* What we return */ 713bbbf1280Sopenharmony_ci int k; /* Function enum from k_* */ 714bbbf1280Sopenharmony_ci int n; /* Used as returns for scanfs */ 715bbbf1280Sopenharmony_ci int argtype=2, rettype=2; /* for do_op */ 716bbbf1280Sopenharmony_ci 717bbbf1280Sopenharmony_ci /* clear ret */ 718bbbf1280Sopenharmony_ci memset(&ret, 0, sizeof(ret)); 719bbbf1280Sopenharmony_ci 720bbbf1280Sopenharmony_ci if (verbose) printf("Parsing line: %s\n", testbuf); 721bbbf1280Sopenharmony_ci while (*testbuf && isspace(*testbuf)) testbuf++; 722bbbf1280Sopenharmony_ci if (testbuf[0] == ';' || testbuf[0] == '#' || testbuf[0] == '!' || 723bbbf1280Sopenharmony_ci testbuf[0] == '>' || testbuf[0] == '\0') { 724bbbf1280Sopenharmony_ci ret.comment = 1; 725bbbf1280Sopenharmony_ci if (verbose) printf("Line is a comment\n"); 726bbbf1280Sopenharmony_ci return ret; 727bbbf1280Sopenharmony_ci } 728bbbf1280Sopenharmony_ci ret.comment = 0; 729bbbf1280Sopenharmony_ci 730bbbf1280Sopenharmony_ci if (*testbuf == '+') { 731bbbf1280Sopenharmony_ci if (oldtest.valid) { 732bbbf1280Sopenharmony_ci ret = oldtest; /* structure copy */ 733bbbf1280Sopenharmony_ci } else { 734bbbf1280Sopenharmony_ci fprintf(stderr, "copy from invalid: ignored\n"); 735bbbf1280Sopenharmony_ci } 736bbbf1280Sopenharmony_ci testbuf++; 737bbbf1280Sopenharmony_ci } 738bbbf1280Sopenharmony_ci 739bbbf1280Sopenharmony_ci ret.random = randomstate; 740bbbf1280Sopenharmony_ci 741bbbf1280Sopenharmony_ci ret.in_err = 0; 742bbbf1280Sopenharmony_ci ret.in_err_limit = e_number_of_errnos; 743bbbf1280Sopenharmony_ci 744bbbf1280Sopenharmony_ci p = strtok(testbuf, " \t"); 745bbbf1280Sopenharmony_ci while (p != NULL) { 746bbbf1280Sopenharmony_ci q = strchr(p, '='); 747bbbf1280Sopenharmony_ci if (!q) 748bbbf1280Sopenharmony_ci goto balderdash; 749bbbf1280Sopenharmony_ci *q++ = '\0'; 750bbbf1280Sopenharmony_ci k = find(p, keywords, sizeof(keywords)); 751bbbf1280Sopenharmony_ci switch (k) { 752bbbf1280Sopenharmony_ci case k_random: 753bbbf1280Sopenharmony_ci randomstate = (!strcmp(q, "on")); 754bbbf1280Sopenharmony_ci ret.comment = 1; 755bbbf1280Sopenharmony_ci return ret; /* otherwise ignore this line */ 756bbbf1280Sopenharmony_ci case k_func: 757bbbf1280Sopenharmony_ci if (verbose) printf("func=%s ", q); 758bbbf1280Sopenharmony_ci //ret.func = find(q, funcs, sizeof(funcs)); 759bbbf1280Sopenharmony_ci ret.func = find_testfunc(q); 760bbbf1280Sopenharmony_ci if (ret.func == NULL) 761bbbf1280Sopenharmony_ci { 762bbbf1280Sopenharmony_ci if (verbose) printf("(id=unknown)\n"); 763bbbf1280Sopenharmony_ci goto balderdash; 764bbbf1280Sopenharmony_ci } 765bbbf1280Sopenharmony_ci if(is_single_argtype(ret.func->argtype)) 766bbbf1280Sopenharmony_ci argtype = 0; 767bbbf1280Sopenharmony_ci else if(is_double_argtype(ret.func->argtype)) 768bbbf1280Sopenharmony_ci argtype = 1; 769bbbf1280Sopenharmony_ci if(is_single_rettype(ret.func->rettype)) 770bbbf1280Sopenharmony_ci rettype = 0; 771bbbf1280Sopenharmony_ci else if(is_double_rettype(ret.func->rettype)) 772bbbf1280Sopenharmony_ci rettype = 1; 773bbbf1280Sopenharmony_ci //ret.size = sizes[ret.func]; 774bbbf1280Sopenharmony_ci if (verbose) printf("(name=%s) (size=%d)\n", ret.func->name, ret.func->argtype); 775bbbf1280Sopenharmony_ci break; 776bbbf1280Sopenharmony_ci case k_op1: 777bbbf1280Sopenharmony_ci case k_op1r: 778bbbf1280Sopenharmony_ci n = do_op(q,ret.op1r,"op1r",2,argtype); 779bbbf1280Sopenharmony_ci if (n < 1) 780bbbf1280Sopenharmony_ci goto balderdash; 781bbbf1280Sopenharmony_ci break; 782bbbf1280Sopenharmony_ci case k_op1i: 783bbbf1280Sopenharmony_ci n = do_op(q,ret.op1i,"op1i",2,argtype); 784bbbf1280Sopenharmony_ci if (n < 1) 785bbbf1280Sopenharmony_ci goto balderdash; 786bbbf1280Sopenharmony_ci break; 787bbbf1280Sopenharmony_ci case k_op2: 788bbbf1280Sopenharmony_ci case k_op2r: 789bbbf1280Sopenharmony_ci n = do_op(q,ret.op2r,"op2r",2,argtype); 790bbbf1280Sopenharmony_ci if (n < 1) 791bbbf1280Sopenharmony_ci goto balderdash; 792bbbf1280Sopenharmony_ci break; 793bbbf1280Sopenharmony_ci case k_op2i: 794bbbf1280Sopenharmony_ci n = do_op(q,ret.op2i,"op2i",2,argtype); 795bbbf1280Sopenharmony_ci if (n < 1) 796bbbf1280Sopenharmony_ci goto balderdash; 797bbbf1280Sopenharmony_ci break; 798bbbf1280Sopenharmony_ci case k_resultc: 799bbbf1280Sopenharmony_ci puts(q); 800bbbf1280Sopenharmony_ci if(strncmp(q,"inf",3)==0) { 801bbbf1280Sopenharmony_ci ret.resultc = rc_infinity; 802bbbf1280Sopenharmony_ci } else if(strcmp(q,"zero")==0) { 803bbbf1280Sopenharmony_ci ret.resultc = rc_zero; 804bbbf1280Sopenharmony_ci } else if(strcmp(q,"nan")==0) { 805bbbf1280Sopenharmony_ci ret.resultc = rc_nan; 806bbbf1280Sopenharmony_ci } else if(strcmp(q,"finite")==0) { 807bbbf1280Sopenharmony_ci ret.resultc = rc_finite; 808bbbf1280Sopenharmony_ci } else { 809bbbf1280Sopenharmony_ci goto balderdash; 810bbbf1280Sopenharmony_ci } 811bbbf1280Sopenharmony_ci break; 812bbbf1280Sopenharmony_ci case k_result: 813bbbf1280Sopenharmony_ci case k_resultr: 814bbbf1280Sopenharmony_ci n = (do_op)(q,ret.resultr,"resultr",3,rettype); 815bbbf1280Sopenharmony_ci if (n < 1) 816bbbf1280Sopenharmony_ci goto balderdash; 817bbbf1280Sopenharmony_ci ret.nresult = n; /* assume real and imaginary have same no. words */ 818bbbf1280Sopenharmony_ci break; 819bbbf1280Sopenharmony_ci case k_resulti: 820bbbf1280Sopenharmony_ci n = do_op(q,ret.resulti,"resulti",3,rettype); 821bbbf1280Sopenharmony_ci if (n < 1) 822bbbf1280Sopenharmony_ci goto balderdash; 823bbbf1280Sopenharmony_ci break; 824bbbf1280Sopenharmony_ci case k_res2: 825bbbf1280Sopenharmony_ci n = do_op(q,ret.res2,"res2",2,rettype); 826bbbf1280Sopenharmony_ci if (n < 1) 827bbbf1280Sopenharmony_ci goto balderdash; 828bbbf1280Sopenharmony_ci break; 829bbbf1280Sopenharmony_ci case k_status: 830bbbf1280Sopenharmony_ci while (*q) { 831bbbf1280Sopenharmony_ci if (*q == 'i') ret.status |= FE_INVALID; 832bbbf1280Sopenharmony_ci if (*q == 'z') ret.status |= FE_DIVBYZERO; 833bbbf1280Sopenharmony_ci if (*q == 'o') ret.status |= FE_OVERFLOW; 834bbbf1280Sopenharmony_ci if (*q == 'u') ret.status |= FE_UNDERFLOW; 835bbbf1280Sopenharmony_ci q++; 836bbbf1280Sopenharmony_ci } 837bbbf1280Sopenharmony_ci break; 838bbbf1280Sopenharmony_ci case k_maybeerror: 839bbbf1280Sopenharmony_ci n = find(q, errors, sizeof(errors)); 840bbbf1280Sopenharmony_ci if (n < 0) 841bbbf1280Sopenharmony_ci goto balderdash; 842bbbf1280Sopenharmony_ci if(math_errhandling&MATH_ERREXCEPT) { 843bbbf1280Sopenharmony_ci switch(n) { 844bbbf1280Sopenharmony_ci case e_domain: ret.maybestatus |= FE_INVALID; break; 845bbbf1280Sopenharmony_ci case e_divbyzero: ret.maybestatus |= FE_DIVBYZERO; break; 846bbbf1280Sopenharmony_ci case e_overflow: ret.maybestatus |= FE_OVERFLOW; break; 847bbbf1280Sopenharmony_ci case e_underflow: ret.maybestatus |= FE_UNDERFLOW; break; 848bbbf1280Sopenharmony_ci } 849bbbf1280Sopenharmony_ci } 850bbbf1280Sopenharmony_ci { 851bbbf1280Sopenharmony_ci switch(n) { 852bbbf1280Sopenharmony_ci case e_domain: 853bbbf1280Sopenharmony_ci ret.maybeerr = e_EDOM; break; 854bbbf1280Sopenharmony_ci case e_divbyzero: 855bbbf1280Sopenharmony_ci case e_overflow: 856bbbf1280Sopenharmony_ci case e_underflow: 857bbbf1280Sopenharmony_ci ret.maybeerr = e_ERANGE; break; 858bbbf1280Sopenharmony_ci } 859bbbf1280Sopenharmony_ci } 860bbbf1280Sopenharmony_ci case k_maybestatus: 861bbbf1280Sopenharmony_ci while (*q) { 862bbbf1280Sopenharmony_ci if (*q == 'i') ret.maybestatus |= FE_INVALID; 863bbbf1280Sopenharmony_ci if (*q == 'z') ret.maybestatus |= FE_DIVBYZERO; 864bbbf1280Sopenharmony_ci if (*q == 'o') ret.maybestatus |= FE_OVERFLOW; 865bbbf1280Sopenharmony_ci if (*q == 'u') ret.maybestatus |= FE_UNDERFLOW; 866bbbf1280Sopenharmony_ci q++; 867bbbf1280Sopenharmony_ci } 868bbbf1280Sopenharmony_ci break; 869bbbf1280Sopenharmony_ci case k_error: 870bbbf1280Sopenharmony_ci n = find(q, errors, sizeof(errors)); 871bbbf1280Sopenharmony_ci if (n < 0) 872bbbf1280Sopenharmony_ci goto balderdash; 873bbbf1280Sopenharmony_ci if(math_errhandling&MATH_ERREXCEPT) { 874bbbf1280Sopenharmony_ci switch(n) { 875bbbf1280Sopenharmony_ci case e_domain: ret.status |= FE_INVALID; break; 876bbbf1280Sopenharmony_ci case e_divbyzero: ret.status |= FE_DIVBYZERO; break; 877bbbf1280Sopenharmony_ci case e_overflow: ret.status |= FE_OVERFLOW; break; 878bbbf1280Sopenharmony_ci case e_underflow: ret.status |= FE_UNDERFLOW; break; 879bbbf1280Sopenharmony_ci } 880bbbf1280Sopenharmony_ci } 881bbbf1280Sopenharmony_ci if(math_errhandling&MATH_ERRNO) { 882bbbf1280Sopenharmony_ci switch(n) { 883bbbf1280Sopenharmony_ci case e_domain: 884bbbf1280Sopenharmony_ci ret.err = e_EDOM; break; 885bbbf1280Sopenharmony_ci case e_divbyzero: 886bbbf1280Sopenharmony_ci case e_overflow: 887bbbf1280Sopenharmony_ci case e_underflow: 888bbbf1280Sopenharmony_ci ret.err = e_ERANGE; break; 889bbbf1280Sopenharmony_ci } 890bbbf1280Sopenharmony_ci } 891bbbf1280Sopenharmony_ci if(!(math_errhandling&MATH_ERRNO)) { 892bbbf1280Sopenharmony_ci switch(n) { 893bbbf1280Sopenharmony_ci case e_domain: 894bbbf1280Sopenharmony_ci ret.maybeerr = e_EDOM; break; 895bbbf1280Sopenharmony_ci case e_divbyzero: 896bbbf1280Sopenharmony_ci case e_overflow: 897bbbf1280Sopenharmony_ci case e_underflow: 898bbbf1280Sopenharmony_ci ret.maybeerr = e_ERANGE; break; 899bbbf1280Sopenharmony_ci } 900bbbf1280Sopenharmony_ci } 901bbbf1280Sopenharmony_ci break; 902bbbf1280Sopenharmony_ci case k_errno: 903bbbf1280Sopenharmony_ci ret.err = find(q, errnos, sizeof(errnos)); 904bbbf1280Sopenharmony_ci if (ret.err < 0) 905bbbf1280Sopenharmony_ci goto balderdash; 906bbbf1280Sopenharmony_ci break; 907bbbf1280Sopenharmony_ci case k_errno_in: 908bbbf1280Sopenharmony_ci ret.in_err = find(q, errnos, sizeof(errnos)); 909bbbf1280Sopenharmony_ci if (ret.err < 0) 910bbbf1280Sopenharmony_ci goto balderdash; 911bbbf1280Sopenharmony_ci ret.in_err_limit = ret.in_err + 1; 912bbbf1280Sopenharmony_ci break; 913bbbf1280Sopenharmony_ci case k_wrongresult: 914bbbf1280Sopenharmony_ci case k_wrongstatus: 915bbbf1280Sopenharmony_ci case k_wrongres2: 916bbbf1280Sopenharmony_ci case k_wrongerrno: 917bbbf1280Sopenharmony_ci /* quietly ignore these keys */ 918bbbf1280Sopenharmony_ci break; 919bbbf1280Sopenharmony_ci default: 920bbbf1280Sopenharmony_ci goto balderdash; 921bbbf1280Sopenharmony_ci } 922bbbf1280Sopenharmony_ci p = strtok(NULL, " \t"); 923bbbf1280Sopenharmony_ci } 924bbbf1280Sopenharmony_ci ret.valid = 1; 925bbbf1280Sopenharmony_ci return ret; 926bbbf1280Sopenharmony_ci 927bbbf1280Sopenharmony_ci /* come here from almost any error */ 928bbbf1280Sopenharmony_ci balderdash: 929bbbf1280Sopenharmony_ci ret.valid = 0; 930bbbf1280Sopenharmony_ci return ret; 931bbbf1280Sopenharmony_ci} 932bbbf1280Sopenharmony_ci 933bbbf1280Sopenharmony_citypedef enum { 934bbbf1280Sopenharmony_ci test_comment, /* deliberately not a test */ 935bbbf1280Sopenharmony_ci test_invalid, /* accidentally not a test */ 936bbbf1280Sopenharmony_ci test_decline, /* was a test, and wasn't run */ 937bbbf1280Sopenharmony_ci test_fail, /* was a test, and failed */ 938bbbf1280Sopenharmony_ci test_pass /* was a test, and passed */ 939bbbf1280Sopenharmony_ci} testresult; 940bbbf1280Sopenharmony_ci 941bbbf1280Sopenharmony_cichar failtext[512]; 942bbbf1280Sopenharmony_ci 943bbbf1280Sopenharmony_citypedef union { 944bbbf1280Sopenharmony_ci unsigned i[2]; 945bbbf1280Sopenharmony_ci double f; 946bbbf1280Sopenharmony_ci double da[2]; 947bbbf1280Sopenharmony_ci} dbl; 948bbbf1280Sopenharmony_ci 949bbbf1280Sopenharmony_citypedef union { 950bbbf1280Sopenharmony_ci unsigned i; 951bbbf1280Sopenharmony_ci float f; 952bbbf1280Sopenharmony_ci float da[2]; 953bbbf1280Sopenharmony_ci} sgl; 954bbbf1280Sopenharmony_ci 955bbbf1280Sopenharmony_ci/* helper function for runtest */ 956bbbf1280Sopenharmony_civoid print_error(int rettype, unsigned *result, char* text, char** failp) { 957bbbf1280Sopenharmony_ci special_op *sop; 958bbbf1280Sopenharmony_ci char *str; 959bbbf1280Sopenharmony_ci 960bbbf1280Sopenharmony_ci if(result) { 961bbbf1280Sopenharmony_ci *failp += sprintf(*failp," %s=",text); 962bbbf1280Sopenharmony_ci sop = find_special_op_from_op(result[0],result[1],is_double_rettype(rettype)); 963bbbf1280Sopenharmony_ci if(sop) { 964bbbf1280Sopenharmony_ci *failp += sprintf(*failp,"%s",sop->name); 965bbbf1280Sopenharmony_ci } else { 966bbbf1280Sopenharmony_ci if(is_double_rettype(rettype)) { 967bbbf1280Sopenharmony_ci str="%08x.%08x"; 968bbbf1280Sopenharmony_ci } else { 969bbbf1280Sopenharmony_ci str="%08x"; 970bbbf1280Sopenharmony_ci } 971bbbf1280Sopenharmony_ci *failp += sprintf(*failp,str,result[0],result[1]); 972bbbf1280Sopenharmony_ci } 973bbbf1280Sopenharmony_ci } 974bbbf1280Sopenharmony_ci} 975bbbf1280Sopenharmony_ci 976bbbf1280Sopenharmony_ci 977bbbf1280Sopenharmony_civoid print_ulps_helper(const char *name, long long ulps, char** failp) { 978bbbf1280Sopenharmony_ci if(ulps == LLONG_MAX) { 979bbbf1280Sopenharmony_ci *failp += sprintf(*failp, " %s=HUGE", name); 980bbbf1280Sopenharmony_ci } else { 981bbbf1280Sopenharmony_ci *failp += sprintf(*failp, " %s=%.3f", name, (double)ulps / ULPUNIT); 982bbbf1280Sopenharmony_ci } 983bbbf1280Sopenharmony_ci} 984bbbf1280Sopenharmony_ci 985bbbf1280Sopenharmony_ci/* for complex args make ulpsr or ulpsri = 0 to not print */ 986bbbf1280Sopenharmony_civoid print_ulps(int rettype, long long ulpsr, long long ulpsi, char** failp) { 987bbbf1280Sopenharmony_ci if(is_complex_rettype(rettype)) { 988bbbf1280Sopenharmony_ci if (ulpsr) print_ulps_helper("ulpsr",ulpsr,failp); 989bbbf1280Sopenharmony_ci if (ulpsi) print_ulps_helper("ulpsi",ulpsi,failp); 990bbbf1280Sopenharmony_ci } else { 991bbbf1280Sopenharmony_ci if (ulpsr) print_ulps_helper("ulps",ulpsr,failp); 992bbbf1280Sopenharmony_ci } 993bbbf1280Sopenharmony_ci} 994bbbf1280Sopenharmony_ci 995bbbf1280Sopenharmony_ciint runtest(testdetail t) { 996bbbf1280Sopenharmony_ci int err, status; 997bbbf1280Sopenharmony_ci 998bbbf1280Sopenharmony_ci dbl d_arg1, d_arg2, d_res, d_res2; 999bbbf1280Sopenharmony_ci sgl s_arg1, s_arg2, s_res, s_res2; 1000bbbf1280Sopenharmony_ci 1001bbbf1280Sopenharmony_ci int deferred_decline = FALSE; 1002bbbf1280Sopenharmony_ci char *failp = failtext; 1003bbbf1280Sopenharmony_ci 1004bbbf1280Sopenharmony_ci unsigned int intres=0; 1005bbbf1280Sopenharmony_ci 1006bbbf1280Sopenharmony_ci int res2_adjust = 0; 1007bbbf1280Sopenharmony_ci 1008bbbf1280Sopenharmony_ci if (t.comment) 1009bbbf1280Sopenharmony_ci return test_comment; 1010bbbf1280Sopenharmony_ci if (!t.valid) 1011bbbf1280Sopenharmony_ci return test_invalid; 1012bbbf1280Sopenharmony_ci 1013bbbf1280Sopenharmony_ci /* Set IEEE status to mathlib-normal */ 1014bbbf1280Sopenharmony_ci feclearexcept(FE_ALL_EXCEPT); 1015bbbf1280Sopenharmony_ci 1016bbbf1280Sopenharmony_ci /* Deal with operands */ 1017bbbf1280Sopenharmony_ci#define DO_DOP(arg,op) arg.i[dmsd] = t.op[0]; arg.i[dlsd] = t.op[1] 1018bbbf1280Sopenharmony_ci DO_DOP(d_arg1,op1r); 1019bbbf1280Sopenharmony_ci DO_DOP(d_arg2,op2r); 1020bbbf1280Sopenharmony_ci s_arg1.i = t.op1r[0]; s_arg2.i = t.op2r[0]; 1021bbbf1280Sopenharmony_ci 1022bbbf1280Sopenharmony_ci /* 1023bbbf1280Sopenharmony_ci * Detect NaNs, infinities and denormals on input, and set a 1024bbbf1280Sopenharmony_ci * deferred decline flag if we're in FO mode. 1025bbbf1280Sopenharmony_ci * 1026bbbf1280Sopenharmony_ci * (We defer the decline rather than doing it immediately 1027bbbf1280Sopenharmony_ci * because even in FO mode the operation is not permitted to 1028bbbf1280Sopenharmony_ci * crash or tight-loop; so we _run_ the test, and then ignore 1029bbbf1280Sopenharmony_ci * all the results.) 1030bbbf1280Sopenharmony_ci */ 1031bbbf1280Sopenharmony_ci if (fo) { 1032bbbf1280Sopenharmony_ci if (is_double_argtype(t.func->argtype) && is_dhard(t.op1r)) 1033bbbf1280Sopenharmony_ci deferred_decline = TRUE; 1034bbbf1280Sopenharmony_ci if (t.func->argtype==at_d2 && is_dhard(t.op2r)) 1035bbbf1280Sopenharmony_ci deferred_decline = TRUE; 1036bbbf1280Sopenharmony_ci if (is_single_argtype(t.func->argtype) && is_shard(t.op1r)) 1037bbbf1280Sopenharmony_ci deferred_decline = TRUE; 1038bbbf1280Sopenharmony_ci if (t.func->argtype==at_s2 && is_shard(t.op2r)) 1039bbbf1280Sopenharmony_ci deferred_decline = TRUE; 1040bbbf1280Sopenharmony_ci if (is_double_rettype(t.func->rettype) && is_dhard(t.resultr)) 1041bbbf1280Sopenharmony_ci deferred_decline = TRUE; 1042bbbf1280Sopenharmony_ci if (t.func->rettype==rt_d2 && is_dhard(t.res2)) 1043bbbf1280Sopenharmony_ci deferred_decline = TRUE; 1044bbbf1280Sopenharmony_ci if (is_single_argtype(t.func->rettype) && is_shard(t.resultr)) 1045bbbf1280Sopenharmony_ci deferred_decline = TRUE; 1046bbbf1280Sopenharmony_ci if (t.func->rettype==rt_s2 && is_shard(t.res2)) 1047bbbf1280Sopenharmony_ci deferred_decline = TRUE; 1048bbbf1280Sopenharmony_ci if (t.err == e_ERANGE) 1049bbbf1280Sopenharmony_ci deferred_decline = TRUE; 1050bbbf1280Sopenharmony_ci } 1051bbbf1280Sopenharmony_ci 1052bbbf1280Sopenharmony_ci /* 1053bbbf1280Sopenharmony_ci * Perform the operation 1054bbbf1280Sopenharmony_ci */ 1055bbbf1280Sopenharmony_ci 1056bbbf1280Sopenharmony_ci errno = t.in_err == e_EDOM ? EDOM : t.in_err == e_ERANGE ? ERANGE : 0; 1057bbbf1280Sopenharmony_ci if (t.err == e_0) 1058bbbf1280Sopenharmony_ci t.err = t.in_err; 1059bbbf1280Sopenharmony_ci if (t.maybeerr == e_0) 1060bbbf1280Sopenharmony_ci t.maybeerr = t.in_err; 1061bbbf1280Sopenharmony_ci 1062bbbf1280Sopenharmony_ci if(t.func->type == t_func) { 1063bbbf1280Sopenharmony_ci switch(t.func->argtype) { 1064bbbf1280Sopenharmony_ci case at_d: d_res.f = t.func->func.d_d_ptr(d_arg1.f); break; 1065bbbf1280Sopenharmony_ci case at_s: s_res.f = t.func->func.s_s_ptr(s_arg1.f); break; 1066bbbf1280Sopenharmony_ci case at_d2: d_res.f = t.func->func.d2_d_ptr(d_arg1.f, d_arg2.f); break; 1067bbbf1280Sopenharmony_ci case at_s2: s_res.f = t.func->func.s2_s_ptr(s_arg1.f, s_arg2.f); break; 1068bbbf1280Sopenharmony_ci case at_di: d_res.f = t.func->func.di_d_ptr(d_arg1.f, d_arg2.i[dmsd]); break; 1069bbbf1280Sopenharmony_ci case at_si: s_res.f = t.func->func.si_s_ptr(s_arg1.f, s_arg2.i); break; 1070bbbf1280Sopenharmony_ci case at_dip: d_res.f = t.func->func.dip_d_ptr(d_arg1.f, (int*)&intres); break; 1071bbbf1280Sopenharmony_ci case at_sip: s_res.f = t.func->func.sip_s_ptr(s_arg1.f, (int*)&intres); break; 1072bbbf1280Sopenharmony_ci case at_ddp: d_res.f = t.func->func.ddp_d_ptr(d_arg1.f, &d_res2.f); break; 1073bbbf1280Sopenharmony_ci case at_ssp: s_res.f = t.func->func.ssp_s_ptr(s_arg1.f, &s_res2.f); break; 1074bbbf1280Sopenharmony_ci default: 1075bbbf1280Sopenharmony_ci printf("unhandled function: %s\n",t.func->name); 1076bbbf1280Sopenharmony_ci return test_fail; 1077bbbf1280Sopenharmony_ci } 1078bbbf1280Sopenharmony_ci } else { 1079bbbf1280Sopenharmony_ci /* printf("macro: name=%s, num=%i, s1.i=0x%08x s1.f=%f\n",t.func->name, t.func->macro_name, s_arg1.i, (double)s_arg1.f); */ 1080bbbf1280Sopenharmony_ci switch(t.func->macro_name) { 1081bbbf1280Sopenharmony_ci case m_isfinite: intres = isfinite(d_arg1.f); break; 1082bbbf1280Sopenharmony_ci case m_isinf: intres = isinf(d_arg1.f); break; 1083bbbf1280Sopenharmony_ci case m_isnan: intres = isnan(d_arg1.f); break; 1084bbbf1280Sopenharmony_ci case m_isnormal: intres = isnormal(d_arg1.f); break; 1085bbbf1280Sopenharmony_ci case m_signbit: intres = signbit(d_arg1.f); break; 1086bbbf1280Sopenharmony_ci case m_fpclassify: intres = fpclassify(d_arg1.f); break; 1087bbbf1280Sopenharmony_ci case m_isgreater: intres = isgreater(d_arg1.f, d_arg2.f); break; 1088bbbf1280Sopenharmony_ci case m_isgreaterequal: intres = isgreaterequal(d_arg1.f, d_arg2.f); break; 1089bbbf1280Sopenharmony_ci case m_isless: intres = isless(d_arg1.f, d_arg2.f); break; 1090bbbf1280Sopenharmony_ci case m_islessequal: intres = islessequal(d_arg1.f, d_arg2.f); break; 1091bbbf1280Sopenharmony_ci case m_islessgreater: intres = islessgreater(d_arg1.f, d_arg2.f); break; 1092bbbf1280Sopenharmony_ci case m_isunordered: intres = isunordered(d_arg1.f, d_arg2.f); break; 1093bbbf1280Sopenharmony_ci 1094bbbf1280Sopenharmony_ci case m_isfinitef: intres = isfinite(s_arg1.f); break; 1095bbbf1280Sopenharmony_ci case m_isinff: intres = isinf(s_arg1.f); break; 1096bbbf1280Sopenharmony_ci case m_isnanf: intres = isnan(s_arg1.f); break; 1097bbbf1280Sopenharmony_ci case m_isnormalf: intres = isnormal(s_arg1.f); break; 1098bbbf1280Sopenharmony_ci case m_signbitf: intres = signbit(s_arg1.f); break; 1099bbbf1280Sopenharmony_ci case m_fpclassifyf: intres = fpclassify(s_arg1.f); break; 1100bbbf1280Sopenharmony_ci case m_isgreaterf: intres = isgreater(s_arg1.f, s_arg2.f); break; 1101bbbf1280Sopenharmony_ci case m_isgreaterequalf: intres = isgreaterequal(s_arg1.f, s_arg2.f); break; 1102bbbf1280Sopenharmony_ci case m_islessf: intres = isless(s_arg1.f, s_arg2.f); break; 1103bbbf1280Sopenharmony_ci case m_islessequalf: intres = islessequal(s_arg1.f, s_arg2.f); break; 1104bbbf1280Sopenharmony_ci case m_islessgreaterf: intres = islessgreater(s_arg1.f, s_arg2.f); break; 1105bbbf1280Sopenharmony_ci case m_isunorderedf: intres = isunordered(s_arg1.f, s_arg2.f); break; 1106bbbf1280Sopenharmony_ci 1107bbbf1280Sopenharmony_ci default: 1108bbbf1280Sopenharmony_ci printf("unhandled macro: %s\n",t.func->name); 1109bbbf1280Sopenharmony_ci return test_fail; 1110bbbf1280Sopenharmony_ci } 1111bbbf1280Sopenharmony_ci } 1112bbbf1280Sopenharmony_ci 1113bbbf1280Sopenharmony_ci /* 1114bbbf1280Sopenharmony_ci * Decline the test if the deferred decline flag was set above. 1115bbbf1280Sopenharmony_ci */ 1116bbbf1280Sopenharmony_ci if (deferred_decline) 1117bbbf1280Sopenharmony_ci return test_decline; 1118bbbf1280Sopenharmony_ci 1119bbbf1280Sopenharmony_ci /* printf("intres=%i\n",intres); */ 1120bbbf1280Sopenharmony_ci 1121bbbf1280Sopenharmony_ci /* Clear the fail text (indicating a pass unless we change it) */ 1122bbbf1280Sopenharmony_ci failp[0] = '\0'; 1123bbbf1280Sopenharmony_ci 1124bbbf1280Sopenharmony_ci /* Check the IEEE status bits (except INX, which we disregard). 1125bbbf1280Sopenharmony_ci * We don't bother with this for complex numbers, because the 1126bbbf1280Sopenharmony_ci * complex functions are hard to get exactly right and we don't 1127bbbf1280Sopenharmony_ci * have to anyway (C99 annex G is only informative). */ 1128bbbf1280Sopenharmony_ci if (!(is_complex_argtype(t.func->argtype) || is_complex_rettype(t.func->rettype))) { 1129bbbf1280Sopenharmony_ci status = fetestexcept(FE_INVALID|FE_DIVBYZERO|FE_OVERFLOW|FE_UNDERFLOW); 1130bbbf1280Sopenharmony_ci if ((status|t.maybestatus|~statusmask) != (t.status|t.maybestatus|~statusmask)) { 1131bbbf1280Sopenharmony_ci if (quiet) failtext[0]='x'; 1132bbbf1280Sopenharmony_ci else { 1133bbbf1280Sopenharmony_ci failp += sprintf(failp, 1134bbbf1280Sopenharmony_ci " wrongstatus=%s%s%s%s%s", 1135bbbf1280Sopenharmony_ci (status & FE_INVALID ? "i" : ""), 1136bbbf1280Sopenharmony_ci (status & FE_DIVBYZERO ? "z" : ""), 1137bbbf1280Sopenharmony_ci (status & FE_OVERFLOW ? "o" : ""), 1138bbbf1280Sopenharmony_ci (status & FE_UNDERFLOW ? "u" : ""), 1139bbbf1280Sopenharmony_ci (status ? "" : "OK")); 1140bbbf1280Sopenharmony_ci } 1141bbbf1280Sopenharmony_ci } 1142bbbf1280Sopenharmony_ci } 1143bbbf1280Sopenharmony_ci 1144bbbf1280Sopenharmony_ci /* Check the result */ 1145bbbf1280Sopenharmony_ci { 1146bbbf1280Sopenharmony_ci unsigned resultr[2], resulti[2]; 1147bbbf1280Sopenharmony_ci unsigned tresultr[3], tresulti[3], wres; 1148bbbf1280Sopenharmony_ci 1149bbbf1280Sopenharmony_ci switch(t.func->rettype) { 1150bbbf1280Sopenharmony_ci case rt_d: 1151bbbf1280Sopenharmony_ci case rt_d2: 1152bbbf1280Sopenharmony_ci tresultr[0] = t.resultr[0]; 1153bbbf1280Sopenharmony_ci tresultr[1] = t.resultr[1]; 1154bbbf1280Sopenharmony_ci resultr[0] = d_res.i[dmsd]; resultr[1] = d_res.i[dlsd]; 1155bbbf1280Sopenharmony_ci wres = 2; 1156bbbf1280Sopenharmony_ci break; 1157bbbf1280Sopenharmony_ci case rt_i: 1158bbbf1280Sopenharmony_ci tresultr[0] = t.resultr[0]; 1159bbbf1280Sopenharmony_ci resultr[0] = intres; 1160bbbf1280Sopenharmony_ci wres = 1; 1161bbbf1280Sopenharmony_ci break; 1162bbbf1280Sopenharmony_ci case rt_s: 1163bbbf1280Sopenharmony_ci case rt_s2: 1164bbbf1280Sopenharmony_ci tresultr[0] = t.resultr[0]; 1165bbbf1280Sopenharmony_ci resultr[0] = s_res.i; 1166bbbf1280Sopenharmony_ci wres = 1; 1167bbbf1280Sopenharmony_ci break; 1168bbbf1280Sopenharmony_ci default: 1169bbbf1280Sopenharmony_ci puts("unhandled rettype in runtest"); 1170bbbf1280Sopenharmony_ci wres = 0; 1171bbbf1280Sopenharmony_ci } 1172bbbf1280Sopenharmony_ci if(t.resultc != rc_none) { 1173bbbf1280Sopenharmony_ci int err = 0; 1174bbbf1280Sopenharmony_ci switch(t.resultc) { 1175bbbf1280Sopenharmony_ci case rc_zero: 1176bbbf1280Sopenharmony_ci if(resultr[0] != 0 || resulti[0] != 0 || 1177bbbf1280Sopenharmony_ci (wres==2 && (resultr[1] != 0 || resulti[1] != 0))) { 1178bbbf1280Sopenharmony_ci err = 1; 1179bbbf1280Sopenharmony_ci } 1180bbbf1280Sopenharmony_ci break; 1181bbbf1280Sopenharmony_ci case rc_infinity: 1182bbbf1280Sopenharmony_ci if(wres==1) { 1183bbbf1280Sopenharmony_ci if(!((resultr[0]&0x7fffffff)==0x7f800000 || 1184bbbf1280Sopenharmony_ci (resulti[0]&0x7fffffff)==0x7f800000)) { 1185bbbf1280Sopenharmony_ci err = 1; 1186bbbf1280Sopenharmony_ci } 1187bbbf1280Sopenharmony_ci } else { 1188bbbf1280Sopenharmony_ci if(!(((resultr[0]&0x7fffffff)==0x7ff00000 && resultr[1]==0) || 1189bbbf1280Sopenharmony_ci ((resulti[0]&0x7fffffff)==0x7ff00000 && resulti[1]==0))) { 1190bbbf1280Sopenharmony_ci err = 1; 1191bbbf1280Sopenharmony_ci } 1192bbbf1280Sopenharmony_ci } 1193bbbf1280Sopenharmony_ci break; 1194bbbf1280Sopenharmony_ci case rc_nan: 1195bbbf1280Sopenharmony_ci if(wres==1) { 1196bbbf1280Sopenharmony_ci if(!((resultr[0]&0x7fffffff)>0x7f800000 || 1197bbbf1280Sopenharmony_ci (resulti[0]&0x7fffffff)>0x7f800000)) { 1198bbbf1280Sopenharmony_ci err = 1; 1199bbbf1280Sopenharmony_ci } 1200bbbf1280Sopenharmony_ci } else { 1201bbbf1280Sopenharmony_ci canon_dNaN(resultr); 1202bbbf1280Sopenharmony_ci canon_dNaN(resulti); 1203bbbf1280Sopenharmony_ci if(!(((resultr[0]&0x7fffffff)>0x7ff00000 && resultr[1]==1) || 1204bbbf1280Sopenharmony_ci ((resulti[0]&0x7fffffff)>0x7ff00000 && resulti[1]==1))) { 1205bbbf1280Sopenharmony_ci err = 1; 1206bbbf1280Sopenharmony_ci } 1207bbbf1280Sopenharmony_ci } 1208bbbf1280Sopenharmony_ci break; 1209bbbf1280Sopenharmony_ci case rc_finite: 1210bbbf1280Sopenharmony_ci if(wres==1) { 1211bbbf1280Sopenharmony_ci if(!((resultr[0]&0x7fffffff)<0x7f800000 || 1212bbbf1280Sopenharmony_ci (resulti[0]&0x7fffffff)<0x7f800000)) { 1213bbbf1280Sopenharmony_ci err = 1; 1214bbbf1280Sopenharmony_ci } 1215bbbf1280Sopenharmony_ci } else { 1216bbbf1280Sopenharmony_ci if(!((resultr[0]&0x7fffffff)<0x7ff00000 || 1217bbbf1280Sopenharmony_ci (resulti[0]&0x7fffffff)<0x7ff00000)) { 1218bbbf1280Sopenharmony_ci err = 1; 1219bbbf1280Sopenharmony_ci } 1220bbbf1280Sopenharmony_ci } 1221bbbf1280Sopenharmony_ci break; 1222bbbf1280Sopenharmony_ci default: 1223bbbf1280Sopenharmony_ci break; 1224bbbf1280Sopenharmony_ci } 1225bbbf1280Sopenharmony_ci if(err) { 1226bbbf1280Sopenharmony_ci print_error(t.func->rettype,resultr,"wrongresultr",&failp); 1227bbbf1280Sopenharmony_ci print_error(t.func->rettype,resulti,"wrongresulti",&failp); 1228bbbf1280Sopenharmony_ci } 1229bbbf1280Sopenharmony_ci } else if (t.nresult > wres) { 1230bbbf1280Sopenharmony_ci /* 1231bbbf1280Sopenharmony_ci * The test case data has provided the result to more 1232bbbf1280Sopenharmony_ci * than double precision. Instead of testing exact 1233bbbf1280Sopenharmony_ci * equality, we test against our maximum error 1234bbbf1280Sopenharmony_ci * tolerance. 1235bbbf1280Sopenharmony_ci */ 1236bbbf1280Sopenharmony_ci int rshift, ishift; 1237bbbf1280Sopenharmony_ci long long ulpsr, ulpsi, ulptolerance; 1238bbbf1280Sopenharmony_ci 1239bbbf1280Sopenharmony_ci tresultr[wres] = t.resultr[wres] << (32-EXTRABITS); 1240bbbf1280Sopenharmony_ci tresulti[wres] = t.resulti[wres] << (32-EXTRABITS); 1241bbbf1280Sopenharmony_ci if(strict) { 1242bbbf1280Sopenharmony_ci ulptolerance = 4096; /* one ulp */ 1243bbbf1280Sopenharmony_ci } else { 1244bbbf1280Sopenharmony_ci ulptolerance = t.func->tolerance; 1245bbbf1280Sopenharmony_ci } 1246bbbf1280Sopenharmony_ci rshift = ishift = 0; 1247bbbf1280Sopenharmony_ci if (ulptolerance & ABSLOWERBOUND) { 1248bbbf1280Sopenharmony_ci /* 1249bbbf1280Sopenharmony_ci * Hack for the lgamma functions, which have an 1250bbbf1280Sopenharmony_ci * error behaviour that can't conveniently be 1251bbbf1280Sopenharmony_ci * characterised in pure ULPs. Really, we want to 1252bbbf1280Sopenharmony_ci * say that the error in lgamma is "at most N ULPs, 1253bbbf1280Sopenharmony_ci * or at most an absolute error of X, whichever is 1254bbbf1280Sopenharmony_ci * larger", for appropriately chosen N,X. But since 1255bbbf1280Sopenharmony_ci * these two functions are the only cases where it 1256bbbf1280Sopenharmony_ci * arises, I haven't bothered to do it in a nice way 1257bbbf1280Sopenharmony_ci * in the function table above. 1258bbbf1280Sopenharmony_ci * 1259bbbf1280Sopenharmony_ci * (The difficult cases arise with negative input 1260bbbf1280Sopenharmony_ci * values such that |gamma(x)| is very near to 1; in 1261bbbf1280Sopenharmony_ci * this situation implementations tend to separately 1262bbbf1280Sopenharmony_ci * compute lgamma(|x|) and the log of the correction 1263bbbf1280Sopenharmony_ci * term from the Euler reflection formula, and 1264bbbf1280Sopenharmony_ci * subtract - which catastrophically loses 1265bbbf1280Sopenharmony_ci * significance.) 1266bbbf1280Sopenharmony_ci * 1267bbbf1280Sopenharmony_ci * As far as I can tell, nobody cares about this: 1268bbbf1280Sopenharmony_ci * GNU libm doesn't get those cases right either, 1269bbbf1280Sopenharmony_ci * and OpenCL explicitly doesn't state a ULP error 1270bbbf1280Sopenharmony_ci * limit for lgamma. So my guess is that this is 1271bbbf1280Sopenharmony_ci * simply considered acceptable error behaviour for 1272bbbf1280Sopenharmony_ci * this particular function, and hence I feel free 1273bbbf1280Sopenharmony_ci * to allow for it here. 1274bbbf1280Sopenharmony_ci */ 1275bbbf1280Sopenharmony_ci ulptolerance &= ~ABSLOWERBOUND; 1276bbbf1280Sopenharmony_ci if (t.op1r[0] & 0x80000000) { 1277bbbf1280Sopenharmony_ci if (t.func->rettype == rt_d) 1278bbbf1280Sopenharmony_ci rshift = 0x400 - ((tresultr[0] >> 20) & 0x7ff); 1279bbbf1280Sopenharmony_ci else if (t.func->rettype == rt_s) 1280bbbf1280Sopenharmony_ci rshift = 0x80 - ((tresultr[0] >> 23) & 0xff); 1281bbbf1280Sopenharmony_ci if (rshift < 0) 1282bbbf1280Sopenharmony_ci rshift = 0; 1283bbbf1280Sopenharmony_ci } 1284bbbf1280Sopenharmony_ci } 1285bbbf1280Sopenharmony_ci if (ulptolerance & PLUSMINUSPIO2) { 1286bbbf1280Sopenharmony_ci ulptolerance &= ~PLUSMINUSPIO2; 1287bbbf1280Sopenharmony_ci /* 1288bbbf1280Sopenharmony_ci * Hack for range reduction, which can reduce 1289bbbf1280Sopenharmony_ci * borderline cases in the wrong direction, i.e. 1290bbbf1280Sopenharmony_ci * return a value just outside one end of the interval 1291bbbf1280Sopenharmony_ci * [-pi/4,+pi/4] when it could have returned a value 1292bbbf1280Sopenharmony_ci * just inside the other end by subtracting an 1293bbbf1280Sopenharmony_ci * adjacent multiple of pi/2. 1294bbbf1280Sopenharmony_ci * 1295bbbf1280Sopenharmony_ci * We tolerate this, up to a point, because the 1296bbbf1280Sopenharmony_ci * trigonometric functions making use of the output of 1297bbbf1280Sopenharmony_ci * rred can cope and because making the range reducer 1298bbbf1280Sopenharmony_ci * do the exactly right thing in every case would be 1299bbbf1280Sopenharmony_ci * more expensive. 1300bbbf1280Sopenharmony_ci */ 1301bbbf1280Sopenharmony_ci if (wres == 1) { 1302bbbf1280Sopenharmony_ci /* Upper bound of overshoot derived in rredf.h */ 1303bbbf1280Sopenharmony_ci if ((resultr[0]&0x7FFFFFFF) <= 0x3f494b02 && 1304bbbf1280Sopenharmony_ci (resultr[0]&0x7FFFFFFF) > 0x3f490fda && 1305bbbf1280Sopenharmony_ci (resultr[0]&0x80000000) != (tresultr[0]&0x80000000)) { 1306bbbf1280Sopenharmony_ci unsigned long long val; 1307bbbf1280Sopenharmony_ci val = tresultr[0]; 1308bbbf1280Sopenharmony_ci val = (val << 32) | tresultr[1]; 1309bbbf1280Sopenharmony_ci /* 1310bbbf1280Sopenharmony_ci * Compute the alternative permitted result by 1311bbbf1280Sopenharmony_ci * subtracting from the sum of the extended 1312bbbf1280Sopenharmony_ci * single-precision bit patterns of +pi/4 and 1313bbbf1280Sopenharmony_ci * -pi/4. This is a horrible hack which only 1314bbbf1280Sopenharmony_ci * works because we can be confident that 1315bbbf1280Sopenharmony_ci * numbers in this range all have the same 1316bbbf1280Sopenharmony_ci * exponent! 1317bbbf1280Sopenharmony_ci */ 1318bbbf1280Sopenharmony_ci val = 0xfe921fb54442d184ULL - val; 1319bbbf1280Sopenharmony_ci tresultr[0] = val >> 32; 1320bbbf1280Sopenharmony_ci tresultr[1] = (val >> (32-EXTRABITS)) << (32-EXTRABITS); 1321bbbf1280Sopenharmony_ci /* 1322bbbf1280Sopenharmony_ci * Also, expect a correspondingly different 1323bbbf1280Sopenharmony_ci * value of res2 as a result of this change. 1324bbbf1280Sopenharmony_ci * The adjustment depends on whether we just 1325bbbf1280Sopenharmony_ci * flipped the result from + to - or vice 1326bbbf1280Sopenharmony_ci * versa. 1327bbbf1280Sopenharmony_ci */ 1328bbbf1280Sopenharmony_ci if (resultr[0] & 0x80000000) { 1329bbbf1280Sopenharmony_ci res2_adjust = +1; 1330bbbf1280Sopenharmony_ci } else { 1331bbbf1280Sopenharmony_ci res2_adjust = -1; 1332bbbf1280Sopenharmony_ci } 1333bbbf1280Sopenharmony_ci } 1334bbbf1280Sopenharmony_ci } 1335bbbf1280Sopenharmony_ci } 1336bbbf1280Sopenharmony_ci ulpsr = calc_error(resultr, tresultr, rshift, t.func->rettype); 1337bbbf1280Sopenharmony_ci if(is_complex_rettype(t.func->rettype)) { 1338bbbf1280Sopenharmony_ci ulpsi = calc_error(resulti, tresulti, ishift, t.func->rettype); 1339bbbf1280Sopenharmony_ci } else { 1340bbbf1280Sopenharmony_ci ulpsi = 0; 1341bbbf1280Sopenharmony_ci } 1342bbbf1280Sopenharmony_ci unsigned *rr = (ulpsr > ulptolerance || ulpsr < -ulptolerance) ? resultr : NULL; 1343bbbf1280Sopenharmony_ci unsigned *ri = (ulpsi > ulptolerance || ulpsi < -ulptolerance) ? resulti : NULL; 1344bbbf1280Sopenharmony_ci/* printf("tolerance=%i, ulpsr=%i, ulpsi=%i, rr=%p, ri=%p\n",ulptolerance,ulpsr,ulpsi,rr,ri); */ 1345bbbf1280Sopenharmony_ci if (rr || ri) { 1346bbbf1280Sopenharmony_ci if (quiet) failtext[0]='x'; 1347bbbf1280Sopenharmony_ci else { 1348bbbf1280Sopenharmony_ci print_error(t.func->rettype,rr,"wrongresultr",&failp); 1349bbbf1280Sopenharmony_ci print_error(t.func->rettype,ri,"wrongresulti",&failp); 1350bbbf1280Sopenharmony_ci print_ulps(t.func->rettype,rr ? ulpsr : 0, ri ? ulpsi : 0,&failp); 1351bbbf1280Sopenharmony_ci } 1352bbbf1280Sopenharmony_ci } 1353bbbf1280Sopenharmony_ci } else { 1354bbbf1280Sopenharmony_ci if(is_complex_rettype(t.func->rettype)) 1355bbbf1280Sopenharmony_ci /* 1356bbbf1280Sopenharmony_ci * Complex functions are not fully supported, 1357bbbf1280Sopenharmony_ci * this is unreachable, but prevents warnings. 1358bbbf1280Sopenharmony_ci */ 1359bbbf1280Sopenharmony_ci abort(); 1360bbbf1280Sopenharmony_ci /* 1361bbbf1280Sopenharmony_ci * The test case data has provided the result in 1362bbbf1280Sopenharmony_ci * exactly the output precision. Therefore we must 1363bbbf1280Sopenharmony_ci * complain about _any_ violation. 1364bbbf1280Sopenharmony_ci */ 1365bbbf1280Sopenharmony_ci switch(t.func->rettype) { 1366bbbf1280Sopenharmony_ci case rt_dc: 1367bbbf1280Sopenharmony_ci canon_dNaN(tresulti); 1368bbbf1280Sopenharmony_ci canon_dNaN(resulti); 1369bbbf1280Sopenharmony_ci if (fo) { 1370bbbf1280Sopenharmony_ci dnormzero(tresulti); 1371bbbf1280Sopenharmony_ci dnormzero(resulti); 1372bbbf1280Sopenharmony_ci } 1373bbbf1280Sopenharmony_ci /* deliberate fall-through */ 1374bbbf1280Sopenharmony_ci case rt_d: 1375bbbf1280Sopenharmony_ci canon_dNaN(tresultr); 1376bbbf1280Sopenharmony_ci canon_dNaN(resultr); 1377bbbf1280Sopenharmony_ci if (fo) { 1378bbbf1280Sopenharmony_ci dnormzero(tresultr); 1379bbbf1280Sopenharmony_ci dnormzero(resultr); 1380bbbf1280Sopenharmony_ci } 1381bbbf1280Sopenharmony_ci break; 1382bbbf1280Sopenharmony_ci case rt_sc: 1383bbbf1280Sopenharmony_ci canon_sNaN(tresulti); 1384bbbf1280Sopenharmony_ci canon_sNaN(resulti); 1385bbbf1280Sopenharmony_ci if (fo) { 1386bbbf1280Sopenharmony_ci snormzero(tresulti); 1387bbbf1280Sopenharmony_ci snormzero(resulti); 1388bbbf1280Sopenharmony_ci } 1389bbbf1280Sopenharmony_ci /* deliberate fall-through */ 1390bbbf1280Sopenharmony_ci case rt_s: 1391bbbf1280Sopenharmony_ci canon_sNaN(tresultr); 1392bbbf1280Sopenharmony_ci canon_sNaN(resultr); 1393bbbf1280Sopenharmony_ci if (fo) { 1394bbbf1280Sopenharmony_ci snormzero(tresultr); 1395bbbf1280Sopenharmony_ci snormzero(resultr); 1396bbbf1280Sopenharmony_ci } 1397bbbf1280Sopenharmony_ci break; 1398bbbf1280Sopenharmony_ci default: 1399bbbf1280Sopenharmony_ci break; 1400bbbf1280Sopenharmony_ci } 1401bbbf1280Sopenharmony_ci if(is_complex_rettype(t.func->rettype)) { 1402bbbf1280Sopenharmony_ci unsigned *rr, *ri; 1403bbbf1280Sopenharmony_ci if(resultr[0] != tresultr[0] || 1404bbbf1280Sopenharmony_ci (wres > 1 && resultr[1] != tresultr[1])) { 1405bbbf1280Sopenharmony_ci rr = resultr; 1406bbbf1280Sopenharmony_ci } else { 1407bbbf1280Sopenharmony_ci rr = NULL; 1408bbbf1280Sopenharmony_ci } 1409bbbf1280Sopenharmony_ci if(resulti[0] != tresulti[0] || 1410bbbf1280Sopenharmony_ci (wres > 1 && resulti[1] != tresulti[1])) { 1411bbbf1280Sopenharmony_ci ri = resulti; 1412bbbf1280Sopenharmony_ci } else { 1413bbbf1280Sopenharmony_ci ri = NULL; 1414bbbf1280Sopenharmony_ci } 1415bbbf1280Sopenharmony_ci if(rr || ri) { 1416bbbf1280Sopenharmony_ci if (quiet) failtext[0]='x'; 1417bbbf1280Sopenharmony_ci print_error(t.func->rettype,rr,"wrongresultr",&failp); 1418bbbf1280Sopenharmony_ci print_error(t.func->rettype,ri,"wrongresulti",&failp); 1419bbbf1280Sopenharmony_ci } 1420bbbf1280Sopenharmony_ci } else if (resultr[0] != tresultr[0] || 1421bbbf1280Sopenharmony_ci (wres > 1 && resultr[1] != tresultr[1])) { 1422bbbf1280Sopenharmony_ci if (quiet) failtext[0]='x'; 1423bbbf1280Sopenharmony_ci print_error(t.func->rettype,resultr,"wrongresult",&failp); 1424bbbf1280Sopenharmony_ci } 1425bbbf1280Sopenharmony_ci } 1426bbbf1280Sopenharmony_ci /* 1427bbbf1280Sopenharmony_ci * Now test res2, for those functions (frexp, modf, rred) 1428bbbf1280Sopenharmony_ci * which use it. 1429bbbf1280Sopenharmony_ci */ 1430bbbf1280Sopenharmony_ci if (t.func->func.ptr == &frexp || t.func->func.ptr == &frexpf || 1431bbbf1280Sopenharmony_ci t.func->macro_name == m_rred || t.func->macro_name == m_rredf) { 1432bbbf1280Sopenharmony_ci unsigned tres2 = t.res2[0]; 1433bbbf1280Sopenharmony_ci if (res2_adjust) { 1434bbbf1280Sopenharmony_ci /* Fix for range reduction, propagated from further up */ 1435bbbf1280Sopenharmony_ci tres2 = (tres2 + res2_adjust) & 3; 1436bbbf1280Sopenharmony_ci } 1437bbbf1280Sopenharmony_ci if (tres2 != intres) { 1438bbbf1280Sopenharmony_ci if (quiet) failtext[0]='x'; 1439bbbf1280Sopenharmony_ci else { 1440bbbf1280Sopenharmony_ci failp += sprintf(failp, 1441bbbf1280Sopenharmony_ci " wrongres2=%08x", intres); 1442bbbf1280Sopenharmony_ci } 1443bbbf1280Sopenharmony_ci } 1444bbbf1280Sopenharmony_ci } else if (t.func->func.ptr == &modf || t.func->func.ptr == &modff) { 1445bbbf1280Sopenharmony_ci tresultr[0] = t.res2[0]; 1446bbbf1280Sopenharmony_ci tresultr[1] = t.res2[1]; 1447bbbf1280Sopenharmony_ci if (is_double_rettype(t.func->rettype)) { 1448bbbf1280Sopenharmony_ci canon_dNaN(tresultr); 1449bbbf1280Sopenharmony_ci resultr[0] = d_res2.i[dmsd]; 1450bbbf1280Sopenharmony_ci resultr[1] = d_res2.i[dlsd]; 1451bbbf1280Sopenharmony_ci canon_dNaN(resultr); 1452bbbf1280Sopenharmony_ci if (fo) { 1453bbbf1280Sopenharmony_ci dnormzero(tresultr); 1454bbbf1280Sopenharmony_ci dnormzero(resultr); 1455bbbf1280Sopenharmony_ci } 1456bbbf1280Sopenharmony_ci } else { 1457bbbf1280Sopenharmony_ci canon_sNaN(tresultr); 1458bbbf1280Sopenharmony_ci resultr[0] = s_res2.i; 1459bbbf1280Sopenharmony_ci resultr[1] = s_res2.i; 1460bbbf1280Sopenharmony_ci canon_sNaN(resultr); 1461bbbf1280Sopenharmony_ci if (fo) { 1462bbbf1280Sopenharmony_ci snormzero(tresultr); 1463bbbf1280Sopenharmony_ci snormzero(resultr); 1464bbbf1280Sopenharmony_ci } 1465bbbf1280Sopenharmony_ci } 1466bbbf1280Sopenharmony_ci if (resultr[0] != tresultr[0] || 1467bbbf1280Sopenharmony_ci (wres > 1 && resultr[1] != tresultr[1])) { 1468bbbf1280Sopenharmony_ci if (quiet) failtext[0]='x'; 1469bbbf1280Sopenharmony_ci else { 1470bbbf1280Sopenharmony_ci if (is_double_rettype(t.func->rettype)) 1471bbbf1280Sopenharmony_ci failp += sprintf(failp, " wrongres2=%08x.%08x", 1472bbbf1280Sopenharmony_ci resultr[0], resultr[1]); 1473bbbf1280Sopenharmony_ci else 1474bbbf1280Sopenharmony_ci failp += sprintf(failp, " wrongres2=%08x", 1475bbbf1280Sopenharmony_ci resultr[0]); 1476bbbf1280Sopenharmony_ci } 1477bbbf1280Sopenharmony_ci } 1478bbbf1280Sopenharmony_ci } 1479bbbf1280Sopenharmony_ci } 1480bbbf1280Sopenharmony_ci 1481bbbf1280Sopenharmony_ci /* Check errno */ 1482bbbf1280Sopenharmony_ci err = (errno == EDOM ? e_EDOM : errno == ERANGE ? e_ERANGE : e_0); 1483bbbf1280Sopenharmony_ci if (err != t.err && err != t.maybeerr) { 1484bbbf1280Sopenharmony_ci if (quiet) failtext[0]='x'; 1485bbbf1280Sopenharmony_ci else { 1486bbbf1280Sopenharmony_ci failp += sprintf(failp, " wrongerrno=%s expecterrno=%s ", errnos[err], errnos[t.err]); 1487bbbf1280Sopenharmony_ci } 1488bbbf1280Sopenharmony_ci } 1489bbbf1280Sopenharmony_ci 1490bbbf1280Sopenharmony_ci return *failtext ? test_fail : test_pass; 1491bbbf1280Sopenharmony_ci} 1492bbbf1280Sopenharmony_ci 1493bbbf1280Sopenharmony_ciint passed, failed, declined; 1494bbbf1280Sopenharmony_ci 1495bbbf1280Sopenharmony_civoid runtests(char *name, FILE *fp) { 1496bbbf1280Sopenharmony_ci char testbuf[512], linebuf[512]; 1497bbbf1280Sopenharmony_ci int lineno = 1; 1498bbbf1280Sopenharmony_ci testdetail test; 1499bbbf1280Sopenharmony_ci 1500bbbf1280Sopenharmony_ci test.valid = 0; 1501bbbf1280Sopenharmony_ci 1502bbbf1280Sopenharmony_ci if (verbose) printf("runtests: %s\n", name); 1503bbbf1280Sopenharmony_ci while (fgets(testbuf, sizeof(testbuf), fp)) { 1504bbbf1280Sopenharmony_ci int res, print_errno; 1505bbbf1280Sopenharmony_ci testbuf[strcspn(testbuf, "\r\n")] = '\0'; 1506bbbf1280Sopenharmony_ci strcpy(linebuf, testbuf); 1507bbbf1280Sopenharmony_ci test = parsetest(testbuf, test); 1508bbbf1280Sopenharmony_ci print_errno = 0; 1509bbbf1280Sopenharmony_ci while (test.in_err < test.in_err_limit) { 1510bbbf1280Sopenharmony_ci res = runtest(test); 1511bbbf1280Sopenharmony_ci if (res == test_pass) { 1512bbbf1280Sopenharmony_ci if (verbose) 1513bbbf1280Sopenharmony_ci printf("%s:%d: pass\n", name, lineno); 1514bbbf1280Sopenharmony_ci ++passed; 1515bbbf1280Sopenharmony_ci } else if (res == test_decline) { 1516bbbf1280Sopenharmony_ci if (verbose) 1517bbbf1280Sopenharmony_ci printf("%s:%d: declined\n", name, lineno); 1518bbbf1280Sopenharmony_ci ++declined; 1519bbbf1280Sopenharmony_ci } else if (res == test_fail) { 1520bbbf1280Sopenharmony_ci if (!quiet) 1521bbbf1280Sopenharmony_ci printf("%s:%d: FAIL%s: %s%s%s%s\n", name, lineno, 1522bbbf1280Sopenharmony_ci test.random ? " (random)" : "", 1523bbbf1280Sopenharmony_ci linebuf, 1524bbbf1280Sopenharmony_ci print_errno ? " errno_in=" : "", 1525bbbf1280Sopenharmony_ci print_errno ? errnos[test.in_err] : "", 1526bbbf1280Sopenharmony_ci failtext); 1527bbbf1280Sopenharmony_ci ++failed; 1528bbbf1280Sopenharmony_ci } else if (res == test_invalid) { 1529bbbf1280Sopenharmony_ci printf("%s:%d: malformed: %s\n", name, lineno, linebuf); 1530bbbf1280Sopenharmony_ci ++failed; 1531bbbf1280Sopenharmony_ci } 1532bbbf1280Sopenharmony_ci test.in_err++; 1533bbbf1280Sopenharmony_ci print_errno = 1; 1534bbbf1280Sopenharmony_ci } 1535bbbf1280Sopenharmony_ci lineno++; 1536bbbf1280Sopenharmony_ci } 1537bbbf1280Sopenharmony_ci} 1538bbbf1280Sopenharmony_ci 1539bbbf1280Sopenharmony_ciint main(int ac, char **av) { 1540bbbf1280Sopenharmony_ci char **files; 1541bbbf1280Sopenharmony_ci int i, nfiles = 0; 1542bbbf1280Sopenharmony_ci dbl d; 1543bbbf1280Sopenharmony_ci 1544bbbf1280Sopenharmony_ci#ifdef MICROLIB 1545bbbf1280Sopenharmony_ci /* 1546bbbf1280Sopenharmony_ci * Invent argc and argv ourselves. 1547bbbf1280Sopenharmony_ci */ 1548bbbf1280Sopenharmony_ci char *argv[256]; 1549bbbf1280Sopenharmony_ci char args[256]; 1550bbbf1280Sopenharmony_ci { 1551bbbf1280Sopenharmony_ci int sargs[2]; 1552bbbf1280Sopenharmony_ci char *p; 1553bbbf1280Sopenharmony_ci 1554bbbf1280Sopenharmony_ci ac = 0; 1555bbbf1280Sopenharmony_ci 1556bbbf1280Sopenharmony_ci sargs[0]=(int)args; 1557bbbf1280Sopenharmony_ci sargs[1]=(int)sizeof(args); 1558bbbf1280Sopenharmony_ci if (!__semihost(0x15, sargs)) { 1559bbbf1280Sopenharmony_ci args[sizeof(args)-1] = '\0'; /* just in case */ 1560bbbf1280Sopenharmony_ci p = args; 1561bbbf1280Sopenharmony_ci while (1) { 1562bbbf1280Sopenharmony_ci while (*p == ' ' || *p == '\t') p++; 1563bbbf1280Sopenharmony_ci if (!*p) break; 1564bbbf1280Sopenharmony_ci argv[ac++] = p; 1565bbbf1280Sopenharmony_ci while (*p && *p != ' ' && *p != '\t') p++; 1566bbbf1280Sopenharmony_ci if (*p) *p++ = '\0'; 1567bbbf1280Sopenharmony_ci } 1568bbbf1280Sopenharmony_ci } 1569bbbf1280Sopenharmony_ci 1570bbbf1280Sopenharmony_ci av = argv; 1571bbbf1280Sopenharmony_ci } 1572bbbf1280Sopenharmony_ci#endif 1573bbbf1280Sopenharmony_ci 1574bbbf1280Sopenharmony_ci /* Sort tfuncs */ 1575bbbf1280Sopenharmony_ci qsort(tfuncs, sizeof(tfuncs)/sizeof(test_func), sizeof(test_func), &compare_tfuncs); 1576bbbf1280Sopenharmony_ci 1577bbbf1280Sopenharmony_ci /* 1578bbbf1280Sopenharmony_ci * Autodetect the `double' endianness. 1579bbbf1280Sopenharmony_ci */ 1580bbbf1280Sopenharmony_ci dmsd = 0; 1581bbbf1280Sopenharmony_ci d.f = 1.0; /* 0x3ff00000 / 0x00000000 */ 1582bbbf1280Sopenharmony_ci if (d.i[dmsd] == 0) { 1583bbbf1280Sopenharmony_ci dmsd = 1; 1584bbbf1280Sopenharmony_ci } 1585bbbf1280Sopenharmony_ci /* 1586bbbf1280Sopenharmony_ci * Now dmsd denotes what the compiler thinks we're at. Let's 1587bbbf1280Sopenharmony_ci * check that it agrees with what the runtime thinks. 1588bbbf1280Sopenharmony_ci */ 1589bbbf1280Sopenharmony_ci d.i[0] = d.i[1] = 0x11111111;/* a random +ve number */ 1590bbbf1280Sopenharmony_ci d.f /= d.f; /* must now be one */ 1591bbbf1280Sopenharmony_ci if (d.i[dmsd] == 0) { 1592bbbf1280Sopenharmony_ci fprintf(stderr, "YIKES! Compiler and runtime disagree on endianness" 1593bbbf1280Sopenharmony_ci " of `double'. Bailing out\n"); 1594bbbf1280Sopenharmony_ci return 1; 1595bbbf1280Sopenharmony_ci } 1596bbbf1280Sopenharmony_ci dlsd = !dmsd; 1597bbbf1280Sopenharmony_ci 1598bbbf1280Sopenharmony_ci /* default is terse */ 1599bbbf1280Sopenharmony_ci verbose = 0; 1600bbbf1280Sopenharmony_ci fo = 0; 1601bbbf1280Sopenharmony_ci strict = 0; 1602bbbf1280Sopenharmony_ci 1603bbbf1280Sopenharmony_ci files = (char **)malloc((ac+1) * sizeof(char *)); 1604bbbf1280Sopenharmony_ci if (!files) { 1605bbbf1280Sopenharmony_ci fprintf(stderr, "initial malloc failed!\n"); 1606bbbf1280Sopenharmony_ci return 1; 1607bbbf1280Sopenharmony_ci } 1608bbbf1280Sopenharmony_ci#ifdef NOCMDLINE 1609bbbf1280Sopenharmony_ci files[nfiles++] = "testfile"; 1610bbbf1280Sopenharmony_ci#endif 1611bbbf1280Sopenharmony_ci 1612bbbf1280Sopenharmony_ci while (--ac) { 1613bbbf1280Sopenharmony_ci char *p = *++av; 1614bbbf1280Sopenharmony_ci if (*p == '-') { 1615bbbf1280Sopenharmony_ci static char *options[] = { 1616bbbf1280Sopenharmony_ci "-fo", 1617bbbf1280Sopenharmony_ci#if 0 1618bbbf1280Sopenharmony_ci "-noinexact", 1619bbbf1280Sopenharmony_ci "-noround", 1620bbbf1280Sopenharmony_ci#endif 1621bbbf1280Sopenharmony_ci "-nostatus", 1622bbbf1280Sopenharmony_ci "-quiet", 1623bbbf1280Sopenharmony_ci "-strict", 1624bbbf1280Sopenharmony_ci "-v", 1625bbbf1280Sopenharmony_ci "-verbose", 1626bbbf1280Sopenharmony_ci }; 1627bbbf1280Sopenharmony_ci enum { 1628bbbf1280Sopenharmony_ci op_fo, 1629bbbf1280Sopenharmony_ci#if 0 1630bbbf1280Sopenharmony_ci op_noinexact, 1631bbbf1280Sopenharmony_ci op_noround, 1632bbbf1280Sopenharmony_ci#endif 1633bbbf1280Sopenharmony_ci op_nostatus, 1634bbbf1280Sopenharmony_ci op_quiet, 1635bbbf1280Sopenharmony_ci op_strict, 1636bbbf1280Sopenharmony_ci op_v, 1637bbbf1280Sopenharmony_ci op_verbose, 1638bbbf1280Sopenharmony_ci }; 1639bbbf1280Sopenharmony_ci switch (find(p, options, sizeof(options))) { 1640bbbf1280Sopenharmony_ci case op_quiet: 1641bbbf1280Sopenharmony_ci quiet = 1; 1642bbbf1280Sopenharmony_ci break; 1643bbbf1280Sopenharmony_ci#if 0 1644bbbf1280Sopenharmony_ci case op_noinexact: 1645bbbf1280Sopenharmony_ci statusmask &= 0x0F; /* remove bit 4 */ 1646bbbf1280Sopenharmony_ci break; 1647bbbf1280Sopenharmony_ci case op_noround: 1648bbbf1280Sopenharmony_ci doround = 0; 1649bbbf1280Sopenharmony_ci break; 1650bbbf1280Sopenharmony_ci#endif 1651bbbf1280Sopenharmony_ci case op_nostatus: /* no status word => noinx,noround */ 1652bbbf1280Sopenharmony_ci statusmask = 0; 1653bbbf1280Sopenharmony_ci doround = 0; 1654bbbf1280Sopenharmony_ci break; 1655bbbf1280Sopenharmony_ci case op_v: 1656bbbf1280Sopenharmony_ci case op_verbose: 1657bbbf1280Sopenharmony_ci verbose = 1; 1658bbbf1280Sopenharmony_ci break; 1659bbbf1280Sopenharmony_ci case op_fo: 1660bbbf1280Sopenharmony_ci fo = 1; 1661bbbf1280Sopenharmony_ci break; 1662bbbf1280Sopenharmony_ci case op_strict: /* tolerance is 1 ulp */ 1663bbbf1280Sopenharmony_ci strict = 1; 1664bbbf1280Sopenharmony_ci break; 1665bbbf1280Sopenharmony_ci default: 1666bbbf1280Sopenharmony_ci fprintf(stderr, "unrecognised option: %s\n", p); 1667bbbf1280Sopenharmony_ci break; 1668bbbf1280Sopenharmony_ci } 1669bbbf1280Sopenharmony_ci } else { 1670bbbf1280Sopenharmony_ci files[nfiles++] = p; 1671bbbf1280Sopenharmony_ci } 1672bbbf1280Sopenharmony_ci } 1673bbbf1280Sopenharmony_ci 1674bbbf1280Sopenharmony_ci passed = failed = declined = 0; 1675bbbf1280Sopenharmony_ci 1676bbbf1280Sopenharmony_ci if (nfiles) { 1677bbbf1280Sopenharmony_ci for (i = 0; i < nfiles; i++) { 1678bbbf1280Sopenharmony_ci FILE *fp = fopen(files[i], "r"); 1679bbbf1280Sopenharmony_ci if (!fp) { 1680bbbf1280Sopenharmony_ci fprintf(stderr, "Couldn't open %s\n", files[i]); 1681bbbf1280Sopenharmony_ci } else 1682bbbf1280Sopenharmony_ci runtests(files[i], fp); 1683bbbf1280Sopenharmony_ci } 1684bbbf1280Sopenharmony_ci } else 1685bbbf1280Sopenharmony_ci runtests("(stdin)", stdin); 1686bbbf1280Sopenharmony_ci 1687bbbf1280Sopenharmony_ci printf("Completed. Passed %d, failed %d (total %d", 1688bbbf1280Sopenharmony_ci passed, failed, passed+failed); 1689bbbf1280Sopenharmony_ci if (declined) 1690bbbf1280Sopenharmony_ci printf(" plus %d declined", declined); 1691bbbf1280Sopenharmony_ci printf(")\n"); 1692bbbf1280Sopenharmony_ci if (failed || passed == 0) 1693bbbf1280Sopenharmony_ci return 1; 1694bbbf1280Sopenharmony_ci printf("** TEST PASSED OK **\n"); 1695bbbf1280Sopenharmony_ci return 0; 1696bbbf1280Sopenharmony_ci} 1697bbbf1280Sopenharmony_ci 1698bbbf1280Sopenharmony_civoid undef_func() { 1699bbbf1280Sopenharmony_ci failed++; 1700bbbf1280Sopenharmony_ci puts("ERROR: undefined function called"); 1701bbbf1280Sopenharmony_ci} 1702