1 /*
2 * Copyright (c) 1994 Cygnus Support.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * and/or other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * at Cygnus Support, Inc. Cygnus Support, Inc. may not be used to
11 * endorse or promote products derived from this software without
12 * specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16 */
17 /*
18 Test the library maths functions using trusted precomputed test
19 vectors.
20
21 These vectors were originally generated on a sun3 with a 68881 using
22 80 bit precision, but ...
23
24 Each function is called with a variety of interesting arguments.
25 Note that many of the polynomials we use behave badly when the
26 domain is stressed, so the numbers in the vectors depend on what is
27 useful to test - eg sin(1e30) is pointless - the arg has to be
28 reduced modulo pi, and after that there's no bits of significance
29 left to evaluate with - any number would be just as precise as any
30 other.
31
32
33 */
34
35 #include "test.h"
36 #include <math.h>
37 #include <float.h>
38 #include <errno.h>
39 #include <stdio.h>
40 #include <string.h>
41 #include <stdbool.h>
42
43 extern int inacc;
44
45 int merror;
46 double mretval = 64;
47 int traperror = 1;
48 char *mname;
49
50 void
translate_to(FILE * file,double r)51 translate_to (FILE *file,
52 double r)
53 {
54 __ieee_double_shape_type bits;
55 bits.value = r;
56 fprintf(file, "0x%08lx, 0x%08lx", (unsigned long) bits.parts.msw, (unsigned long) bits.parts.lsw);
57 }
58
59 /* Convert double to float, preserving issignaling status and NaN sign */
60
61 #define to_float(f,d) do { \
62 if (__issignaling(d)) { \
63 if (signbit(d)) \
64 (f) = -__builtin_nansf(""); \
65 else \
66 (f) = __builtin_nansf(""); \
67 } else if (isnan(d)) { \
68 if (signbit(d)) \
69 (f) = -__builtin_nanf(""); \
70 else \
71 (f) = __builtin_nanf(""); \
72 } else \
73 (f) = (float) (d); \
74 } while(0)
75
76 #define to_double(d,f) do { \
77 if (__issignalingf(f)) { \
78 if (signbit(f)) \
79 (d) = -__builtin_nans(""); \
80 else \
81 (d) = __builtin_nans(""); \
82 } else if (isnanf(f)) { \
83 if (signbit(f)) \
84 (d) = -__builtin_nan(""); \
85 else \
86 (d) = __builtin_nan(""); \
87 } else \
88 (d) = (double) (f); \
89 } while(0)
90
91 int
ffcheck_id(double is,one_line_type * p,char * name,int serrno,int merror,int id)92 ffcheck_id(double is,
93 one_line_type *p,
94 char *name,
95 int serrno,
96 int merror,
97 int id)
98 {
99 /* Make sure the answer isn't to far wrong from the correct value */
100 __ieee_double_shape_type correct, isbits;
101 int mag;
102 isbits.value = is;
103
104 (void) serrno;
105 (void) merror;
106 correct.parts.msw = p->qs[id].msw;
107 correct.parts.lsw = p->qs[id].lsw;
108
109 int error_bit = p->error_bit;
110
111 mag = mag_of_error(correct.value, is);
112
113 if (error_bit > 63)
114 error_bit = 63;
115
116 /* All signaling nans are the "same", as are all quiet nans.
117 * On i386, just returning a value converts signaling nans to quiet
118 * nans, let that pass
119 */
120 if (isnan(correct.value) && isnan(is)
121 #ifndef __i386__
122 && (issignaling(correct.value) == issignaling(is))
123 #endif
124 )
125 {
126 mag = 64;
127 }
128
129 if (mag < error_bit)
130 {
131 inacc ++;
132
133 printf("%s:%d, inaccurate answer: bit %d (%08lx%08lx %08lx%08lx) (%g %g)\n",
134 name, p->line, mag,
135 (unsigned long) correct.parts.msw,
136 (unsigned long) correct.parts.lsw,
137 (unsigned long) isbits.parts.msw,
138 (unsigned long) isbits.parts.lsw,
139 correct.value, is);
140 }
141
142 #if 0
143 if (p->qs[id].merror != merror)
144 {
145 /* Beware, matherr doesn't exist anymore. */
146 printf("testing %s_vec.c:%d, matherr wrong: %d %d\n",
147 name, p->line, merror, p->qs[id].merror);
148 }
149
150 if (p->qs[id].errno_val != errno)
151 {
152 printf("testing %s_vec.c:%d, errno wrong: %d %d\n",
153 name, p->line, errno, p->qs[id].errno_val);
154
155 }
156 #endif
157 return mag;
158 }
159
160 int
ffcheck(double is,one_line_type * p,char * name,int serrno,int merror)161 ffcheck(double is,
162 one_line_type *p,
163 char *name,
164 int serrno,
165 int merror)
166 {
167 return ffcheck_id(is, p, name, serrno, merror, 0);
168 }
169
170 int
fffcheck_id(float is,one_line_type * p,char * name,int serrno,int merror,int id)171 fffcheck_id (float is,
172 one_line_type *p,
173 char *name,
174 int serrno,
175 int merror,
176 int id)
177 {
178 /* Make sure the answer isn't to far wrong from the correct value */
179 __ieee_float_shape_type correct, isbits;
180 __ieee_double_shape_type correct_double;
181 __ieee_double_shape_type is_double;
182 int mag;
183
184 (void) serrno;
185 (void) merror;
186
187 isbits.value = is;
188 to_double(is_double.value, is);
189
190 correct_double.parts.msw = p->qs[id].msw;
191 correct_double.parts.lsw = p->qs[id].lsw;
192 to_float(correct.value, correct_double.value);
193 // printf("%s got 0x%08x want 0x%08x\n", name, isbits.p1, correct.p1);
194
195 int error_bit = p->error_bit;
196
197 if (error_bit > 31)
198 error_bit = 31;
199
200 mag = fmag_of_error(correct.value, is);
201
202 /* All signaling nans are the "same", as are all quiet nans */
203 if (isnan(correct.value) && isnan(is)
204 #ifndef __i386__
205 /* i386 calling convention ends up always converting snan into qnan */
206 && (__issignalingf(correct.value) == __issignalingf(is))
207 #endif
208 )
209 {
210 mag = 32;
211 }
212
213 if (mag < error_bit)
214 {
215 inacc ++;
216
217 printf("%s:%d, inaccurate answer: bit %d (%08lx %08lx) (%g %g) (is double 0x%08lx, 0x%08lx)\n",
218 name, p->line, mag,
219 (unsigned long) (uint32_t) correct.p1,
220 (unsigned long) (uint32_t) isbits.p1,
221 (double) correct.value,
222 (double) is,
223 (unsigned long) (uint32_t) is_double.parts.msw,
224 (unsigned long) (uint32_t) is_double.parts.lsw);
225 }
226
227 #if 0
228 if (p->qs[id].merror != merror)
229 {
230 /* Beware, matherr doesn't exist anymore. */
231 printf("testing %s_vec.c:%d, matherr wrong: %d %d\n",
232 name, p->line, merror, p->qs[id].merror);
233 }
234
235 if (p->qs[id].errno_val != errno)
236 {
237 printf("testing %s_vec.c:%d, errno wrong: %d %d\n",
238 name, p->line, errno, p->qs[id].errno_val);
239
240 }
241 #endif
242 return mag;
243 }
244
245 int
fffcheck(float is,one_line_type * p,char * name,int serrno,int merror)246 fffcheck (float is,
247 one_line_type *p,
248 char *name,
249 int serrno,
250 int merror)
251 {
252 return fffcheck_id(is, p, name, serrno, merror, 0);
253 }
254
255 double
thedouble(uint32_t msw,uint32_t lsw,double * r)256 thedouble (uint32_t msw,
257 uint32_t lsw, double *r)
258 {
259 __ieee_double_shape_type x;
260
261 x.parts.msw = msw;
262 x.parts.lsw = lsw;
263 if (r)
264 memcpy(r, &x.value, sizeof(double));
265 return x.value;
266 }
267
268 int calc;
269 extern int reduce;
270
271
272 void
frontline(FILE * f,int mag,one_line_type * p,double result,int merror,int my_errno,char * args,char * name)273 frontline (FILE *f,
274 int mag,
275 one_line_type *p,
276 double result,
277 int merror,
278 int my_errno,
279 char *args,
280 char *name)
281 {
282 (void) name;
283 /* float returns can never have more than 32 bits of accuracy */
284 if (*args == 'f' && mag > 32)
285 mag = 32;
286
287 if (reduce && p->error_bit < mag)
288 {
289 fprintf(f, "{%2d,", p->error_bit);
290 }
291 else
292 {
293 fprintf(f, "{%2d,",mag);
294 }
295
296
297 fprintf(f,"%2d,%3d,", merror,my_errno);
298 fprintf(f, "__LINE__, ");
299
300 if (calc)
301 {
302 translate_to(f, result);
303 }
304 else
305 {
306 translate_to(f, thedouble(p->qs[0].msw, p->qs[0].lsw, NULL));
307 }
308
309 fprintf(f, ", ");
310
311 fprintf(f,"0x%08lx, 0x%08lx", (unsigned long) p->qs[1].msw, (unsigned long) p->qs[1].lsw);
312
313
314 if (args[2])
315 {
316 fprintf(f, ", ");
317 fprintf(f,"0x%08lx, 0x%08lx", (unsigned long) p->qs[2].msw, (unsigned long) p->qs[2].lsw);
318 }
319
320 fprintf(f,"}, /* %g=f(%g",result,
321 thedouble(p->qs[1].msw, p->qs[1].lsw, NULL));
322
323 if (args[2])
324 {
325 fprintf(f,", %g", thedouble(p->qs[2].msw,p->qs[2].lsw, NULL));
326 }
327 fprintf(f, ")*/\n");
328 }
329
330 void
finish(FILE * f,int vector,double result,one_line_type * p,char * args,char * name)331 finish (FILE *f,
332 int vector,
333 double result,
334 one_line_type *p,
335 char *args,
336 char *name)
337 {
338 int mag;
339
340 mag = ffcheck(result, p,name, merror, errno);
341 if (vector)
342 {
343 frontline(f, mag, p, result, merror, errno, args , name);
344 }
345 }
346
347 void
finish2(FILE * f,int vector,double result,double result2,one_line_type * p,char * args,char * name)348 finish2 (FILE *f,
349 int vector,
350 double result,
351 double result2,
352 one_line_type *p,
353 char *args,
354 char *name)
355 {
356 int mag, mag2;
357
358 mag = ffcheck(result, p,name, merror, errno);
359 mag2 = ffcheck_id(result2, p,name, merror, errno, 2);
360 if (mag2 < mag)
361 mag = mag2;
362 if (vector)
363 {
364 __ieee_double_shape_type result2_double;
365 result2_double.value = result2;
366 p->qs[2].msw = result2_double.parts.msw;
367 p->qs[2].lsw = result2_double.parts.lsw;
368 frontline(f, mag, p, result, merror, errno, args , name);
369 }
370 }
371
372 void
ffinish(FILE * f,int vector,float fresult,one_line_type * p,char * args,char * name)373 ffinish (FILE *f,
374 int vector,
375 float fresult,
376 one_line_type *p,
377 char *args,
378 char *name)
379 {
380 int mag;
381
382 mag = fffcheck(fresult, p,name, merror, errno);
383 if (vector)
384 {
385 frontline(f, mag, p, (double) fresult, merror, errno, args , name);
386 }
387 }
388
389 void
ffinish2(FILE * f,int vector,float fresult,float fresult2,one_line_type * p,char * args,char * name)390 ffinish2 (FILE *f,
391 int vector,
392 float fresult,
393 float fresult2,
394 one_line_type *p,
395 char *args,
396 char *name)
397 {
398 int mag, mag2;
399
400 mag = fffcheck(fresult, p,name, merror, errno);
401 mag2 = fffcheck_id(fresult2, p, name, merror, errno, 2);
402 if (mag2 < mag)
403 mag = mag2;
404 if (vector)
405 {
406 __ieee_double_shape_type result2_double;
407 to_double(result2_double.value, (double) fresult2);
408 p->qs[2].msw = result2_double.parts.msw;
409 p->qs[2].lsw = result2_double.parts.lsw;
410 frontline(f, mag, p, (double) fresult, merror, errno, args , name);
411 }
412 }
413
414 extern int redo;
415
416 bool
in_float_range(double arg)417 in_float_range(double arg)
418 {
419 if (isinf(arg) || isnan(arg))
420 return true;
421 return -(double) FLT_MAX <= arg && arg < (double) FLT_MAX;
422 }
423
424 void
run_vector_1(int vector,one_line_type * p,char * func,char * name,char * args)425 run_vector_1 (int vector,
426 one_line_type *p,
427 char *func,
428 char *name,
429 char *args)
430 {
431 FILE *f = NULL;
432 double result;
433 float fresult;
434
435 #if 0
436 if (vector)
437 {
438
439 VECOPEN(name, f);
440
441 if (redo)
442 {
443 double k;
444 union {
445 struct { uint32_t a, b; };
446 double d;
447 } d, d4;
448
449 for (k = -.2; k < .2; k+= 0.00132)
450 {
451 d.d = k;
452 d4.d = k + 4;
453 fprintf(f,"{1,1, 1,1, 0,0,0x%08lx,0x%08lx, 0x%08lx, 0x%08lx},\n",
454 (unsigned long) d.a, (unsigned long) d.b, (unsigned long) d4.a, (unsigned long) d4.b);
455
456 }
457
458 for (k = -1.2; k < 1.2; k+= 0.01)
459 {
460 d.d = k;
461 d4.d = k + 4;
462 fprintf(f,"{1,1, 1,1, 0,0,0x%08lx,0x%08lx, 0x%08lx, 0x%08lx},\n",
463 (unsigned long) d.a, (unsigned long) d.b, (unsigned long) d4.a, (unsigned long) d4.b);
464
465 }
466 for (k = -M_PI *2; k < M_PI *2; k+= M_PI/2)
467 {
468 d.d = k;
469 d4.d = k + 4;
470 fprintf(f,"{1,1, 1,1, 0,0,0x%08lx,0x%08lx, 0x%08lx, 0x%08lx},\n",
471 (unsigned long) d.a, (unsigned long) d.b, (unsigned long) d4.a, (unsigned long) d4.b);
472
473 }
474
475 for (k = -30; k < 30; k+= 1.7)
476 {
477 d.d = k;
478 d4.d = k + 4;
479 fprintf(f,"{2,2, 1,1, 0,0, 0x%08lx,0x%08lx, 0x%08lx, 0x%08lx},\n",
480 (unsigned long) d.a, (unsigned long) d.b, (unsigned long) d4.a, (unsigned long) d4.b);
481
482 }
483 VECCLOSE(f, name, args);
484 return;
485 }
486 }
487 #endif
488
489 newfunc(name);
490 while (p->line)
491 {
492 double arg1;
493 thedouble(p->qs[1].msw, p->qs[1].lsw, &arg1);
494 double arg2;
495 thedouble(p->qs[2].msw, p->qs[2].lsw, &arg2);
496
497 errno = 0;
498 merror = 0;
499 mname = 0;
500
501
502 line(p->line);
503
504 merror = 0;
505 errno = 123;
506
507 if (strcmp(args,"dd")==0)
508 {
509 typedef double (*pdblfunc) (double);
510
511 /* Double function returning a double */
512
513 result = ((pdblfunc)(func))(arg1);
514
515 finish(f,vector, result, p, args, name);
516 }
517 else if (strcmp(args,"ff")==0)
518 {
519 float arga;
520
521 typedef float (*pdblfunc) (float);
522
523 /* Double function returning a double */
524
525 if (in_float_range(arg1))
526 {
527 to_float(arga, arg1);
528 fresult = ((pdblfunc)(func))(arga);
529 ffinish(f, vector, fresult, p,args, name);
530 }
531 }
532 else if (strcmp(args,"ddd")==0)
533 {
534 typedef double (*pdblfunc) (double,double);
535
536 result = ((pdblfunc)(func))(arg1,arg2);
537 finish(f, vector, result, p,args, name);
538 }
539 else if (strcmp(args,"fff")==0)
540 {
541 float arga;
542 float argb;
543
544 typedef float (*pdblfunc) (float,float);
545
546 if (in_float_range(arg1) && in_float_range(arg2))
547 {
548 to_float(arga, arg1);
549 to_float(argb, arg2);
550 fresult = ((pdblfunc)(func))(arga, argb);
551 // printf("0x%08x = %s(0x%08x, 0x%08x)\n",
552 // float_bits(fresult), name, float_bits(arga), float_bits(argb));
553 ffinish(f, vector, fresult, p,args, name);
554 }
555 }
556 else if (strcmp(args,"did")==0)
557 {
558 typedef double (*pdblfunc) (int,double);
559
560 result = ((pdblfunc)(func))((int)arg1,arg2);
561 finish(f, vector, result, p,args, name);
562 }
563 else if (strcmp(args,"fif")==0)
564 {
565 float argb;
566
567 typedef float (*pdblfunc) (int,float);
568
569
570 if (in_float_range(arg2))
571 {
572 to_float(argb, arg2);
573 fresult = ((pdblfunc)(func))((int)arg1, argb);
574 ffinish(f, vector, fresult, p,args, name);
575 }
576 }
577 else if (strcmp(args,"id")==0)
578 {
579 typedef int (*pdblfunc)(double);
580
581 result = (double) ((pdblfunc)(func))(arg1);
582 finish(f, vector, result, p, args, name);
583 }
584 else if (strcmp(args,"ddp") == 0)
585 {
586 typedef double (*pdblfunc)(double, double *);
587 double result2;
588
589 result = (double) ((pdblfunc)(func))(arg1, &result2);
590 finish2(f, vector, result, result2, p, args, name);
591 }
592 else if (strcmp(args,"ffp") == 0)
593 {
594 typedef float (*pdblfunc)(float, float *);
595 float result2;
596
597 fresult = (float) ((pdblfunc)(func))(arg1, &result2);
598 ffinish2(f, vector, fresult, result2, p, args, name);
599 }
600 else if (strcmp(args,"ddi") == 0)
601 {
602 typedef double (*pdblfunc)(double, int);
603
604 result = ((pdblfunc)func) (arg1, (int) arg2);
605 finish(f, vector, result, p, args, name);
606 }
607 else if (strcmp(args,"ffi") == 0)
608 {
609 typedef float (*pdblfunc)(float, int);
610
611 fresult = ((pdblfunc)func) (arg1, (int) arg2);
612 ffinish(f, vector, fresult, p, args, name);
613 }
614 p++;
615 }
616 if (vector && f)
617 {
618 VECCLOSE(f, name, args);
619 }
620 }
621
622 void
test_math(int vector)623 test_math (int vector)
624 {
625 test_acos(vector);
626 test_acosf(vector);
627 test_acosh(vector);
628 test_acoshf(vector);
629 test_asin(vector);
630 test_asinf(vector);
631 test_asinh(vector);
632 test_asinhf(vector);
633 test_atan(vector);
634 test_atan2(vector);
635 test_atan2f(vector);
636 test_atanf(vector);
637 test_atanh(vector);
638 test_atanhf(vector);
639 test_ceil(vector);
640 test_ceilf(vector);
641 test_copysign(vector);
642 test_copysignf(vector);
643 test_cos(vector);
644 test_cosf(vector);
645 test_cosh(vector);
646 test_coshf(vector);
647 test_erf(vector);
648 test_erfc(vector);
649 test_erfcf(vector);
650 test_erff(vector);
651 test_exp(vector);
652 test_expf(vector);
653 test_fabs(vector);
654 test_fabsf(vector);
655 test_floor(vector);
656 test_floorf(vector);
657 test_fmod(vector);
658 test_fmodf(vector);
659 test_gamma(vector);
660 test_gammaf(vector);
661 test_hypot(vector);
662 test_hypotf(vector);
663 test_issignaling(vector);
664 test_j0(vector);
665 test_j0f(vector);
666 test_j1(vector);
667 test_j1f(vector);
668 test_jn(vector);
669 test_jnf(vector);
670 test_log(vector);
671 test_log10(vector);
672 test_log10f(vector);
673 test_log1p(vector);
674 test_log1pf(vector);
675 test_log2(vector);
676 test_log2f(vector);
677 test_logf(vector);
678 test_modf(vector);
679 test_modff(vector);
680 test_pow_vec(vector);
681 test_powf_vec(vector);
682 test_scalb(vector);
683 test_scalbf(vector);
684 test_scalbn(vector);
685 test_scalbnf(vector);
686 test_sin(vector);
687 test_sinf(vector);
688 test_sinh(vector);
689 test_sinhf(vector);
690 test_sqrt(vector);
691 test_sqrtf(vector);
692 test_tan(vector);
693 test_tanf(vector);
694 test_tanh(vector);
695 test_tanhf(vector);
696 test_trunc(vector);
697 test_truncf(vector);
698 test_y0(vector);
699 test_y0f(vector);
700 test_y1(vector);
701 test_y1f(vector);
702 test_y1f(vector);
703 test_ynf(vector);
704 }
705
706 /* These have to be played with to get to compile on machines which
707 don't have the fancy <foo>f entry points
708 */
709
710 #if 0
711 float cosf (float a) { return cos((double)a); }
712 float sinf (float a) { return sin((double)a); }
713 float log1pf (float a) { return log1p((double)a); }
714 float tanf (float a) { return tan((double)a); }
715 float ceilf (float a) { return ceil(a); }
716 float floorf (float a) { return floor(a); }
717 #endif
718
719 /*ndef HAVE_FLOAT*/
720 #if 0
721
722 float fmodf(a,b) float a,b; { return fmod(a,b); }
723 float hypotf(a,b) float a,b; { return hypot(a,b); }
724
725 float acosf(a) float a; { return acos(a); }
726 float acoshf(a) float a; { return acosh(a); }
727 float asinf(a) float a; { return asin(a); }
728 float asinhf(a) float a; { return asinh(a); }
729 float atanf(a) float a; { return atan(a); }
730 float atanhf(a) float a; { return atanh(a); }
731
732 float coshf(a) float a; { return cosh(a); }
733 float erff(a) float a; { return erf(a); }
734 float erfcf(a) float a; { return erfc(a); }
735 float expf(a) float a; { return exp(a); }
736 float fabsf(a) float a; { return fabs(a); }
737
738 float gammaf(a) float a; { return gamma(a); }
739 float j0f(a) float a; { return j0(a); }
740 float j1f(a) float a; { return j1(a); }
741 float log10f(a) float a; { return log10(a); }
742
743 float logf(a) float a; { return log(a); }
744
745 float sinhf(a) float a; { return sinh(a); }
746 float sqrtf(a) float a; { return sqrt(a); }
747
748 float tanhf(a) float a; { return tanh(a); }
749 float y0f(a) float a; { return y0(a); }
750 float y1f(a) float a; { return y1(a); }
751 #endif
752