2 Consistency tests for math functions.
3 To get strict rounding rules on a 386 or 68000 computer,
6 With NTRIALS=10000, the following are typical results for
7 IEEE double precision arithmetic.
9 Consistency test of math functions.
10 Max and rms relative errors for 10000 random arguments.
11 x = cbrt( cube(x) ): max = 0.00E+00 rms = 0.00E+00
12 x = atan( tan(x) ): max = 2.21E-16 rms = 3.27E-17
13 x = sin( asin(x) ): max = 2.13E-16 rms = 2.95E-17
14 x = sqrt( square(x) ): max = 0.00E+00 rms = 0.00E+00
15 x = log( exp(x) ): max = 1.11E-16 A rms = 4.35E-18 A
16 x = tanh( atanh(x) ): max = 2.22E-16 rms = 2.43E-17
17 x = asinh( sinh(x) ): max = 2.05E-16 rms = 3.49E-18
18 x = acosh( cosh(x) ): max = 1.43E-15 A rms = 1.54E-17 A
19 x = log10( exp10(x) ): max = 5.55E-17 A rms = 1.27E-18 A
20 x = pow( pow(x,a),1/a ): max = 7.60E-14 rms = 1.05E-15
21 x = cos( acos(x) ): max = 2.22E-16 A rms = 6.90E-17 A
25 Cephes Math Library Release 2.1: December, 1988
26 Copyright 1984, 1987, 1988 by Stephen L. Moshier
37 #define WTRIALS (NTRIALS/5)
40 float sqrtf(), cbrtf(), expf(), logf();
41 float exp10f(), log10f(), tanf(), atanf();
42 float sinf(), asinf(), cosf(), acosf(), powf();
43 float tanhf(), atanhf(), sinhf(), asinhf(), coshf(), acoshf();
46 #define fabsf(x) ((x) < 0 ? -(x) : (x))
57 /* Provide inverses for square root and cube root: */
78 /* lookup table for each function */
81 char *nam1; /* the function */
83 float (*name) (float);
87 char *nam2; /* its inverse */
93 int tstyp; /* type code of the function */
94 long ctrl; /* relative error flag */
95 float arg1w; /* width of domain for 1st arg */
96 float arg1l; /* lower bound domain 1st arg */
97 long arg1f; /* flags, e.g. integer arg */
102 char *nam1; /* the function */
104 float (*name) (float, float);
108 char *nam2; /* its inverse */
110 float (*inv )(float, float);
114 int tstyp; /* type code of the function */
115 long ctrl; /* relative error flag */
116 float arg1w; /* width of domain for 1st arg */
117 float arg1l; /* lower bound domain 1st arg */
118 long arg1f; /* flags, e.g. integer arg */
119 float arg2w; /* same info for args 2, 3, 4 */
127 /* fundef.tstyp test types: */
135 /* fundef.argNf argument flag bits: */
139 extern float MINLOGF;
140 extern float MAXLOGF;
144 define MINLOGF -170.0
145 define MAXLOGF +170.0
146 define PIF 3.14159265358979323846
147 define PIO2F 1.570796326794896619
151 struct oneargument defs1arg[N1TESTS] = {
152 {" cube", cube, " cbrt", cbrtf, 0, 1, 2002.0, -1001.0, 0},
153 {" tan", tanf, " atan", atanf, 0, 1, 0.0, 0.0, 0},
154 {" asin", asinf, " sin", sinf, 0, 1, 2.0, -1.0, 0},
155 {"square", square, " sqrt", sqrtf, 0, 1, 87.0, -43.5, EXPSCAL},
156 {" exp", expf, " log", logf, 0, 0, 174.0, -87.0, 0},
157 {" atanh", atanhf, " tanh", tanhf, 0, 1, 2.0, -1.0, 0},
158 {" sinh", sinhf, " asinh", asinhf, 0, 1, 174.0, 0.0, 0},
159 {" cosh", coshf, " acosh", acoshf, 0, 0, 174.0, 0.0, 0},
160 {" exp10", exp10f, " log10", log10f, 0, 0, 76.0, -38.0, 0},
161 {" acos", acosf, " cos", cosf, 0, 0, 2.0, -1.0, 0},
165 struct twoarguments defs2arg[N2TESTS] = {
166 {"pow", powf, "pow", powf, POWER, 1, 20.0, 0.01, 0,
170 static char *headrs[] = {
172 "x = %s( %s(x,a),1/a ): ", /* power */
173 "Legendre %s, %s: ", /* ellip */
174 "%s(x) = log(%s(x)): ", /* gamma */
175 "Wronksian of %s, %s: ",
176 "Wronksian of %s, %s: ",
177 "Wronksian of %s, %s: "
193 static double doublea;
198 float (*fun1 )(float);
199 float (*ifun1 )(float);
200 float (*fun2 )(float, float);
201 float (*ifun2 )(float, float);
210 long arg1f, arg2f, ctrl;
211 float arg1l, arg2l, arg1w, arg2w;
212 int i, k, itst, ntsts, iargs;
216 sprec(); /* set coprocessor precision */
219 printf( "Consistency test of math functions.\n" );
220 printf( "Max and rms relative errors for %d random arguments.\n",
223 /* Initialize machine dependent parameters: */
225 defs1arg[1].arg1w = PIF;
226 defs1arg[1].arg1l = -PIF/2.0;
228 /* Microsoft C has trouble with denormal numbers. */
230 defs[3].arg1w = MAXLOGF;
231 defs[3].arg1l = -MAXLOGF/2.0F;
232 defs[4].arg1w = 2*MAXLOGF;
233 defs[4].arg1l = -MAXLOGF;
235 defs1arg[6].arg1w = 2.0F*MAXLOGF;
236 defs1arg[6].arg1l = -MAXLOGF;
237 defs1arg[7].arg1w = MAXLOGF;
238 defs1arg[7].arg1l = 0.0;
241 /* Outer outer loop, on number of function arguments. */
242 for( iargs=1; iargs <=2; iargs++)
252 /* Outer loop, on the test number: */
253 for( itst=STRTST; itst<ntsts; itst++ )
258 tstyp = defs2arg[itst].tstyp;
259 fun2 = defs2arg[itst].name;
260 ifun2 = defs2arg[itst].inv;
261 nam1 = defs2arg[itst].nam1;
262 nam2 = defs2arg[itst].nam2;
263 arg1w = defs2arg[itst].arg1w;
264 arg1l = defs2arg[itst].arg1l;
265 arg1f = defs2arg[itst].arg1f;
266 arg2w = defs2arg[itst].arg2w;
267 arg2l = defs2arg[itst].arg2l;
268 arg2f = defs2arg[itst].arg2f;
269 ctrl = defs2arg[itst].ctrl;
273 tstyp = defs1arg[itst].tstyp;
274 fun1 = defs1arg[itst].name;
275 ifun1 = defs1arg[itst].inv;
276 nam1 = defs1arg[itst].nam1;
277 nam2 = defs1arg[itst].nam2;
278 arg1w = defs1arg[itst].arg1w;
279 arg1l = defs1arg[itst].arg1l;
280 arg1f = defs1arg[itst].arg1f;
281 ctrl = defs1arg[itst].ctrl;
290 /* Absolute error criterion starts with gamma function
291 * (put all such at end of table)
294 printf( "Absolute error criterion (but relative if >1):\n" );
296 /* Smaller number of trials for Wronksians
297 * (put them at end of list)
299 if( tstyp == WRONK1 )
302 printf( "Absolute error and only %d trials:\n", ntr );
305 printf( headrs[tstyp], nam2, nam1 );
307 for( i=0; i<ntr; i++ )
311 /* make random number(s) in desired range(s) */
320 a = arg2w * ( doublea - 1.0 ) + arg2l;
321 if( arg2f & EXPSCAL )
326 a -= 1.0e-13 * a * y2;
336 x = arg1w * ( doublea - 1.0 ) + arg1l;
337 if( arg1f & EXPSCAL )
342 x += 1.0e-13F * x * a;
347 /* compute function under test */
356 yy1 = (*fun2)( k, x ); /* jn */
357 y2 = (*fun2)( k+1, x );
358 y3 = (*ifun2)( k, x ); /* yn */
359 y4 = (*ifun2)( k+1, x );
363 yy1 = (*fun2)( a, x ); /* iv */
364 y2 = (*fun2)( a+1.0F, x );
365 y3 = (*ifun2)( k, x ); /* kn */
366 y4 = (*ifun2)( k+1, x );
371 y = (*ifun2)( k, z );
379 y = (*ifun2)( z, 1.0F/a );
384 y = (*ifun2)( a, z );
393 yy1 = ( *(fun1) )(x);
394 y2 = ( *(fun1) )(1.0F-x);
395 y3 = ( *(ifun1) )(x);
396 y4 = ( *(ifun1) )(1.0F-x);
414 printf( "Illegal nargs= %d", nargs );
421 e = (y2*y3 - yy1*y4) - 2.0F/(PIF*x); /* Jn, Yn */
425 e = (y2*y3 + yy1*y4) - 1.0F/x; /* In, Kn */
429 e = (yy1-y3)*y4 + y3*y2 - PIO2F;
441 if( fabsf(x) > 1.0F )
446 /* absolute value of error */
450 /* peak detect the error */
457 printf("x %.6E z %.6E y %.6E max %.4E\n",
461 printf( "a %.6E\n", a );
463 if( tstyp >= WRONK1 )
465 printf( "yy1 %.4E y2 %.4E y3 %.4E y4 %.4E k %d x %.4E\n",
466 yy1, y2, y3, y4, k, x );
471 printf("%.8E %.8E %.4E %6ld \n", x, y, max, n);
472 printf("%d %.8E %.8E %.4E %6ld \n", k, x, y, max, n);
473 printf("%.6E %.6E %.6E %.4E %6ld \n", a, x, y, max, n);
474 printf("%.6E %.6E %.6E %.6E %.4E %6ld \n", a, b, x, y, max, n);
475 printf("%.4E %.4E %.4E %.4E %.4E %.4E %6ld \n",
476 a, b, c, x, y, max, n);
480 /* accumulate rms error */
481 e *= 1.0e7F; /* adjust range */
482 rmsa += e * e; /* accumulate the square of the error */
485 /* report after NTRIALS trials */
486 rms = 1.0e-7F * sqrtf( rmsa/m );
488 printf(" max = %.10E rms = %.10E\n", max, rms );
490 printf(" max = %.10E A rms = %.10E A\n", max, rms );
492 } /* loop on number of args */