00001
00002
00003
00004
00005
00006 #ifndef _GMTL_MATH_H_
00007 #define _GMTL_MATH_H_
00008
00009 #include <math.h>
00010 #include <stdlib.h>
00011 #include <gmtl/Defines.h>
00012 #include <gmtl/Util/Assert.h>
00013 #include <gmtl/Util/StaticAssert.h>
00014
00015 namespace gmtl
00016 {
00017
00022 struct RotationOrderBase { enum { IS_ROTORDER = 1 }; };
00023
00026 struct XYZ : public RotationOrderBase { enum { ID = 0 }; };
00027
00030 struct ZYX : public RotationOrderBase { enum { ID = 1 }; };
00031
00034 struct ZXY : public RotationOrderBase { enum { ID = 2 }; };
00035
00036 namespace Math
00037 {
00042 const float TWO_PI = 6.28318530717958647692f;
00043 const float PI = 3.14159265358979323846f;
00044 const float PI_OVER_2 = 1.57079632679489661923f;
00045 const float PI_OVER_4 = 0.78539816339744830962f;
00052
00053 template <typename T>
00054 inline T abs( T iValue )
00055 {
00056 return static_cast<T>( iValue >= static_cast<T>(0) ? iValue : -iValue );
00057 }
00058
00059 inline float abs(float iValue)
00060 { return fabsf(iValue); }
00061 inline double abs(double iValue)
00062 { return fabs(iValue); }
00063 inline int abs(int iValue)
00064 { return ::abs(iValue); }
00065 inline long abs(long iValue)
00066 { return labs(iValue); }
00067
00068
00069 template <typename T>
00070 inline T ceil( T fValue );
00071 inline float ceil( float fValue )
00072 {
00073 #ifdef NO_CEILF
00074 return float(::ceil(fValue));
00075 #else
00076 return float( ::ceilf( fValue ) );
00077 #endif
00078 }
00079 inline double ceil( double fValue )
00080 {
00081 return double( ::ceil( fValue ) );
00082 }
00083
00084 template <typename T>
00085 inline T floor( T fValue );
00086 inline float floor( float fValue )
00087 {
00088 #ifdef NO_FLOORF
00089 return float(::floor(fValue));
00090 #else
00091 return float( ::floorf( fValue ) );
00092 #endif
00093 }
00094 inline double floor( double fValue )
00095 {
00096 return double( ::floor( fValue ) );
00097 }
00098
00099 template <typename T>
00100 inline int sign( T iValue )
00101 {
00102 if (iValue > static_cast<T>(0))
00103 {
00104 return 1;
00105 }
00106 else
00107 {
00108 if (iValue < static_cast<T>(0))
00109 {
00110 return -1;
00111 }
00112 else
00113 {
00114 return 0;
00115 }
00116 }
00117 }
00118
00127 template <typename T>
00128 inline T zeroClamp( T value, T eps = static_cast<T>(0) )
00129 {
00130 return ( (gmtl::Math::abs(value) <= eps) ? static_cast<T>(0) : value );
00131 }
00132
00133
00134
00135
00136
00137 template <typename T>
00138 inline T aCos( T fValue );
00139 inline float aCos( float fValue )
00140 {
00141 if ( -1.0f < fValue )
00142 {
00143 if ( fValue < 1.0f )
00144 {
00145 #ifdef NO_ACOSF
00146 return static_cast<float>(::acos(fValue));
00147 #else
00148 return static_cast<float>(::acosf(fValue));
00149 #endif
00150 }
00151 else
00152 return 0.0f;
00153 }
00154 else
00155 {
00156 return static_cast<float>(gmtl::Math::PI);
00157 }
00158 }
00159 inline double aCos( double fValue )
00160 {
00161 if ( -1.0 < fValue )
00162 {
00163 if ( fValue < 1.0 )
00164 return static_cast<double>(::acos(fValue));
00165 else
00166 return 0.0;
00167 }
00168 else
00169 {
00170 return static_cast<double>(gmtl::Math::PI);
00171 }
00172 }
00173
00174 template <typename T>
00175 inline T aSin( T fValue );
00176 inline float aSin( float fValue )
00177 {
00178 if ( -1.0f < fValue )
00179 {
00180 if ( fValue < 1.0f )
00181 {
00182 #ifdef NO_ASINF
00183 return static_cast<float>(::asin(fValue));
00184 #else
00185 return static_cast<float>(::asinf(fValue));
00186 #endif
00187 }
00188 else
00189 return static_cast<float>(-gmtl::Math::PI_OVER_2);
00190 }
00191 else
00192 {
00193 return static_cast<float>(gmtl::Math::PI_OVER_2);
00194 }
00195 }
00196 inline double aSin( double fValue )
00197 {
00198 if ( -1.0 < fValue )
00199 {
00200 if ( fValue < 1.0 )
00201 return static_cast<double>(::asin(fValue));
00202 else
00203 return static_cast<double>(-gmtl::Math::PI_OVER_2);
00204 }
00205 else
00206 {
00207 return static_cast<double>(gmtl::Math::PI_OVER_2);
00208 }
00209 }
00210
00211 template <typename T>
00212 inline T aTan( T fValue );
00213 inline double aTan( double fValue )
00214 {
00215 return ::atan( fValue );
00216 }
00217 inline float aTan( float fValue )
00218 {
00219 #ifdef NO_TANF
00220 return static_cast<float>(::atan(fValue));
00221 #else
00222 return static_cast<float>(::atanf(fValue));
00223 #endif
00224 }
00225
00226 template <typename T>
00227 inline T aTan2( T fY, T fX );
00228 inline float aTan2( float fY, float fX )
00229 {
00230 #ifdef NO_ATAN2F
00231 return static_cast<float>(::atan2(fY, fX));
00232 #else
00233 return static_cast<float>(::atan2f(fY, fX));
00234 #endif
00235 }
00236 inline double aTan2( double fY, double fX )
00237 {
00238 return static_cast<double>(::atan2(fY, fX));
00239 }
00240
00241 template <typename T>
00242 inline T cos( T fValue );
00243 inline float cos( float fValue )
00244 {
00245 #ifdef NO_COSF
00246 return static_cast<float>(::cos(fValue));
00247 #else
00248 return static_cast<float>(::cosf(fValue));
00249 #endif
00250 }
00251 inline double cos( double fValue )
00252 {
00253 return static_cast<double>(::cos(fValue));
00254 }
00255
00256 template <typename T>
00257 inline T exp( T fValue );
00258 inline float exp( float fValue )
00259 {
00260 #ifdef NO_EXPF
00261 return static_cast<float>(::exp(fValue));
00262 #else
00263 return static_cast<float>(::expf(fValue));
00264 #endif
00265 }
00266 inline double exp( double fValue )
00267 {
00268 return static_cast<double>(::exp(fValue));
00269 }
00270
00271 template <typename T>
00272 inline T log( T fValue );
00273 inline double log( double fValue )
00274 {
00275 return static_cast<double>(::log(fValue));
00276 }
00277 inline float log( float fValue )
00278 {
00279 #ifdef NO_LOGF
00280 return static_cast<float>(::log(fValue));
00281 #else
00282 return static_cast<float>(::logf(fValue));
00283 #endif
00284 }
00285
00286 inline double pow( double fBase, double fExponent)
00287 {
00288 return static_cast<double>(::pow(fBase, fExponent));
00289 }
00290 inline float pow( float fBase, float fExponent)
00291 {
00292 #ifdef NO_POWF
00293 return static_cast<float>(::pow(fBase, fExponent));
00294 #else
00295 return static_cast<float>(::powf(fBase, fExponent));
00296 #endif
00297 }
00298
00299 template <typename T>
00300 inline T sin( T fValue );
00301 inline double sin( double fValue )
00302 {
00303 return static_cast<double>(::sin(fValue));
00304 }
00305 inline float sin( float fValue )
00306 {
00307 #ifdef NO_SINF
00308 return static_cast<float>(::sin(fValue));
00309 #else
00310 return static_cast<float>(::sinf(fValue));
00311 #endif
00312 }
00313
00314 template <typename T>
00315 inline T tan( T fValue );
00316 inline double tan( double fValue )
00317 {
00318 return static_cast<double>(::tan(fValue));
00319 }
00320 inline float tan( float fValue )
00321 {
00322 #ifdef NO_TANF
00323 return static_cast<float>(::tan(fValue));
00324 #else
00325 return static_cast<float>(::tanf(fValue));
00326 #endif
00327 }
00328
00329 template <typename T>
00330 inline T sqr( T fValue )
00331 {
00332 return static_cast<T>(fValue * fValue);
00333 }
00334
00335 template <typename T>
00336 inline T sqrt( T fValue )
00337 {
00338 #ifdef NO_SQRTF
00339 return static_cast<T>(::sqrt((static_cast<float>(fValue))));
00340 #else
00341 return static_cast<T>(::sqrtf((static_cast<float>(fValue))));
00342 #endif
00343 }
00344 inline double sqrt( double fValue )
00345 {
00346 return static_cast<double>(::sqrt(fValue));
00347 }
00348
00351 inline float fastInvSqrt(float x)
00352 {
00353 GMTL_STATIC_ASSERT(sizeof(float) == sizeof(int),
00354 Union_type_sizes_do_not_match);
00355
00356
00357
00358
00359
00360 union
00361 {
00362 float float_value;
00363 int int_value;
00364 } data;
00365
00366 const float xhalf(0.5f*x);
00367 data.float_value = x;
00368
00369 data.int_value = 0x5f3759df - (data.int_value >> 1);
00370 x = data.float_value;
00371 x = x*(1.5f - xhalf*x*x);
00372 return x;
00373 }
00374
00375 inline float fastInvSqrt2(float x)
00376 {
00377 GMTL_STATIC_ASSERT(sizeof(float) == sizeof(int),
00378 Union_type_sizes_do_not_match);
00379
00380
00381
00382
00383
00384 union
00385 {
00386 float float_value;
00387 int int_value;
00388 } data;
00389
00390 const float xhalf(0.5f*x);
00391 data.float_value = x;
00392
00393 data.int_value = 0x5f3759df - (data.int_value >> 1);
00394 x = data.float_value;
00395 x = x*(1.5f - xhalf*x*x);
00396 x = x*(1.5f - xhalf*x*x);
00397 return x;
00398 }
00399
00400 inline float fastInvSqrt3(float x)
00401 {
00402 GMTL_STATIC_ASSERT(sizeof(float) == sizeof(int),
00403 Union_type_sizes_do_not_match);
00404
00405
00406
00407
00408
00409 union
00410 {
00411 float float_value;
00412 int int_value;
00413 } data;
00414
00415 const float xhalf(0.5f*x);
00416 data.float_value = x;
00417
00418 data.int_value = 0x5f3759df - (data.int_value >> 1);
00419 x = data.float_value;
00420 x = x*(1.5f - xhalf*x*x);
00421 x = x*(1.5f - xhalf*x*x);
00422 x = x*(1.5f - xhalf*x*x);
00423 return x;
00424 }
00425
00426
00427
00433 inline void seedRandom(unsigned int seed)
00434 {
00435 ::srand(seed);
00436 }
00437
00441 inline float unitRandom()
00442 {
00443 return static_cast<float>(::rand()) / static_cast<float>(RAND_MAX);
00444 }
00445
00449 inline float rangeRandom( float x1, float x2 )
00450 {
00451 float r = gmtl::Math::unitRandom();
00452 float size = x2 - x1;
00453 return static_cast<float>(r * size + x1);
00454 }
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464 inline float deg2Rad( float fVal )
00465 {
00466 return static_cast<float>(fVal * static_cast<float>(gmtl::Math::PI / 180.0));
00467 }
00468 inline double deg2Rad( double fVal )
00469 {
00470 return static_cast<double>(fVal * static_cast<double>(gmtl::Math::PI / 180.0));
00471 }
00472
00473 inline float rad2Deg( float fVal )
00474 {
00475 return static_cast<float>(fVal * static_cast<float>(180.0 / gmtl::Math::PI));
00476 }
00477 inline double rad2Deg( double fVal )
00478 {
00479 return static_cast<float>(fVal * static_cast<double>(180.0 / gmtl::Math::PI));
00480 }
00481
00482
00487 template <class T>
00488 inline bool isEqual( const T& a, const T& b, const T& tolerance )
00489 {
00490 gmtlASSERT(tolerance >= static_cast<T>(0));
00491 return gmtl::Math::abs( a - b ) <= tolerance;
00492 }
00493
00495 template <class T>
00496 inline T trunc( T val )
00497 {
00498 return static_cast<T>((val < static_cast<T>(0)) ?
00499 gmtl::Math::ceil(val) :
00500 gmtl::Math::floor(val));
00501 }
00503 template <class T>
00504 inline T round( T p )
00505 {
00506 return static_cast<T>(gmtl::Math::floor(p + static_cast<T>(0.5)));
00507 }
00508
00510 template <class T>
00511 inline T Min( const T& x, const T& y )
00512 {
00513 return ( x > y ) ? y : x;
00514 }
00516 template <class T>
00517 inline T Min( const T& x, const T& y, const T& z )
00518 {
00519 return Min( gmtl::Math::Min( x, y ), z );
00520 }
00522 template <class T>
00523 inline T Min( const T& w, const T& x, const T& y, const T& z )
00524 {
00525 return gmtl::Math::Min( gmtl::Math::Min( w, x ), gmtl::Math::Min( y, z ) );
00526 }
00527
00529 template <class T>
00530 inline T Max( const T& x, const T& y )
00531 {
00532 return ( x > y ) ? x : y;
00533 }
00535 template <class T>
00536 inline T Max( const T& x, const T& y, const T& z )
00537 {
00538 return Max( gmtl::Math::Max( x, y ), z );
00539 }
00541 template <class T>
00542 inline T Max( const T& w, const T& x, const T& y, const T& z )
00543 {
00544 return gmtl::Math::Max( gmtl::Math::Max( w, x ), gmtl::Math::Max( y, z ) );
00545 }
00546
00552 template<class T>
00553 inline T factorial(T rhs)
00554 {
00555 T lhs = static_cast<T>(1);
00556
00557 for( T x = static_cast<T>(1); x <= rhs; ++x )
00558 {
00559 lhs *= x;
00560 }
00561
00562 return lhs;
00563 }
00569 template <class T>
00570 inline T clamp( T number, T lo, T hi )
00571 {
00572 if (number > hi) number = hi;
00573 else if (number < lo) number = lo;
00574 return number;
00575 }
00576
00586 template <class T, typename U>
00587 inline void lerp( T& result, const U& lerp, const T& a, const T& b )
00588 {
00589 T size = b - a;
00590 result = static_cast<U>(a) + (static_cast<U>(size) * lerp);
00591 }
00606 template <class T>
00607 inline bool quadraticFormula(T& r1, T& r2, const T& a, const T& b, const T& c)
00608 {
00609 const T q = b * b - static_cast<T>(4) * a * c;
00610
00611
00612 if (q >= 0)
00613 {
00614 const T sq = gmtl::Math::sqrt(q);
00615 const T d = static_cast<T>(1) / (static_cast<T>(2) * a);
00616 r1 = (-b + sq) * d;
00617 r2 = (-b - sq) * d;
00618 return true;
00619 }
00620
00621 else
00622 {
00623 return false;
00624 }
00625 }
00626
00627 }
00628 }
00629
00630 #endif