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