forked from len0rd/rockbox
This ports id Software's Quake to run on the SDL plugin runtime. The source code originated from id under the GPLv2 license. I used https://github.com/ahefner/sdlquake as the base of my port. Performance is, unsurprisingly, not on par with what you're probably used to on PC. I average about 10FPS on ipod6g, but it's still playable. Sound works well enough, but in-game music is not supported. I've written ARM assembly routines for the inner sound loop. Make sure you turn the "brightness" all the way down, or colors will look funky. To run, extract Quake's data files to /.rockbox/quake. Have fun! Change-Id: I4285036e967d7f0722802d43cf2096c808ca5799
1460 lines
47 KiB
C
1460 lines
47 KiB
C
#include "plugin.h"
|
|
|
|
#include "fixedpoint.h"
|
|
|
|
#include <SDL.h>
|
|
|
|
extern bool printf_enabled;
|
|
|
|
/* fixed-point wrappers */
|
|
static unsigned long lastphase = 0;
|
|
static long lastsin = 0, lastcos = 0x7fffffff;
|
|
|
|
#define PI 3.1415926535897932384626433832795
|
|
|
|
void fatal(char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
|
|
rb->splash(HZ, "FATAL");
|
|
|
|
va_start(ap, fmt);
|
|
char buf[80];
|
|
vsnprintf(buf, 80, fmt, ap);
|
|
printf("%s", buf);
|
|
rb->splash(HZ * 2, buf);
|
|
va_end(ap);
|
|
|
|
exit(1);
|
|
}
|
|
|
|
char *strtok_wrapper(char *str, const char *delim)
|
|
{
|
|
static char *save = NULL;
|
|
return strtok_r(str, delim, &save);
|
|
}
|
|
|
|
/* Implementation of strtod() and atof(),
|
|
taken from SanOS (http://www.jbox.dk/sanos/). */
|
|
static int rb_errno = 0;
|
|
|
|
static double rb_strtod(const char *str, char **endptr)
|
|
{
|
|
double number;
|
|
int exponent;
|
|
int negative;
|
|
char *p = (char *) str;
|
|
double p10;
|
|
int n;
|
|
int num_digits;
|
|
int num_decimals;
|
|
|
|
/* Reset Rockbox errno -- W.B. */
|
|
#ifdef ROCKBOX
|
|
rb_errno = 0;
|
|
#endif
|
|
|
|
// Skip leading whitespace
|
|
while (isspace(*p)) p++;
|
|
|
|
// Handle optional sign
|
|
negative = 0;
|
|
switch (*p)
|
|
{
|
|
case '-': negative = 1; // Fall through to increment position
|
|
case '+': p++;
|
|
}
|
|
|
|
number = 0.;
|
|
exponent = 0;
|
|
num_digits = 0;
|
|
num_decimals = 0;
|
|
|
|
// Process string of digits
|
|
while (isdigit(*p))
|
|
{
|
|
number = number * 10. + (*p - '0');
|
|
p++;
|
|
num_digits++;
|
|
}
|
|
|
|
// Process decimal part
|
|
if (*p == '.')
|
|
{
|
|
p++;
|
|
|
|
while (isdigit(*p))
|
|
{
|
|
number = number * 10. + (*p - '0');
|
|
p++;
|
|
num_digits++;
|
|
num_decimals++;
|
|
}
|
|
|
|
exponent -= num_decimals;
|
|
}
|
|
|
|
if (num_digits == 0)
|
|
{
|
|
#ifdef ROCKBOX
|
|
rb_errno = 1;
|
|
#else
|
|
errno = ERANGE;
|
|
#endif
|
|
return 0.0;
|
|
}
|
|
|
|
// Correct for sign
|
|
if (negative) number = -number;
|
|
|
|
// Process an exponent string
|
|
if (*p == 'e' || *p == 'E')
|
|
{
|
|
// Handle optional sign
|
|
negative = 0;
|
|
switch(*++p)
|
|
{
|
|
case '-': negative = 1; // Fall through to increment pos
|
|
case '+': p++;
|
|
}
|
|
|
|
// Process string of digits
|
|
n = 0;
|
|
while (isdigit(*p))
|
|
{
|
|
n = n * 10 + (*p - '0');
|
|
p++;
|
|
}
|
|
|
|
if (negative)
|
|
exponent -= n;
|
|
else
|
|
exponent += n;
|
|
}
|
|
|
|
#ifndef ROCKBOX
|
|
if (exponent < DBL_MIN_EXP || exponent > DBL_MAX_EXP)
|
|
{
|
|
errno = ERANGE;
|
|
return HUGE_VAL;
|
|
}
|
|
#endif
|
|
|
|
// Scale the result
|
|
p10 = 10.;
|
|
n = exponent;
|
|
if (n < 0) n = -n;
|
|
while (n)
|
|
{
|
|
if (n & 1)
|
|
{
|
|
if (exponent < 0)
|
|
number /= p10;
|
|
else
|
|
number *= p10;
|
|
}
|
|
n >>= 1;
|
|
p10 *= p10;
|
|
}
|
|
|
|
#ifndef ROCKBOX
|
|
if (number == HUGE_VAL) errno = ERANGE;
|
|
#endif
|
|
if (endptr) *endptr = p;
|
|
|
|
return number;
|
|
}
|
|
|
|
// stolen from Quake
|
|
float atof_wrapper (char *str)
|
|
{
|
|
double val;
|
|
int sign;
|
|
int c;
|
|
int decimal, total;
|
|
|
|
if (*str == '-')
|
|
{
|
|
sign = -1;
|
|
str++;
|
|
}
|
|
else
|
|
sign = 1;
|
|
|
|
val = 0;
|
|
|
|
//
|
|
// check for hex
|
|
//
|
|
if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') )
|
|
{
|
|
str += 2;
|
|
while (1)
|
|
{
|
|
c = *str++;
|
|
if (c >= '0' && c <= '9')
|
|
val = (val*16) + c - '0';
|
|
else if (c >= 'a' && c <= 'f')
|
|
val = (val*16) + c - 'a' + 10;
|
|
else if (c >= 'A' && c <= 'F')
|
|
val = (val*16) + c - 'A' + 10;
|
|
else
|
|
return val*sign;
|
|
}
|
|
}
|
|
|
|
//
|
|
// check for character
|
|
//
|
|
if (str[0] == '\'')
|
|
{
|
|
return sign * str[1];
|
|
}
|
|
|
|
//
|
|
// assume decimal
|
|
//
|
|
decimal = -1;
|
|
total = 0;
|
|
while (1)
|
|
{
|
|
c = *str++;
|
|
if (c == '.')
|
|
{
|
|
decimal = total;
|
|
continue;
|
|
}
|
|
if (c <'0' || c > '9')
|
|
break;
|
|
val = val*10 + c - '0';
|
|
total++;
|
|
}
|
|
|
|
if (decimal == -1)
|
|
return val*sign;
|
|
while (total > decimal)
|
|
{
|
|
val /= 10;
|
|
total--;
|
|
}
|
|
|
|
return val*sign;
|
|
}
|
|
|
|
double sin_wrapper(double rads)
|
|
{
|
|
/* we want [0, 2*PI) */
|
|
while(rads >= 2*PI)
|
|
rads -= 2*PI;
|
|
while(rads < 0)
|
|
rads += 2*PI;
|
|
|
|
unsigned long phase = rads/(2*PI) * 4294967296.0;
|
|
|
|
/* caching */
|
|
if(phase == lastphase)
|
|
{
|
|
return lastsin/(lastsin < 0 ? 2147483648.0 : 2147483647.0);
|
|
}
|
|
|
|
lastphase = phase;
|
|
lastsin = fp_sincos(phase, &lastcos);
|
|
return lastsin/(lastsin < 0 ? 2147483648.0 : 2147483647.0);
|
|
}
|
|
|
|
double cos_wrapper(double rads)
|
|
{
|
|
/* we want [0, 2*PI) */
|
|
while(rads >= 2*PI)
|
|
rads -= 2*PI;
|
|
while(rads < 0)
|
|
rads += 2*PI;
|
|
|
|
unsigned long phase = rads/(2*PI) * 4294967296.0;
|
|
|
|
/* caching */
|
|
if(phase == lastphase)
|
|
{
|
|
return lastcos/(lastcos < 0 ? 2147483648.0 : 2147483647.0);
|
|
}
|
|
|
|
lastphase = phase;
|
|
lastsin = fp_sincos(phase, &lastcos);
|
|
return lastcos/(lastcos < 0 ? 2147483648.0 : 2147483647.0);
|
|
}
|
|
|
|
float tan_wrapper(float f)
|
|
{
|
|
return sin_wrapper(f)/cos_wrapper(f);
|
|
}
|
|
|
|
// Total hack. Supports only format strings of the form %Cc, where C
|
|
// is a format specifier and c is a delimiter. Surprisingly, most
|
|
// format strings aren't that complicated to need a real fscanf. This
|
|
// is just enough to make Quake run!
|
|
int fscanf_wrapper(FILE *f, const char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
|
|
if(strlen(fmt) != 3)
|
|
return 0; // not implemented
|
|
|
|
if(fmt[0] != '%')
|
|
return 0; // not implemented
|
|
|
|
char format = fmt[1];
|
|
char delim = fmt[2];
|
|
|
|
// extract argument
|
|
char buf[1024];
|
|
char *ptr = (format == 's' ? va_arg(ap, char*) : buf);
|
|
int c;
|
|
do {
|
|
c = fgetc(f);
|
|
*ptr++ = c;
|
|
} while(c != delim && c != EOF);
|
|
|
|
// overwrite delimiter
|
|
*(ptr-1) = 0;
|
|
|
|
//rb->splashf(HZ, "got argument %s, %s\n", fmt, buf);
|
|
|
|
switch(format)
|
|
{
|
|
case 'i':
|
|
*va_arg(ap, int*) = atoi(buf);
|
|
break;
|
|
case 'f':
|
|
*va_arg(ap, float*) = atof(buf);
|
|
break;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/* stolen from doom */
|
|
// Here is a hacked up printf command to get the output from the game.
|
|
int printf_wrapper(const char *fmt, ...)
|
|
{
|
|
static int p_xtpt;
|
|
char p_buf[256];
|
|
rb->yield();
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
vsnprintf(p_buf,sizeof(p_buf), fmt, ap);
|
|
va_end(ap);
|
|
|
|
rb->lcd_setfont(FONT_SYSFIXED);
|
|
rb->lcd_putsxy(0,p_xtpt, (unsigned char *)p_buf);
|
|
if (printf_enabled)
|
|
rb->lcd_update();
|
|
LOGF("%s", p_buf);
|
|
|
|
p_xtpt+=8;
|
|
if(p_xtpt>LCD_HEIGHT-8)
|
|
{
|
|
p_xtpt=0;
|
|
if (printf_enabled)
|
|
{
|
|
rb->lcd_set_backdrop(NULL);
|
|
rb->lcd_clear_display();
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int vprintf(const char *fmt, va_list ap)
|
|
{
|
|
char buf[256];
|
|
vsnprintf(buf, 256, fmt, ap);
|
|
return printf("%s", buf);
|
|
}
|
|
|
|
int sprintf_wrapper(char *str, const char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
va_start(ap, fmt);
|
|
int ret = vsnprintf(str, 9999, fmt, ap);
|
|
va_end(ap);
|
|
return ret;
|
|
}
|
|
|
|
int vsprintf_wrapper(char *str, const char *fmt, va_list ap)
|
|
{
|
|
return vsnprintf(str, 99999, fmt, ap);
|
|
}
|
|
|
|
char *strcpy_wrapper(char *dest, const char *src)
|
|
{
|
|
strlcpy(dest, src, 999);
|
|
return dest;
|
|
}
|
|
|
|
char *strdup_wrapper(const char *s) {
|
|
char *r = malloc(1+strlen(s));
|
|
strcpy(r,s);
|
|
return r;
|
|
}
|
|
|
|
char *strcat_wrapper(char *dest, const char *src)
|
|
{
|
|
rb->strlcat(dest, src, 999);
|
|
return dest;
|
|
}
|
|
|
|
char *strpbrk_wrapper(const char *s1, const char *s2)
|
|
{
|
|
while(*s1)
|
|
if(strchr(s2, *s1++))
|
|
return (char*)--s1;
|
|
return 0;
|
|
}
|
|
|
|
/* A union which permits us to convert between a float and a 32 bit
|
|
int. */
|
|
|
|
typedef union
|
|
{
|
|
float value;
|
|
uint32_t word;
|
|
} ieee_float_shape_type;
|
|
|
|
/* Get a 32 bit int from a float. */
|
|
|
|
#define GET_FLOAT_WORD(i,d) \
|
|
do { \
|
|
ieee_float_shape_type gf_u; \
|
|
gf_u.value = (d); \
|
|
(i) = gf_u.word; \
|
|
} while (0)
|
|
|
|
/* Set a float from a 32 bit int. */
|
|
|
|
#define SET_FLOAT_WORD(d,i) \
|
|
do { \
|
|
ieee_float_shape_type sf_u; \
|
|
sf_u.word = (i); \
|
|
(d) = sf_u.value; \
|
|
} while (0)
|
|
|
|
/* Absolute value, simple calculus */
|
|
float fabs_wrapper(float x)
|
|
{
|
|
return (x < 0.0f) ? -x : x;
|
|
}
|
|
|
|
float fmod(float x, float y)
|
|
{
|
|
return x - (int) (x / y) * y;
|
|
}
|
|
|
|
/* Arc tangent,
|
|
taken from glibc-2.8. */
|
|
|
|
static const float atanhi[] = {
|
|
4.6364760399e-01, /* atan(0.5)hi 0x3eed6338 */
|
|
7.8539812565e-01, /* atan(1.0)hi 0x3f490fda */
|
|
9.8279368877e-01, /* atan(1.5)hi 0x3f7b985e */
|
|
1.5707962513e+00, /* atan(inf)hi 0x3fc90fda */
|
|
};
|
|
|
|
static const float atanlo[] = {
|
|
5.0121582440e-09, /* atan(0.5)lo 0x31ac3769 */
|
|
3.7748947079e-08, /* atan(1.0)lo 0x33222168 */
|
|
3.4473217170e-08, /* atan(1.5)lo 0x33140fb4 */
|
|
7.5497894159e-08, /* atan(inf)lo 0x33a22168 */
|
|
};
|
|
|
|
static const float aT[] = {
|
|
3.3333334327e-01, /* 0x3eaaaaaa */
|
|
-2.0000000298e-01, /* 0xbe4ccccd */
|
|
1.4285714924e-01, /* 0x3e124925 */
|
|
-1.1111110449e-01, /* 0xbde38e38 */
|
|
9.0908870101e-02, /* 0x3dba2e6e */
|
|
-7.6918758452e-02, /* 0xbd9d8795 */
|
|
6.6610731184e-02, /* 0x3d886b35 */
|
|
-5.8335702866e-02, /* 0xbd6ef16b */
|
|
4.9768779427e-02, /* 0x3d4bda59 */
|
|
-3.6531571299e-02, /* 0xbd15a221 */
|
|
1.6285819933e-02, /* 0x3c8569d7 */
|
|
};
|
|
|
|
static const float zero = 0.0;
|
|
|
|
static const float
|
|
huge = 1.0e+30,
|
|
tiny = 1.0e-30,
|
|
one = 1.0f;
|
|
|
|
/* Square root function, original. */
|
|
float sqrt_wrapper(float x)
|
|
{
|
|
float z;
|
|
int32_t sign = (int)0x80000000;
|
|
int32_t ix,s,q,m,t,i;
|
|
uint32_t r;
|
|
|
|
GET_FLOAT_WORD(ix,x);
|
|
|
|
/* take care of Inf and NaN */
|
|
if((ix&0x7f800000)==0x7f800000) {
|
|
return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf
|
|
sqrt(-inf)=sNaN */
|
|
}
|
|
/* take care of zero */
|
|
if(ix<=0) {
|
|
if((ix&(~sign))==0) return x;/* sqrt(+-0) = +-0 */
|
|
else if(ix<0)
|
|
return (x-x)/(x-x); /* sqrt(-ve) = sNaN */
|
|
}
|
|
/* normalize x */
|
|
m = (ix>>23);
|
|
if(m==0) { /* subnormal x */
|
|
for(i=0;(ix&0x00800000)==0;i++) ix<<=1;
|
|
m -= i-1;
|
|
}
|
|
m -= 127; /* unbias exponent */
|
|
ix = (ix&0x007fffff)|0x00800000;
|
|
if(m&1) /* odd m, double x to make it even */
|
|
ix += ix;
|
|
m >>= 1; /* m = [m/2] */
|
|
|
|
/* generate sqrt(x) bit by bit */
|
|
ix += ix;
|
|
q = s = 0; /* q = sqrt(x) */
|
|
r = 0x01000000; /* r = moving bit from right to left */
|
|
|
|
while(r!=0) {
|
|
t = s+r;
|
|
if(t<=ix) {
|
|
s = t+r;
|
|
ix -= t;
|
|
q += r;
|
|
}
|
|
ix += ix;
|
|
r>>=1;
|
|
}
|
|
|
|
/* use floating add to find out rounding direction */
|
|
if(ix!=0) {
|
|
z = one-tiny; /* trigger inexact flag */
|
|
if (z>=one) {
|
|
z = one+tiny;
|
|
if (z>one)
|
|
q += 2;
|
|
else
|
|
q += (q&1);
|
|
}
|
|
}
|
|
ix = (q>>1)+0x3f000000;
|
|
ix += (m <<23);
|
|
SET_FLOAT_WORD(z,ix);
|
|
return z;
|
|
}
|
|
|
|
float atan_wrapper(float x)
|
|
{
|
|
float w,s1,s2,z;
|
|
int32_t ix,hx,id;
|
|
|
|
GET_FLOAT_WORD(hx,x);
|
|
ix = hx&0x7fffffff;
|
|
if(ix>=0x50800000) { /* if |x| >= 2^34 */
|
|
if(ix>0x7f800000)
|
|
return x+x; /* NaN */
|
|
if(hx>0) return atanhi[3]+atanlo[3];
|
|
else return -atanhi[3]-atanlo[3];
|
|
} if (ix < 0x3ee00000) { /* |x| < 0.4375 */
|
|
if (ix < 0x31000000) { /* |x| < 2^-29 */
|
|
if(huge+x>one) return x; /* raise inexact */
|
|
}
|
|
id = -1;
|
|
} else {
|
|
x = fabs_wrapper(x);
|
|
if (ix < 0x3f980000) { /* |x| < 1.1875 */
|
|
if (ix < 0x3f300000) { /* 7/16 <=|x|<11/16 */
|
|
id = 0; x = ((float)2.0*x-one)/((float)2.0+x);
|
|
} else { /* 11/16<=|x|< 19/16 */
|
|
id = 1; x = (x-one)/(x+one);
|
|
}
|
|
} else {
|
|
if (ix < 0x401c0000) { /* |x| < 2.4375 */
|
|
id = 2; x = (x-(float)1.5)/(one+(float)1.5*x);
|
|
} else { /* 2.4375 <= |x| < 2^66 */
|
|
id = 3; x = -(float)1.0/x;
|
|
}
|
|
}}
|
|
/* end of argument reduction */
|
|
z = x*x;
|
|
w = z*z;
|
|
/* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */
|
|
s1 = z*(aT[0]+w*(aT[2]+w*(aT[4]+w*(aT[6]+w*(aT[8]+w*aT[10])))));
|
|
s2 = w*(aT[1]+w*(aT[3]+w*(aT[5]+w*(aT[7]+w*aT[9]))));
|
|
if (id<0) return x - x*(s1+s2);
|
|
else {
|
|
z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x);
|
|
return (hx<0)? -z:z;
|
|
}
|
|
}
|
|
|
|
/* Arc tangent from two variables, original. */
|
|
|
|
static const float
|
|
pi_o_4 = 7.8539818525e-01, /* 0x3f490fdb */
|
|
pi_o_2 = 1.5707963705e+00, /* 0x3fc90fdb */
|
|
pi = 3.1415927410e+00, /* 0x40490fdb */
|
|
pi_lo = -8.7422776573e-08; /* 0xb3bbbd2e */
|
|
|
|
float atan2_wrapper(float y, float x)
|
|
{
|
|
float z;
|
|
int32_t k,m,hx,hy,ix,iy;
|
|
|
|
GET_FLOAT_WORD(hx,x);
|
|
ix = hx&0x7fffffff;
|
|
GET_FLOAT_WORD(hy,y);
|
|
iy = hy&0x7fffffff;
|
|
if((ix>0x7f800000)||
|
|
(iy>0x7f800000)) /* x or y is NaN */
|
|
return x+y;
|
|
if(hx==0x3f800000) return atan_wrapper(y); /* x=1.0 */
|
|
m = ((hy>>31)&1)|((hx>>30)&2); /* 2*sign(x)+sign(y) */
|
|
|
|
/* when y = 0 */
|
|
if(iy==0) {
|
|
switch(m) {
|
|
case 0:
|
|
case 1: return y; /* atan(+-0,+anything)=+-0 */
|
|
case 2: return pi+tiny;/* atan(+0,-anything) = pi */
|
|
case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */
|
|
}
|
|
}
|
|
/* when x = 0 */
|
|
if(ix==0) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny;
|
|
|
|
/* when x is INF */
|
|
if(ix==0x7f800000) {
|
|
if(iy==0x7f800000) {
|
|
switch(m) {
|
|
case 0: return pi_o_4+tiny;/* atan(+INF,+INF) */
|
|
case 1: return -pi_o_4-tiny;/* atan(-INF,+INF) */
|
|
case 2: return (float)3.0*pi_o_4+tiny;/*atan(+INF,-INF)*/
|
|
case 3: return (float)-3.0*pi_o_4-tiny;/*atan(-INF,-INF)*/
|
|
}
|
|
} else {
|
|
switch(m) {
|
|
case 0: return zero ; /* atan(+...,+INF) */
|
|
case 1: return -zero ; /* atan(-...,+INF) */
|
|
case 2: return pi+tiny ; /* atan(+...,-INF) */
|
|
case 3: return -pi-tiny ; /* atan(-...,-INF) */
|
|
}
|
|
}
|
|
}
|
|
/* when y is INF */
|
|
if(iy==0x7f800000) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny;
|
|
|
|
/* compute y/x */
|
|
k = (iy-ix)>>23;
|
|
if(k > 60) z=pi_o_2+(float)0.5*pi_lo; /* |y/x| > 2**60 */
|
|
else if(hx<0&&k<-60) z=0.0; /* |y|/x < -2**60 */
|
|
else z=atan_wrapper(fabs_wrapper(y/x)); /* safe to do y/x */
|
|
switch (m) {
|
|
case 0: return z ; /* atan(+,+) */
|
|
case 1: {
|
|
uint32_t zh;
|
|
GET_FLOAT_WORD(zh,z);
|
|
SET_FLOAT_WORD(z,zh ^ 0x80000000);
|
|
}
|
|
return z ; /* atan(-,+) */
|
|
case 2: return pi-(z-pi_lo);/* atan(+,-) */
|
|
default: /* case 3 */
|
|
return (z-pi_lo)-pi;/* atan(-,-) */
|
|
}
|
|
}
|
|
union ieee754_double
|
|
{
|
|
double d;
|
|
|
|
/* This is the IEEE 754 double-precision format. */
|
|
struct
|
|
{
|
|
#ifdef ROCKBOX_BIG_ENDIAN
|
|
unsigned int negative:1;
|
|
unsigned int exponent:11;
|
|
/* Together these comprise the mantissa. */
|
|
unsigned int mantissa0:20;
|
|
unsigned int mantissa1:32;
|
|
#else /* ROCKBOX_LITTLE_ENDIAN */
|
|
/* Together these comprise the mantissa. */
|
|
unsigned int mantissa1:32;
|
|
unsigned int mantissa0:20;
|
|
unsigned int exponent:11;
|
|
unsigned int negative:1;
|
|
#endif /* ROCKBOX_LITTLE_ENDIAN */
|
|
} ieee;
|
|
|
|
/* This format makes it easier to see if a NaN is a signalling NaN. */
|
|
struct
|
|
{
|
|
#ifdef ROCKBOX_BIG_ENDIAN
|
|
unsigned int negative:1;
|
|
unsigned int exponent:11;
|
|
unsigned int quiet_nan:1;
|
|
/* Together these comprise the mantissa. */
|
|
unsigned int mantissa0:19;
|
|
unsigned int mantissa1:32;
|
|
#else /* ROCKBOX_LITTLE_ENDIAN */
|
|
/* Together these comprise the mantissa. */
|
|
unsigned int mantissa1:32;
|
|
unsigned int mantissa0:19;
|
|
unsigned int quiet_nan:1;
|
|
unsigned int exponent:11;
|
|
unsigned int negative:1;
|
|
#endif /* ROCKBOX_LITTLE_ENDIAN */
|
|
} ieee_nan;
|
|
};
|
|
|
|
static const volatile float TWOM100 = 7.88860905e-31;
|
|
static const volatile float TWO127 = 1.7014118346e+38;
|
|
|
|
/* Exponential function,
|
|
taken from glibc-2.8
|
|
As it uses double values and udefines some symbols,
|
|
it was moved to the end of the source code */
|
|
|
|
#define W52 (2.22044605e-16)
|
|
#define W55 (2.77555756e-17)
|
|
#define W58 (3.46944695e-18)
|
|
#define W59 (1.73472348e-18)
|
|
#define W60 (8.67361738e-19)
|
|
const float __exp_deltatable[178] = {
|
|
0*W60, 16558714*W60, -10672149*W59, 1441652*W60,
|
|
-15787963*W55, 462888*W60, 7291806*W60, 1698880*W60,
|
|
-14375103*W58, -2021016*W60, 728829*W60, -3759654*W60,
|
|
3202123*W60, -10916019*W58, -251570*W60, -1043086*W60,
|
|
8207536*W60, -409964*W60, -5993931*W60, -475500*W60,
|
|
2237522*W60, 324170*W60, -244117*W60, 32077*W60,
|
|
123907*W60, -1019734*W60, -143*W60, 813077*W60,
|
|
743345*W60, 462461*W60, 629794*W60, 2125066*W60,
|
|
-2339121*W60, -337951*W60, 9922067*W60, -648704*W60,
|
|
149407*W60, -2687209*W60, -631608*W60, 2128280*W60,
|
|
-4882082*W60, 2001360*W60, 175074*W60, 2923216*W60,
|
|
-538947*W60, -1212193*W60, -1920926*W60, -1080577*W60,
|
|
3690196*W60, 2643367*W60, 2911937*W60, 671455*W60,
|
|
-1128674*W60, 593282*W60, -5219347*W60, -1941490*W60,
|
|
11007953*W60, 239609*W60, -2969658*W60, -1183650*W60,
|
|
942998*W60, 699063*W60, 450569*W60, -329250*W60,
|
|
-7257875*W60, -312436*W60, 51626*W60, 555877*W60,
|
|
-641761*W60, 1565666*W60, 884327*W60, -10960035*W60,
|
|
-2004679*W60, -995793*W60, -2229051*W60, -146179*W60,
|
|
-510327*W60, 1453482*W60, -3778852*W60, -2238056*W60,
|
|
-4895983*W60, 3398883*W60, -252738*W60, 1230155*W60,
|
|
346918*W60, 1109352*W60, 268941*W60, -2930483*W60,
|
|
-1036263*W60, -1159280*W60, 1328176*W60, 2937642*W60,
|
|
-9371420*W60, -6902650*W60, -1419134*W60, 1442904*W60,
|
|
-1319056*W60, -16369*W60, 696555*W60, -279987*W60,
|
|
-7919763*W60, 252741*W60, 459711*W60, -1709645*W60,
|
|
354913*W60, 6025867*W60, -421460*W60, -853103*W60,
|
|
-338649*W60, 962151*W60, 955965*W60, 784419*W60,
|
|
-3633653*W60, 2277133*W60, -8847927*W52, 1223028*W60,
|
|
5907079*W60, 623167*W60, 5142888*W60, 2599099*W60,
|
|
1214280*W60, 4870359*W60, 593349*W60, -57705*W60,
|
|
7761209*W60, -5564097*W60, 2051261*W60, 6216869*W60,
|
|
4692163*W60, 601691*W60, -5264906*W60, 1077872*W60,
|
|
-3205949*W60, 1833082*W60, 2081746*W60, -987363*W60,
|
|
-1049535*W60, 2015244*W60, 874230*W60, 2168259*W60,
|
|
-1740124*W60, -10068269*W60, -18242*W60, -3013583*W60,
|
|
580601*W60, -2547161*W60, -535689*W60, 2220815*W60,
|
|
1285067*W60, 2806933*W60, -983086*W60, -1729097*W60,
|
|
-1162985*W60, -2561904*W60, 801988*W60, 244351*W60,
|
|
1441893*W60, -7517981*W60, 271781*W60, -15021588*W60,
|
|
-2341588*W60, -919198*W60, 1642232*W60, 4771771*W60,
|
|
-1220099*W60, -3062372*W60, 628624*W60, 1278114*W60,
|
|
13083513*W60, -10521925*W60, 3180310*W60, -1659307*W60,
|
|
3543773*W60, 2501203*W60, 4151*W60, -340748*W60,
|
|
-2285625*W60, 2495202*W60
|
|
};
|
|
|
|
const double __exp_atable[355] /* __attribute__((mode(DF))) */ = {
|
|
0.707722561055888932371, /* 0x0.b52d4e46605c27ffd */
|
|
0.709106182438804188967, /* 0x0.b587fb96f75097ffb */
|
|
0.710492508843861281234, /* 0x0.b5e2d649899167ffd */
|
|
0.711881545564593931623, /* 0x0.b63dde74d36bdfffe */
|
|
0.713273297897442870573, /* 0x0.b699142f945f87ffc */
|
|
0.714667771153751463236, /* 0x0.b6f477909c4ea0001 */
|
|
0.716064970655995725059, /* 0x0.b75008aec758f8004 */
|
|
0.717464901723956938193, /* 0x0.b7abc7a0eea7e0002 */
|
|
0.718867569715736398602, /* 0x0.b807b47e1586c7ff8 */
|
|
0.720272979947266023271, /* 0x0.b863cf5d10e380003 */
|
|
0.721681137825144314297, /* 0x0.b8c01855195c37ffb */
|
|
0.723092048691992950199, /* 0x0.b91c8f7d213740004 */
|
|
0.724505717938892290800, /* 0x0.b97934ec5002d0007 */
|
|
0.725922150953176470431, /* 0x0.b9d608b9c92ea7ffc */
|
|
0.727341353138962865022, /* 0x0.ba330afcc29e98003 */
|
|
0.728763329918453162104, /* 0x0.ba903bcc8618b7ffc */
|
|
0.730188086709957051568, /* 0x0.baed9b40591ba0000 */
|
|
0.731615628948127705309, /* 0x0.bb4b296f931e30002 */
|
|
0.733045962086486091436, /* 0x0.bba8e671a05617ff9 */
|
|
0.734479091556371366251, /* 0x0.bc06d25dd49568001 */
|
|
0.735915022857225542529, /* 0x0.bc64ed4bce8f6fff9 */
|
|
0.737353761441304711410, /* 0x0.bcc33752f915d7ff9 */
|
|
0.738795312814142124419, /* 0x0.bd21b08af98e78005 */
|
|
0.740239682467211168593, /* 0x0.bd80590b65e9a8000 */
|
|
0.741686875913991849885, /* 0x0.bddf30ebec4a10000 */
|
|
0.743136898669507939299, /* 0x0.be3e38443c84e0007 */
|
|
0.744589756269486091620, /* 0x0.be9d6f2c1d32a0002 */
|
|
0.746045454254026796384, /* 0x0.befcd5bb59baf8004 */
|
|
0.747503998175051087583, /* 0x0.bf5c6c09ca84c0003 */
|
|
0.748965393601880857739, /* 0x0.bfbc322f5b18b7ff8 */
|
|
0.750429646104262104698, /* 0x0.c01c2843f776fffff */
|
|
0.751896761271877989160, /* 0x0.c07c4e5fa18b88002 */
|
|
0.753366744698445112140, /* 0x0.c0dca49a5fb18fffd */
|
|
0.754839601988627206827, /* 0x0.c13d2b0c444db0005 */
|
|
0.756315338768691947122, /* 0x0.c19de1cd798578006 */
|
|
0.757793960659406629066, /* 0x0.c1fec8f623723fffd */
|
|
0.759275473314173443536, /* 0x0.c25fe09e8a0f47ff8 */
|
|
0.760759882363831851927, /* 0x0.c2c128dedc88f8000 */
|
|
0.762247193485956486805, /* 0x0.c322a1cf7d6e7fffa */
|
|
0.763737412354726363781, /* 0x0.c3844b88cb9347ffc */
|
|
0.765230544649828092739, /* 0x0.c3e626232bd8f7ffc */
|
|
0.766726596071518051729, /* 0x0.c44831b719bf18002 */
|
|
0.768225572321911687194, /* 0x0.c4aa6e5d12d078001 */
|
|
0.769727479119219348810, /* 0x0.c50cdc2da64a37ffb */
|
|
0.771232322196981678892, /* 0x0.c56f7b41744490001 */
|
|
0.772740107296721268087, /* 0x0.c5d24bb1259e70004 */
|
|
0.774250840160724651565, /* 0x0.c6354d95640dd0007 */
|
|
0.775764526565368872643, /* 0x0.c6988106fec447fff */
|
|
0.777281172269557396602, /* 0x0.c6fbe61eb1bd0ffff */
|
|
0.778800783068235302750, /* 0x0.c75f7cf560942fffc */
|
|
0.780323364758801041312, /* 0x0.c7c345a3f1983fffe */
|
|
0.781848923151573727006, /* 0x0.c8274043594cb0002 */
|
|
0.783377464064598849602, /* 0x0.c88b6cec94b3b7ff9 */
|
|
0.784908993312207869935, /* 0x0.c8efcbb89cba27ffe */
|
|
0.786443516765346961618, /* 0x0.c9545cc0a88c70003 */
|
|
0.787981040257604625744, /* 0x0.c9b9201dc643bfffa */
|
|
0.789521569657452682047, /* 0x0.ca1e15e92a5410007 */
|
|
0.791065110849462849192, /* 0x0.ca833e3c1ae510005 */
|
|
0.792611669712891875319, /* 0x0.cae8992fd84667ffd */
|
|
0.794161252150049179450, /* 0x0.cb4e26ddbc207fff8 */
|
|
0.795713864077794763584, /* 0x0.cbb3e75f301b60003 */
|
|
0.797269511407239561694, /* 0x0.cc19dacd978cd8002 */
|
|
0.798828200086368567220, /* 0x0.cc8001427e55d7ffb */
|
|
0.800389937624300440456, /* 0x0.cce65ade24d360006 */
|
|
0.801954725261124767840, /* 0x0.cd4ce7a5de839fffb */
|
|
0.803522573691593189330, /* 0x0.cdb3a7c79a678fffd */
|
|
0.805093487311204114563, /* 0x0.ce1a9b563965ffffc */
|
|
0.806667472122675088819, /* 0x0.ce81c26b838db8000 */
|
|
0.808244534127439906441, /* 0x0.cee91d213f8428002 */
|
|
0.809824679342317166307, /* 0x0.cf50ab9144d92fff9 */
|
|
0.811407913793616542005, /* 0x0.cfb86dd5758c2ffff */
|
|
0.812994243520784198882, /* 0x0.d0206407c20e20005 */
|
|
0.814583674571603966162, /* 0x0.d0888e4223facfff9 */
|
|
0.816176213022088536960, /* 0x0.d0f0ec9eb3f7c8002 */
|
|
0.817771864936188586101, /* 0x0.d1597f377d6768002 */
|
|
0.819370636400374108252, /* 0x0.d1c24626a46eafff8 */
|
|
0.820972533518165570298, /* 0x0.d22b41865ff1e7ff9 */
|
|
0.822577562404315121269, /* 0x0.d2947170f32ec7ff9 */
|
|
0.824185729164559344159, /* 0x0.d2fdd60097795fff8 */
|
|
0.825797039949601741075, /* 0x0.d3676f4fb796d0001 */
|
|
0.827411500902565544264, /* 0x0.d3d13d78b5f68fffb */
|
|
0.829029118181348834154, /* 0x0.d43b40960546d8001 */
|
|
0.830649897953322891022, /* 0x0.d4a578c222a058000 */
|
|
0.832273846408250750368, /* 0x0.d50fe617a3ba78005 */
|
|
0.833900969738858188772, /* 0x0.d57a88b1218e90002 */
|
|
0.835531274148056613016, /* 0x0.d5e560a94048f8006 */
|
|
0.837164765846411529371, /* 0x0.d6506e1aac8078003 */
|
|
0.838801451086016225394, /* 0x0.d6bbb1204074e0001 */
|
|
0.840441336100884561780, /* 0x0.d72729d4c28518004 */
|
|
0.842084427144139224814, /* 0x0.d792d8530e12b0001 */
|
|
0.843730730487052604790, /* 0x0.d7febcb61273e7fff */
|
|
0.845380252404570153833, /* 0x0.d86ad718c308dfff9 */
|
|
0.847032999194574087728, /* 0x0.d8d727962c69d7fff */
|
|
0.848688977161248581090, /* 0x0.d943ae49621ce7ffb */
|
|
0.850348192619261200615, /* 0x0.d9b06b4d832ef8005 */
|
|
0.852010651900976245816, /* 0x0.da1d5ebdc22220005 */
|
|
0.853676361342631029337, /* 0x0.da8a88b555baa0006 */
|
|
0.855345327311054837175, /* 0x0.daf7e94f965f98004 */
|
|
0.857017556155879489641, /* 0x0.db6580a7c98f7fff8 */
|
|
0.858693054267390953857, /* 0x0.dbd34ed9617befff8 */
|
|
0.860371828028939855647, /* 0x0.dc4153ffc8b65fff9 */
|
|
0.862053883854957292436, /* 0x0.dcaf90368bfca8004 */
|
|
0.863739228154875360306, /* 0x0.dd1e0399328d87ffe */
|
|
0.865427867361348468455, /* 0x0.dd8cae435d303fff9 */
|
|
0.867119807911702289458, /* 0x0.ddfb9050b1cee8006 */
|
|
0.868815056264353846599, /* 0x0.de6aa9dced8448001 */
|
|
0.870513618890481399881, /* 0x0.ded9fb03db7320006 */
|
|
0.872215502247877139094, /* 0x0.df4983e1380657ff8 */
|
|
0.873920712852848668986, /* 0x0.dfb94490ffff77ffd */
|
|
0.875629257204025623884, /* 0x0.e0293d2f1cb01fff9 */
|
|
0.877341141814212965880, /* 0x0.e0996dd786fff0007 */
|
|
0.879056373217612985183, /* 0x0.e109d6a64f5d57ffc */
|
|
0.880774957955916648615, /* 0x0.e17a77b78e72a7ffe */
|
|
0.882496902590150900078, /* 0x0.e1eb5127722cc7ff8 */
|
|
0.884222213673356738383, /* 0x0.e25c63121fb0c8006 */
|
|
0.885950897802399772740, /* 0x0.e2cdad93ec5340003 */
|
|
0.887682961567391237685, /* 0x0.e33f30c925fb97ffb */
|
|
0.889418411575228162725, /* 0x0.e3b0ecce2d05ffff9 */
|
|
0.891157254447957902797, /* 0x0.e422e1bf727718006 */
|
|
0.892899496816652704641, /* 0x0.e4950fb9713fc7ffe */
|
|
0.894645145323828439008, /* 0x0.e50776d8b0e60fff8 */
|
|
0.896394206626591749641, /* 0x0.e57a1739c8fadfffc */
|
|
0.898146687421414902124, /* 0x0.e5ecf0f97c5798007 */
|
|
0.899902594367530173098, /* 0x0.e660043464e378005 */
|
|
0.901661934163603406867, /* 0x0.e6d3510747e150006 */
|
|
0.903424713533971135418, /* 0x0.e746d78f06cd97ffd */
|
|
0.905190939194458810123, /* 0x0.e7ba97e879c91fffc */
|
|
0.906960617885092856864, /* 0x0.e82e92309390b0007 */
|
|
0.908733756358986566306, /* 0x0.e8a2c6845544afffa */
|
|
0.910510361377119825629, /* 0x0.e9173500c8abc7ff8 */
|
|
0.912290439722343249336, /* 0x0.e98bddc30f98b0002 */
|
|
0.914073998177417412765, /* 0x0.ea00c0e84bc4c7fff */
|
|
0.915861043547953501680, /* 0x0.ea75de8db8094fffe */
|
|
0.917651582652244779397, /* 0x0.eaeb36d09d3137ffe */
|
|
0.919445622318405764159, /* 0x0.eb60c9ce4ed3dffff */
|
|
0.921243169397334638073, /* 0x0.ebd697a43995b0007 */
|
|
0.923044230737526172328, /* 0x0.ec4ca06fc7768fffa */
|
|
0.924848813220121135342, /* 0x0.ecc2e44e865b6fffb */
|
|
0.926656923710931002014, /* 0x0.ed39635df34e70006 */
|
|
0.928468569126343790092, /* 0x0.edb01dbbc2f5b7ffa */
|
|
0.930283756368834757725, /* 0x0.ee2713859aab57ffa */
|
|
0.932102492359406786818, /* 0x0.ee9e44d9342870004 */
|
|
0.933924784042873379360, /* 0x0.ef15b1d4635438005 */
|
|
0.935750638358567643520, /* 0x0.ef8d5a94f60f50007 */
|
|
0.937580062297704630580, /* 0x0.f0053f38f345cffff */
|
|
0.939413062815381727516, /* 0x0.f07d5fde3a2d98001 */
|
|
0.941249646905368053689, /* 0x0.f0f5bca2d481a8004 */
|
|
0.943089821583810716806, /* 0x0.f16e55a4e497d7ffe */
|
|
0.944933593864477061592, /* 0x0.f1e72b028a2827ffb */
|
|
0.946780970781518460559, /* 0x0.f2603cd9fb5430001 */
|
|
0.948631959382661205081, /* 0x0.f2d98b497d2a87ff9 */
|
|
0.950486566729423554277, /* 0x0.f353166f63e3dffff */
|
|
0.952344799896018723290, /* 0x0.f3ccde6a11ae37ffe */
|
|
0.954206665969085765512, /* 0x0.f446e357f66120000 */
|
|
0.956072172053890279009, /* 0x0.f4c12557964f0fff9 */
|
|
0.957941325265908139014, /* 0x0.f53ba48781046fffb */
|
|
0.959814132734539637840, /* 0x0.f5b66106555d07ffa */
|
|
0.961690601603558903308, /* 0x0.f6315af2c2027fffc */
|
|
0.963570739036113010927, /* 0x0.f6ac926b8aeb80004 */
|
|
0.965454552202857141381, /* 0x0.f728078f7c5008002 */
|
|
0.967342048278315158608, /* 0x0.f7a3ba7d66a908001 */
|
|
0.969233234469444204768, /* 0x0.f81fab543e1897ffb */
|
|
0.971128118008140250896, /* 0x0.f89bda33122c78007 */
|
|
0.973026706099345495256, /* 0x0.f9184738d4cf97ff8 */
|
|
0.974929006031422851235, /* 0x0.f994f284d3a5c0008 */
|
|
0.976835024947348973265, /* 0x0.fa11dc35bc7820002 */
|
|
0.978744770239899142285, /* 0x0.fa8f046b4fb7f8007 */
|
|
0.980658249138918636210, /* 0x0.fb0c6b449ab1cfff9 */
|
|
0.982575468959622777535, /* 0x0.fb8a10e1088fb7ffa */
|
|
0.984496437054508843888, /* 0x0.fc07f5602d79afffc */
|
|
0.986421160608523028820, /* 0x0.fc8618e0e55e47ffb */
|
|
0.988349647107594098099, /* 0x0.fd047b83571b1fffa */
|
|
0.990281903873210800357, /* 0x0.fd831d66f4c018002 */
|
|
0.992217938695037382475, /* 0x0.fe01fead3320bfff8 */
|
|
0.994157757657894713987, /* 0x0.fe811f703491e8006 */
|
|
0.996101369488558541238, /* 0x0.ff007fd5744490005 */
|
|
0.998048781093141101932, /* 0x0.ff801ffa9b9280007 */
|
|
1.000000000000000000000, /* 0x1.00000000000000000 */
|
|
1.001955033605393285965, /* 0x1.0080200565d29ffff */
|
|
1.003913889319761887310, /* 0x1.0100802aa0e80fff0 */
|
|
1.005876574715736104818, /* 0x1.01812090377240007 */
|
|
1.007843096764807100351, /* 0x1.020201541aad7fff6 */
|
|
1.009813464316352327214, /* 0x1.0283229c4c9820007 */
|
|
1.011787683565730677817, /* 0x1.030484836910a000e */
|
|
1.013765762469146736174, /* 0x1.0386272b9c077fffe */
|
|
1.015747708536026694351, /* 0x1.04080ab526304fff0 */
|
|
1.017733529475172815584, /* 0x1.048a2f412375ffff0 */
|
|
1.019723232714418781378, /* 0x1.050c94ef7ad5e000a */
|
|
1.021716825883923762690, /* 0x1.058f3be0f1c2d0004 */
|
|
1.023714316605201180057, /* 0x1.06122436442e2000e */
|
|
1.025715712440059545995, /* 0x1.06954e0fec63afff2 */
|
|
1.027721021151397406936, /* 0x1.0718b98f41c92fff6 */
|
|
1.029730250269221158939, /* 0x1.079c66d49bb2ffff1 */
|
|
1.031743407506447551857, /* 0x1.082056011a9230009 */
|
|
1.033760500517691527387, /* 0x1.08a487359ebd50002 */
|
|
1.035781537016238873464, /* 0x1.0928fa93490d4fff3 */
|
|
1.037806524719013578963, /* 0x1.09adb03b3e5b3000d */
|
|
1.039835471338248051878, /* 0x1.0a32a84e9e5760004 */
|
|
1.041868384612101516848, /* 0x1.0ab7e2eea5340ffff */
|
|
1.043905272300907460835, /* 0x1.0b3d603ca784f0009 */
|
|
1.045946142174331239262, /* 0x1.0bc3205a042060000 */
|
|
1.047991002016745332165, /* 0x1.0c4923682a086fffe */
|
|
1.050039859627715177527, /* 0x1.0ccf698898f3a000d */
|
|
1.052092722826109660856, /* 0x1.0d55f2dce5d1dfffb */
|
|
1.054149599440827866881, /* 0x1.0ddcbf86b09a5fff6 */
|
|
1.056210497317612961855, /* 0x1.0e63cfa7abc97fffd */
|
|
1.058275424318780855142, /* 0x1.0eeb23619c146fffb */
|
|
1.060344388322010722446, /* 0x1.0f72bad65714bffff */
|
|
1.062417397220589476718, /* 0x1.0ffa9627c38d30004 */
|
|
1.064494458915699715017, /* 0x1.1082b577d0eef0003 */
|
|
1.066575581342167566880, /* 0x1.110b18e893a90000a */
|
|
1.068660772440545025953, /* 0x1.1193c09c267610006 */
|
|
1.070750040138235936705, /* 0x1.121cacb4959befff6 */
|
|
1.072843392435016474095, /* 0x1.12a5dd543cf36ffff */
|
|
1.074940837302467588937, /* 0x1.132f529d59552000b */
|
|
1.077042382749654914030, /* 0x1.13b90cb250d08fff5 */
|
|
1.079148036789447484528, /* 0x1.14430bb58da3dfff9 */
|
|
1.081257807444460983297, /* 0x1.14cd4fc984c4a000e */
|
|
1.083371702785017154417, /* 0x1.1557d910df9c7000e */
|
|
1.085489730853784307038, /* 0x1.15e2a7ae292d30002 */
|
|
1.087611899742884524772, /* 0x1.166dbbc422d8c0004 */
|
|
1.089738217537583819804, /* 0x1.16f9157586772ffff */
|
|
1.091868692357631731528, /* 0x1.1784b4e533cacfff0 */
|
|
1.094003332327482702577, /* 0x1.18109a360fc23fff2 */
|
|
1.096142145591650907149, /* 0x1.189cc58b155a70008 */
|
|
1.098285140311341168136, /* 0x1.1929370751ea50002 */
|
|
1.100432324652149906842, /* 0x1.19b5eecdd79cefff0 */
|
|
1.102583706811727015711, /* 0x1.1a42ed01dbdba000e */
|
|
1.104739294993289488947, /* 0x1.1ad031c69a2eafff0 */
|
|
1.106899097422573863281, /* 0x1.1b5dbd3f66e120003 */
|
|
1.109063122341542140286, /* 0x1.1beb8f8fa8150000b */
|
|
1.111231377994659874592, /* 0x1.1c79a8dac6ad0fff4 */
|
|
1.113403872669181282605, /* 0x1.1d0809445a97ffffc */
|
|
1.115580614653132185460, /* 0x1.1d96b0effc9db000e */
|
|
1.117761612217810673898, /* 0x1.1e25a001332190000 */
|
|
1.119946873713312474002, /* 0x1.1eb4d69bdb2a9fff1 */
|
|
1.122136407473298902480, /* 0x1.1f4454e3bfae00006 */
|
|
1.124330221845670330058, /* 0x1.1fd41afcbb48bfff8 */
|
|
1.126528325196519908506, /* 0x1.2064290abc98c0001 */
|
|
1.128730725913251964394, /* 0x1.20f47f31c9aa7000f */
|
|
1.130937432396844410880, /* 0x1.21851d95f776dfff0 */
|
|
1.133148453059692917203, /* 0x1.2216045b6784efffa */
|
|
1.135363796355857157764, /* 0x1.22a733a6692ae0004 */
|
|
1.137583470716100553249, /* 0x1.2338ab9b3221a0004 */
|
|
1.139807484614418608939, /* 0x1.23ca6c5e27aadfff7 */
|
|
1.142035846532929888057, /* 0x1.245c7613b7f6c0004 */
|
|
1.144268564977221958089, /* 0x1.24eec8e06b035000c */
|
|
1.146505648458203463465, /* 0x1.258164e8cea85fff8 */
|
|
1.148747105501412235671, /* 0x1.26144a5180d380009 */
|
|
1.150992944689175123667, /* 0x1.26a7793f5de2efffa */
|
|
1.153243174560058870217, /* 0x1.273af1d712179000d */
|
|
1.155497803703682491111, /* 0x1.27ceb43d81d42fff1 */
|
|
1.157756840726344771440, /* 0x1.2862c097a3d29000c */
|
|
1.160020294239811677834, /* 0x1.28f7170a74cf4fff1 */
|
|
1.162288172883275239058, /* 0x1.298bb7bb0faed0004 */
|
|
1.164560485298402170388, /* 0x1.2a20a2ce920dffff4 */
|
|
1.166837240167474476460, /* 0x1.2ab5d86a4631ffff6 */
|
|
1.169118446164539637555, /* 0x1.2b4b58b36d5220009 */
|
|
1.171404112007080167155, /* 0x1.2be123cf786790002 */
|
|
1.173694246390975415341, /* 0x1.2c7739e3c0aac000d */
|
|
1.175988858069749065617, /* 0x1.2d0d9b15deb58fff6 */
|
|
1.178287955789017793514, /* 0x1.2da4478b627040002 */
|
|
1.180591548323240091978, /* 0x1.2e3b3f69fb794fffc */
|
|
1.182899644456603782686, /* 0x1.2ed282d76421d0004 */
|
|
1.185212252993012693694, /* 0x1.2f6a11f96c685fff3 */
|
|
1.187529382762033236513, /* 0x1.3001ecf60082ffffa */
|
|
1.189851042595508889847, /* 0x1.309a13f30f28a0004 */
|
|
1.192177241354644978669, /* 0x1.31328716a758cfff7 */
|
|
1.194507987909589896687, /* 0x1.31cb4686e1e85fffb */
|
|
1.196843291137896336843, /* 0x1.32645269dfd04000a */
|
|
1.199183159977805113226, /* 0x1.32fdaae604c39000f */
|
|
1.201527603343041317132, /* 0x1.339750219980dfff3 */
|
|
1.203876630171082595692, /* 0x1.3431424300e480007 */
|
|
1.206230249419600664189, /* 0x1.34cb8170b3fee000e */
|
|
1.208588470077065268869, /* 0x1.35660dd14dbd4fffc */
|
|
1.210951301134513435915, /* 0x1.3600e78b6bdfc0005 */
|
|
1.213318751604272271958, /* 0x1.369c0ec5c38ebfff2 */
|
|
1.215690830512196507537, /* 0x1.373783a718d29000f */
|
|
1.218067546930756250870, /* 0x1.37d3465662f480007 */
|
|
1.220448909901335365929, /* 0x1.386f56fa770fe0008 */
|
|
1.222834928513994334780, /* 0x1.390bb5ba5fc540004 */
|
|
1.225225611877684750397, /* 0x1.39a862bd3c7a8fff3 */
|
|
1.227620969111500981433, /* 0x1.3a455e2a37bcafffd */
|
|
1.230021009336254911271, /* 0x1.3ae2a8287dfbefff6 */
|
|
1.232425741726685064472, /* 0x1.3b8040df76f39fffa */
|
|
1.234835175450728295084, /* 0x1.3c1e287682e48fff1 */
|
|
1.237249319699482263931, /* 0x1.3cbc5f151b86bfff8 */
|
|
1.239668183679933477545, /* 0x1.3d5ae4e2cc0a8000f */
|
|
1.242091776620540377629, /* 0x1.3df9ba07373bf0006 */
|
|
1.244520107762172811399, /* 0x1.3e98deaa0d8cafffe */
|
|
1.246953186383919165383, /* 0x1.3f3852f32973efff0 */
|
|
1.249391019292643401078, /* 0x1.3fd816ffc72b90001 */
|
|
1.251833623164381181797, /* 0x1.40782b17863250005 */
|
|
1.254280999953110153911, /* 0x1.41188f42caf400000 */
|
|
1.256733161434815393410, /* 0x1.41b943b42945bfffd */
|
|
1.259190116985283935980, /* 0x1.425a4893e5f10000a */
|
|
1.261651875958665236542, /* 0x1.42fb9e0a2df4c0009 */
|
|
1.264118447754797758244, /* 0x1.439d443f608c4fff9 */
|
|
1.266589841787181258708, /* 0x1.443f3b5bebf850008 */
|
|
1.269066067469190262045, /* 0x1.44e183883e561fff7 */
|
|
1.271547134259576328224, /* 0x1.45841cecf7a7a0001 */
|
|
1.274033051628237434048, /* 0x1.462707b2c43020009 */
|
|
1.276523829025464573684, /* 0x1.46ca44023aa410007 */
|
|
1.279019475999373156531, /* 0x1.476dd2045d46ffff0 */
|
|
1.281520002043128991825, /* 0x1.4811b1e1f1f19000b */
|
|
1.284025416692967214122, /* 0x1.48b5e3c3edd74fff4 */
|
|
1.286535729509738823464, /* 0x1.495a67d3613c8fff7 */
|
|
1.289050950070396384145, /* 0x1.49ff3e396e19d000b */
|
|
1.291571087985403654081, /* 0x1.4aa4671f5b401fff1 */
|
|
1.294096152842774794011, /* 0x1.4b49e2ae56d19000d */
|
|
1.296626154297237043484, /* 0x1.4befb10fd84a3fff4 */
|
|
1.299161101984141142272, /* 0x1.4c95d26d41d84fff8 */
|
|
1.301701005575179204100, /* 0x1.4d3c46f01d9f0fff3 */
|
|
1.304245874766450485904, /* 0x1.4de30ec21097d0003 */
|
|
1.306795719266019562007, /* 0x1.4e8a2a0ccce3d0002 */
|
|
1.309350548792467483458, /* 0x1.4f3198fa10346fff5 */
|
|
1.311910373099227200545, /* 0x1.4fd95bb3be8cffffd */
|
|
1.314475201942565174546, /* 0x1.50817263bf0e5fffb */
|
|
1.317045045107389400535, /* 0x1.5129dd3418575000e */
|
|
1.319619912422941299109, /* 0x1.51d29c4f01c54ffff */
|
|
1.322199813675649204855, /* 0x1.527bafde83a310009 */
|
|
1.324784758729532718739, /* 0x1.5325180cfb8b3fffd */
|
|
1.327374757430096474625, /* 0x1.53ced504b2bd0fff4 */
|
|
1.329969819671041886272, /* 0x1.5478e6f02775e0001 */
|
|
1.332569955346704748651, /* 0x1.55234df9d8a59fff8 */
|
|
1.335175174370685002822, /* 0x1.55ce0a4c5a6a9fff6 */
|
|
1.337785486688218616860, /* 0x1.56791c1263abefff7 */
|
|
1.340400902247843806217, /* 0x1.57248376aef21fffa */
|
|
1.343021431036279800211, /* 0x1.57d040a420c0bfff3 */
|
|
1.345647083048053138662, /* 0x1.587c53c5a630f0002 */
|
|
1.348277868295411074918, /* 0x1.5928bd063fd7bfff9 */
|
|
1.350913796821875845231, /* 0x1.59d57c9110ad60006 */
|
|
1.353554878672557082439, /* 0x1.5a8292913d68cfffc */
|
|
1.356201123929036356254, /* 0x1.5b2fff3212db00007 */
|
|
1.358852542671913132777, /* 0x1.5bddc29edcc06fff3 */
|
|
1.361509145047255398051, /* 0x1.5c8bdd032ed16000f */
|
|
1.364170941142184734180, /* 0x1.5d3a4e8a5bf61fff4 */
|
|
1.366837941171020309735, /* 0x1.5de9176042f1effff */
|
|
1.369510155261156381121, /* 0x1.5e9837b062f4e0005 */
|
|
1.372187593620959988833, /* 0x1.5f47afa69436cfff1 */
|
|
1.374870266463378287715, /* 0x1.5ff77f6eb3f8cfffd */
|
|
1.377558184010425845733, /* 0x1.60a7a734a9742fff9 */
|
|
1.380251356531521533853, /* 0x1.6158272490016000c */
|
|
1.382949794301995272203, /* 0x1.6208ff6a8978a000f */
|
|
1.385653507605306700170, /* 0x1.62ba3032c0a280004 */
|
|
1.388362506772382154503, /* 0x1.636bb9a994784000f */
|
|
1.391076802081129493127, /* 0x1.641d9bfb29a7bfff6 */
|
|
1.393796403973427855412, /* 0x1.64cfd7545928b0002 */
|
|
1.396521322756352656542, /* 0x1.65826be167badfff8 */
|
|
1.399251568859207761660, /* 0x1.663559cf20826000c */
|
|
1.401987152677323100733, /* 0x1.66e8a14a29486fffc */
|
|
1.404728084651919228815, /* 0x1.679c427f5a4b6000b */
|
|
1.407474375243217723560, /* 0x1.68503d9ba0add000f */
|
|
1.410226034922914983815, /* 0x1.690492cbf6303fff9 */
|
|
1.412983074197955213304, /* 0x1.69b9423d7b548fff6 */
|
|
};
|
|
|
|
/* All floating-point numbers can be put in one of these categories. */
|
|
enum
|
|
{
|
|
FP_NAN,
|
|
# define FP_NAN FP_NAN
|
|
FP_INFINITE,
|
|
# define FP_INFINITE FP_INFINITE
|
|
FP_ZERO,
|
|
# define FP_ZERO FP_ZERO
|
|
FP_SUBNORMAL,
|
|
# define FP_SUBNORMAL FP_SUBNORMAL
|
|
FP_NORMAL
|
|
# define FP_NORMAL FP_NORMAL
|
|
};
|
|
|
|
|
|
int
|
|
__fpclassifyf (float x)
|
|
{
|
|
uint32_t wx;
|
|
int retval = FP_NORMAL;
|
|
|
|
GET_FLOAT_WORD (wx, x);
|
|
wx &= 0x7fffffff;
|
|
if (wx == 0)
|
|
retval = FP_ZERO;
|
|
else if (wx < 0x800000)
|
|
retval = FP_SUBNORMAL;
|
|
else if (wx >= 0x7f800000)
|
|
retval = wx > 0x7f800000 ? FP_NAN : FP_INFINITE;
|
|
|
|
return retval;
|
|
}
|
|
|
|
|
|
int
|
|
__isinff (float x)
|
|
{
|
|
int32_t ix,t;
|
|
GET_FLOAT_WORD(ix,x);
|
|
t = ix & 0x7fffffff;
|
|
t ^= 0x7f800000;
|
|
t |= -t;
|
|
return ~(t >> 31) & (ix >> 30);
|
|
}
|
|
|
|
/* Return nonzero value if arguments are unordered. */
|
|
#define fpclassify(x) \
|
|
(sizeof (x) == sizeof (float) ? __fpclassifyf (x) : __fpclassifyf (x))
|
|
|
|
#ifndef isunordered
|
|
#define isunordered(u, v) \
|
|
(__extension__ \
|
|
({ __typeof__(u) __u = (u); __typeof__(v) __v = (v); \
|
|
fpclassify (__u) == FP_NAN || fpclassify (__v) == FP_NAN; }))
|
|
#endif
|
|
|
|
/* Return nonzero value if X is less than Y. */
|
|
#ifndef isless
|
|
#define isless(x, y) \
|
|
(__extension__ \
|
|
({ __typeof__(x) __x = (x); __typeof__(y) __y = (y); \
|
|
!isunordered (__x, __y) && __x < __y; }))
|
|
#endif
|
|
|
|
/* Return nonzero value if X is greater than Y. */
|
|
#ifndef isgreater
|
|
#define isgreater(x, y) \
|
|
(__extension__ \
|
|
({ __typeof__(x) __x = (x); __typeof__(y) __y = (y); \
|
|
!isunordered (__x, __y) && __x > __y; }))
|
|
#endif
|
|
|
|
float rb_exp(float x)
|
|
{
|
|
static const float himark = 88.72283935546875;
|
|
static const float lomark = -103.972084045410;
|
|
/* Check for usual case. */
|
|
if (isless (x, himark) && isgreater (x, lomark))
|
|
{
|
|
static const float THREEp42 = 13194139533312.0;
|
|
static const float THREEp22 = 12582912.0;
|
|
/* 1/ln(2). */
|
|
#undef M_1_LN2
|
|
static const float M_1_LN2 = 1.44269502163f;
|
|
/* ln(2) */
|
|
#undef M_LN2
|
|
static const double M_LN2 = .6931471805599452862;
|
|
|
|
int tval;
|
|
double x22, t, result, dx;
|
|
float n, delta;
|
|
union ieee754_double ex2_u;
|
|
#ifndef ROCKBOX
|
|
fenv_t oldenv;
|
|
|
|
feholdexcept (&oldenv);
|
|
#endif
|
|
|
|
#ifdef FE_TONEAREST
|
|
fesetround (FE_TONEAREST);
|
|
#endif
|
|
|
|
/* Calculate n. */
|
|
n = x * M_1_LN2 + THREEp22;
|
|
n -= THREEp22;
|
|
dx = x - n*M_LN2;
|
|
|
|
/* Calculate t/512. */
|
|
t = dx + THREEp42;
|
|
t -= THREEp42;
|
|
dx -= t;
|
|
|
|
/* Compute tval = t. */
|
|
tval = (int) (t * 512.0);
|
|
|
|
if (t >= 0)
|
|
delta = - __exp_deltatable[tval];
|
|
else
|
|
delta = __exp_deltatable[-tval];
|
|
|
|
/* Compute ex2 = 2^n e^(t/512+delta[t]). */
|
|
ex2_u.d = __exp_atable[tval+177];
|
|
ex2_u.ieee.exponent += (int) n;
|
|
|
|
/* Approximate e^(dx+delta) - 1, using a second-degree polynomial,
|
|
with maximum error in [-2^-10-2^-28,2^-10+2^-28]
|
|
less than 5e-11. */
|
|
x22 = (0.5000000496709180453 * dx + 1.0000001192102037084) * dx + delta;
|
|
|
|
/* Return result. */
|
|
#ifndef ROCKBOX
|
|
fesetenv (&oldenv);
|
|
#endif
|
|
|
|
result = x22 * ex2_u.d + ex2_u.d;
|
|
return (float) result;
|
|
}
|
|
/* Exceptional cases: */
|
|
else if (isless (x, himark))
|
|
{
|
|
if (__isinff (x))
|
|
/* e^-inf == 0, with no error. */
|
|
return 0;
|
|
else
|
|
/* Underflow */
|
|
return TWOM100 * TWOM100;
|
|
}
|
|
else
|
|
/* Return x, if x is a NaN or Inf; or overflow, otherwise. */
|
|
return TWO127*x;
|
|
}
|
|
|
|
/* Power function, taken from glibc-2.8 and dietlibc-0.32 */
|
|
float pow_wrapper(float x, float y)
|
|
{
|
|
unsigned int e;
|
|
float result;
|
|
|
|
/* Special cases 0^x */
|
|
if(x == 0.0f)
|
|
{
|
|
if(y > 0.0f)
|
|
return 0.0f;
|
|
else if(y == 0.0f)
|
|
return 1.0f;
|
|
else
|
|
return 1.0f / x;
|
|
}
|
|
|
|
/* Special case x^n where n is integer */
|
|
if(y == (int) (e = (int) y))
|
|
{
|
|
if((int) e < 0)
|
|
{
|
|
e = -e;
|
|
x = 1.0f / x;
|
|
}
|
|
|
|
result = 1.0f;
|
|
|
|
while(1)
|
|
{
|
|
if(e & 1)
|
|
result *= x;
|
|
|
|
if((e >>= 1) == 0)
|
|
break;
|
|
|
|
x *= x;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/* Normal case */
|
|
return rb_exp(rb_log(x) * y);
|
|
}
|
|
|
|
double floor_wrapper(double n)
|
|
{
|
|
if(n < 0.0)
|
|
{
|
|
int y = (int)n;
|
|
return ((float)y == n) ? y : y - 1;
|
|
}
|
|
else
|
|
return (int)n;
|
|
}
|
|
|
|
double ceil_wrapper(double n)
|
|
{
|
|
return floor_wrapper(n) + 1.0;
|
|
}
|
|
|
|
/* Natural logarithm.
|
|
Taken from glibc-2.8 */
|
|
static const float
|
|
ln2_hi = 6.9313812256e-01, /* 0x3f317180 */
|
|
ln2_lo = 9.0580006145e-06, /* 0x3717f7d1 */
|
|
two25 = 3.355443200e+07, /* 0x4c000000 */
|
|
Lg1 = 6.6666668653e-01, /* 3F2AAAAB */
|
|
Lg2 = 4.0000000596e-01, /* 3ECCCCCD */
|
|
Lg3 = 2.8571429849e-01, /* 3E924925 */
|
|
Lg4 = 2.2222198546e-01, /* 3E638E29 */
|
|
Lg5 = 1.8183572590e-01, /* 3E3A3325 */
|
|
Lg6 = 1.5313838422e-01, /* 3E1CD04F */
|
|
Lg7 = 1.4798198640e-01; /* 3E178897 */
|
|
|
|
/* Get a 32 bit int from a float. */
|
|
|
|
#define GET_FLOAT_WORD(i,d) \
|
|
do { \
|
|
ieee_float_shape_type gf_u; \
|
|
gf_u.value = (d); \
|
|
(i) = gf_u.word; \
|
|
} while (0)
|
|
|
|
/* Set a float from a 32 bit int. */
|
|
|
|
#define SET_FLOAT_WORD(d,i) \
|
|
do { \
|
|
ieee_float_shape_type sf_u; \
|
|
sf_u.word = (i); \
|
|
(d) = sf_u.value; \
|
|
} while (0)
|
|
|
|
#ifdef ROCKBOX_LITTLE_ENDIAN
|
|
#define __HI(x) *(1+(int*)&x)
|
|
#define __LO(x) *(int*)&x
|
|
#define __HIp(x) *(1+(int*)x)
|
|
#define __LOp(x) *(int*)x
|
|
#else
|
|
#define __HI(x) *(int*)&x
|
|
#define __LO(x) *(1+(int*)&x)
|
|
#define __HIp(x) *(int*)x
|
|
#define __LOp(x) *(1+(int*)x)
|
|
#endif
|
|
|
|
float rb_log(float x)
|
|
{
|
|
float hfsq, f, s, z, R, w, t1, t2, dk;
|
|
int32_t k, ix, i, j;
|
|
|
|
GET_FLOAT_WORD(ix,x);
|
|
|
|
k=0;
|
|
if (ix < 0x00800000) { /* x < 2**-126 */
|
|
if ((ix&0x7fffffff)==0)
|
|
return -two25/(x-x); /* log(+-0)=-inf */
|
|
if (ix<0) return (x-x)/(x-x); /* log(-#) = NaN */
|
|
k -= 25; x *= two25; /* subnormal number, scale up x */
|
|
GET_FLOAT_WORD(ix,x);
|
|
}
|
|
if (ix >= 0x7f800000) return x+x;
|
|
k += (ix>>23)-127;
|
|
ix &= 0x007fffff;
|
|
i = (ix+(0x95f64<<3))&0x800000;
|
|
SET_FLOAT_WORD(x,ix|(i^0x3f800000)); /* normalize x or x/2 */
|
|
k += (i>>23);
|
|
f = x-(float)1.0;
|
|
if((0x007fffff&(15+ix))<16) { /* |f| < 2**-20 */
|
|
if(f==zero) {
|
|
if(k==0)
|
|
return zero;
|
|
else
|
|
{
|
|
dk=(float)k;
|
|
return dk*ln2_hi+dk*ln2_lo;
|
|
}
|
|
}
|
|
R = f*f*((float)0.5-(float)0.33333333333333333*f);
|
|
if(k==0)
|
|
return f-R;
|
|
else
|
|
{
|
|
dk=(float)k;
|
|
return dk*ln2_hi-((R-dk*ln2_lo)-f);
|
|
}
|
|
}
|
|
s = f/((float)2.0+f);
|
|
dk = (float)k;
|
|
z = s*s;
|
|
i = ix-(0x6147a<<3);
|
|
w = z*z;
|
|
j = (0x6b851<<3)-ix;
|
|
t1= w*(Lg2+w*(Lg4+w*Lg6));
|
|
t2= z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7)));
|
|
i |= j;
|
|
R = t2+t1;
|
|
if(i>0) {
|
|
hfsq=(float)0.5*f*f;
|
|
if(k==0)
|
|
return f-(hfsq-s*(hfsq+R));
|
|
else
|
|
return dk*ln2_hi-((hfsq-(s*(hfsq+R)+dk*ln2_lo))-f);
|
|
} else {
|
|
if(k==0)
|
|
return f-s*(f-R);
|
|
else
|
|
return dk*ln2_hi-((s*(f-R)-dk*ln2_lo)-f);
|
|
}
|
|
}
|