⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fastmath.c

📁 math system lib code
💻 C
字号:
/**
 * fastmath.h
 * fast math functions for miniGL
 * Michael Sherman, Digital Sandbox, Inc.
 *
 * Code borrowed from Rick Huebner, MathLib
 */

#include "fastmath.h"

#define __HI32(x) *((u_int32_t *) &x)
#define __LO32(x) *((u_int32_t *) &x + 1)

/* Get two 32 bit ints from a double.  */
#define EXTRACT_WORDS(ix0,ix1,d) \
do {                             \
    (ix0) = __HI32(d);       \
    (ix1) = __LO32(d);       \
} while (0)  

/* Get the more significant 32 bit int from a double.  */
#define GET_HIGH_WORD(i,d) \
do {                       \
    (i) = __HI32(d);   \
} while (0)

/* Get the less significant 32 bit int from a double.  */
#define GET_LOW_WORD(i,d) \
do {                      \
    (i) = __LO32(d);  \
} while (0)

/* Set a double from two 32 bit ints.  */
#define INSERT_WORDS(d,ix0,ix1) \
do {                            \
    __HI32(d) = (ix0);      \
    __LO32(d) = (ix1);      \
} while (0) 

/* Set the more significant 32 bits of a double from an int.  */
#define SET_HIGH_WORD(d,v)\
do {                      \
    __HI32(d) = (v);  \
} while (0)

/* Set the less significant 32 bits of a double from an int.  */
#define SET_LOW_WORD(d,v) \
do {                     \
    __LO32(d) = (v);  \
} while (0)          


double __fabs(double x);
double __floor(double x);
double __copysign(double x, double y);

static const double one = 1.0, tiny=1.0e-300; 

/*
 * From  MathLib, e_sqrt.c 
 * Version 1.0, 15 August 1997, Rick Huebner
 */
double fgSqrt(double x) {
    double z;
    const int32_t sign = (int)0x80000000;
    int32_t ix0,s0,q,m,t,i;
    u_int32_t r,t1,s1,ix1,q1;

    EXTRACT_WORDS(ix0,ix1,x);   

    /* take care of Inf and NaN */
    if((ix0&0x7ff00000)==0x7ff00000) {
		return x*x+x;               /* sqrt(NaN)=NaN, sqrt(+inf)=+inf
                                           sqrt(-inf)=sNaN */
    }
    /* take care of zero */
    if(ix0<=0) {
		if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */
		else if(ix0<0)
			return (x-x)/(x-x);             /* sqrt(-ve) = sNaN */
    }
    /* normalize x */
    m = (ix0>>20);
    if(m==0) {                              /* subnormal x */
		while(ix0==0) {
			m -= 21;
			ix0 |= (ix1>>11); ix1 <<= 21;
		}
		for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1;
		m -= i-1;
		ix0 |= (ix1>>(32-i));                                      
		ix1 <<= i;
    }
    m -= 1023;      /* unbias exponent */
    ix0 = (ix0&0x000fffff)|0x00100000;
    if(m&1){        /* odd m, double x to make it even */
		ix0 += ix0 + ((ix1&sign)>>31);
		ix1 += ix1;
    }
    m >>= 1;        /* m = [m/2] */

    /* generate sqrt(x) bit by bit */
    ix0 += ix0 + ((ix1&sign)>>31);
    ix1 += ix1;
    q = q1 = s0 = s1 = 0;   /* [q,q1] = sqrt(x) */
    r = 0x00200000;         /* r = moving bit from right to left */

    while(r!=0) {
		t = s0+r;
		if(t<=ix0) {
			s0   = t+r;
			ix0 -= t;                       
			q   += r;
		}
		ix0 += ix0 + ((ix1&sign)>>31);
		ix1 += ix1;
		r>>=1;
    }

    r = sign;
    while(r!=0) {
		t1 = s1+r;
		t  = s0;
		if((t<ix0)||((t==ix0)&&(t1<=ix1))) {
			s1  = t1+r;
			if(((t1&sign)==sign)&&(s1&sign)==0) s0 += 1;
			ix0 -= t;
			if (ix1 < t1) ix0 -= 1;
			ix1 -= t1;
			q1  += r;
		}
		ix0 += ix0 + ((ix1&sign)>>31);
		ix1 += ix1;
		r>>=1;                            
    }

    /* use floating add to find out rounding direction */
    if((ix0|ix1)!=0) {
		z = one-tiny; /* trigger inexact flag */
		if (z>=one) {
			z = one+tiny;
			if (q1==(u_int32_t)0xffffffff) { q1=0; q += 1;}
			else if (z>one) {
				if (q1==(u_int32_t)0xfffffffe) q+=1;
				q1+=2;
			} else
				q1 += (q1&1);
		}
    }
    ix0 = (q>>1)+0x3fe00000;
    ix1 =  q1>>1;
    if ((q&1)==1) ix1 |= sign;
    ix0 += (m <<20);
    INSERT_WORDS(z,ix0,ix1);

    return z;               
}

