00001 
00032 #ifndef LLMATH_H
00033 #define LLMATH_H
00034 
00035 
00036 #if LL_WINDOWS
00037 #define llisnan(val)    _isnan(val)
00038 #define llfinite(val)   _finite(val)
00039 #elif (LL_LINUX && __GNUC__ <= 2)
00040 #define llisnan(val)    isnan(val)
00041 #define llfinite(val)   isfinite(val)
00042 #elif LL_SOLARIS
00043 #define llisnan(val)    isnan(val)
00044 #define llfinite(val)   (val <= std::numeric_limits<double>::max())
00045 #else
00046 #define llisnan(val)    std::isnan(val)
00047 #define llfinite(val)   std::isfinite(val)
00048 #endif
00049 
00050 
00051 #ifndef fsqrtf
00052 #define fsqrtf(x)               ((F32)sqrt((F64)(x)))
00053 #endif
00054 #ifndef sqrtf
00055 #define sqrtf(x)                ((F32)sqrt((F64)(x)))
00056 #endif
00057 
00058 #ifndef cosf
00059 #define cosf(x)         ((F32)cos((F64)(x)))
00060 #endif
00061 #ifndef sinf
00062 #define sinf(x)         ((F32)sin((F64)(x)))
00063 #endif
00064 #ifndef tanf
00065 #define tanf(x)         ((F32)tan((F64)(x)))
00066 #endif
00067 #ifndef acosf
00068 #define acosf(x)                ((F32)acos((F64)(x)))
00069 #endif
00070 
00071 #ifndef powf
00072 #define powf(x,y) ((F32)pow((F64)(x),(F64)(y)))
00073 #endif
00074 
00075 const F32       GRAVITY                 = -9.8f;
00076 
00077 
00078 const F32       F_PI            = 3.1415926535897932384626433832795f;
00079 const F32       F_TWO_PI        = 6.283185307179586476925286766559f;
00080 const F32       F_PI_BY_TWO     = 1.5707963267948966192313216916398f;
00081 const F32       F_SQRT2         = 1.4142135623730950488016887242097f;
00082 const F32       F_SQRT3         = 1.73205080756888288657986402541f;
00083 const F32       OO_SQRT2        = 0.7071067811865475244008443621049f;
00084 const F32       DEG_TO_RAD      = 0.017453292519943295769236907684886f;
00085 const F32       RAD_TO_DEG      = 57.295779513082320876798154814105f;
00086 const F32       F_APPROXIMATELY_ZERO = 0.00001f;
00087 const F32       F_LN2           = 0.69314718056f;
00088 const F32       OO_LN2          = 1.4426950408889634073599246810019f;
00089 
00090 
00091 const F32 FP_MAG_THRESHOLD = 0.0000001f;
00092 
00093 
00094 inline BOOL is_approx_zero( F32 f ) { return (-F_APPROXIMATELY_ZERO < f) && (f < F_APPROXIMATELY_ZERO); }
00095 
00096 inline BOOL is_approx_equal(F32 x, F32 y)
00097 {
00098         const S32 COMPARE_MANTISSA_UP_TO_BIT = 0x02;
00099         return (abs((S32) ((U32&)x - (U32&)y) ) < COMPARE_MANTISSA_UP_TO_BIT);
00100 }
00101 
00102 inline BOOL is_approx_equal_fraction(F32 x, F32 y, U32 frac_bits)
00103 {
00104         BOOL ret = TRUE;
00105         F32 diff = (F32) fabs(x - y);
00106 
00107         S32 diffInt = (S32) diff;
00108         S32 diffFracTolerance = (S32) ((diff - (F32) diffInt) * (1 << frac_bits));
00109         
00110         
00111         
00112         
00113         
00114         
00115         if (diffInt != 0 || diffFracTolerance > 1)
00116         {
00117                 ret = FALSE;
00118         }
00119 
00120         return ret;
00121 }
00122 
00123 inline S32 llabs(const S32 a)
00124 {
00125         return S32(labs(a));
00126 }
00127 
00128 inline F32 llabs(const F32 a)
00129 {
00130         return F32(fabs(a));
00131 }
00132 
00133 inline F64 llabs(const F64 a)
00134 {
00135         return F64(fabs(a));
00136 }
00137 
00138 inline S32 lltrunc( F32 f )
00139 {
00140 #if LL_WINDOWS && !defined( __INTEL_COMPILER )
00141                 
00142                 
00143                 const static U32 zpfp[] = { 0xBEFFFFFF, 0x3EFFFFFF };
00144                 S32 result;
00145                 __asm {
00146                         fld             f
00147                         mov             eax,    f
00148                         shr             eax,    29
00149                         and             eax,    4
00150                         fadd    dword ptr [zpfp + eax]
00151                         fistp   result
00152                 }
00153                 return result;
00154 #else
00155                 return (S32)f;
00156 #endif
00157 }
00158 
00159 inline S32 lltrunc( F64 f )
00160 {
00161         return (S32)f;
00162 }
00163 
00164 inline S32 llfloor( F32 f )
00165 {
00166 #if LL_WINDOWS && !defined( __INTEL_COMPILER )
00167                 
00168                 
00169                 
00170                 const U32 zpfp = 0xBEFFFFFF;
00171                 S32 result;
00172                 __asm { 
00173                         fld             f
00174                         fadd    dword ptr [zpfp]
00175                         fistp   result
00176                 }
00177                 return result;
00178 #else
00179                 return (S32)floor(f);
00180 #endif
00181 }
00182 
00183 
00184 inline S32 llceil( F32 f )
00185 {
00186         
00187         return (S32)ceil(f);
00188 }
00189 
00190 
00191 #ifndef BOGUS_ROUND
00192 
00193 inline S32 llround(const F32 val)
00194 {
00195         return llfloor(val + 0.5f);
00196 }
00197 
00198 #else // BOGUS_ROUND
00199 
00200 
00201 
00202 inline S32 llround(const F32 val)
00203 {
00204         #if LL_WINDOWS
00205                 
00206                 S32 ret_val;
00207                 _asm fld        val
00208                 _asm fistp      ret_val;
00209                 return ret_val;
00210         #elif LL_LINUX
00211                 
00212                 
00213                 S32 ret_val;
00214                 __asm__ __volatile__( "flds %1    \n\t"
00215                                                           "fistpl %0  \n\t"
00216                                                           : "=m" (ret_val)
00217                                                           : "m" (val) );
00218                 return ret_val;
00219         #else
00220                 return llfloor(val + 0.5f);
00221         #endif
00222 }
00223 
00224 
00225 inline int round_int(double x)
00226 {
00227         const float round_to_nearest = 0.5f;
00228         int i;
00229         __asm
00230         {
00231                 fld x
00232                 fadd st, st (0)
00233                 fadd round_to_nearest
00234                 fistp i
00235                 sar i, 1
00236         }
00237         return (i);
00238 }
00239 #endif // BOGUS_ROUND
00240 
00241 inline F32 llround( F32 val, F32 nearest )
00242 {
00243         return F32(floor(val * (1.0f / nearest) + 0.5f)) * nearest;
00244 }
00245 
00246 inline F64 llround( F64 val, F64 nearest )
00247 {
00248         return F64(floor(val * (1.0 / nearest) + 0.5)) * nearest;
00249 }
00250 
00251 
00252 
00253 
00254 
00255 
00256 
00257 const F32 FAST_MAG_ALPHA = 0.960433870103f;
00258 const F32 FAST_MAG_BETA = 0.397824734759f;
00259 
00260 
00261 
00262 
00263 
00264 
00265 
00266 
00267 
00268 
00269 inline F32 fastMagnitude(F32 a, F32 b)
00270 { 
00271         a = (a > 0) ? a : -a;
00272         b = (b > 0) ? b : -b;
00273         return(FAST_MAG_ALPHA * llmax(a,b) + FAST_MAG_BETA * llmin(a,b));
00274 }
00275 
00276 
00277 
00279 
00280 
00281 
00282 
00283 
00284 const F64 LL_DOUBLE_TO_FIX_MAGIC        = 68719476736.0*1.5;     
00285 const S32 LL_SHIFT_AMOUNT                       = 16;                    
00286 
00287 
00288 #ifdef LL_LITTLE_ENDIAN
00289         #define LL_EXP_INDEX                            1
00290         #define LL_MAN_INDEX                            0
00291 #else
00292         #define LL_EXP_INDEX                            0
00293         #define LL_MAN_INDEX                            1
00294 #endif
00295 
00296 
00297 
00298 
00299 
00300 
00301 
00302 
00303 
00304 
00305 
00306 
00307 
00308 
00309 
00310 
00311 
00312 
00313 
00314 
00316 
00317 
00318 
00319 
00320 
00321 
00322 static union
00323 {
00324         double d;
00325         struct
00326         {
00327 #ifdef LL_LITTLE_ENDIAN
00328                 S32 j, i;
00329 #else
00330                 S32 i, j;
00331 #endif
00332         } n;
00333 } LLECO; 
00334 
00335 #define LL_EXP_A (1048576 * OO_LN2) // use 1512775 for integer
00336 #define LL_EXP_C (60801)                        // this value of C good for -4 < y < 4
00337 
00338 #define LL_FAST_EXP(y) (LLECO.n.i = llround(F32(LL_EXP_A*(y))) + (1072693248 - LL_EXP_C), LLECO.d)
00339 
00340 
00341 
00342 inline F32 llfastpow(const F32 x, const F32 y)
00343 {
00344         return (F32)(LL_FAST_EXP(y * log(x)));
00345 }
00346 
00347 
00348 inline F32 snap_to_sig_figs(F32 foo, S32 sig_figs)
00349 {
00350         
00351         F32 bar = 1.f;
00352         for (S32 i = 0; i < sig_figs; i++)
00353         {
00354                 bar *= 10.f;
00355         }
00356 
00357         foo = (F32)llround(foo * bar);
00358 
00359         
00360         foo /= bar;
00361         return foo;
00362 }
00363 
00364 inline F32 lerp(F32 a, F32 b, F32 u) 
00365 {
00366         return a + ((b - a) * u);
00367 }
00368 
00369 inline F32 lerp2d(F32 x00, F32 x01, F32 x10, F32 x11, F32 u, F32 v)
00370 {
00371         F32 a = x00 + (x01-x00)*u;
00372         F32 b = x10 + (x11-x10)*u;
00373         F32 r = a + (b-a)*v;
00374         return r;
00375 }
00376 
00377 inline F32 ramp(F32 x, F32 a, F32 b)
00378 {
00379         return (a == b) ? 0.0f : ((a - x) / (a - b));
00380 }
00381 
00382 inline F32 rescale(F32 x, F32 x1, F32 x2, F32 y1, F32 y2)
00383 {
00384         return lerp(y1, y2, ramp(x, x1, x2));
00385 }
00386 
00387 inline F32 clamp_rescale(F32 x, F32 x1, F32 x2, F32 y1, F32 y2)
00388 {
00389         if (y1 < y2)
00390         {
00391                 return llclamp(rescale(x,x1,x2,y1,y2),y1,y2);
00392         }
00393         else
00394         {
00395                 return llclamp(rescale(x,x1,x2,y1,y2),y2,y1);
00396         }
00397 }
00398 
00399 
00400 inline F32 cubic_step( F32 x, F32 x0, F32 x1, F32 s0, F32 s1 )
00401 {
00402         if (x <= x0)
00403                 return s0;
00404 
00405         if (x >= x1)
00406                 return s1;
00407 
00408         F32 f = (x - x0) / (x1 - x0);
00409 
00410         return  s0 + (s1 - s0) * (f * f) * (3.0f - 2.0f * f);
00411 }
00412 
00413 inline F32 cubic_step( F32 x )
00414 {
00415         x = llclampf(x);
00416 
00417         return  (x * x) * (3.0f - 2.0f * x);
00418 }
00419 
00420 inline F32 quadratic_step( F32 x, F32 x0, F32 x1, F32 s0, F32 s1 )
00421 {
00422         if (x <= x0)
00423                 return s0;
00424 
00425         if (x >= x1)
00426                 return s1;
00427 
00428         F32 f = (x - x0) / (x1 - x0);
00429         F32 f_squared = f * f;
00430 
00431         return  (s0 * (1.f - f_squared)) + ((s1 - s0) * f_squared);
00432 }
00433 
00434 inline F32 llsimple_angle(F32 angle)
00435 {
00436         while(angle <= -F_PI)
00437                 angle += F_TWO_PI;
00438         while(angle >  F_PI)
00439                 angle -= F_TWO_PI;
00440         return angle;
00441 }
00442 
00443 #endif