00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #ifndef _GMTL_MATH_H_
00036 #define _GMTL_MATH_H_
00037
00038 #include <math.h>
00039 #include <stdlib.h>
00040 #include <gmtl/Defines.h>
00041 #include <gmtl/Util/Assert.h>
00042
00043 namespace gmtl
00044 {
00045
00050 struct RotationOrderBase { enum { IS_ROTORDER = 1 }; };
00051
00054 struct XYZ : public RotationOrderBase { enum { ID = 0 }; };
00055
00058 struct ZYX : public RotationOrderBase { enum { ID = 1 }; };
00059
00062 struct ZXY : public RotationOrderBase { enum { ID = 2 }; };
00063
00064 namespace Math
00065 {
00070 const float PI = 3.14159265358979323846f;
00071 const float PI_OVER_2 = 1.57079632679489661923f;
00072 const float PI_OVER_4 = 0.78539816339744830962f;
00079
00080 template <typename T>
00081 inline T abs( T iValue )
00082 {
00083 return T( iValue >= ((T)0) ? iValue : -iValue );
00084 }
00085
00086 template <typename T>
00087 inline T ceil( T fValue );
00088 inline float ceil( float fValue )
00089 {
00090 #ifdef NO_CEILF
00091 return float(::ceil(fValue));
00092 #else
00093 return float( ::ceilf( fValue ) );
00094 #endif
00095 }
00096 inline double ceil( double fValue )
00097 {
00098 return double( ::ceil( fValue ) );
00099 }
00100
00101 template <typename T>
00102 inline T floor( T fValue );
00103 inline float floor( float fValue )
00104 {
00105 #ifdef NO_FLOORF
00106 return float(::floor(fValue));
00107 #else
00108 return float( ::floorf( fValue ) );
00109 #endif
00110 }
00111 inline double floor( double fValue )
00112 {
00113 return double( ::floor( fValue ) );
00114 }
00115
00116 template <typename T>
00117 inline int sign( T iValue )
00118 {
00119 if (iValue > T(0))
00120 {
00121 return 1;
00122 }
00123 else
00124 {
00125 if (iValue < T(0))
00126 {
00127 return -1;
00128 }
00129 else
00130 {
00131 return 0;
00132 }
00133 }
00134 }
00135
00144 template <typename T>
00145 inline T zeroClamp( T value, T eps = T(0) )
00146 {
00147 return ( (gmtl::Math::abs(value) <= eps) ? T(0) : value );
00148 }
00149
00150
00151
00152
00153
00154 template <typename T>
00155 inline T aCos( T fValue );
00156 inline float aCos( float fValue )
00157 {
00158 if ( -1.0f < fValue )
00159 {
00160 if ( fValue < 1.0f )
00161 {
00162 #ifdef NO_ACOSF
00163 return float(::acos(fValue));
00164 #else
00165 return float( ::acosf( fValue ) );
00166 #endif
00167 }
00168 else
00169 return 0.0f;
00170 }
00171 else
00172 {
00173 return (float)gmtl::Math::PI;
00174 }
00175 }
00176 inline double aCos( double fValue )
00177 {
00178 if ( -1.0 < fValue )
00179 {
00180 if ( fValue < 1.0 )
00181 return double( ::acos( fValue ) );
00182 else
00183 return 0.0;
00184 }
00185 else
00186 {
00187 return (double)gmtl::Math::PI;
00188 }
00189 }
00190
00191 template <typename T>
00192 inline T aSin( T fValue );
00193 inline float aSin( float fValue )
00194 {
00195 if ( -1.0f < fValue )
00196 {
00197 if ( fValue < 1.0f )
00198 {
00199 #ifdef NO_ASINF
00200 return float(::asin(fValue));
00201 #else
00202 return float( ::asinf( fValue ) );
00203 #endif
00204 }
00205 else
00206 return (float)-gmtl::Math::PI_OVER_2;
00207 }
00208 else
00209 {
00210 return (float)gmtl::Math::PI_OVER_2;
00211 }
00212 }
00213 inline double aSin( double fValue )
00214 {
00215 if ( -1.0 < fValue )
00216 {
00217 if ( fValue < 1.0 )
00218 return double( ::asin( fValue ) );
00219 else
00220 return (double)-gmtl::Math::PI_OVER_2;
00221 }
00222 else
00223 {
00224 return (double)gmtl::Math::PI_OVER_2;
00225 }
00226 }
00227
00228 template <typename T>
00229 inline T aTan( T fValue );
00230 inline double aTan( double fValue )
00231 {
00232 return ::atan( fValue );
00233 }
00234 inline float aTan( float fValue )
00235 {
00236 #ifdef NO_TANF
00237 return float(::atan(fValue));
00238 #else
00239 return float( ::atanf( fValue ) );
00240 #endif
00241 }
00242
00243 template <typename T>
00244 inline T atan2( T fY, T fX );
00245 inline float aTan2( float fY, float fX )
00246 {
00247 #ifdef NO_ATAN2F
00248 return float(::atan2(fY, fX));
00249 #else
00250 return float( ::atan2f( fY, fX ) );
00251 #endif
00252 }
00253 inline double aTan2( double fY, double fX )
00254 {
00255 return double( ::atan2( fY, fX ) );
00256 }
00257
00258 template <typename T>
00259 inline T cos( T fValue );
00260 inline float cos( float fValue )
00261 {
00262 #ifdef NO_COSF
00263 return float(::cos(fValue));
00264 #else
00265 return float( ::cosf( fValue ) );
00266 #endif
00267 }
00268 inline double cos( double fValue )
00269 {
00270 return double( ::cos( fValue ) );
00271 }
00272
00273 template <typename T>
00274 inline T exp( T fValue );
00275 inline float exp( float fValue )
00276 {
00277 #ifdef NO_EXPF
00278 return float(::exp(fValue));
00279 #else
00280 return float( ::expf( fValue ) );
00281 #endif
00282 }
00283 inline double exp( double fValue )
00284 {
00285 return double( ::exp( fValue ) );
00286 }
00287
00288 template <typename T>
00289 inline T log( T fValue );
00290 inline double log( double fValue )
00291 {
00292 return double( ::log( fValue ) );
00293 }
00294 inline float log( float fValue )
00295 {
00296 #ifdef NO_LOGF
00297 return float(::log(fValue));
00298 #else
00299 return float( ::logf( fValue ) );
00300 #endif
00301 }
00302
00303 inline double pow( double fBase, double fExponent)
00304 {
00305 return double( ::pow( fBase, fExponent ) );
00306 }
00307 inline float pow( float fBase, float fExponent)
00308 {
00309 #ifdef NO_POWF
00310 return float(::pow(fBase, fExponent));
00311 #else
00312 return float( ::powf( fBase, fExponent ) );
00313 #endif
00314 }
00315
00316 template <typename T>
00317 inline T sin( T fValue );
00318 inline double sin( double fValue )
00319 {
00320 return double( ::sin( fValue ) );
00321 }
00322 inline float sin( float fValue )
00323 {
00324 #ifdef NO_SINF
00325 return float(::sin(fValue));
00326 #else
00327 return float( ::sinf( fValue ) );
00328 #endif
00329 }
00330
00331 template <typename T>
00332 inline T tan( T fValue );
00333 inline double tan( double fValue )
00334 {
00335 return double( ::tan( fValue ) );
00336 }
00337 inline float tan( float fValue )
00338 {
00339 #ifdef NO_TANF
00340 return float(::tan(fValue));
00341 #else
00342 return float( ::tanf( fValue ) );
00343 #endif
00344 }
00345
00346 template <typename T>
00347 inline T sqr( T fValue )
00348 {
00349 return T( fValue * fValue );
00350 }
00351
00352 template <typename T>
00353 inline T sqrt( T fValue )
00354 {
00355 #ifdef NO_SQRTF
00356 return T(::sqrt(((float)fValue)));
00357 #else
00358 return T( ::sqrtf( ((float)fValue) ) );
00359 #endif
00360 }
00361 inline double sqrt( double fValue )
00362 {
00363 return double( ::sqrt( fValue ) );
00364 }
00365
00366
00372 inline void seedRandom(unsigned int seed)
00373 {
00374 ::srand(seed);
00375 }
00376
00380 inline float unitRandom()
00381 {
00382 return float(::rand())/float(RAND_MAX);
00383 }
00384
00388 inline float rangeRandom( float x1, float x2 )
00389 {
00390 float r = gmtl::Math::unitRandom();
00391 float size = x2 - x1;
00392 return float( r * size + x1 );
00393 }
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403 inline float deg2Rad( float fVal )
00404 {
00405 return float( fVal * (float)(gmtl::Math::PI/180.0) );
00406 }
00407 inline double deg2Rad( double fVal )
00408 {
00409 return double( fVal * (double)(gmtl::Math::PI/180.0) );
00410 }
00411
00412 inline float rad2Deg( float fVal )
00413 {
00414 return float( fVal * (float)(180.0/gmtl::Math::PI) );
00415 }
00416 inline double rad2Deg( double fVal )
00417 {
00418 return double( fVal * (double)(180.0/gmtl::Math::PI) );
00419 }
00420
00421
00426 template <class T>
00427 inline bool isEqual( const T& a, const T& b, const T& tolerance )
00428 {
00429 gmtlASSERT( tolerance >= (T)0 );
00430 return bool( gmtl::Math::abs( a - b ) <= tolerance );
00431 }
00432
00434 template <class T>
00435 inline T trunc( T val )
00436 {
00437 return T( (val < ((T)0)) ? gmtl::Math::ceil( val ) : gmtl::Math::floor( val ) );
00438 }
00440 template <class T>
00441 inline T round( T p )
00442 {
00443 return T( gmtl::Math::floor( p + (T)0.5 ) );
00444 }
00445
00447 template <class T>
00448 inline T Min( const T& x, const T& y )
00449 {
00450 return ( x > y ) ? y : x;
00451 }
00453 template <class T>
00454 inline T Min( const T& x, const T& y, const T& z )
00455 {
00456 return Min( gmtl::Math::Min( x, y ), z );
00457 }
00459 template <class T>
00460 inline T Min( const T& w, const T& x, const T& y, const T& z )
00461 {
00462 return gmtl::Math::Min( gmtl::Math::Min( w, x ), gmtl::Math::Min( y, z ) );
00463 }
00464
00466 template <class T>
00467 inline T Max( const T& x, const T& y )
00468 {
00469 return ( x > y ) ? x : y;
00470 }
00472 template <class T>
00473 inline T Max( const T& x, const T& y, const T& z )
00474 {
00475 return Max( gmtl::Math::Max( x, y ), z );
00476 }
00478 template <class T>
00479 inline T Max( const T& w, const T& x, const T& y, const T& z )
00480 {
00481 return gmtl::Math::Max( gmtl::Math::Max( w, x ), gmtl::Math::Max( y, z ) );
00482 }
00483
00489 template<class T>
00490 inline T factorial(T rhs)
00491 {
00492 T lhs = (T)1;
00493
00494 for( T x = (T)1; x <= rhs; ++x )
00495 {
00496 lhs *= x;
00497 }
00498
00499 return lhs;
00500 }
00506 template <class T>
00507 inline T clamp( T number, T lo, T hi )
00508 {
00509 if (number > hi) number = hi;
00510 else if (number < lo) number = lo;
00511 return number;
00512 }
00513
00522 template <class T, typename U>
00523 inline void lerp( T& result, const U& lerp, const T& a, const T& b )
00524 {
00525 T size = b - a;
00526 result = ((U)a) + (((U)size) * lerp);
00527 }
00542 template <class T>
00543 inline bool quadraticFormula(T& r1, T& r2, const T& a, const T& b, const T& c)
00544 {
00545 const T q = b*b - T(4)*a*c;
00546
00547
00548 if (q >= 0)
00549 {
00550 const T sq = gmtl::Math::sqrt(q);
00551 const T d = T(1) / (T(2) * a);
00552 r1 = (-b + sq) * d;
00553 r2 = (-b - sq) * d;
00554 return true;
00555 }
00556
00557 else
00558 {
00559 return false;
00560 }
00561 }
00562
00563 }
00564 }
00565
00566 #endif