Franklin Wei | a855d62 | 2017-01-21 15:18:31 -0500 | [diff] [blame] | 1 | #include "plugin.h" |
| 2 | |
| 3 | #include "fixedpoint.h" |
| 4 | |
| 5 | #include <SDL.h> |
| 6 | |
| 7 | extern bool printf_enabled; |
| 8 | |
| 9 | /* fixed-point wrappers */ |
| 10 | static unsigned long lastphase = 0; |
| 11 | static long lastsin = 0, lastcos = 0x7fffffff; |
| 12 | |
| 13 | #define PI 3.1415926535897932384626433832795 |
| 14 | |
| 15 | void 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 Wei | 3f59fc8 | 2019-07-07 22:00:20 -0400 | [diff] [blame] | 24 | printf("%s", buf); |
Franklin Wei | a855d62 | 2017-01-21 15:18:31 -0500 | [diff] [blame] | 25 | rb->splash(HZ * 2, buf); |
| 26 | va_end(ap); |
| 27 | |
| 28 | exit(1); |
| 29 | } |
| 30 | |
| 31 | char *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/). */ |
| 39 | static int rb_errno = 0; |
| 40 | |
| 41 | static 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 Wei | 5d05b9d | 2018-02-11 15:34:30 -0500 | [diff] [blame] | 168 | // stolen from Quake |
| 169 | float atof_wrapper (char *str) |
Franklin Wei | a855d62 | 2017-01-21 15:18:31 -0500 | [diff] [blame] | 170 | { |
Franklin Wei | 5d05b9d | 2018-02-11 15:34:30 -0500 | [diff] [blame] | 171 | 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 Wei | a855d62 | 2017-01-21 15:18:31 -0500 | [diff] [blame] | 242 | } |
| 243 | |
| 244 | double 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 | |
| 265 | double 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 | |
| 286 | float tan_wrapper(float f) |
| 287 | { |
| 288 | return sin_wrapper(f)/cos_wrapper(f); |
| 289 | } |
| 290 | |
Franklin Wei | 5d05b9d | 2018-02-11 15:34:30 -0500 | [diff] [blame] | 291 | // 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! |
| 295 | int 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 Wei | a855d62 | 2017-01-21 15:18:31 -0500 | [diff] [blame] | 336 | /* stolen from doom */ |
| 337 | // Here is a hacked up printf command to get the output from the game. |
| 338 | int 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 | |
| 368 | int 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 | |
| 375 | int 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 | |
| 384 | int vsprintf_wrapper(char *str, const char *fmt, va_list ap) |
| 385 | { |
| 386 | return vsnprintf(str, 99999, fmt, ap); |
| 387 | } |
| 388 | |
| 389 | char *strcpy_wrapper(char *dest, const char *src) |
| 390 | { |
Franklin Wei | 5d05b9d | 2018-02-11 15:34:30 -0500 | [diff] [blame] | 391 | strlcpy(dest, src, 999); |
Franklin Wei | a855d62 | 2017-01-21 15:18:31 -0500 | [diff] [blame] | 392 | return dest; |
| 393 | } |
| 394 | |
| 395 | char *strdup_wrapper(const char *s) { |
| 396 | char *r = malloc(1+strlen(s)); |
| 397 | strcpy(r,s); |
| 398 | return r; |
| 399 | } |
| 400 | |
| 401 | char *strcat_wrapper(char *dest, const char *src) |
| 402 | { |
| 403 | rb->strlcat(dest, src, 999); |
| 404 | return dest; |
| 405 | } |
| 406 | |
| 407 | char *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 | |
| 418 | typedef 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) \ |
| 427 | do { \ |
| 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) \ |
| 436 | do { \ |
| 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 */ |
| 443 | float fabs_wrapper(float x) |
| 444 | { |
| 445 | return (x < 0.0f) ? -x : x; |
| 446 | } |
| 447 | |
| 448 | float 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 | |
| 456 | static 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 | |
| 463 | static 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 | |
| 470 | static 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 | |
| 484 | static const float zero = 0.0; |
| 485 | |
| 486 | static const float |
| 487 | huge = 1.0e+30, |
| 488 | tiny = 1.0e-30, |
| 489 | one = 1.0f; |
| 490 | |
| 491 | /* Square root function, original. */ |
| 492 | float 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 | |
| 557 | float 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 | |
| 604 | static const float |
| 605 | pi_o_4 = 7.8539818525e-01, /* 0x3f490fdb */ |
| 606 | pi_o_2 = 1.5707963705e+00, /* 0x3fc90fdb */ |
| 607 | pi = 3.1415927410e+00, /* 0x40490fdb */ |
| 608 | pi_lo = -8.7422776573e-08; /* 0xb3bbbd2e */ |
| 609 | |
| 610 | float 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 | } |
| 676 | union 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 | |
| 719 | static const volatile float TWOM100 = 7.88860905e-31; |
| 720 | static 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) |
| 732 | const 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 | |
| 780 | const 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. */ |
| 1139 | enum |
| 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 | |
| 1154 | int |
| 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 | |
| 1173 | int |
| 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 | |
| 1211 | float 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 */ |
| 1292 | float 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 | |
| 1337 | double 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 | |
| 1348 | double ceil_wrapper(double n) |
| 1349 | { |
| 1350 | return floor_wrapper(n) + 1.0; |
| 1351 | } |
| 1352 | |
| 1353 | /* Natural logarithm. |
| 1354 | Taken from glibc-2.8 */ |
| 1355 | static const float |
| 1356 | ln2_hi = 6.9313812256e-01, /* 0x3f317180 */ |
| 1357 | ln2_lo = 9.0580006145e-06, /* 0x3717f7d1 */ |
| 1358 | two25 = 3.355443200e+07, /* 0x4c000000 */ |
| 1359 | Lg1 = 6.6666668653e-01, /* 3F2AAAAB */ |
| 1360 | Lg2 = 4.0000000596e-01, /* 3ECCCCCD */ |
| 1361 | Lg3 = 2.8571429849e-01, /* 3E924925 */ |
| 1362 | Lg4 = 2.2222198546e-01, /* 3E638E29 */ |
| 1363 | Lg5 = 1.8183572590e-01, /* 3E3A3325 */ |
| 1364 | Lg6 = 1.5313838422e-01, /* 3E1CD04F */ |
| 1365 | Lg7 = 1.4798198640e-01; /* 3E178897 */ |
| 1366 | |
| 1367 | /* Get a 32 bit int from a float. */ |
| 1368 | |
| 1369 | #define GET_FLOAT_WORD(i,d) \ |
| 1370 | do { \ |
| 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) \ |
| 1379 | do { \ |
| 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 | |
| 1397 | float 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 | } |