blob: 02e9db1992f0b8bbf4eb9cccf359a7f1b13fb734 [file] [log] [blame]
Franklin Weia855d622017-01-21 15:18:31 -05001#include "plugin.h"
2
3#include "fixedpoint.h"
4
5#include <SDL.h>
6
7extern bool printf_enabled;
8
9/* fixed-point wrappers */
10static unsigned long lastphase = 0;
11static long lastsin = 0, lastcos = 0x7fffffff;
12
13#define PI 3.1415926535897932384626433832795
14
15void fatal(char *fmt, ...)
16{
17 va_list ap;
18
19 rb->splash(HZ, "FATAL");
20
21 va_start(ap, fmt);
22 char buf[80];
23 vsnprintf(buf, 80, fmt, ap);
Franklin Wei3f59fc82019-07-07 22:00:20 -040024 printf("%s", buf);
Franklin Weia855d622017-01-21 15:18:31 -050025 rb->splash(HZ * 2, buf);
26 va_end(ap);
27
28 exit(1);
29}
30
31char *strtok_wrapper(char *str, const char *delim)
32{
33 static char *save = NULL;
34 return strtok_r(str, delim, &save);
35}
36
37/* Implementation of strtod() and atof(),
38 taken from SanOS (http://www.jbox.dk/sanos/). */
39static int rb_errno = 0;
40
41static double rb_strtod(const char *str, char **endptr)
42{
43 double number;
44 int exponent;
45 int negative;
46 char *p = (char *) str;
47 double p10;
48 int n;
49 int num_digits;
50 int num_decimals;
51
52 /* Reset Rockbox errno -- W.B. */
53#ifdef ROCKBOX
54 rb_errno = 0;
55#endif
56
57 // Skip leading whitespace
58 while (isspace(*p)) p++;
59
60 // Handle optional sign
61 negative = 0;
62 switch (*p)
63 {
64 case '-': negative = 1; // Fall through to increment position
65 case '+': p++;
66 }
67
68 number = 0.;
69 exponent = 0;
70 num_digits = 0;
71 num_decimals = 0;
72
73 // Process string of digits
74 while (isdigit(*p))
75 {
76 number = number * 10. + (*p - '0');
77 p++;
78 num_digits++;
79 }
80
81 // Process decimal part
82 if (*p == '.')
83 {
84 p++;
85
86 while (isdigit(*p))
87 {
88 number = number * 10. + (*p - '0');
89 p++;
90 num_digits++;
91 num_decimals++;
92 }
93
94 exponent -= num_decimals;
95 }
96
97 if (num_digits == 0)
98 {
99#ifdef ROCKBOX
100 rb_errno = 1;
101#else
102 errno = ERANGE;
103#endif
104 return 0.0;
105 }
106
107 // Correct for sign
108 if (negative) number = -number;
109
110 // Process an exponent string
111 if (*p == 'e' || *p == 'E')
112 {
113 // Handle optional sign
114 negative = 0;
115 switch(*++p)
116 {
117 case '-': negative = 1; // Fall through to increment pos
118 case '+': p++;
119 }
120
121 // Process string of digits
122 n = 0;
123 while (isdigit(*p))
124 {
125 n = n * 10 + (*p - '0');
126 p++;
127 }
128
129 if (negative)
130 exponent -= n;
131 else
132 exponent += n;
133 }
134
135#ifndef ROCKBOX
136 if (exponent < DBL_MIN_EXP || exponent > DBL_MAX_EXP)
137 {
138 errno = ERANGE;
139 return HUGE_VAL;
140 }
141#endif
142
143 // Scale the result
144 p10 = 10.;
145 n = exponent;
146 if (n < 0) n = -n;
147 while (n)
148 {
149 if (n & 1)
150 {
151 if (exponent < 0)
152 number /= p10;
153 else
154 number *= p10;
155 }
156 n >>= 1;
157 p10 *= p10;
158 }
159
160#ifndef ROCKBOX
161 if (number == HUGE_VAL) errno = ERANGE;
162#endif
163 if (endptr) *endptr = p;
164
165 return number;
166}
167
Franklin Wei5d05b9d2018-02-11 15:34:30 -0500168// stolen from Quake
169float atof_wrapper (char *str)
Franklin Weia855d622017-01-21 15:18:31 -0500170{
Franklin Wei5d05b9d2018-02-11 15:34:30 -0500171 double val;
172 int sign;
173 int c;
174 int decimal, total;
175
176 if (*str == '-')
177 {
178 sign = -1;
179 str++;
180 }
181 else
182 sign = 1;
183
184 val = 0;
185
186//
187// check for hex
188//
189 if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') )
190 {
191 str += 2;
192 while (1)
193 {
194 c = *str++;
195 if (c >= '0' && c <= '9')
196 val = (val*16) + c - '0';
197 else if (c >= 'a' && c <= 'f')
198 val = (val*16) + c - 'a' + 10;
199 else if (c >= 'A' && c <= 'F')
200 val = (val*16) + c - 'A' + 10;
201 else
202 return val*sign;
203 }
204 }
205
206//
207// check for character
208//
209 if (str[0] == '\'')
210 {
211 return sign * str[1];
212 }
213
214//
215// assume decimal
216//
217 decimal = -1;
218 total = 0;
219 while (1)
220 {
221 c = *str++;
222 if (c == '.')
223 {
224 decimal = total;
225 continue;
226 }
227 if (c <'0' || c > '9')
228 break;
229 val = val*10 + c - '0';
230 total++;
231 }
232
233 if (decimal == -1)
234 return val*sign;
235 while (total > decimal)
236 {
237 val /= 10;
238 total--;
239 }
240
241 return val*sign;
Franklin Weia855d622017-01-21 15:18:31 -0500242}
243
244double sin_wrapper(double rads)
245{
246 /* we want [0, 2*PI) */
247 while(rads >= 2*PI)
248 rads -= 2*PI;
249 while(rads < 0)
250 rads += 2*PI;
251
252 unsigned long phase = rads/(2*PI) * 4294967296.0;
253
254 /* caching */
255 if(phase == lastphase)
256 {
257 return lastsin/(lastsin < 0 ? 2147483648.0 : 2147483647.0);
258 }
259
260 lastphase = phase;
261 lastsin = fp_sincos(phase, &lastcos);
262 return lastsin/(lastsin < 0 ? 2147483648.0 : 2147483647.0);
263}
264
265double cos_wrapper(double rads)
266{
267 /* we want [0, 2*PI) */
268 while(rads >= 2*PI)
269 rads -= 2*PI;
270 while(rads < 0)
271 rads += 2*PI;
272
273 unsigned long phase = rads/(2*PI) * 4294967296.0;
274
275 /* caching */
276 if(phase == lastphase)
277 {
278 return lastcos/(lastcos < 0 ? 2147483648.0 : 2147483647.0);
279 }
280
281 lastphase = phase;
282 lastsin = fp_sincos(phase, &lastcos);
283 return lastcos/(lastcos < 0 ? 2147483648.0 : 2147483647.0);
284}
285
286float tan_wrapper(float f)
287{
288 return sin_wrapper(f)/cos_wrapper(f);
289}
290
Franklin Wei5d05b9d2018-02-11 15:34:30 -0500291// Total hack. Supports only format strings of the form %Cc, where C
292// is a format specifier and c is a delimiter. Surprisingly, most
293// format strings aren't that complicated to need a real fscanf. This
294// is just enough to make Quake run!
295int fscanf_wrapper(FILE *f, const char *fmt, ...)
296{
297 va_list ap;
298
299 va_start(ap, fmt);
300
301 if(strlen(fmt) != 3)
302 return 0; // not implemented
303
304 if(fmt[0] != '%')
305 return 0; // not implemented
306
307 char format = fmt[1];
308 char delim = fmt[2];
309
310 // extract argument
311 char buf[1024];
312 char *ptr = (format == 's' ? va_arg(ap, char*) : buf);
313 int c;
314 do {
315 c = fgetc(f);
316 *ptr++ = c;
317 } while(c != delim && c != EOF);
318
319 // overwrite delimiter
320 *(ptr-1) = 0;
321
322 //rb->splashf(HZ, "got argument %s, %s\n", fmt, buf);
323
324 switch(format)
325 {
326 case 'i':
327 *va_arg(ap, int*) = atoi(buf);
328 break;
329 case 'f':
330 *va_arg(ap, float*) = atof(buf);
331 break;
332 }
333 return 1;
334}
335
Franklin Weia855d622017-01-21 15:18:31 -0500336/* stolen from doom */
337// Here is a hacked up printf command to get the output from the game.
338int printf_wrapper(const char *fmt, ...)
339{
340 static int p_xtpt;
341 char p_buf[256];
342 rb->yield();
343 va_list ap;
344
345 va_start(ap, fmt);
346 vsnprintf(p_buf,sizeof(p_buf), fmt, ap);
347 va_end(ap);
348
349 rb->lcd_setfont(FONT_SYSFIXED);
350 rb->lcd_putsxy(0,p_xtpt, (unsigned char *)p_buf);
351 if (printf_enabled)
352 rb->lcd_update();
353 LOGF("%s", p_buf);
354
355 p_xtpt+=8;
356 if(p_xtpt>LCD_HEIGHT-8)
357 {
358 p_xtpt=0;
359 if (printf_enabled)
360 {
361 rb->lcd_set_backdrop(NULL);
362 rb->lcd_clear_display();
363 }
364 }
365 return 1;
366}
367
368int vprintf(const char *fmt, va_list ap)
369{
370 char buf[256];
371 vsnprintf(buf, 256, fmt, ap);
372 return printf("%s", buf);
373}
374
375int sprintf_wrapper(char *str, const char *fmt, ...)
376{
377 va_list ap;
378 va_start(ap, fmt);
379 int ret = vsnprintf(str, 9999, fmt, ap);
380 va_end(ap);
381 return ret;
382}
383
384int vsprintf_wrapper(char *str, const char *fmt, va_list ap)
385{
386 return vsnprintf(str, 99999, fmt, ap);
387}
388
389char *strcpy_wrapper(char *dest, const char *src)
390{
Franklin Wei5d05b9d2018-02-11 15:34:30 -0500391 strlcpy(dest, src, 999);
Franklin Weia855d622017-01-21 15:18:31 -0500392 return dest;
393}
394
395char *strdup_wrapper(const char *s) {
396 char *r = malloc(1+strlen(s));
397 strcpy(r,s);
398 return r;
399}
400
401char *strcat_wrapper(char *dest, const char *src)
402{
403 rb->strlcat(dest, src, 999);
404 return dest;
405}
406
407char *strpbrk_wrapper(const char *s1, const char *s2)
408{
409 while(*s1)
410 if(strchr(s2, *s1++))
411 return (char*)--s1;
412 return 0;
413}
414
415/* A union which permits us to convert between a float and a 32 bit
416 int. */
417
418typedef union
419{
420 float value;
421 uint32_t word;
422} ieee_float_shape_type;
423
424/* Get a 32 bit int from a float. */
425
426#define GET_FLOAT_WORD(i,d) \
427do { \
428 ieee_float_shape_type gf_u; \
429 gf_u.value = (d); \
430 (i) = gf_u.word; \
431} while (0)
432
433/* Set a float from a 32 bit int. */
434
435#define SET_FLOAT_WORD(d,i) \
436do { \
437 ieee_float_shape_type sf_u; \
438 sf_u.word = (i); \
439 (d) = sf_u.value; \
440} while (0)
441
442/* Absolute value, simple calculus */
443float fabs_wrapper(float x)
444{
445 return (x < 0.0f) ? -x : x;
446}
447
448float fmod(float x, float y)
449{
450 return x - (int) (x / y) * y;
451}
452
453/* Arc tangent,
454 taken from glibc-2.8. */
455
456static const float atanhi[] = {
457 4.6364760399e-01, /* atan(0.5)hi 0x3eed6338 */
458 7.8539812565e-01, /* atan(1.0)hi 0x3f490fda */
459 9.8279368877e-01, /* atan(1.5)hi 0x3f7b985e */
460 1.5707962513e+00, /* atan(inf)hi 0x3fc90fda */
461};
462
463static const float atanlo[] = {
464 5.0121582440e-09, /* atan(0.5)lo 0x31ac3769 */
465 3.7748947079e-08, /* atan(1.0)lo 0x33222168 */
466 3.4473217170e-08, /* atan(1.5)lo 0x33140fb4 */
467 7.5497894159e-08, /* atan(inf)lo 0x33a22168 */
468};
469
470static const float aT[] = {
471 3.3333334327e-01, /* 0x3eaaaaaa */
472 -2.0000000298e-01, /* 0xbe4ccccd */
473 1.4285714924e-01, /* 0x3e124925 */
474 -1.1111110449e-01, /* 0xbde38e38 */
475 9.0908870101e-02, /* 0x3dba2e6e */
476 -7.6918758452e-02, /* 0xbd9d8795 */
477 6.6610731184e-02, /* 0x3d886b35 */
478 -5.8335702866e-02, /* 0xbd6ef16b */
479 4.9768779427e-02, /* 0x3d4bda59 */
480 -3.6531571299e-02, /* 0xbd15a221 */
481 1.6285819933e-02, /* 0x3c8569d7 */
482};
483
484static const float zero = 0.0;
485
486static const float
487huge = 1.0e+30,
488tiny = 1.0e-30,
489one = 1.0f;
490
491/* Square root function, original. */
492float sqrt_wrapper(float x)
493{
494 float z;
495 int32_t sign = (int)0x80000000;
496 int32_t ix,s,q,m,t,i;
497 uint32_t r;
498
499 GET_FLOAT_WORD(ix,x);
500
501 /* take care of Inf and NaN */
502 if((ix&0x7f800000)==0x7f800000) {
503 return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf
504 sqrt(-inf)=sNaN */
505 }
506 /* take care of zero */
507 if(ix<=0) {
508 if((ix&(~sign))==0) return x;/* sqrt(+-0) = +-0 */
509 else if(ix<0)
510 return (x-x)/(x-x); /* sqrt(-ve) = sNaN */
511 }
512 /* normalize x */
513 m = (ix>>23);
514 if(m==0) { /* subnormal x */
515 for(i=0;(ix&0x00800000)==0;i++) ix<<=1;
516 m -= i-1;
517 }
518 m -= 127; /* unbias exponent */
519 ix = (ix&0x007fffff)|0x00800000;
520 if(m&1) /* odd m, double x to make it even */
521 ix += ix;
522 m >>= 1; /* m = [m/2] */
523
524 /* generate sqrt(x) bit by bit */
525 ix += ix;
526 q = s = 0; /* q = sqrt(x) */
527 r = 0x01000000; /* r = moving bit from right to left */
528
529 while(r!=0) {
530 t = s+r;
531 if(t<=ix) {
532 s = t+r;
533 ix -= t;
534 q += r;
535 }
536 ix += ix;
537 r>>=1;
538 }
539
540 /* use floating add to find out rounding direction */
541 if(ix!=0) {
542 z = one-tiny; /* trigger inexact flag */
543 if (z>=one) {
544 z = one+tiny;
545 if (z>one)
546 q += 2;
547 else
548 q += (q&1);
549 }
550 }
551 ix = (q>>1)+0x3f000000;
552 ix += (m <<23);
553 SET_FLOAT_WORD(z,ix);
554 return z;
555}
556
557float atan_wrapper(float x)
558{
559 float w,s1,s2,z;
560 int32_t ix,hx,id;
561
562 GET_FLOAT_WORD(hx,x);
563 ix = hx&0x7fffffff;
564 if(ix>=0x50800000) { /* if |x| >= 2^34 */
565 if(ix>0x7f800000)
566 return x+x; /* NaN */
567 if(hx>0) return atanhi[3]+atanlo[3];
568 else return -atanhi[3]-atanlo[3];
569 } if (ix < 0x3ee00000) { /* |x| < 0.4375 */
570 if (ix < 0x31000000) { /* |x| < 2^-29 */
571 if(huge+x>one) return x; /* raise inexact */
572 }
573 id = -1;
574 } else {
575 x = fabs_wrapper(x);
576 if (ix < 0x3f980000) { /* |x| < 1.1875 */
577 if (ix < 0x3f300000) { /* 7/16 <=|x|<11/16 */
578 id = 0; x = ((float)2.0*x-one)/((float)2.0+x);
579 } else { /* 11/16<=|x|< 19/16 */
580 id = 1; x = (x-one)/(x+one);
581 }
582 } else {
583 if (ix < 0x401c0000) { /* |x| < 2.4375 */
584 id = 2; x = (x-(float)1.5)/(one+(float)1.5*x);
585 } else { /* 2.4375 <= |x| < 2^66 */
586 id = 3; x = -(float)1.0/x;
587 }
588 }}
589 /* end of argument reduction */
590 z = x*x;
591 w = z*z;
592 /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */
593 s1 = z*(aT[0]+w*(aT[2]+w*(aT[4]+w*(aT[6]+w*(aT[8]+w*aT[10])))));
594 s2 = w*(aT[1]+w*(aT[3]+w*(aT[5]+w*(aT[7]+w*aT[9]))));
595 if (id<0) return x - x*(s1+s2);
596 else {
597 z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x);
598 return (hx<0)? -z:z;
599 }
600}
601
602/* Arc tangent from two variables, original. */
603
604static const float
605pi_o_4 = 7.8539818525e-01, /* 0x3f490fdb */
606pi_o_2 = 1.5707963705e+00, /* 0x3fc90fdb */
607pi = 3.1415927410e+00, /* 0x40490fdb */
608pi_lo = -8.7422776573e-08; /* 0xb3bbbd2e */
609
610float atan2_wrapper(float y, float x)
611{
612 float z;
613 int32_t k,m,hx,hy,ix,iy;
614
615 GET_FLOAT_WORD(hx,x);
616 ix = hx&0x7fffffff;
617 GET_FLOAT_WORD(hy,y);
618 iy = hy&0x7fffffff;
619 if((ix>0x7f800000)||
620 (iy>0x7f800000)) /* x or y is NaN */
621 return x+y;
622 if(hx==0x3f800000) return atan_wrapper(y); /* x=1.0 */
623 m = ((hy>>31)&1)|((hx>>30)&2); /* 2*sign(x)+sign(y) */
624
625 /* when y = 0 */
626 if(iy==0) {
627 switch(m) {
628 case 0:
629 case 1: return y; /* atan(+-0,+anything)=+-0 */
630 case 2: return pi+tiny;/* atan(+0,-anything) = pi */
631 case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */
632 }
633 }
634 /* when x = 0 */
635 if(ix==0) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny;
636
637 /* when x is INF */
638 if(ix==0x7f800000) {
639 if(iy==0x7f800000) {
640 switch(m) {
641 case 0: return pi_o_4+tiny;/* atan(+INF,+INF) */
642 case 1: return -pi_o_4-tiny;/* atan(-INF,+INF) */
643 case 2: return (float)3.0*pi_o_4+tiny;/*atan(+INF,-INF)*/
644 case 3: return (float)-3.0*pi_o_4-tiny;/*atan(-INF,-INF)*/
645 }
646 } else {
647 switch(m) {
648 case 0: return zero ; /* atan(+...,+INF) */
649 case 1: return -zero ; /* atan(-...,+INF) */
650 case 2: return pi+tiny ; /* atan(+...,-INF) */
651 case 3: return -pi-tiny ; /* atan(-...,-INF) */
652 }
653 }
654 }
655 /* when y is INF */
656 if(iy==0x7f800000) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny;
657
658 /* compute y/x */
659 k = (iy-ix)>>23;
660 if(k > 60) z=pi_o_2+(float)0.5*pi_lo; /* |y/x| > 2**60 */
661 else if(hx<0&&k<-60) z=0.0; /* |y|/x < -2**60 */
662 else z=atan_wrapper(fabs_wrapper(y/x)); /* safe to do y/x */
663 switch (m) {
664 case 0: return z ; /* atan(+,+) */
665 case 1: {
666 uint32_t zh;
667 GET_FLOAT_WORD(zh,z);
668 SET_FLOAT_WORD(z,zh ^ 0x80000000);
669 }
670 return z ; /* atan(-,+) */
671 case 2: return pi-(z-pi_lo);/* atan(+,-) */
672 default: /* case 3 */
673 return (z-pi_lo)-pi;/* atan(-,-) */
674 }
675}
676union ieee754_double
677 {
678 double d;
679
680 /* This is the IEEE 754 double-precision format. */
681 struct
682 {
683#ifdef ROCKBOX_BIG_ENDIAN
684 unsigned int negative:1;
685 unsigned int exponent:11;
686 /* Together these comprise the mantissa. */
687 unsigned int mantissa0:20;
688 unsigned int mantissa1:32;
689#else /* ROCKBOX_LITTLE_ENDIAN */
690 /* Together these comprise the mantissa. */
691 unsigned int mantissa1:32;
692 unsigned int mantissa0:20;
693 unsigned int exponent:11;
694 unsigned int negative:1;
695#endif /* ROCKBOX_LITTLE_ENDIAN */
696 } ieee;
697
698 /* This format makes it easier to see if a NaN is a signalling NaN. */
699 struct
700 {
701#ifdef ROCKBOX_BIG_ENDIAN
702 unsigned int negative:1;
703 unsigned int exponent:11;
704 unsigned int quiet_nan:1;
705 /* Together these comprise the mantissa. */
706 unsigned int mantissa0:19;
707 unsigned int mantissa1:32;
708#else /* ROCKBOX_LITTLE_ENDIAN */
709 /* Together these comprise the mantissa. */
710 unsigned int mantissa1:32;
711 unsigned int mantissa0:19;
712 unsigned int quiet_nan:1;
713 unsigned int exponent:11;
714 unsigned int negative:1;
715#endif /* ROCKBOX_LITTLE_ENDIAN */
716 } ieee_nan;
717 };
718
719static const volatile float TWOM100 = 7.88860905e-31;
720static const volatile float TWO127 = 1.7014118346e+38;
721
722/* Exponential function,
723 taken from glibc-2.8
724 As it uses double values and udefines some symbols,
725 it was moved to the end of the source code */
726
727#define W52 (2.22044605e-16)
728#define W55 (2.77555756e-17)
729#define W58 (3.46944695e-18)
730#define W59 (1.73472348e-18)
731#define W60 (8.67361738e-19)
732const float __exp_deltatable[178] = {
733 0*W60, 16558714*W60, -10672149*W59, 1441652*W60,
734 -15787963*W55, 462888*W60, 7291806*W60, 1698880*W60,
735 -14375103*W58, -2021016*W60, 728829*W60, -3759654*W60,
736 3202123*W60, -10916019*W58, -251570*W60, -1043086*W60,
737 8207536*W60, -409964*W60, -5993931*W60, -475500*W60,
738 2237522*W60, 324170*W60, -244117*W60, 32077*W60,
739 123907*W60, -1019734*W60, -143*W60, 813077*W60,
740 743345*W60, 462461*W60, 629794*W60, 2125066*W60,
741 -2339121*W60, -337951*W60, 9922067*W60, -648704*W60,
742 149407*W60, -2687209*W60, -631608*W60, 2128280*W60,
743 -4882082*W60, 2001360*W60, 175074*W60, 2923216*W60,
744 -538947*W60, -1212193*W60, -1920926*W60, -1080577*W60,
745 3690196*W60, 2643367*W60, 2911937*W60, 671455*W60,
746 -1128674*W60, 593282*W60, -5219347*W60, -1941490*W60,
747 11007953*W60, 239609*W60, -2969658*W60, -1183650*W60,
748 942998*W60, 699063*W60, 450569*W60, -329250*W60,
749 -7257875*W60, -312436*W60, 51626*W60, 555877*W60,
750 -641761*W60, 1565666*W60, 884327*W60, -10960035*W60,
751 -2004679*W60, -995793*W60, -2229051*W60, -146179*W60,
752 -510327*W60, 1453482*W60, -3778852*W60, -2238056*W60,
753 -4895983*W60, 3398883*W60, -252738*W60, 1230155*W60,
754 346918*W60, 1109352*W60, 268941*W60, -2930483*W60,
755 -1036263*W60, -1159280*W60, 1328176*W60, 2937642*W60,
756 -9371420*W60, -6902650*W60, -1419134*W60, 1442904*W60,
757 -1319056*W60, -16369*W60, 696555*W60, -279987*W60,
758 -7919763*W60, 252741*W60, 459711*W60, -1709645*W60,
759 354913*W60, 6025867*W60, -421460*W60, -853103*W60,
760 -338649*W60, 962151*W60, 955965*W60, 784419*W60,
761 -3633653*W60, 2277133*W60, -8847927*W52, 1223028*W60,
762 5907079*W60, 623167*W60, 5142888*W60, 2599099*W60,
763 1214280*W60, 4870359*W60, 593349*W60, -57705*W60,
764 7761209*W60, -5564097*W60, 2051261*W60, 6216869*W60,
765 4692163*W60, 601691*W60, -5264906*W60, 1077872*W60,
766 -3205949*W60, 1833082*W60, 2081746*W60, -987363*W60,
767 -1049535*W60, 2015244*W60, 874230*W60, 2168259*W60,
768 -1740124*W60, -10068269*W60, -18242*W60, -3013583*W60,
769 580601*W60, -2547161*W60, -535689*W60, 2220815*W60,
770 1285067*W60, 2806933*W60, -983086*W60, -1729097*W60,
771 -1162985*W60, -2561904*W60, 801988*W60, 244351*W60,
772 1441893*W60, -7517981*W60, 271781*W60, -15021588*W60,
773 -2341588*W60, -919198*W60, 1642232*W60, 4771771*W60,
774 -1220099*W60, -3062372*W60, 628624*W60, 1278114*W60,
775 13083513*W60, -10521925*W60, 3180310*W60, -1659307*W60,
776 3543773*W60, 2501203*W60, 4151*W60, -340748*W60,
777 -2285625*W60, 2495202*W60
778};
779
780const double __exp_atable[355] /* __attribute__((mode(DF))) */ = {
781 0.707722561055888932371, /* 0x0.b52d4e46605c27ffd */
782 0.709106182438804188967, /* 0x0.b587fb96f75097ffb */
783 0.710492508843861281234, /* 0x0.b5e2d649899167ffd */
784 0.711881545564593931623, /* 0x0.b63dde74d36bdfffe */
785 0.713273297897442870573, /* 0x0.b699142f945f87ffc */
786 0.714667771153751463236, /* 0x0.b6f477909c4ea0001 */
787 0.716064970655995725059, /* 0x0.b75008aec758f8004 */
788 0.717464901723956938193, /* 0x0.b7abc7a0eea7e0002 */
789 0.718867569715736398602, /* 0x0.b807b47e1586c7ff8 */
790 0.720272979947266023271, /* 0x0.b863cf5d10e380003 */
791 0.721681137825144314297, /* 0x0.b8c01855195c37ffb */
792 0.723092048691992950199, /* 0x0.b91c8f7d213740004 */
793 0.724505717938892290800, /* 0x0.b97934ec5002d0007 */
794 0.725922150953176470431, /* 0x0.b9d608b9c92ea7ffc */
795 0.727341353138962865022, /* 0x0.ba330afcc29e98003 */
796 0.728763329918453162104, /* 0x0.ba903bcc8618b7ffc */
797 0.730188086709957051568, /* 0x0.baed9b40591ba0000 */
798 0.731615628948127705309, /* 0x0.bb4b296f931e30002 */
799 0.733045962086486091436, /* 0x0.bba8e671a05617ff9 */
800 0.734479091556371366251, /* 0x0.bc06d25dd49568001 */
801 0.735915022857225542529, /* 0x0.bc64ed4bce8f6fff9 */
802 0.737353761441304711410, /* 0x0.bcc33752f915d7ff9 */
803 0.738795312814142124419, /* 0x0.bd21b08af98e78005 */
804 0.740239682467211168593, /* 0x0.bd80590b65e9a8000 */
805 0.741686875913991849885, /* 0x0.bddf30ebec4a10000 */
806 0.743136898669507939299, /* 0x0.be3e38443c84e0007 */
807 0.744589756269486091620, /* 0x0.be9d6f2c1d32a0002 */
808 0.746045454254026796384, /* 0x0.befcd5bb59baf8004 */
809 0.747503998175051087583, /* 0x0.bf5c6c09ca84c0003 */
810 0.748965393601880857739, /* 0x0.bfbc322f5b18b7ff8 */
811 0.750429646104262104698, /* 0x0.c01c2843f776fffff */
812 0.751896761271877989160, /* 0x0.c07c4e5fa18b88002 */
813 0.753366744698445112140, /* 0x0.c0dca49a5fb18fffd */
814 0.754839601988627206827, /* 0x0.c13d2b0c444db0005 */
815 0.756315338768691947122, /* 0x0.c19de1cd798578006 */
816 0.757793960659406629066, /* 0x0.c1fec8f623723fffd */
817 0.759275473314173443536, /* 0x0.c25fe09e8a0f47ff8 */
818 0.760759882363831851927, /* 0x0.c2c128dedc88f8000 */
819 0.762247193485956486805, /* 0x0.c322a1cf7d6e7fffa */
820 0.763737412354726363781, /* 0x0.c3844b88cb9347ffc */
821 0.765230544649828092739, /* 0x0.c3e626232bd8f7ffc */
822 0.766726596071518051729, /* 0x0.c44831b719bf18002 */
823 0.768225572321911687194, /* 0x0.c4aa6e5d12d078001 */
824 0.769727479119219348810, /* 0x0.c50cdc2da64a37ffb */
825 0.771232322196981678892, /* 0x0.c56f7b41744490001 */
826 0.772740107296721268087, /* 0x0.c5d24bb1259e70004 */
827 0.774250840160724651565, /* 0x0.c6354d95640dd0007 */
828 0.775764526565368872643, /* 0x0.c6988106fec447fff */
829 0.777281172269557396602, /* 0x0.c6fbe61eb1bd0ffff */
830 0.778800783068235302750, /* 0x0.c75f7cf560942fffc */
831 0.780323364758801041312, /* 0x0.c7c345a3f1983fffe */
832 0.781848923151573727006, /* 0x0.c8274043594cb0002 */
833 0.783377464064598849602, /* 0x0.c88b6cec94b3b7ff9 */
834 0.784908993312207869935, /* 0x0.c8efcbb89cba27ffe */
835 0.786443516765346961618, /* 0x0.c9545cc0a88c70003 */
836 0.787981040257604625744, /* 0x0.c9b9201dc643bfffa */
837 0.789521569657452682047, /* 0x0.ca1e15e92a5410007 */
838 0.791065110849462849192, /* 0x0.ca833e3c1ae510005 */
839 0.792611669712891875319, /* 0x0.cae8992fd84667ffd */
840 0.794161252150049179450, /* 0x0.cb4e26ddbc207fff8 */
841 0.795713864077794763584, /* 0x0.cbb3e75f301b60003 */
842 0.797269511407239561694, /* 0x0.cc19dacd978cd8002 */
843 0.798828200086368567220, /* 0x0.cc8001427e55d7ffb */
844 0.800389937624300440456, /* 0x0.cce65ade24d360006 */
845 0.801954725261124767840, /* 0x0.cd4ce7a5de839fffb */
846 0.803522573691593189330, /* 0x0.cdb3a7c79a678fffd */
847 0.805093487311204114563, /* 0x0.ce1a9b563965ffffc */
848 0.806667472122675088819, /* 0x0.ce81c26b838db8000 */
849 0.808244534127439906441, /* 0x0.cee91d213f8428002 */
850 0.809824679342317166307, /* 0x0.cf50ab9144d92fff9 */
851 0.811407913793616542005, /* 0x0.cfb86dd5758c2ffff */
852 0.812994243520784198882, /* 0x0.d0206407c20e20005 */
853 0.814583674571603966162, /* 0x0.d0888e4223facfff9 */
854 0.816176213022088536960, /* 0x0.d0f0ec9eb3f7c8002 */
855 0.817771864936188586101, /* 0x0.d1597f377d6768002 */
856 0.819370636400374108252, /* 0x0.d1c24626a46eafff8 */
857 0.820972533518165570298, /* 0x0.d22b41865ff1e7ff9 */
858 0.822577562404315121269, /* 0x0.d2947170f32ec7ff9 */
859 0.824185729164559344159, /* 0x0.d2fdd60097795fff8 */
860 0.825797039949601741075, /* 0x0.d3676f4fb796d0001 */
861 0.827411500902565544264, /* 0x0.d3d13d78b5f68fffb */
862 0.829029118181348834154, /* 0x0.d43b40960546d8001 */
863 0.830649897953322891022, /* 0x0.d4a578c222a058000 */
864 0.832273846408250750368, /* 0x0.d50fe617a3ba78005 */
865 0.833900969738858188772, /* 0x0.d57a88b1218e90002 */
866 0.835531274148056613016, /* 0x0.d5e560a94048f8006 */
867 0.837164765846411529371, /* 0x0.d6506e1aac8078003 */
868 0.838801451086016225394, /* 0x0.d6bbb1204074e0001 */
869 0.840441336100884561780, /* 0x0.d72729d4c28518004 */
870 0.842084427144139224814, /* 0x0.d792d8530e12b0001 */
871 0.843730730487052604790, /* 0x0.d7febcb61273e7fff */
872 0.845380252404570153833, /* 0x0.d86ad718c308dfff9 */
873 0.847032999194574087728, /* 0x0.d8d727962c69d7fff */
874 0.848688977161248581090, /* 0x0.d943ae49621ce7ffb */
875 0.850348192619261200615, /* 0x0.d9b06b4d832ef8005 */
876 0.852010651900976245816, /* 0x0.da1d5ebdc22220005 */
877 0.853676361342631029337, /* 0x0.da8a88b555baa0006 */
878 0.855345327311054837175, /* 0x0.daf7e94f965f98004 */
879 0.857017556155879489641, /* 0x0.db6580a7c98f7fff8 */
880 0.858693054267390953857, /* 0x0.dbd34ed9617befff8 */
881 0.860371828028939855647, /* 0x0.dc4153ffc8b65fff9 */
882 0.862053883854957292436, /* 0x0.dcaf90368bfca8004 */
883 0.863739228154875360306, /* 0x0.dd1e0399328d87ffe */
884 0.865427867361348468455, /* 0x0.dd8cae435d303fff9 */
885 0.867119807911702289458, /* 0x0.ddfb9050b1cee8006 */
886 0.868815056264353846599, /* 0x0.de6aa9dced8448001 */
887 0.870513618890481399881, /* 0x0.ded9fb03db7320006 */
888 0.872215502247877139094, /* 0x0.df4983e1380657ff8 */
889 0.873920712852848668986, /* 0x0.dfb94490ffff77ffd */
890 0.875629257204025623884, /* 0x0.e0293d2f1cb01fff9 */
891 0.877341141814212965880, /* 0x0.e0996dd786fff0007 */
892 0.879056373217612985183, /* 0x0.e109d6a64f5d57ffc */
893 0.880774957955916648615, /* 0x0.e17a77b78e72a7ffe */
894 0.882496902590150900078, /* 0x0.e1eb5127722cc7ff8 */
895 0.884222213673356738383, /* 0x0.e25c63121fb0c8006 */
896 0.885950897802399772740, /* 0x0.e2cdad93ec5340003 */
897 0.887682961567391237685, /* 0x0.e33f30c925fb97ffb */
898 0.889418411575228162725, /* 0x0.e3b0ecce2d05ffff9 */
899 0.891157254447957902797, /* 0x0.e422e1bf727718006 */
900 0.892899496816652704641, /* 0x0.e4950fb9713fc7ffe */
901 0.894645145323828439008, /* 0x0.e50776d8b0e60fff8 */
902 0.896394206626591749641, /* 0x0.e57a1739c8fadfffc */
903 0.898146687421414902124, /* 0x0.e5ecf0f97c5798007 */
904 0.899902594367530173098, /* 0x0.e660043464e378005 */
905 0.901661934163603406867, /* 0x0.e6d3510747e150006 */
906 0.903424713533971135418, /* 0x0.e746d78f06cd97ffd */
907 0.905190939194458810123, /* 0x0.e7ba97e879c91fffc */
908 0.906960617885092856864, /* 0x0.e82e92309390b0007 */
909 0.908733756358986566306, /* 0x0.e8a2c6845544afffa */
910 0.910510361377119825629, /* 0x0.e9173500c8abc7ff8 */
911 0.912290439722343249336, /* 0x0.e98bddc30f98b0002 */
912 0.914073998177417412765, /* 0x0.ea00c0e84bc4c7fff */
913 0.915861043547953501680, /* 0x0.ea75de8db8094fffe */
914 0.917651582652244779397, /* 0x0.eaeb36d09d3137ffe */
915 0.919445622318405764159, /* 0x0.eb60c9ce4ed3dffff */
916 0.921243169397334638073, /* 0x0.ebd697a43995b0007 */
917 0.923044230737526172328, /* 0x0.ec4ca06fc7768fffa */
918 0.924848813220121135342, /* 0x0.ecc2e44e865b6fffb */
919 0.926656923710931002014, /* 0x0.ed39635df34e70006 */
920 0.928468569126343790092, /* 0x0.edb01dbbc2f5b7ffa */
921 0.930283756368834757725, /* 0x0.ee2713859aab57ffa */
922 0.932102492359406786818, /* 0x0.ee9e44d9342870004 */
923 0.933924784042873379360, /* 0x0.ef15b1d4635438005 */
924 0.935750638358567643520, /* 0x0.ef8d5a94f60f50007 */
925 0.937580062297704630580, /* 0x0.f0053f38f345cffff */
926 0.939413062815381727516, /* 0x0.f07d5fde3a2d98001 */
927 0.941249646905368053689, /* 0x0.f0f5bca2d481a8004 */
928 0.943089821583810716806, /* 0x0.f16e55a4e497d7ffe */
929 0.944933593864477061592, /* 0x0.f1e72b028a2827ffb */
930 0.946780970781518460559, /* 0x0.f2603cd9fb5430001 */
931 0.948631959382661205081, /* 0x0.f2d98b497d2a87ff9 */
932 0.950486566729423554277, /* 0x0.f353166f63e3dffff */
933 0.952344799896018723290, /* 0x0.f3ccde6a11ae37ffe */
934 0.954206665969085765512, /* 0x0.f446e357f66120000 */
935 0.956072172053890279009, /* 0x0.f4c12557964f0fff9 */
936 0.957941325265908139014, /* 0x0.f53ba48781046fffb */
937 0.959814132734539637840, /* 0x0.f5b66106555d07ffa */
938 0.961690601603558903308, /* 0x0.f6315af2c2027fffc */
939 0.963570739036113010927, /* 0x0.f6ac926b8aeb80004 */
940 0.965454552202857141381, /* 0x0.f728078f7c5008002 */
941 0.967342048278315158608, /* 0x0.f7a3ba7d66a908001 */
942 0.969233234469444204768, /* 0x0.f81fab543e1897ffb */
943 0.971128118008140250896, /* 0x0.f89bda33122c78007 */
944 0.973026706099345495256, /* 0x0.f9184738d4cf97ff8 */
945 0.974929006031422851235, /* 0x0.f994f284d3a5c0008 */
946 0.976835024947348973265, /* 0x0.fa11dc35bc7820002 */
947 0.978744770239899142285, /* 0x0.fa8f046b4fb7f8007 */
948 0.980658249138918636210, /* 0x0.fb0c6b449ab1cfff9 */
949 0.982575468959622777535, /* 0x0.fb8a10e1088fb7ffa */
950 0.984496437054508843888, /* 0x0.fc07f5602d79afffc */
951 0.986421160608523028820, /* 0x0.fc8618e0e55e47ffb */
952 0.988349647107594098099, /* 0x0.fd047b83571b1fffa */
953 0.990281903873210800357, /* 0x0.fd831d66f4c018002 */
954 0.992217938695037382475, /* 0x0.fe01fead3320bfff8 */
955 0.994157757657894713987, /* 0x0.fe811f703491e8006 */
956 0.996101369488558541238, /* 0x0.ff007fd5744490005 */
957 0.998048781093141101932, /* 0x0.ff801ffa9b9280007 */
958 1.000000000000000000000, /* 0x1.00000000000000000 */
959 1.001955033605393285965, /* 0x1.0080200565d29ffff */
960 1.003913889319761887310, /* 0x1.0100802aa0e80fff0 */
961 1.005876574715736104818, /* 0x1.01812090377240007 */
962 1.007843096764807100351, /* 0x1.020201541aad7fff6 */
963 1.009813464316352327214, /* 0x1.0283229c4c9820007 */
964 1.011787683565730677817, /* 0x1.030484836910a000e */
965 1.013765762469146736174, /* 0x1.0386272b9c077fffe */
966 1.015747708536026694351, /* 0x1.04080ab526304fff0 */
967 1.017733529475172815584, /* 0x1.048a2f412375ffff0 */
968 1.019723232714418781378, /* 0x1.050c94ef7ad5e000a */
969 1.021716825883923762690, /* 0x1.058f3be0f1c2d0004 */
970 1.023714316605201180057, /* 0x1.06122436442e2000e */
971 1.025715712440059545995, /* 0x1.06954e0fec63afff2 */
972 1.027721021151397406936, /* 0x1.0718b98f41c92fff6 */
973 1.029730250269221158939, /* 0x1.079c66d49bb2ffff1 */
974 1.031743407506447551857, /* 0x1.082056011a9230009 */
975 1.033760500517691527387, /* 0x1.08a487359ebd50002 */
976 1.035781537016238873464, /* 0x1.0928fa93490d4fff3 */
977 1.037806524719013578963, /* 0x1.09adb03b3e5b3000d */
978 1.039835471338248051878, /* 0x1.0a32a84e9e5760004 */
979 1.041868384612101516848, /* 0x1.0ab7e2eea5340ffff */
980 1.043905272300907460835, /* 0x1.0b3d603ca784f0009 */
981 1.045946142174331239262, /* 0x1.0bc3205a042060000 */
982 1.047991002016745332165, /* 0x1.0c4923682a086fffe */
983 1.050039859627715177527, /* 0x1.0ccf698898f3a000d */
984 1.052092722826109660856, /* 0x1.0d55f2dce5d1dfffb */
985 1.054149599440827866881, /* 0x1.0ddcbf86b09a5fff6 */
986 1.056210497317612961855, /* 0x1.0e63cfa7abc97fffd */
987 1.058275424318780855142, /* 0x1.0eeb23619c146fffb */
988 1.060344388322010722446, /* 0x1.0f72bad65714bffff */
989 1.062417397220589476718, /* 0x1.0ffa9627c38d30004 */
990 1.064494458915699715017, /* 0x1.1082b577d0eef0003 */
991 1.066575581342167566880, /* 0x1.110b18e893a90000a */
992 1.068660772440545025953, /* 0x1.1193c09c267610006 */
993 1.070750040138235936705, /* 0x1.121cacb4959befff6 */
994 1.072843392435016474095, /* 0x1.12a5dd543cf36ffff */
995 1.074940837302467588937, /* 0x1.132f529d59552000b */
996 1.077042382749654914030, /* 0x1.13b90cb250d08fff5 */
997 1.079148036789447484528, /* 0x1.14430bb58da3dfff9 */
998 1.081257807444460983297, /* 0x1.14cd4fc984c4a000e */
999 1.083371702785017154417, /* 0x1.1557d910df9c7000e */
1000 1.085489730853784307038, /* 0x1.15e2a7ae292d30002 */
1001 1.087611899742884524772, /* 0x1.166dbbc422d8c0004 */
1002 1.089738217537583819804, /* 0x1.16f9157586772ffff */
1003 1.091868692357631731528, /* 0x1.1784b4e533cacfff0 */
1004 1.094003332327482702577, /* 0x1.18109a360fc23fff2 */
1005 1.096142145591650907149, /* 0x1.189cc58b155a70008 */
1006 1.098285140311341168136, /* 0x1.1929370751ea50002 */
1007 1.100432324652149906842, /* 0x1.19b5eecdd79cefff0 */
1008 1.102583706811727015711, /* 0x1.1a42ed01dbdba000e */
1009 1.104739294993289488947, /* 0x1.1ad031c69a2eafff0 */
1010 1.106899097422573863281, /* 0x1.1b5dbd3f66e120003 */
1011 1.109063122341542140286, /* 0x1.1beb8f8fa8150000b */
1012 1.111231377994659874592, /* 0x1.1c79a8dac6ad0fff4 */
1013 1.113403872669181282605, /* 0x1.1d0809445a97ffffc */
1014 1.115580614653132185460, /* 0x1.1d96b0effc9db000e */
1015 1.117761612217810673898, /* 0x1.1e25a001332190000 */
1016 1.119946873713312474002, /* 0x1.1eb4d69bdb2a9fff1 */
1017 1.122136407473298902480, /* 0x1.1f4454e3bfae00006 */
1018 1.124330221845670330058, /* 0x1.1fd41afcbb48bfff8 */
1019 1.126528325196519908506, /* 0x1.2064290abc98c0001 */
1020 1.128730725913251964394, /* 0x1.20f47f31c9aa7000f */
1021 1.130937432396844410880, /* 0x1.21851d95f776dfff0 */
1022 1.133148453059692917203, /* 0x1.2216045b6784efffa */
1023 1.135363796355857157764, /* 0x1.22a733a6692ae0004 */
1024 1.137583470716100553249, /* 0x1.2338ab9b3221a0004 */
1025 1.139807484614418608939, /* 0x1.23ca6c5e27aadfff7 */
1026 1.142035846532929888057, /* 0x1.245c7613b7f6c0004 */
1027 1.144268564977221958089, /* 0x1.24eec8e06b035000c */
1028 1.146505648458203463465, /* 0x1.258164e8cea85fff8 */
1029 1.148747105501412235671, /* 0x1.26144a5180d380009 */
1030 1.150992944689175123667, /* 0x1.26a7793f5de2efffa */
1031 1.153243174560058870217, /* 0x1.273af1d712179000d */
1032 1.155497803703682491111, /* 0x1.27ceb43d81d42fff1 */
1033 1.157756840726344771440, /* 0x1.2862c097a3d29000c */
1034 1.160020294239811677834, /* 0x1.28f7170a74cf4fff1 */
1035 1.162288172883275239058, /* 0x1.298bb7bb0faed0004 */
1036 1.164560485298402170388, /* 0x1.2a20a2ce920dffff4 */
1037 1.166837240167474476460, /* 0x1.2ab5d86a4631ffff6 */
1038 1.169118446164539637555, /* 0x1.2b4b58b36d5220009 */
1039 1.171404112007080167155, /* 0x1.2be123cf786790002 */
1040 1.173694246390975415341, /* 0x1.2c7739e3c0aac000d */
1041 1.175988858069749065617, /* 0x1.2d0d9b15deb58fff6 */
1042 1.178287955789017793514, /* 0x1.2da4478b627040002 */
1043 1.180591548323240091978, /* 0x1.2e3b3f69fb794fffc */
1044 1.182899644456603782686, /* 0x1.2ed282d76421d0004 */
1045 1.185212252993012693694, /* 0x1.2f6a11f96c685fff3 */
1046 1.187529382762033236513, /* 0x1.3001ecf60082ffffa */
1047 1.189851042595508889847, /* 0x1.309a13f30f28a0004 */
1048 1.192177241354644978669, /* 0x1.31328716a758cfff7 */
1049 1.194507987909589896687, /* 0x1.31cb4686e1e85fffb */
1050 1.196843291137896336843, /* 0x1.32645269dfd04000a */
1051 1.199183159977805113226, /* 0x1.32fdaae604c39000f */
1052 1.201527603343041317132, /* 0x1.339750219980dfff3 */
1053 1.203876630171082595692, /* 0x1.3431424300e480007 */
1054 1.206230249419600664189, /* 0x1.34cb8170b3fee000e */
1055 1.208588470077065268869, /* 0x1.35660dd14dbd4fffc */
1056 1.210951301134513435915, /* 0x1.3600e78b6bdfc0005 */
1057 1.213318751604272271958, /* 0x1.369c0ec5c38ebfff2 */
1058 1.215690830512196507537, /* 0x1.373783a718d29000f */
1059 1.218067546930756250870, /* 0x1.37d3465662f480007 */
1060 1.220448909901335365929, /* 0x1.386f56fa770fe0008 */
1061 1.222834928513994334780, /* 0x1.390bb5ba5fc540004 */
1062 1.225225611877684750397, /* 0x1.39a862bd3c7a8fff3 */
1063 1.227620969111500981433, /* 0x1.3a455e2a37bcafffd */
1064 1.230021009336254911271, /* 0x1.3ae2a8287dfbefff6 */
1065 1.232425741726685064472, /* 0x1.3b8040df76f39fffa */
1066 1.234835175450728295084, /* 0x1.3c1e287682e48fff1 */
1067 1.237249319699482263931, /* 0x1.3cbc5f151b86bfff8 */
1068 1.239668183679933477545, /* 0x1.3d5ae4e2cc0a8000f */
1069 1.242091776620540377629, /* 0x1.3df9ba07373bf0006 */
1070 1.244520107762172811399, /* 0x1.3e98deaa0d8cafffe */
1071 1.246953186383919165383, /* 0x1.3f3852f32973efff0 */
1072 1.249391019292643401078, /* 0x1.3fd816ffc72b90001 */
1073 1.251833623164381181797, /* 0x1.40782b17863250005 */
1074 1.254280999953110153911, /* 0x1.41188f42caf400000 */
1075 1.256733161434815393410, /* 0x1.41b943b42945bfffd */
1076 1.259190116985283935980, /* 0x1.425a4893e5f10000a */
1077 1.261651875958665236542, /* 0x1.42fb9e0a2df4c0009 */
1078 1.264118447754797758244, /* 0x1.439d443f608c4fff9 */
1079 1.266589841787181258708, /* 0x1.443f3b5bebf850008 */
1080 1.269066067469190262045, /* 0x1.44e183883e561fff7 */
1081 1.271547134259576328224, /* 0x1.45841cecf7a7a0001 */
1082 1.274033051628237434048, /* 0x1.462707b2c43020009 */
1083 1.276523829025464573684, /* 0x1.46ca44023aa410007 */
1084 1.279019475999373156531, /* 0x1.476dd2045d46ffff0 */
1085 1.281520002043128991825, /* 0x1.4811b1e1f1f19000b */
1086 1.284025416692967214122, /* 0x1.48b5e3c3edd74fff4 */
1087 1.286535729509738823464, /* 0x1.495a67d3613c8fff7 */
1088 1.289050950070396384145, /* 0x1.49ff3e396e19d000b */
1089 1.291571087985403654081, /* 0x1.4aa4671f5b401fff1 */
1090 1.294096152842774794011, /* 0x1.4b49e2ae56d19000d */
1091 1.296626154297237043484, /* 0x1.4befb10fd84a3fff4 */
1092 1.299161101984141142272, /* 0x1.4c95d26d41d84fff8 */
1093 1.301701005575179204100, /* 0x1.4d3c46f01d9f0fff3 */
1094 1.304245874766450485904, /* 0x1.4de30ec21097d0003 */
1095 1.306795719266019562007, /* 0x1.4e8a2a0ccce3d0002 */
1096 1.309350548792467483458, /* 0x1.4f3198fa10346fff5 */
1097 1.311910373099227200545, /* 0x1.4fd95bb3be8cffffd */
1098 1.314475201942565174546, /* 0x1.50817263bf0e5fffb */
1099 1.317045045107389400535, /* 0x1.5129dd3418575000e */
1100 1.319619912422941299109, /* 0x1.51d29c4f01c54ffff */
1101 1.322199813675649204855, /* 0x1.527bafde83a310009 */
1102 1.324784758729532718739, /* 0x1.5325180cfb8b3fffd */
1103 1.327374757430096474625, /* 0x1.53ced504b2bd0fff4 */
1104 1.329969819671041886272, /* 0x1.5478e6f02775e0001 */
1105 1.332569955346704748651, /* 0x1.55234df9d8a59fff8 */
1106 1.335175174370685002822, /* 0x1.55ce0a4c5a6a9fff6 */
1107 1.337785486688218616860, /* 0x1.56791c1263abefff7 */
1108 1.340400902247843806217, /* 0x1.57248376aef21fffa */
1109 1.343021431036279800211, /* 0x1.57d040a420c0bfff3 */
1110 1.345647083048053138662, /* 0x1.587c53c5a630f0002 */
1111 1.348277868295411074918, /* 0x1.5928bd063fd7bfff9 */
1112 1.350913796821875845231, /* 0x1.59d57c9110ad60006 */
1113 1.353554878672557082439, /* 0x1.5a8292913d68cfffc */
1114 1.356201123929036356254, /* 0x1.5b2fff3212db00007 */
1115 1.358852542671913132777, /* 0x1.5bddc29edcc06fff3 */
1116 1.361509145047255398051, /* 0x1.5c8bdd032ed16000f */
1117 1.364170941142184734180, /* 0x1.5d3a4e8a5bf61fff4 */
1118 1.366837941171020309735, /* 0x1.5de9176042f1effff */
1119 1.369510155261156381121, /* 0x1.5e9837b062f4e0005 */
1120 1.372187593620959988833, /* 0x1.5f47afa69436cfff1 */
1121 1.374870266463378287715, /* 0x1.5ff77f6eb3f8cfffd */
1122 1.377558184010425845733, /* 0x1.60a7a734a9742fff9 */
1123 1.380251356531521533853, /* 0x1.6158272490016000c */
1124 1.382949794301995272203, /* 0x1.6208ff6a8978a000f */
1125 1.385653507605306700170, /* 0x1.62ba3032c0a280004 */
1126 1.388362506772382154503, /* 0x1.636bb9a994784000f */
1127 1.391076802081129493127, /* 0x1.641d9bfb29a7bfff6 */
1128 1.393796403973427855412, /* 0x1.64cfd7545928b0002 */
1129 1.396521322756352656542, /* 0x1.65826be167badfff8 */
1130 1.399251568859207761660, /* 0x1.663559cf20826000c */
1131 1.401987152677323100733, /* 0x1.66e8a14a29486fffc */
1132 1.404728084651919228815, /* 0x1.679c427f5a4b6000b */
1133 1.407474375243217723560, /* 0x1.68503d9ba0add000f */
1134 1.410226034922914983815, /* 0x1.690492cbf6303fff9 */
1135 1.412983074197955213304, /* 0x1.69b9423d7b548fff6 */
1136};
1137
1138/* All floating-point numbers can be put in one of these categories. */
1139enum
1140 {
1141 FP_NAN,
1142# define FP_NAN FP_NAN
1143 FP_INFINITE,
1144# define FP_INFINITE FP_INFINITE
1145 FP_ZERO,
1146# define FP_ZERO FP_ZERO
1147 FP_SUBNORMAL,
1148# define FP_SUBNORMAL FP_SUBNORMAL
1149 FP_NORMAL
1150# define FP_NORMAL FP_NORMAL
1151 };
1152
1153
1154int
1155__fpclassifyf (float x)
1156{
1157 uint32_t wx;
1158 int retval = FP_NORMAL;
1159
1160 GET_FLOAT_WORD (wx, x);
1161 wx &= 0x7fffffff;
1162 if (wx == 0)
1163 retval = FP_ZERO;
1164 else if (wx < 0x800000)
1165 retval = FP_SUBNORMAL;
1166 else if (wx >= 0x7f800000)
1167 retval = wx > 0x7f800000 ? FP_NAN : FP_INFINITE;
1168
1169 return retval;
1170}
1171
1172
1173int
1174__isinff (float x)
1175{
1176 int32_t ix,t;
1177 GET_FLOAT_WORD(ix,x);
1178 t = ix & 0x7fffffff;
1179 t ^= 0x7f800000;
1180 t |= -t;
1181 return ~(t >> 31) & (ix >> 30);
1182}
1183
1184/* Return nonzero value if arguments are unordered. */
1185#define fpclassify(x) \
1186 (sizeof (x) == sizeof (float) ? __fpclassifyf (x) : __fpclassifyf (x))
1187
1188#ifndef isunordered
1189#define isunordered(u, v) \
1190 (__extension__ \
1191 ({ __typeof__(u) __u = (u); __typeof__(v) __v = (v); \
1192 fpclassify (__u) == FP_NAN || fpclassify (__v) == FP_NAN; }))
1193#endif
1194
1195/* Return nonzero value if X is less than Y. */
1196#ifndef isless
1197#define isless(x, y) \
1198 (__extension__ \
1199 ({ __typeof__(x) __x = (x); __typeof__(y) __y = (y); \
1200 !isunordered (__x, __y) && __x < __y; }))
1201#endif
1202
1203/* Return nonzero value if X is greater than Y. */
1204#ifndef isgreater
1205#define isgreater(x, y) \
1206 (__extension__ \
1207 ({ __typeof__(x) __x = (x); __typeof__(y) __y = (y); \
1208 !isunordered (__x, __y) && __x > __y; }))
1209#endif
1210
1211float rb_exp(float x)
1212{
1213 static const float himark = 88.72283935546875;
1214 static const float lomark = -103.972084045410;
1215 /* Check for usual case. */
1216 if (isless (x, himark) && isgreater (x, lomark))
1217 {
1218 static const float THREEp42 = 13194139533312.0;
1219 static const float THREEp22 = 12582912.0;
1220 /* 1/ln(2). */
1221#undef M_1_LN2
1222 static const float M_1_LN2 = 1.44269502163f;
1223 /* ln(2) */
1224#undef M_LN2
1225 static const double M_LN2 = .6931471805599452862;
1226
1227 int tval;
1228 double x22, t, result, dx;
1229 float n, delta;
1230 union ieee754_double ex2_u;
1231#ifndef ROCKBOX
1232 fenv_t oldenv;
1233
1234 feholdexcept (&oldenv);
1235#endif
1236
1237#ifdef FE_TONEAREST
1238 fesetround (FE_TONEAREST);
1239#endif
1240
1241 /* Calculate n. */
1242 n = x * M_1_LN2 + THREEp22;
1243 n -= THREEp22;
1244 dx = x - n*M_LN2;
1245
1246 /* Calculate t/512. */
1247 t = dx + THREEp42;
1248 t -= THREEp42;
1249 dx -= t;
1250
1251 /* Compute tval = t. */
1252 tval = (int) (t * 512.0);
1253
1254 if (t >= 0)
1255 delta = - __exp_deltatable[tval];
1256 else
1257 delta = __exp_deltatable[-tval];
1258
1259 /* Compute ex2 = 2^n e^(t/512+delta[t]). */
1260 ex2_u.d = __exp_atable[tval+177];
1261 ex2_u.ieee.exponent += (int) n;
1262
1263 /* Approximate e^(dx+delta) - 1, using a second-degree polynomial,
1264 with maximum error in [-2^-10-2^-28,2^-10+2^-28]
1265 less than 5e-11. */
1266 x22 = (0.5000000496709180453 * dx + 1.0000001192102037084) * dx + delta;
1267
1268 /* Return result. */
1269#ifndef ROCKBOX
1270 fesetenv (&oldenv);
1271#endif
1272
1273 result = x22 * ex2_u.d + ex2_u.d;
1274 return (float) result;
1275 }
1276 /* Exceptional cases: */
1277 else if (isless (x, himark))
1278 {
1279 if (__isinff (x))
1280 /* e^-inf == 0, with no error. */
1281 return 0;
1282 else
1283 /* Underflow */
1284 return TWOM100 * TWOM100;
1285 }
1286 else
1287 /* Return x, if x is a NaN or Inf; or overflow, otherwise. */
1288 return TWO127*x;
1289}
1290
1291/* Power function, taken from glibc-2.8 and dietlibc-0.32 */
1292float pow_wrapper(float x, float y)
1293{
1294 unsigned int e;
1295 float result;
1296
1297 /* Special cases 0^x */
1298 if(x == 0.0f)
1299 {
1300 if(y > 0.0f)
1301 return 0.0f;
1302 else if(y == 0.0f)
1303 return 1.0f;
1304 else
1305 return 1.0f / x;
1306 }
1307
1308 /* Special case x^n where n is integer */
1309 if(y == (int) (e = (int) y))
1310 {
1311 if((int) e < 0)
1312 {
1313 e = -e;
1314 x = 1.0f / x;
1315 }
1316
1317 result = 1.0f;
1318
1319 while(1)
1320 {
1321 if(e & 1)
1322 result *= x;
1323
1324 if((e >>= 1) == 0)
1325 break;
1326
1327 x *= x;
1328 }
1329
1330 return result;
1331 }
1332
1333 /* Normal case */
1334 return rb_exp(rb_log(x) * y);
1335}
1336
1337double floor_wrapper(double n)
1338{
1339 if(n < 0.0)
1340 {
1341 int y = (int)n;
1342 return ((float)y == n) ? y : y - 1;
1343 }
1344 else
1345 return (int)n;
1346}
1347
1348double ceil_wrapper(double n)
1349{
1350 return floor_wrapper(n) + 1.0;
1351}
1352
1353/* Natural logarithm.
1354 Taken from glibc-2.8 */
1355static const float
1356ln2_hi = 6.9313812256e-01, /* 0x3f317180 */
1357ln2_lo = 9.0580006145e-06, /* 0x3717f7d1 */
1358two25 = 3.355443200e+07, /* 0x4c000000 */
1359Lg1 = 6.6666668653e-01, /* 3F2AAAAB */
1360Lg2 = 4.0000000596e-01, /* 3ECCCCCD */
1361Lg3 = 2.8571429849e-01, /* 3E924925 */
1362Lg4 = 2.2222198546e-01, /* 3E638E29 */
1363Lg5 = 1.8183572590e-01, /* 3E3A3325 */
1364Lg6 = 1.5313838422e-01, /* 3E1CD04F */
1365Lg7 = 1.4798198640e-01; /* 3E178897 */
1366
1367/* Get a 32 bit int from a float. */
1368
1369#define GET_FLOAT_WORD(i,d) \
1370do { \
1371 ieee_float_shape_type gf_u; \
1372 gf_u.value = (d); \
1373 (i) = gf_u.word; \
1374} while (0)
1375
1376/* Set a float from a 32 bit int. */
1377
1378#define SET_FLOAT_WORD(d,i) \
1379do { \
1380 ieee_float_shape_type sf_u; \
1381 sf_u.word = (i); \
1382 (d) = sf_u.value; \
1383} while (0)
1384
1385#ifdef ROCKBOX_LITTLE_ENDIAN
1386#define __HI(x) *(1+(int*)&x)
1387#define __LO(x) *(int*)&x
1388#define __HIp(x) *(1+(int*)x)
1389#define __LOp(x) *(int*)x
1390#else
1391#define __HI(x) *(int*)&x
1392#define __LO(x) *(1+(int*)&x)
1393#define __HIp(x) *(int*)x
1394#define __LOp(x) *(1+(int*)x)
1395#endif
1396
1397float rb_log(float x)
1398{
1399 float hfsq, f, s, z, R, w, t1, t2, dk;
1400 int32_t k, ix, i, j;
1401
1402 GET_FLOAT_WORD(ix,x);
1403
1404 k=0;
1405 if (ix < 0x00800000) { /* x < 2**-126 */
1406 if ((ix&0x7fffffff)==0)
1407 return -two25/(x-x); /* log(+-0)=-inf */
1408 if (ix<0) return (x-x)/(x-x); /* log(-#) = NaN */
1409 k -= 25; x *= two25; /* subnormal number, scale up x */
1410 GET_FLOAT_WORD(ix,x);
1411 }
1412 if (ix >= 0x7f800000) return x+x;
1413 k += (ix>>23)-127;
1414 ix &= 0x007fffff;
1415 i = (ix+(0x95f64<<3))&0x800000;
1416 SET_FLOAT_WORD(x,ix|(i^0x3f800000)); /* normalize x or x/2 */
1417 k += (i>>23);
1418 f = x-(float)1.0;
1419 if((0x007fffff&(15+ix))<16) { /* |f| < 2**-20 */
1420 if(f==zero) {
1421 if(k==0)
1422 return zero;
1423 else
1424 {
1425 dk=(float)k;
1426 return dk*ln2_hi+dk*ln2_lo;
1427 }
1428 }
1429 R = f*f*((float)0.5-(float)0.33333333333333333*f);
1430 if(k==0)
1431 return f-R;
1432 else
1433 {
1434 dk=(float)k;
1435 return dk*ln2_hi-((R-dk*ln2_lo)-f);
1436 }
1437 }
1438 s = f/((float)2.0+f);
1439 dk = (float)k;
1440 z = s*s;
1441 i = ix-(0x6147a<<3);
1442 w = z*z;
1443 j = (0x6b851<<3)-ix;
1444 t1= w*(Lg2+w*(Lg4+w*Lg6));
1445 t2= z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7)));
1446 i |= j;
1447 R = t2+t1;
1448 if(i>0) {
1449 hfsq=(float)0.5*f*f;
1450 if(k==0)
1451 return f-(hfsq-s*(hfsq+R));
1452 else
1453 return dk*ln2_hi-((hfsq-(s*(hfsq+R)+dk*ln2_lo))-f);
1454 } else {
1455 if(k==0)
1456 return f-s*(f-R);
1457 else
1458 return dk*ln2_hi-((s*(f-R)-dk*ln2_lo)-f);
1459 }
1460}