1 /* $OpenBSD: testvect.c,v 1.2 2013/08/02 20:23:28 kettenis Exp $ */
2
3 /*
4 * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 /* Test vectors for math functions.
20 See C9X section F.9. */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 int __isfinite (double);
26
27 /* C9X spells lgam lgamma. */
28 #define GLIBC2 1
29
30 extern double PI;
31 static double MPI, PIO2, MPIO2, PIO4, MPIO4, THPIO4, MTHPIO4;
32
33 #if 0
34 #define PI 3.141592653589793238463E0
35 #define PIO2 1.570796326794896619231E0
36 #define PIO4 7.853981633974483096157E-1
37 #define THPIO4 2.35619449019234492884698
38 #define SQRT2 1.414213562373095048802E0
39 #define SQRTH 7.071067811865475244008E-1
40 #define INF (1.0/0.0)
41 #define MINF (-1.0/0.0)
42 #endif
43
44 extern double MACHEP, SQRTH, SQRT2;
45 extern double NAN, INFINITY, NEGZERO;
46 static double INF, MINF;
47 static double ZERO, MZERO, HALF, MHALF, ONE, MONE, TWO, MTWO, THREE, MTHREE;
48 /* #define NAN (1.0/0.0 - 1.0/0.0) */
49
50 /* Functions of one variable. */
51 double log (double);
52 double exp ( double);
53 double atan (double);
54 double sin (double);
55 double cos (double);
56 double tan (double);
57 double acos (double);
58 double asin (double);
59 double acosh (double);
60 double asinh (double);
61 double atanh (double);
62 double sinh (double);
63 double cosh (double);
64 double tanh (double);
65 double exp2 (double);
66 double expm1 (double);
67 double log10 (double);
68 double log1p (double);
69 double log2 (double);
70 double fabs (double);
71 double erf (double);
72 double erfc (double);
73 double tgamma (double);
74 double floor (double);
75 double ceil (double);
76 double cbrt (double);
77 #if GLIBC2
78 double lgamma (double);
79 #else
80 double lgam (double);
81 #endif
82
83 struct oneargument
84 {
85 char *name; /* Name of the function. */
86 double (*func) (double);
87 double *arg1;
88 double *answer;
89 int thresh; /* Error report threshold. */
90 };
91
92 static struct oneargument test1[] =
93 {
94 {"atan", atan, &ONE, &PIO4, 0},
95 {"sin", sin, &PIO2, &ONE, 0},
96 #if 0
97 {"cos", cos, &PIO4, &SQRTH, 0},
98 {"sin", sin, 32767., 1.8750655394138942394239E-1, 0},
99 {"cos", cos, 32767., 9.8226335176928229845654E-1, 0},
100 {"tan", tan, 32767., 1.9089234430221485740826E-1, 0},
101 {"sin", sin, 8388607., 9.9234509376961249835628E-1, 0},
102 {"cos", cos, 8388607., -1.2349580912475928183718E-1, 0},
103 {"tan", tan, 8388607., -8.0354556223613614748329E0, 0},
104 /*
105 {"sin", sin, 2147483647., -7.2491655514455639054829E-1, 0},
106 {"cos", cos, 2147483647., -6.8883669187794383467976E-1, 0},
107 {"tan", tan, 2147483647., 1.0523779637351339136698E0, 0},
108 */
109 {"cos", cos, &PIO2, 6.1232339957367574e-17, 1},
110 {"sin", sin, &PIO4, &SQRTH, 1},
111 #endif
112 {"acos", acos, &NAN, &NAN, 0},
113 {"acos", acos, &ONE, &ZERO, 0},
114 {"acos", acos, &TWO, &NAN, 0},
115 {"acos", acos, &MTWO, &NAN, 0},
116 {"asin", asin, &NAN, &NAN, 0},
117 {"asin", asin, &ZERO, &ZERO, 0},
118 {"asin", asin, &MZERO, &MZERO, 0},
119 {"asin", asin, &TWO, &NAN, 0},
120 {"asin", asin, &MTWO, &NAN, 0},
121 {"atan", atan, &NAN, &NAN, 0},
122 {"atan", atan, &ZERO, &ZERO, 0},
123 {"atan", atan, &MZERO, &MZERO, 0},
124 {"atan", atan, &INF, &PIO2, 0},
125 {"atan", atan, &MINF, &MPIO2, 0},
126 {"cos", cos, &NAN, &NAN, 0},
127 {"cos", cos, &ZERO, &ONE, 0},
128 {"cos", cos, &MZERO, &ONE, 0},
129 {"cos", cos, &INF, &NAN, 0},
130 {"cos", cos, &MINF, &NAN, 0},
131 {"sin", sin, &NAN, &NAN, 0},
132 {"sin", sin, &MZERO, &MZERO, 0},
133 {"sin", sin, &ZERO, &ZERO, 0},
134 {"sin", sin, &INF, &NAN, 0},
135 {"sin", sin, &MINF, &NAN, 0},
136 {"tan", tan, &NAN, &NAN, 0},
137 {"tan", tan, &ZERO, &ZERO, 0},
138 {"tan", tan, &MZERO, &MZERO, 0},
139 {"tan", tan, &INF, &NAN, 0},
140 {"tan", tan, &MINF, &NAN, 0},
141 {"acosh", acosh, &NAN, &NAN, 0},
142 {"acosh", acosh, &ONE, &ZERO, 0},
143 {"acosh", acosh, &INF, &INF, 0},
144 {"acosh", acosh, &HALF, &NAN, 0},
145 {"acosh", acosh, &MONE, &NAN, 0},
146 {"asinh", asinh, &NAN, &NAN, 0},
147 {"asinh", asinh, &ZERO, &ZERO, 0},
148 {"asinh", asinh, &MZERO, &MZERO, 0},
149 {"asinh", asinh, &INF, &INF, 0},
150 {"asinh", asinh, &MINF, &MINF, 0},
151 {"atanh", atanh, &NAN, &NAN, 0},
152 {"atanh", atanh, &ZERO, &ZERO, 0},
153 {"atanh", atanh, &MZERO, &MZERO, 0},
154 {"atanh", atanh, &ONE, &INF, 0},
155 {"atanh", atanh, &MONE, &MINF, 0},
156 {"atanh", atanh, &TWO, &NAN, 0},
157 {"atanh", atanh, &MTWO, &NAN, 0},
158 {"cosh", cosh, &NAN, &NAN, 0},
159 {"cosh", cosh, &ZERO, &ONE, 0},
160 {"cosh", cosh, &MZERO, &ONE, 0},
161 {"cosh", cosh, &INF, &INF, 0},
162 {"cosh", cosh, &MINF, &INF, 0},
163 {"sinh", sinh, &NAN, &NAN, 0},
164 {"sinh", sinh, &ZERO, &ZERO, 0},
165 {"sinh", sinh, &MZERO, &MZERO, 0},
166 {"sinh", sinh, &INF, &INF, 0},
167 {"sinh", sinh, &MINF, &MINF, 0},
168 {"tanh", tanh, &NAN, &NAN, 0},
169 {"tanh", tanh, &ZERO, &ZERO, 0},
170 {"tanh", tanh, &MZERO, &MZERO, 0},
171 {"tanh", tanh, &INF, &ONE, 0},
172 {"tanh", tanh, &MINF, &MONE, 0},
173 {"exp", exp, &NAN, &NAN, 0},
174 {"exp", exp, &ZERO, &ONE, 0},
175 {"exp", exp, &MZERO, &ONE, 0},
176 {"exp", exp, &INF, &INF, 0},
177 {"exp", exp, &MINF, &ZERO, 0},
178 #if !GLIBC2
179 {"exp2", exp2, &NAN, &NAN, 0},
180 {"exp2", exp2, &ZERO, &ONE, 0},
181 {"exp2", exp2, &MZERO, &ONE, 0},
182 {"exp2", exp2, &INF, &INF, 0},
183 {"exp2", exp2, &MINF, &ZERO, 0},
184 #endif
185 {"expm1", expm1, &NAN, &NAN, 0},
186 {"expm1", expm1, &ZERO, &ZERO, 0},
187 {"expm1", expm1, &MZERO, &MZERO, 0},
188 {"expm1", expm1, &INF, &INF, 0},
189 {"expm1", expm1, &MINF, &MONE, 0},
190 {"log", log, &NAN, &NAN, 0},
191 {"log", log, &ZERO, &MINF, 0},
192 {"log", log, &MZERO, &MINF, 0},
193 {"log", log, &ONE, &ZERO, 0},
194 {"log", log, &MONE, &NAN, 0},
195 {"log", log, &INF, &INF, 0},
196 {"log10", log10, &NAN, &NAN, 0},
197 {"log10", log10, &ZERO, &MINF, 0},
198 {"log10", log10, &MZERO, &MINF, 0},
199 {"log10", log10, &ONE, &ZERO, 0},
200 {"log10", log10, &MONE, &NAN, 0},
201 {"log10", log10, &INF, &INF, 0},
202 {"log1p", log1p, &NAN, &NAN, 0},
203 {"log1p", log1p, &ZERO, &ZERO, 0},
204 {"log1p", log1p, &MZERO, &MZERO, 0},
205 {"log1p", log1p, &MONE, &MINF, 0},
206 {"log1p", log1p, &MTWO, &NAN, 0},
207 {"log1p", log1p, &INF, &INF, 0},
208 #if !GLIBC2
209 {"log2", log2, &NAN, &NAN, 0},
210 {"log2", log2, &ZERO, &MINF, 0},
211 {"log2", log2, &MZERO, &MINF, 0},
212 {"log2", log2, &MONE, &NAN, 0},
213 {"log2", log2, &INF, &INF, 0},
214 #endif
215 /* {"fabs", fabs, NAN, NAN, 0}, */
216 {"fabs", fabs, &ONE, &ONE, 0},
217 {"fabs", fabs, &MONE, &ONE, 0},
218 {"fabs", fabs, &ZERO, &ZERO, 0},
219 {"fabs", fabs, &MZERO, &ZERO, 0},
220 {"fabs", fabs, &INF, &INF, 0},
221 {"fabs", fabs, &MINF, &INF, 0},
222 {"cbrt", cbrt, &NAN, &NAN, 0},
223 {"cbrt", cbrt, &ZERO, &ZERO, 0},
224 {"cbrt", cbrt, &MZERO, &MZERO, 0},
225 {"cbrt", cbrt, &INF, &INF, 0},
226 {"cbrt", cbrt, &MINF, &MINF, 0},
227 {"erf", erf, &NAN, &NAN, 0},
228 {"erf", erf, &ZERO, &ZERO, 0},
229 {"erf", erf, &MZERO, &MZERO, 0},
230 {"erf", erf, &INF, &ONE, 0},
231 {"erf", erf, &MINF, &MONE, 0},
232 {"erfc", erfc, &NAN, &NAN, 0},
233 {"erfc", erfc, &INF, &ZERO, 0},
234 {"erfc", erfc, &MINF, &TWO, 0},
235 {"tgamma", tgamma, &NAN, &NAN, 0},
236 {"tgamma", tgamma, &INF, &INF, 0},
237 {"tgamma", tgamma, &MONE, &NAN, 0},
238 {"tgamma", tgamma, &ZERO, &INF, 0},
239 {"tgamma", tgamma, &MINF, &NAN, 0},
240 #if GLIBC2
241 {"lgamma", lgamma, &NAN, &NAN, 0},
242 {"lgamma", lgamma, &INF, &INF, 0},
243 {"lgamma", lgamma, &MONE, &INF, 0},
244 {"lgamma", lgamma, &ZERO, &INF, 0},
245 {"lgamma", lgamma, &MINF, &INF, 0},
246 #else
247 {"lgam", lgam, &NAN, &NAN, 0},
248 {"lgam", lgam, &INF, &INF, 0},
249 {"lgam", lgam, &MONE, &INF, 0},
250 {"lgam", lgam, &ZERO, &INF, 0},
251 {"lgam", lgam, &MINF, &INF, 0},
252 #endif
253 {"ceil", ceil, &NAN, &NAN, 0},
254 {"ceil", ceil, &ZERO, &ZERO, 0},
255 {"ceil", ceil, &MZERO, &MZERO, 0},
256 {"ceil", ceil, &INF, &INF, 0},
257 {"ceil", ceil, &MINF, &MINF, 0},
258 {"floor", floor, &NAN, &NAN, 0},
259 {"floor", floor, &ZERO, &ZERO, 0},
260 {"floor", floor, &MZERO, &MZERO, 0},
261 {"floor", floor, &INF, &INF, 0},
262 {"floor", floor, &MINF, &MINF, 0},
263 {"null", NULL, &ZERO, &ZERO, 0},
264 };
265
266 /* Functions of two variables. */
267 double atan2 (double, double);
268 double pow (double, double);
269
270 struct twoarguments
271 {
272 char *name; /* Name of the function. */
273 double (*func) (double, double);
274 double *arg1;
275 double *arg2;
276 double *answer;
277 int thresh;
278 };
279
280 static struct twoarguments test2[] =
281 {
282 {"atan2", atan2, &ZERO, &ONE, &ZERO, 0},
283 {"atan2", atan2, &MZERO, &ONE, &MZERO, 0},
284 {"atan2", atan2, &ZERO, &ZERO, &ZERO, 0},
285 {"atan2", atan2, &MZERO, &ZERO, &MZERO, 0},
286 {"atan2", atan2, &ZERO, &MONE, &PI, 0},
287 {"atan2", atan2, &MZERO, &MONE, &MPI, 0},
288 {"atan2", atan2, &ZERO, &MZERO, &PI, 0},
289 {"atan2", atan2, &MZERO, &MZERO, &MPI, 0},
290 {"atan2", atan2, &ONE, &ZERO, &PIO2, 0},
291 {"atan2", atan2, &ONE, &MZERO, &PIO2, 0},
292 {"atan2", atan2, &MONE, &ZERO, &MPIO2, 0},
293 {"atan2", atan2, &MONE, &MZERO, &MPIO2, 0},
294 {"atan2", atan2, &ONE, &INF, &ZERO, 0},
295 {"atan2", atan2, &MONE, &INF, &MZERO, 0},
296 {"atan2", atan2, &INF, &ONE, &PIO2, 0},
297 {"atan2", atan2, &INF, &MONE, &PIO2, 0},
298 {"atan2", atan2, &MINF, &ONE, &MPIO2, 0},
299 {"atan2", atan2, &MINF, &MONE, &MPIO2, 0},
300 {"atan2", atan2, &ONE, &MINF, &PI, 0},
301 {"atan2", atan2, &MONE, &MINF, &MPI, 0},
302 {"atan2", atan2, &INF, &INF, &PIO4, 0},
303 {"atan2", atan2, &MINF, &INF, &MPIO4, 0},
304 {"atan2", atan2, &INF, &MINF, &THPIO4, 0},
305 {"atan2", atan2, &MINF, &MINF, &MTHPIO4, 0},
306 {"atan2", atan2, &ONE, &ONE, &PIO4, 0},
307 {"atan2", atan2, &NAN, &ONE, &NAN, 0},
308 {"atan2", atan2, &ONE, &NAN, &NAN, 0},
309 {"atan2", atan2, &NAN, &NAN, &NAN, 0},
310 {"pow", pow, &ONE, &ZERO, &ONE, 0},
311 {"pow", pow, &ONE, &MZERO, &ONE, 0},
312 {"pow", pow, &MONE, &ZERO, &ONE, 0},
313 {"pow", pow, &MONE, &MZERO, &ONE, 0},
314 {"pow", pow, &INF, &ZERO, &ONE, 0},
315 {"pow", pow, &INF, &MZERO, &ONE, 0},
316 {"pow", pow, &NAN, &ZERO, &ONE, 0},
317 {"pow", pow, &NAN, &MZERO, &ONE, 0},
318 {"pow", pow, &TWO, &INF, &INF, 0},
319 {"pow", pow, &MTWO, &INF, &INF, 0},
320 {"pow", pow, &HALF, &INF, &ZERO, 0},
321 {"pow", pow, &MHALF, &INF, &ZERO, 0},
322 {"pow", pow, &TWO, &MINF, &ZERO, 0},
323 {"pow", pow, &MTWO, &MINF, &ZERO, 0},
324 {"pow", pow, &HALF, &MINF, &INF, 0},
325 {"pow", pow, &MHALF, &MINF, &INF, 0},
326 {"pow", pow, &INF, &HALF, &INF, 0},
327 {"pow", pow, &INF, &TWO, &INF, 0},
328 {"pow", pow, &INF, &MHALF, &ZERO, 0},
329 {"pow", pow, &INF, &MTWO, &ZERO, 0},
330 {"pow", pow, &MINF, &THREE, &MINF, 0},
331 {"pow", pow, &MINF, &TWO, &INF, 0},
332 {"pow", pow, &MINF, &MTHREE, &MZERO, 0},
333 {"pow", pow, &MINF, &MTWO, &ZERO, 0},
334 {"pow", pow, &NAN, &ONE, &NAN, 0},
335 {"pow", pow, &ONE, &NAN, &ONE, 0},
336 {"pow", pow, &NAN, &NAN, &NAN, 0},
337 {"pow", pow, &ONE, &INF, &ONE, 0},
338 {"pow", pow, &MONE, &INF, &ONE, 0},
339 {"pow", pow, &ONE, &MINF, &ONE, 0},
340 {"pow", pow, &MONE, &MINF, &ONE, 0},
341 {"pow", pow, &MTWO, &HALF, &NAN, 0},
342 {"pow", pow, &ZERO, &MTHREE, &INF, 0},
343 {"pow", pow, &MZERO, &MTHREE, &MINF, 0},
344 {"pow", pow, &ZERO, &MHALF, &INF, 0},
345 {"pow", pow, &MZERO, &MHALF, &INF, 0},
346 {"pow", pow, &ZERO, &THREE, &ZERO, 0},
347 {"pow", pow, &MZERO, &THREE, &MZERO, 0},
348 {"pow", pow, &ZERO, &HALF, &ZERO, 0},
349 {"pow", pow, &MZERO, &HALF, &ZERO, 0},
350 {"null", NULL, &ZERO, &ZERO, &ZERO, 0},
351 };
352
353 /* Integer functions of one variable. */
354
355 int isnan (double);
356 int __signbit (double);
357
358 struct intans
359 {
360 char *name; /* Name of the function. */
361 int (*func) (double);
362 double *arg1;
363 int ianswer;
364 };
365
366 static struct intans test3[] =
367 {
368 {"isfinite", __isfinite, &ZERO, 1},
369 {"isfinite", __isfinite, &INF, 0},
370 {"isfinite", __isfinite, &MINF, 0},
371 {"isnan", isnan, &NAN, 1},
372 {"isnan", isnan, &INF, 0},
373 {"isnan", isnan, &ZERO, 0},
374 {"isnan", isnan, &MZERO, 0},
375 {"signbit", __signbit, &MZERO, 1},
376 {"signbit", __signbit, &MONE, 1},
377 {"signbit", __signbit, &ZERO, 0},
378 {"signbit", __signbit, &ONE, 0},
379 {"signbit", __signbit, &MINF, 1},
380 {"signbit", __signbit, &INF, 0},
381 {"null", NULL, &ZERO, 0},
382 };
383
384 static volatile double x1;
385 static volatile double x2;
386 static volatile double y;
387 static volatile double answer;
388
389 static void
pvec(x)390 pvec(x)
391 double x;
392 {
393 union
394 {
395 double d;
396 unsigned short s[4];
397 } u;
398 int i;
399
400 u.d = x;
401 for (i = 0; i < 4; i++)
402 printf ("0x%04x ", u.s[i]);
403 printf ("\n");
404 }
405
406
407 int
testvect()408 testvect ()
409 {
410 int i, nerrors, k, ianswer, ntests;
411 double (*fun1) (double);
412 double (*fun2) (double, double);
413 int (*fun3) (double);
414 double e;
415 union
416 {
417 double d;
418 char c[8];
419 } u, v;
420
421 ZERO = 0.0;
422 MZERO = NEGZERO;
423 HALF = 0.5;
424 MHALF = -HALF;
425 ONE = 1.0;
426 MONE = -ONE;
427 TWO = 2.0;
428 MTWO = -TWO;
429 THREE = 3.0;
430 MTHREE = -THREE;
431 INF = INFINITY;
432 MINF = -INFINITY;
433 MPI = -PI;
434 PIO2 = 0.5 * PI;
435 MPIO2 = -PIO2;
436 PIO4 = 0.5 * PIO2;
437 MPIO4 = -PIO4;
438 THPIO4 = 3.0 * PIO4;
439 MTHPIO4 = -THPIO4;
440
441 nerrors = 0;
442 ntests = 0;
443 i = 0;
444 for (;;)
445 {
446 fun1 = test1[i].func;
447 if (fun1 == NULL)
448 break;
449 x1 = *(test1[i].arg1);
450 y = (*(fun1)) (x1);
451 answer = *(test1[i].answer);
452 if (test1[i].thresh == 0)
453 {
454 v.d = answer;
455 u.d = y;
456 if (memcmp(u.c, v.c, 8) != 0)
457 {
458 if( isnan(v.d) && isnan(u.d) )
459 goto nxttest1;
460 goto wrongone;
461 }
462 else
463 goto nxttest1;
464 }
465 if (y != answer)
466 {
467 e = y - answer;
468 if (answer != 0.0)
469 e = e / answer;
470 if (e < 0)
471 e = -e;
472 if (e > test1[i].thresh * MACHEP)
473 {
474 wrongone:
475 printf ("%s (%.16e) = %.16e\n should be %.16e\n",
476 test1[i].name, x1, y, answer);
477 nerrors += 1;
478 }
479 }
480 nxttest1:
481 ntests += 1;
482 i += 1;
483 }
484
485 i = 0;
486 for (;;)
487 {
488 fun2 = test2[i].func;
489 if (fun2 == NULL)
490 break;
491 x1 = *(test2[i].arg1);
492 x2 = *(test2[i].arg2);
493 y = (*(fun2)) (x1, x2);
494 answer = *(test2[i].answer);
495 if (test2[i].thresh == 0)
496 {
497 v.d = answer;
498 u.d = y;
499 if (memcmp(u.c, v.c, 8) != 0)
500 {
501 if( isnan(v.d) && isnan(u.d) )
502 goto nxttest2;
503 #if 0
504 if( isnan(v.d) )
505 pvec(v.d);
506 if( isnan(u.d) )
507 pvec(u.d);
508 #endif
509 goto wrongtwo;
510 }
511 else
512 goto nxttest2;
513 }
514 if (y != answer)
515 {
516 e = y - answer;
517 if (answer != 0.0)
518 e = e / answer;
519 if (e < 0)
520 e = -e;
521 if (e > test2[i].thresh * MACHEP)
522 {
523 wrongtwo:
524 printf ("%s (%.16e, %.16e) = %.16e\n should be %.16e\n",
525 test2[i].name, x1, x2, y, answer);
526 nerrors += 1;
527 }
528 }
529 nxttest2:
530 ntests += 1;
531 i += 1;
532 }
533
534
535 i = 0;
536 for (;;)
537 {
538 fun3 = test3[i].func;
539 if (fun3 == NULL)
540 break;
541 x1 = *(test3[i].arg1);
542 k = (*(fun3)) (x1);
543 ianswer = test3[i].ianswer;
544 if (k != ianswer)
545 {
546 printf ("%s (%.16e) = %d\n should be. %d\n",
547 test3[i].name, x1, k, ianswer);
548 nerrors += 1;
549 }
550 ntests += 1;
551 i += 1;
552 }
553
554 printf ("%d errors in %d tests\n", nerrors, ntests);
555 return (nerrors);
556 }
557