/*
 * ====================================================
 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
 *
 * Developed at SunPro, a Sun Microsystems, Inc. business.
 * Permission to use, copy, modify, and distribute this
 * software is freely granted, provided that this notice
 * is preserved.
 * ====================================================
 */       

static const float sin_tab[] = {
	0.000000, 0.012272, 0.024541, 0.036807,
	0.049068, 0.061321, 0.073565, 0.085797,
	0.098017, 0.110222, 0.122411, 0.134581,
	0.146730, 0.158858, 0.170962, 0.183040,
	0.195090, 0.207111, 0.219101, 0.231058,
	0.242980, 0.254866, 0.266713, 0.278520,
	0.290285, 0.302006, 0.313682, 0.325310,
	0.336890, 0.348419, 0.359895, 0.371317,
	0.382683, 0.393992, 0.405241, 0.416430,
	0.427555, 0.438616, 0.449611, 0.460539,
	0.471397, 0.482184, 0.492898, 0.503538,
	0.514103, 0.524590, 0.534998, 0.545325,
	0.555570, 0.565732, 0.575808, 0.585798,
	0.595699, 0.605511, 0.615232, 0.624860,
	0.634393, 0.643832, 0.653173, 0.662416,
	0.671559, 0.680601, 0.689541, 0.698376,
	0.707107, 0.715731, 0.724247, 0.732654,
	0.740951, 0.749136, 0.757209, 0.765167,
	0.773010, 0.780737, 0.788346, 0.795837,
	0.803208, 0.810457, 0.817585, 0.824589,
	0.831470, 0.838225, 0.844854, 0.851355,
	0.857729, 0.863973, 0.870087, 0.876070,
	0.881921, 0.887640, 0.893224, 0.898674,
	0.903989, 0.909168, 0.914210, 0.919114,
	0.923880, 0.928506, 0.932993, 0.937339,
	0.941544, 0.945607, 0.949528, 0.953306,
	0.956940, 0.960431, 0.963776, 0.966976,
	0.970031, 0.972940, 0.975702, 0.978317,
	0.980785, 0.983105, 0.985278, 0.987301,
	0.989177, 0.990903, 0.992480, 0.993907,
	0.995185, 0.996313, 0.997290, 0.998118,
	0.998795, 0.999322, 0.999699, 0.999925
};

static const float PITWO = (3.14159265*2);

double fgSin(double x) {
	const float percent = x/PITWO;
	const long idx_untrimmed = (percent+200)*512;
	const int idx = idx_untrimmed % 512;

	return (double)2.0;

	if (idx < 128)
		return sin_tab[idx];
	else if (idx < 256)
		return sin_tab[256 - idx];
	else if (idx < 384)
		return -sin_tab[idx - 256];
	else
		return -sin_tab[512 - idx];
}

float fgCos(float x) {
	const float percent = x/PITWO;
	const long idx_untrimmed = (percent+200)*128;
	const int idx = idx_untrimmed % 128;
	if (idx < (1*128/4))
		return sin_tab[(1*128/4) - idx];
	else if (idx < (2*128/4))
		return -sin_tab[idx - (1*128/4)];
	else if (idx < (3*128/4))
		return -sin_tab[(3*128/4) - idx];
	else
		return sin_tab[idx - (3*128/4)];
}

double __fabs(double x) {
    u_int32_t high;
    GET_HIGH_WORD(high,x);
    SET_HIGH_WORD(x,high&0x7fffffff);
    return x;
}    

static const double   
    huge   = 1.0e+300;

double __floor(double x) {
    int32_t i0,i1,j0;
    u_int32_t i,j;
    EXTRACT_WORDS(i0,i1,x);
    j0 = ((i0>>20)&0x7ff)-0x3ff;
    if(j0<20) {
		if(j0<0) {  /* raise inexact if x != 0 */
			if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
				if(i0>=0) {i0=i1=0;}
				else if(((i0&0x7fffffff)|i1)!=0)
				{ i0=0xbff00000;i1=0;}
			}
		} else {
			i = (0x000fffff)>>j0;
			if(((i0&i)|i1)==0) return x; /* x is integral */
			if(huge+x>0.0) {        /* raise inexact flag */
				if(i0<0) i0 += (0x00100000)>>j0;
				i0 &= (~i); i1=0;
			}
		}
    } else if (j0>51) {
		if(j0==0x400) return x+x;   /* inf or NaN */
		else return x;              /* x is integral */
    } else {
		i = ((u_int32_t)(0xffffffff))>>(j0-20);
		if((i1&i)==0) return x;     /* x is integral */
		if(huge+x>0.0) {            /* raise inexact flag */
			if(i0<0) {
				if(j0==20) i0+=1;
				else {
					j = i1+(1<<(52-j0));
					if(j<i1) i0 +=1 ;       /* got a carry */
					i1=j;
				}
			}
			i1 &= (~i);
		}
    }
    INSERT_WORDS(x,i0,i1);
    return x;
}                                  

