mtst.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. /* mtst.c
  2. Consistency tests for math functions.
  3. To get strict rounding rules on a 386 or 68000 computer,
  4. define SETPREC to 1.
  5. With NTRIALS=10000, the following are typical results for
  6. IEEE double precision arithmetic.
  7. Consistency test of math functions.
  8. Max and rms relative errors for 10000 random arguments.
  9. x = cbrt( cube(x) ): max = 0.00E+00 rms = 0.00E+00
  10. x = atan( tan(x) ): max = 2.21E-16 rms = 3.27E-17
  11. x = sin( asin(x) ): max = 2.13E-16 rms = 2.95E-17
  12. x = sqrt( square(x) ): max = 0.00E+00 rms = 0.00E+00
  13. x = log( exp(x) ): max = 1.11E-16 A rms = 4.35E-18 A
  14. x = tanh( atanh(x) ): max = 2.22E-16 rms = 2.43E-17
  15. x = asinh( sinh(x) ): max = 2.05E-16 rms = 3.49E-18
  16. x = acosh( cosh(x) ): max = 1.43E-15 A rms = 1.54E-17 A
  17. x = log10( exp10(x) ): max = 5.55E-17 A rms = 1.27E-18 A
  18. x = pow( pow(x,a),1/a ): max = 7.60E-14 rms = 1.05E-15
  19. x = cos( acos(x) ): max = 2.22E-16 A rms = 6.90E-17 A
  20. */
  21. /*
  22. Cephes Math Library Release 2.8: June, 2000
  23. Copyright 1984, 1987, 1988, 2000 by Stephen L. Moshier
  24. */
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <math.h>
  28. #ifndef NTRIALS
  29. #define NTRIALS 10000
  30. #endif
  31. #define SETPREC 1
  32. #define STRTST 0
  33. #define WTRIALS (NTRIALS/5)
  34. #ifdef ANSIPROT
  35. extern double fabs ( double );
  36. extern double sqrt ( double );
  37. extern double cbrt ( double );
  38. extern double exp ( double );
  39. extern double log ( double );
  40. extern double exp10 ( double );
  41. extern double log10 ( double );
  42. extern double tan ( double );
  43. extern double atan ( double );
  44. extern double sin ( double );
  45. extern double asin ( double );
  46. extern double cos ( double );
  47. extern double acos ( double );
  48. extern double pow ( double, double );
  49. extern double tanh ( double );
  50. extern double atanh ( double );
  51. extern double sinh ( double );
  52. extern double asinh ( double x );
  53. extern double cosh ( double );
  54. extern double acosh ( double );
  55. extern double gamma ( double );
  56. extern double lgam ( double );
  57. #else
  58. double fabs(), sqrt(), cbrt(), exp(), log();
  59. double exp10(), log10(), tan(), atan();
  60. double sin(), asin(), cos(), acos(), pow();
  61. double tanh(), atanh(), sinh(), asinh(), cosh(), acosh();
  62. double gamma(), lgam();
  63. #endif
  64. /* C9X spells lgam lgamma. */
  65. #define GLIBC2 0
  66. #if GLIBC2
  67. double lgamma (double);
  68. #endif
  69. #if SETPREC
  70. int dprec();
  71. #endif
  72. int drand();
  73. /* void exit(); */
  74. /* int printf(); */
  75. /* Provide inverses for square root and cube root: */
  76. double square(x)
  77. double x;
  78. {
  79. return( x * x );
  80. }
  81. double cube(x)
  82. double x;
  83. {
  84. return( x * x * x );
  85. }
  86. /* lookup table for each function */
  87. struct fundef
  88. {
  89. char *nam1; /* the function */
  90. double (*name )();
  91. char *nam2; /* its inverse */
  92. double (*inv )();
  93. int nargs; /* number of function arguments */
  94. int tstyp; /* type code of the function */
  95. long ctrl; /* relative error flag */
  96. double arg1w; /* width of domain for 1st arg */
  97. double arg1l; /* lower bound domain 1st arg */
  98. long arg1f; /* flags, e.g. integer arg */
  99. double arg2w; /* same info for args 2, 3, 4 */
  100. double arg2l;
  101. long arg2f;
  102. /*
  103. double arg3w;
  104. double arg3l;
  105. long arg3f;
  106. double arg4w;
  107. double arg4l;
  108. long arg4f;
  109. */
  110. };
  111. /* fundef.ctrl bits: */
  112. #define RELERR 1
  113. /* fundef.tstyp test types: */
  114. #define POWER 1
  115. #define ELLIP 2
  116. #define GAMMA 3
  117. #define WRONK1 4
  118. #define WRONK2 5
  119. #define WRONK3 6
  120. /* fundef.argNf argument flag bits: */
  121. #define INT 2
  122. #define EXPSCAL 4
  123. extern double MINLOG;
  124. extern double MAXLOG;
  125. extern double PI;
  126. extern double PIO2;
  127. /*
  128. define MINLOG -170.0
  129. define MAXLOG +170.0
  130. define PI 3.14159265358979323846
  131. define PIO2 1.570796326794896619
  132. */
  133. #define NTESTS 12
  134. struct fundef defs[NTESTS] = {
  135. {" cube", cube, " cbrt", cbrt, 1, 0, 1, 2002.0, -1001.0, 0,
  136. 0.0, 0.0, 0},
  137. {" tan", tan, " atan", atan, 1, 0, 1, 0.0, 0.0, 0,
  138. 0.0, 0.0, 0},
  139. {" asin", asin, " sin", sin, 1, 0, 1, 2.0, -1.0, 0,
  140. 0.0, 0.0, 0},
  141. {"square", square, " sqrt", sqrt, 1, 0, 1, 170.0, -85.0, EXPSCAL,
  142. 0.0, 0.0, 0},
  143. {" exp", exp, " log", log, 1, 0, 0, 340.0, -170.0, 0,
  144. 0.0, 0.0, 0},
  145. {" atanh", atanh, " tanh", tanh, 1, 0, 1, 2.0, -1.0, 0,
  146. 0.0, 0.0, 0},
  147. {" sinh", sinh, " asinh", asinh, 1, 0, 1, 340.0, 0.0, 0,
  148. 0.0, 0.0, 0},
  149. {" cosh", cosh, " acosh", acosh, 1, 0, 0, 340.0, 0.0, 0,
  150. 0.0, 0.0, 0},
  151. {" exp10", exp10, " log10", log10, 1, 0, 0, 340.0, -170.0, 0,
  152. 0.0, 0.0, 0},
  153. {"pow", pow, "pow", pow, 2, POWER, 1, 21.0, 0.0, 0,
  154. 42.0, -21.0, 0},
  155. {" acos", acos, " cos", cos, 1, 0, 0, 2.0, -1.0, 0,
  156. 0.0, 0.0, 0},
  157. #if GLIBC2
  158. { "gamma", gamma, "lgamma", lgamma, 1, GAMMA, 0, 34.0, 0.0, 0,
  159. 0.0, 0.0, 0},
  160. #else
  161. { "gamma", gamma, "lgam", lgam, 1, GAMMA, 0, 34.0, 0.0, 0,
  162. 0.0, 0.0, 0},
  163. #endif
  164. };
  165. static char *headrs[] = {
  166. "x = %s( %s(x) ): ",
  167. "x = %s( %s(x,a),1/a ): ", /* power */
  168. "Legendre %s, %s: ", /* ellip */
  169. "%s(x) = log(%s(x)): ", /* gamma */
  170. "Wronksian of %s, %s: ",
  171. "Wronksian of %s, %s: ",
  172. "Wronksian of %s, %s: "
  173. };
  174. static double yy1 = 0.0;
  175. static double y2 = 0.0;
  176. static double y3 = 0.0;
  177. static double y4 = 0.0;
  178. static double a = 0.0;
  179. static double x = 0.0;
  180. static double y = 0.0;
  181. static double z = 0.0;
  182. static double e = 0.0;
  183. static double max = 0.0;
  184. static double rmsa = 0.0;
  185. static double rms = 0.0;
  186. static double ave = 0.0;
  187. int main()
  188. {
  189. double (*fun )();
  190. double (*ifun )();
  191. struct fundef *d;
  192. int i, k, itst;
  193. int m, ntr;
  194. #if SETPREC
  195. dprec(); /* set coprocessor precision */
  196. #endif
  197. ntr = NTRIALS;
  198. printf( "Consistency test of math functions.\n" );
  199. printf( "Max and rms relative errors for %d random arguments.\n",
  200. ntr );
  201. /* Initialize machine dependent parameters: */
  202. defs[1].arg1w = PI;
  203. defs[1].arg1l = -PI/2.0;
  204. /* Microsoft C has trouble with denormal numbers. */
  205. #if 0
  206. defs[3].arg1w = MAXLOG;
  207. defs[3].arg1l = -MAXLOG/2.0;
  208. defs[4].arg1w = 2*MAXLOG;
  209. defs[4].arg1l = -MAXLOG;
  210. #endif
  211. defs[6].arg1w = 2.0*MAXLOG;
  212. defs[6].arg1l = -MAXLOG;
  213. defs[7].arg1w = MAXLOG;
  214. defs[7].arg1l = 0.0;
  215. /* Outer loop, on the test number: */
  216. for( itst=STRTST; itst<NTESTS; itst++ )
  217. {
  218. d = &defs[itst];
  219. k = 0;
  220. m = 0;
  221. max = 0.0;
  222. rmsa = 0.0;
  223. ave = 0.0;
  224. fun = d->name;
  225. ifun = d->inv;
  226. /* Absolute error criterion starts with gamma function
  227. * (put all such at end of table)
  228. */
  229. if( d->tstyp == GAMMA )
  230. printf( "Absolute error criterion (but relative if >1):\n" );
  231. /* Smaller number of trials for Wronksians
  232. * (put them at end of list)
  233. */
  234. if( d->tstyp == WRONK1 )
  235. {
  236. ntr = WTRIALS;
  237. printf( "Absolute error and only %d trials:\n", ntr );
  238. }
  239. printf( headrs[d->tstyp], d->nam2, d->nam1 );
  240. for( i=0; i<ntr; i++ )
  241. {
  242. m++;
  243. /* make random number(s) in desired range(s) */
  244. switch( d->nargs )
  245. {
  246. default:
  247. goto illegn;
  248. case 2:
  249. drand( &a );
  250. a = d->arg2w * ( a - 1.0 ) + d->arg2l;
  251. if( d->arg2f & EXPSCAL )
  252. {
  253. a = exp(a);
  254. drand( &y2 );
  255. a -= 1.0e-13 * a * y2;
  256. }
  257. if( d->arg2f & INT )
  258. {
  259. k = a + 0.25;
  260. a = k;
  261. }
  262. case 1:
  263. drand( &x );
  264. x = d->arg1w * ( x - 1.0 ) + d->arg1l;
  265. if( d->arg1f & EXPSCAL )
  266. {
  267. x = exp(x);
  268. drand( &a );
  269. x += 1.0e-13 * x * a;
  270. }
  271. }
  272. /* compute function under test */
  273. switch( d->nargs )
  274. {
  275. case 1:
  276. switch( d->tstyp )
  277. {
  278. case ELLIP:
  279. yy1 = ( *(fun) )(x);
  280. y2 = ( *(fun) )(1.0-x);
  281. y3 = ( *(ifun) )(x);
  282. y4 = ( *(ifun) )(1.0-x);
  283. break;
  284. #if 1
  285. case GAMMA:
  286. #if GLIBC2
  287. y = lgamma(x);
  288. #else
  289. y = lgam(x);
  290. #endif
  291. x = log( gamma(x) );
  292. break;
  293. #endif
  294. default:
  295. z = ( *(fun) )(x);
  296. y = ( *(ifun) )(z);
  297. }
  298. break;
  299. case 2:
  300. if( d->arg2f & INT )
  301. {
  302. switch( d->tstyp )
  303. {
  304. case WRONK1:
  305. yy1 = (*fun)( k, x ); /* jn */
  306. y2 = (*fun)( k+1, x );
  307. y3 = (*ifun)( k, x ); /* yn */
  308. y4 = (*ifun)( k+1, x );
  309. break;
  310. case WRONK2:
  311. yy1 = (*fun)( a, x ); /* iv */
  312. y2 = (*fun)( a+1.0, x );
  313. y3 = (*ifun)( k, x ); /* kn */
  314. y4 = (*ifun)( k+1, x );
  315. break;
  316. default:
  317. z = (*fun)( k, x );
  318. y = (*ifun)( k, z );
  319. }
  320. }
  321. else
  322. {
  323. if( d->tstyp == POWER )
  324. {
  325. z = (*fun)( x, a );
  326. y = (*ifun)( z, 1.0/a );
  327. }
  328. else
  329. {
  330. z = (*fun)( a, x );
  331. y = (*ifun)( a, z );
  332. }
  333. }
  334. break;
  335. default:
  336. illegn:
  337. printf( "Illegal nargs= %d", d->nargs );
  338. exit(1);
  339. }
  340. switch( d->tstyp )
  341. {
  342. case WRONK1:
  343. e = (y2*y3 - yy1*y4) - 2.0/(PI*x); /* Jn, Yn */
  344. break;
  345. case WRONK2:
  346. e = (y2*y3 + yy1*y4) - 1.0/x; /* In, Kn */
  347. break;
  348. case ELLIP:
  349. e = (yy1-y3)*y4 + y3*y2 - PIO2;
  350. break;
  351. default:
  352. e = y - x;
  353. break;
  354. }
  355. if( d->ctrl & RELERR )
  356. e /= x;
  357. else
  358. {
  359. if( fabs(x) > 1.0 )
  360. e /= x;
  361. }
  362. ave += e;
  363. /* absolute value of error */
  364. if( e < 0 )
  365. e = -e;
  366. /* peak detect the error */
  367. if( e > max )
  368. {
  369. max = e;
  370. if( e > 1.0e-10 )
  371. {
  372. printf("x %.6E z %.6E y %.6E max %.4E\n",
  373. x, z, y, max);
  374. if( d->tstyp == POWER )
  375. {
  376. printf( "a %.6E\n", a );
  377. }
  378. if( d->tstyp >= WRONK1 )
  379. {
  380. printf( "yy1 %.4E y2 %.4E y3 %.4E y4 %.4E k %d x %.4E\n",
  381. yy1, y2, y3, y4, k, x );
  382. }
  383. }
  384. /*
  385. printf("%.8E %.8E %.4E %6ld \n", x, y, max, n);
  386. printf("%d %.8E %.8E %.4E %6ld \n", k, x, y, max, n);
  387. printf("%.6E %.6E %.6E %.4E %6ld \n", a, x, y, max, n);
  388. printf("%.6E %.6E %.6E %.6E %.4E %6ld \n", a, b, x, y, max, n);
  389. printf("%.4E %.4E %.4E %.4E %.4E %.4E %6ld \n",
  390. a, b, c, x, y, max, n);
  391. */
  392. }
  393. /* accumulate rms error */
  394. e *= 1.0e16; /* adjust range */
  395. rmsa += e * e; /* accumulate the square of the error */
  396. }
  397. /* report after NTRIALS trials */
  398. rms = 1.0e-16 * sqrt( rmsa/m );
  399. if(d->ctrl & RELERR)
  400. printf(" max = %.2E rms = %.2E\n", max, rms );
  401. else
  402. printf(" max = %.2E A rms = %.2E A\n", max, rms );
  403. } /* loop on itst */
  404. exit(0);
  405. }