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