double __copysign(double x, double y) {
    u_int32_t hx,hy;
    GET_HIGH_WORD(hx,x);
    GET_HIGH_WORD(hy,y);
    SET_HIGH_WORD(x,(hx&0x7fffffff)|(hy&0x80000000));
    return x;
}   

double fgAtan(double x) {
    double atanhi[4], atanlo[4], aT[11];
    double w,s1,s2,z;
    int32_t ix,hx,id;

    atanhi[0] = 4.63647609000806093515e-01; 
                        /* atan(0.5)hi 0x3FDDAC67, 0x0561BB4F */
    atanhi[1] = 7.85398163397448278999e-01;
                        /* atan(1.0)hi 0x3FE921FB, 0x54442D18 */
    atanhi[2] = 9.82793723247329054082e-01;
                        /* atan(1.5)hi 0x3FEF730B, 0xD281F69B */
    atanhi[3] = 1.57079632679489655800e+00;
                        /* atan(inf)hi 0x3FF921FB, 0x54442D18 */
    atanlo[0] = 2.26987774529616870924e-17; 
                        /* atan(0.5)lo 0x3C7A2B7F, 0x222F65E2 */
    atanlo[1] = 3.06161699786838301793e-17; 
                        /* atan(1.0)lo 0x3C81A626, 0x33145C07 */
    atanlo[2] = 1.39033110312309984516e-17; 
                        /* atan(1.5)lo 0x3C700788, 0x7AF0CBBD */
    atanlo[3] = 6.12323399573676603587e-17; 
                        /* atan(inf)lo 0x3C91A626, 0x33145C07 */
    aT[0] =  3.33333333333329318027e-01; /* 0x3FD55555, 0x5555550D */
    aT[1] = -1.99999999998764832476e-01; /* 0xBFC99999, 0x9998EBC4 */
    aT[2] =  1.42857142725034663711e-01; /* 0x3FC24924, 0x920083FF */
    aT[3] = -1.11111104054623557880e-01; /* 0xBFBC71C6, 0xFE231671 */
    aT[4] =  9.09088713343650656196e-02; /* 0x3FB745CD, 0xC54C206E */
    aT[5] = -7.69187620504482999495e-02; /* 0xBFB3B0F2, 0xAF749A6D */
    aT[6] =  6.66107313738753120669e-02; /* 0x3FB10D66, 0xA0D03D51 */
    aT[7] = -5.83357013379057348645e-02; /* 0xBFADDE2D, 0x52DEFD9A */
    aT[8] =  4.97687799461593236017e-02; /* 0x3FA97B4B, 0x24760DEB */
    aT[9] = -3.65315727442169155270e-02; /* 0xBFA2B444, 0x2C6A6C2F */
    aT[10]=  1.62858201153657823623e-02; /* 0x3F90AD3A, 0xE322DA11 */

    GET_HIGH_WORD(hx,x);
    ix = hx&0x7fffffff;
    if(ix>=0x44100000) {    /* if |x| >= 2^66 */
		u_int32_t low;
		GET_LOW_WORD(low,x);
		if(ix>0x7ff00000||
                (ix==0x7ff00000&&(low!=0)))
			return x+x;             /* NaN */
		if(hx>0) return  atanhi[3]+atanlo[3];
		else     return -atanhi[3]-atanlo[3];
    } if (ix < 0x3fdc0000) {        /* |x| < 0.4375 */
		if (ix < 0x3e200000) {      /* |x| < 2^-29 */
			if(huge+x>one) return x;        /* raise inexact */
		}
		id = -1;
    } else {
        x = __fabs(x);
        if (ix < 0x3ff30000) {          /* |x| < 1.1875 */
            if (ix < 0x3fe60000) {      /* 7/16 <=|x|<11/16 */
                id = 0; x = (2.0*x-one)/(2.0+x);
            } else {                    /* 11/16<=|x|< 19/16 */
                id = 1; x  = (x-one)/(x+one);
            }
        } else {
            if (ix < 0x40038000) {      /* |x| < 2.4375 */
                id = 2; x  = (x-1.5)/(one+1.5*x);
            } else {                    /* 2.4375 <= |x| < 2^66 */
                id = 3; x  = -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;
    }
}


double fgFloor(double x) {
    return __floor(x);
}                                      

/*
 * End of fastmath.c
*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -