"L. Spiro Engine"
|
00001 00026 #ifndef __LSM_MATHLIB_H__ 00027 #define __LSM_MATHLIB_H__ 00028 00029 #include "LSSTDStandardLib.h" 00030 using namespace ::lsstd; 00031 00032 #include <cassert> 00033 #include <cmath> 00034 #include "Fixed/LSMFixed.h" // Include the fixed-point class. 00035 00036 #pragma warning( push ) 00037 00038 // warning C4127: conditional expression is constant 00039 #pragma warning( disable : 4127 ) 00040 00049 #define LSM_PERFORMANCE 3 00050 00051 00052 00053 00054 00055 // ======================================== 00056 // Base type. 00057 // ======================================== 00058 // The types of basics available. This is just an enumeration. 00059 // This type is used in all vectors/matrices/etc. 00060 #define LSM_FLOAT 0 00061 #define LSM_DOUBLE 1 00062 #define LSM_FIXED 2 00063 // Now select one from the above list to actually be used. 00064 #ifndef LSM_BASETYPE 00065 #define LSM_BASETYPE LSM_FLOAT 00066 #endif // #ifndef LSM_BASETYPE 00067 // ======================================== 00068 00069 00070 // ======================================== 00071 // Performance. 00072 // ======================================== 00073 // The performance desired. Certain calculations 00074 // are modified depending on this, losing precision 00075 // in favor of speed or vice-versa. 00076 // Values from 0 to 4 are allowed. 00077 // 0 = Fastest, but less accuracy. 00078 // 4 = Slowest, but more accurate. 00079 #ifndef LSM_PERFORMANCE 00080 #define LSM_PERFORMANCE 2 00081 #endif // #ifndef LSM_PERFORMANCE 00082 // ======================================== 00083 00084 00085 00086 // Define all the constants. 00087 #include "LSMConstants.h" 00088 00089 00090 namespace lsm { 00091 00092 // Create the basic type based on the LSM_BASETYPE macro. 00093 // LSREAL is the type we use throughout the engine for all math. 00094 // This also changes which cos(), sin(), etc. functions are used. 00095 #if LSM_BASETYPE == LSM_FLOAT 00096 typedef float LSREAL; 00097 typedef double LSREALHP; // High-precision type. 00098 // Cast from regular precision and high precision. 00099 #define LSREAL_TO_HP( VAL ) (static_cast<LSREALHP>(VAL)) 00100 // Cast from high-precision back to regular precision. 00101 #define HP_TO_LSREAL( VAL ) (static_cast<LSREAL>(VAL)) 00102 #define LSMCOS( F ) ::cosf( static_cast<LSREAL>(F) ) 00103 #define LSMACOS( F ) ::acosf( static_cast<LSREAL>(F) ) 00104 #define LSMSIN( F ) ::sinf( static_cast<LSREAL>(F) ) 00105 #define LSMASIN( F ) ::asinf( static_cast<LSREAL>(F) ) 00106 #define LSMSQRT( F ) ::sqrtf( static_cast<LSREAL>(F) ) 00107 #define LSMPOW( F, Q ) ::powf( static_cast<LSREAL>(F), static_cast<LSREAL>(Q) ) 00108 #define LSMLOG( F ) ::logf( static_cast<LSREAL>(F) ) 00109 #define LSMEXP( F ) ::expf( static_cast<LSREAL>(F) ) 00110 #define LSMABS( F ) ::fabsf( static_cast<LSREAL>(F) ) 00111 #define LSMTAN( F ) ::tanf( static_cast<LSREAL>(F) ) 00112 #define LSMATAN( F ) ::atanf( static_cast<LSREAL>(F) ) 00113 #define LSMATAN2F( Y, X ) ::atan2f( static_cast<LSREAL>(Y), static_cast<LSREAL>(X) ) 00114 #define LSMFMOD( Y, X ) ::fmodf( static_cast<LSREAL>(Y), static_cast<LSREAL>(X) ) 00115 #define LSMFLOOR( F ) ::floorf( static_cast<LSREAL>(F) ) 00116 #define LSMCEIL( F ) ::ceilf( static_cast<LSREAL>(F) ) 00117 00118 #define LSMCOSHP( F ) ::cos( static_cast<LSREALHP>(F) ) 00119 #define LSMACOSHP( F ) ::acos( static_cast<LSREALHP>(F) ) 00120 #define LSMSINHP( F ) ::sin( static_cast<LSREALHP>(F) ) 00121 #define LSMASINHP( F ) ::asin( static_cast<LSREALHP>(F) ) 00122 #define LSMSQRTHP( F ) ::sqrt( static_cast<LSREALHP>(F) ) 00123 #define LSMPOWHP( F, Q ) ::pow( static_cast<LSREALHP>(F), static_cast<LSREALHP>(Q) ) 00124 #define LSMEXPHP( F ) ::exp( static_cast<LSREALHP>(F) ) 00125 #define LSMABSHP( F ) ::fabs( static_cast<LSREALHP>(F) ) 00126 #define LSMTANHP( F ) ::tan( static_cast<LSREALHP>(F) ) 00127 #define LSMATANHP( F ) ::atan( static_cast<LSREALHP>(F) ) 00128 #define LSMATAN2FHP( Y, X ) ::atan2( static_cast<LSREALHP>(Y), static_cast<LSREALHP>(X) ) 00129 #define LSMFMODHP( Y, X ) ::fmod( static_cast<LSREALHP>(Y), static_cast<LSREALHP>(X) ) 00130 #define LSMFLOORHP( F ) ::floor( static_cast<LSREALHP>(F) ) 00131 #define LSMCEILHP( F ) ::ceil( static_cast<LSREALHP>(F) ) 00132 #elif LSM_BASETYPE == LSM_DOUBLE 00133 typedef double LSREAL; 00134 typedef long double LSREALHP; // High-precision type. 00135 // Cast from regular precision and high precision. 00136 #define LSREAL_TO_HP( VAL ) (static_cast<LSREALHP>(VAL)) 00137 // Cast from high-precision back to regular precision. 00138 #define HP_TO_LSREAL( VAL ) (static_cast<LSREAL>(VAL)) 00139 #define LSMCOS( F ) ::cos( static_cast<LSREAL>(F) ) 00140 #define LSMACOS( F ) ::acos( static_cast<LSREAL>(F) ) 00141 #define LSMSIN( F ) ::sin( static_cast<LSREAL>(F) ) 00142 #define LSMASIN( F ) ::asin( static_cast<LSREAL>(F) ) 00143 #define LSMSQRT( F ) ::sqrt( static_cast<LSREAL>(F) ) 00144 #define LSMPOW( F, Q ) ::pow( static_cast<LSREAL>(F), static_cast<LSREAL>(Q) ) 00145 #define LSMLOG( F ) ::log( static_cast<LSREAL>(F) ) 00146 #define LSMEXP( F ) ::exp( static_cast<LSREAL>(F) ) 00147 #define LSMABS( F ) ::fabs( static_cast<LSREAL>(F) ) 00148 #define LSMTAN( F ) ::tan( static_cast<LSREAL>(F) ) 00149 #define LSMATAN( F ) ::atan( static_cast<LSREAL>(F) ) 00150 #define LSMATAN2F( Y, X ) ::atan2( static_cast<LSREAL>(Y), static_cast<LSREAL>(X) ) 00151 #define LSMFMOD( Y, X ) ::fmod( static_cast<LSREAL>(Y), static_cast<LSREAL>(X) ) 00152 #define LSMFLOOR( F ) ::floor( static_cast<LSREAL>(F) ) 00153 #define LSMCEIL( F ) ::ceil( static_cast<LSREAL>(F) ) 00154 00155 #define LSMCOSHP( F ) ::cos( static_cast<LSREALHP>(F) ) 00156 #define LSMACOSHP( F ) ::acos( static_cast<LSREALHP>(F) ) 00157 #define LSMSINHP( F ) ::sin( static_cast<LSREALHP>(F) ) 00158 #define LSMASINHP( F ) ::asin( static_cast<LSREALHP>(F) ) 00159 #define LSMSQRTHP( F ) ::sqrt( static_cast<LSREALHP>(F) ) 00160 #define LSMPOWHP( F, Q ) ::pow( static_cast<LSREALHP>(F), static_cast<LSREALHP>(Q) ) 00161 #define LSMEXPHP( F ) ::exp( static_cast<LSREALHP>(F) ) 00162 #define LSMABSHP( F ) ::fabs( static_cast<LSREALHP>(F) ) 00163 #define LSMTANHP( F ) ::tan( static_cast<LSREALHP>(F) ) 00164 #define LSMATANHP( F ) ::atan( static_cast<LSREALHP>(F) ) 00165 #define LSMATAN2FHP( Y, X ) ::atan2( static_cast<LSREALHP>(Y), static_cast<LSREALHP>(X) ) 00166 #define LSMFMODHP( Y, X ) ::fmod( static_cast<LSREALHP>(Y), static_cast<LSREALHP>(X) ) 00167 #define LSMFLOORHP( F ) ::floor( static_cast<LSREALHP>(F) ) 00168 #define LSMCEILHP( F ) ::ceil( static_cast<LSREALHP>(F) ) 00169 #elif LSM_BASETYPE == LSM_FIXED 00170 typedef CFixed<LSINT32, 10> LSREAL; 00171 typedef CFixed<LSINT64, 24> LSREALHP; // High-precision type. 00172 // Cast from regular precision to high precision. 00173 #define LSREAL_TO_HP( VAL ) (LSREALHP( LSREALHP::CFixedRawType( (VAL).GetRawValue() << (LSREALHP::Bits() - LSREAL::Bits()) ) )) 00174 // Cast from high-precision back to regular precision. 00175 #define HP_TO_LSREAL( VAL ) (LSREAL( LSREAL::CFixedRawType( LSREAL::Cast( (VAL).GetRawValue() >> (LSREALHP::Bits() - LSREAL::Bits()) ) ) )) 00176 #define LSMCOS( F ) static_cast<LSREAL>(::cosf( static_cast<LSFLOAT>(F) )) 00177 #define LSMACOS( F ) static_cast<LSREAL>(::acosf( static_cast<LSFLOAT>(F) )) 00178 #define LSMSIN( F ) static_cast<LSREAL>(::sinf( static_cast<LSFLOAT>(F) )) 00179 #define LSMASIN( F ) static_cast<LSREAL>(::asinf( static_cast<LSFLOAT>(F) )) 00180 #define LSMSQRT( F ) static_cast<LSREAL>(::sqrtf( static_cast<LSFLOAT>(F) )) 00181 #define LSMPOW( F, Q ) static_cast<LSREAL>(::powf( static_cast<LSFLOAT>(F), static_cast<LSFLOAT>(Q) )) 00182 #define LSMLOG( F ) static_cast<LSREAL>(::log( static_cast<LSREAL>(F) )) 00183 #define LSMEXP( F ) static_cast<LSREAL>(::expf( static_cast<LSFLOAT>(F) )) 00184 #define LSMABS( F ) static_cast<LSREAL>(::fabs( static_cast<LSFLOAT>(F) )) 00185 #define LSMTAN( F ) static_cast<LSREAL>(::tanf( static_cast<LSFLOAT>(F) )) 00186 #define LSMATAN( F ) static_cast<LSREAL>(::atanf( static_cast<LSFLOAT>(F) )) 00187 #define LSMATAN2F( Y, X ) static_cast<LSREAL>(::atan2f( static_cast<LSFLOAT>(Y), static_cast<LSFLOAT>(X) )) 00188 #define LSMFMOD( Y, X ) static_cast<LSREAL>(::fmodf( static_cast<LSFLOAT>(Y), static_cast<LSFLOAT>(X) )) 00189 #define LSMFLOOR( F ) static_cast<LSREAL>(::floorf( static_cast<LSFLOAT>(F) )) 00190 #define LSMCEIL( F ) static_cast<LSREAL>(::ceilf( static_cast<LSFLOAT>(F) )) 00191 00192 #define LSMCOSHP( F ) static_cast<LSREALHP>(::cos( static_cast<LSMDOUBLE>(F) )) 00193 #define LSMACOSHP( F ) static_cast<LSREALHP>(::acos( static_cast<LSMDOUBLE>(F) )) 00194 #define LSMSINHP( F ) static_cast<LSREALHP>(::sin( static_cast<LSMDOUBLE>(F) )) 00195 #define LSMASINHP( F ) static_cast<LSREALHP>(::asin( static_cast<LSMDOUBLE>(F) )) 00196 #define LSMSQRTHP( F ) static_cast<LSREALHP>(::sqrt( static_cast<LSMDOUBLE>(F) )) 00197 #define LSMPOWHP( F, Q ) static_cast<LSREALHP>(::pow( static_cast<LSMDOUBLE>(F), static_cast<LSMDOUBLE>(Q) )) 00198 #define LSMEXPHP( F ) static_cast<LSREALHP>(::exp( static_cast<LSMDOUBLE>(F) )) 00199 #define LSMABSHP( F ) static_cast<LSREALHP>(::fabs( static_cast<LSMDOUBLE>(F) )) 00200 #define LSMTANHP( F ) static_cast<LSREALHP>(::tan( static_cast<LSMDOUBLE>(F) )) 00201 #define LSMATANHP( F ) static_cast<LSREALHP>(::atan( static_cast<LSMDOUBLE>(F) )) 00202 #define LSMATAN2FHP( Y, X ) static_cast<LSREALHP>(::atan2( static_cast<LSMDOUBLE>(Y), static_cast<LSMDOUBLE>(X) )) 00203 #define LSMFMODHP( Y, X ) static_cast<LSREALHP>(::fmod( static_cast<LSMDOUBLE>(Y), static_cast<LSMDOUBLE>(X) )) 00204 #define LSMFLOORHP( F ) static_cast<LSREALHP>(::floor( static_cast<LSMDOUBLE>(F) )) 00205 #define LSMCEILHP( F ) static_cast<LSREALHP>(::ceil( static_cast<LSMDOUBLE>(F) )) 00206 #else 00207 #error "LSM_BASETYPE must be set to LSM_FLOAT, LSM_DOUBLE, or LSM_FIXED." 00208 #endif // LSM_BASETYPE 00209 00210 00227 class CMathLib { 00228 public : 00233 static LSVOID LSE_FCALL Init(); 00234 00235 00236 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 00237 // Math functions, built either for speed or for power, depending on the 00238 // LSM_PERFORMANCE macro. 00239 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 00243 static LSREAL LSE_FCALL InvSqrt( LSREAL _fX ); 00244 00248 static LSREAL LSE_FCALL Sqrt( LSREAL _fX ); 00249 00253 static LSREAL LSE_FCALL Sin( LSREAL _fX ); 00254 00258 static LSREAL LSE_FCALL Cos( LSREAL _fX ); 00259 00263 static LSVOID LSE_FCALL SinCos( LSREAL _fA, LSREAL &_fSine, LSREAL &_fCosine ); 00264 00268 static LSREAL LSE_FCALL Tan( LSREAL _fX ); 00269 00273 static LSREAL LSE_FCALL ASin( LSREAL _fX ); 00274 00278 static LSREAL LSE_FCALL ACos( LSREAL _fX ); 00279 00283 static LSREAL LSE_FCALL ATan( LSREAL _fX ); 00284 00288 static LSREAL LSE_FCALL ATan( LSREAL _fY, LSREAL _fX ); 00289 00293 static LSREAL LSE_FCALL Pow( LSREAL _fX, LSREAL _fY ); 00294 00298 static LSREAL LSE_FCALL Exp( LSREAL _fX ); 00299 00307 static LSREAL LSE_FCALL Log( LSREAL _fX, LSREAL _fY ); 00308 00312 static LSREAL LSE_FCALL Abs( LSREAL _fX ); 00313 00317 template <typename _tType> 00318 static _tType LSE_FCALL AbsT( _tType _fX ); 00319 00323 static LSBOOL LSE_FCALL SameSign( LSREAL _fLeft, LSREAL _fRight ); 00324 00328 static LSREAL LSE_FCALL FMod( LSREAL _fX, LSREAL _fMod ); 00329 00333 static LSREAL LSE_FCALL Floor( LSREAL _fX ); 00334 00341 static LSREAL LSE_FCALL Ceil( LSREAL _fX ); 00342 00346 template <typename _tType> 00347 static _tType LSE_FCALL Max( _tType _fX, _tType _fY ); 00348 00352 template <typename _tType> 00353 static _tType LSE_FCALL Min( _tType _fX, _tType _fY ); 00354 00361 template <typename _tType> 00362 static LSVOID LSE_FCALL Swap( LSE_UNALIGNED _tType &_fLeft, LSE_UNALIGNED _tType &_fRight ); 00363 00372 template <typename _tType> 00373 static _tType LSE_FCALL Clamp( _tType _fValue, _tType _fLow, _tType _fHigh ); 00374 00383 static LSBOOL LSE_FCALL Equals( LSREAL _fX, LSREAL _fY, LSREAL _fEpsilon ); 00384 00393 template <typename _tType> 00394 static LSBOOL LSE_FCALL EqualsT( _tType _fX, _tType _fY, _tType _fEpsilon ); 00395 00396 protected : 00397 #if LSM_BASETYPE == LSM_FLOAT || LSM_BASETYPE == LSM_DOUBLE 00398 union LSM_FLINT { 00399 LSUINT32 ui32Int; 00400 LSREAL fReal; 00401 }; 00402 #endif // #if LSM_BASETYPE == LSM_FLOAT || LSM_BASETYPE == LSM_DOUBLE 00403 00407 static LSBOOL m_bInitialized; 00408 00409 00410 00411 #if LSM_PERFORMANCE <= 2 00412 // We have tables for fast cosine and sine look-up if performance 00413 // is desired. 00414 // If you change the table size you must also change the LSMCOS_F() and LSMSIN_F() macros. 00415 // Currently they rely on this size to save time by casting the value to LSUINT16 00416 // (preventing array overflow). You can change LSM_TABLESIZE, but you may have 00417 // to add a % operator for array sanity, which will be slower. 00418 #define LSM_TABLESIZE (0xFFFF+1) 00419 static LSREAL m_fCosTable[LSM_TABLESIZE]; 00420 static LSREAL m_fSinTable[LSM_TABLESIZE]; 00421 00422 // Easily change between the look-up table and the real value. 00423 #define LSMCOS_F( F ) m_fCosTable[static_cast<LSUINT16>(static_cast<LSFLOAT>(1.0/(LSM_PI_DOUBLE*2.0)*LSM_TABLESIZE)*(F))] 00424 #define LSMSIN_F( F ) m_fSinTable[static_cast<LSUINT16>(static_cast<LSFLOAT>(1.0/(LSM_PI_DOUBLE*2.0)*LSM_TABLESIZE)*(F))] 00425 #else 00426 #define LSMCOS_F( F ) LSMCOS( F ) 00427 #define LSMSIN_F( F ) LSMSIN( F ) 00428 #endif // LSM_PERFORMANCE <= 2 00429 }; 00430 00431 00432 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 00433 // DEFINITIONS 00434 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 00435 // == Functions. 00439 LSE_INLINE LSREAL LSE_FCALL CMathLib::InvSqrt( LSREAL _fX ) { 00440 #if LSM_BASETYPE == LSM_FLOAT 00441 #if defined( LSE_GCC ) 00442 // Strange problem with these machines. Maybe they should upgrade their FPU's. 00443 if ( _fX == LSM_ZERO ) { 00444 return (LSM_INFINITY * static_cast<LSREAL>(0.25)); 00445 } 00446 #endif // #if defined( LSE_GCC ) 00447 LSFLOAT fY, fR; 00448 union { 00449 LSFLOAT fVal; 00450 LSINT32 i32Val; 00451 } uVal; 00452 00453 uVal.fVal = _fX; 00454 00455 fY = _fX * LSM_HALF; 00456 uVal.i32Val = /*0x5F375A86*/0x5F3759DF - (uVal.i32Val >> 1); 00457 fR = uVal.fVal * (1.5f - uVal.fVal * uVal.fVal * fY); 00458 fR = fR * (1.5f - fR * fR * fY); 00459 00460 // More accuracy? 00461 #if LSM_PERFORMANCE >= 3 00462 fR = fR * (1.5f - fR * fR * fY); 00463 #endif // #if LSM_PERFORMANCE >= 3 00464 00465 // Even MORE accuracy? 00466 #if LSM_PERFORMANCE >= 4 00467 fR = fR * (1.5f - fR * fR * fY); 00468 #endif // #if LSM_PERFORMANCE >= 4 00469 return static_cast<LSREAL>(fR); 00470 #else // #if LSM_BASETYPE == LSM_FLOAT 00471 return static_cast<LSREAL>(1.0f / ::sqrtf( static_cast<LSFLOAT>(_fX) )); 00472 #endif // #if LSM_BASETYPE == LSM_FLOAT 00473 } 00474 00478 LSE_INLINE LSREAL LSE_FCALL CMathLib::Sqrt( LSREAL _fX ) { 00479 #if LSM_BASETYPE == LSM_FLOAT 00480 return _fX * InvSqrt( _fX ); 00481 #else // #if LSM_BASETYPE == LSM_FLOAT 00482 return LSMSQRT( _fX ); 00483 #endif // #if LSM_BASETYPE == LSM_FLOAT 00484 } 00485 00489 LSE_INLINE LSREAL LSE_FCALL CMathLib::Sin( LSREAL _fX ) { 00490 return LSMSIN_F( _fX ); 00491 } 00492 00496 LSE_INLINE LSREAL LSE_FCALL CMathLib::Cos( LSREAL _fX ) { 00497 return LSMCOS_F( _fX ); 00498 } 00499 00503 LSE_INLINE LSVOID LSE_FCALL CMathLib::SinCos( LSREAL _fA, LSREAL &_fSine, LSREAL &_fCosine ) { 00504 #if LSM_PERFORMANCE <= 2 00505 _fCosine = Cos( _fA ); 00506 _fSine = Sin( _fA ); 00507 #else // #if LSM_PERFORMANCE <= 2 00508 #if defined( LSE_X86 ) && (LSM_BASETYPE == LSM_FLOAT || LSM_BASETYPE == LSM_DOUBLE) 00509 LSE_ASM_BEGIN 00510 fld _fA 00511 fsincos 00512 mov ecx, _fCosine 00513 mov edx, _fSine 00514 #if LSM_BASETYPE == LSM_FLOAT 00515 fstp dword ptr [ecx] 00516 fstp dword ptr [edx] 00517 #elif LSM_BASETYPE == LSM_DOUBLE 00518 fstp qword ptr [ecx] 00519 fstp qword ptr [edx] 00520 #endif // #if LSM_BASETYPE == LSM_FLOAT 00521 LSE_ASM_END 00522 #else // #if defined( LSE_X86 ) && (LSM_BASETYPE == LSM_FLOAT || LSM_BASETYPE == LSM_DOUBLE) 00523 _fCosine = Cos( _fA ); 00524 _fSine = Sin( _fA ); 00525 #endif // #if defined( LSE_X86 ) && (LSM_BASETYPE == LSM_FLOAT || LSM_BASETYPE == LSM_DOUBLE) 00526 #endif // #if LSM_PERFORMANCE <= 2 00527 } 00528 00532 LSE_INLINE LSREAL LSE_FCALL CMathLib::Tan( LSREAL _fX ) { 00533 return LSMTAN( _fX ); 00534 } 00535 00539 LSE_INLINE LSREAL LSE_FCALL CMathLib::ASin( LSREAL _fX ) { 00540 if ( _fX <= static_cast<LSREAL>(-1.0) ) { return -LSM_HALFPI; } 00541 if ( _fX >= LSM_ONE ) { return LSM_HALFPI; } 00542 return LSMASIN( _fX ); 00543 } 00544 00548 LSE_INLINE LSREAL LSE_FCALL CMathLib::ACos( LSREAL _fX ) { 00549 if ( _fX <= static_cast<LSREAL>(-1.0) ) { return LSM_PI; } 00550 if ( _fX >= LSM_ONE ) { return LSM_ZERO; } 00551 return LSMACOS( _fX ); 00552 } 00553 00557 LSE_INLINE LSREAL LSE_FCALL CMathLib::ATan( LSREAL _fX ) { 00558 return LSMATAN( _fX ); 00559 } 00560 00564 LSE_INLINE LSREAL LSE_FCALL CMathLib::ATan( LSREAL _fY, LSREAL _fX ) { 00565 return LSMATAN2F( _fY, _fX ); 00566 } 00567 00571 LSE_INLINE LSREAL LSE_FCALL CMathLib::Pow( LSREAL _fX, LSREAL _fY ) { 00572 return LSMPOW( _fX, _fY ); 00573 } 00574 00578 LSE_INLINE LSREAL LSE_FCALL CMathLib::Exp( LSREAL _fX ) { 00579 return LSMEXP( _fX ); 00580 } 00581 00589 LSE_INLINE LSREAL LSE_FCALL CMathLib::Log( LSREAL _fX, LSREAL _fY ) { 00590 return LSMLOG( _fX ) / LSMLOG( _fY ); 00591 } 00592 00596 LSE_INLINE LSREAL LSE_FCALL CMathLib::Abs( LSREAL _fX ) { 00597 #if LSM_BASETYPE == LSM_FIXED 00598 return LSREAL::CFixedRawType( (_fX.GetRawValue() & LSREAL::SignMask()) ? (0 - _fX.GetRawValue()) : _fX.GetRawValue() ); 00599 #else // #if LSM_BASETYPE == LSM_FIXED 00600 return LSMABS( _fX ); 00601 #endif // #if LSM_BASETYPE == LSM_FIXED 00602 } 00603 00607 template <typename _tType> 00608 _tType LSE_FCALL CMathLib::AbsT( _tType _fX ) { 00609 return _fX < static_cast<_tType>(0.0) ? -_fX : _fX; 00610 } 00611 00615 LSE_INLINE LSBOOL LSE_FCALL CMathLib::SameSign( LSREAL _fLeft, LSREAL _fRight ) { 00616 #if LSM_BASETYPE == LSM_FLOAT 00617 return ((*reinterpret_cast<LSUINT32 *>(&_fLeft)) & 0x80000000) == 00618 ((*reinterpret_cast<LSUINT32 *>(&_fRight)) & 0x80000000); 00619 #elif LSM_BASETYPE == LSM_DOUBLE 00620 return ((*reinterpret_cast<LSUINT64 *>(&_fLeft)) & 0x8000000000000000ULL) == 00621 ((*reinterpret_cast<LSUINT64 *>(&_fRight)) & 0x8000000000000000ULL); 00622 #elif LSM_BASETYPE == LSM_FIXED 00623 return (_fLeft.GetRawValue() & LSREAL::SignMask()) == (_fRight.GetRawValue() & LSREAL::SignMask()); 00624 #else // #if LSM_BASETYPE == LSM_FLOAT 00625 return (_fLeft >= LSM_ZERO && _fRight >= LSM_ZERO) || 00626 (_fLeft < LSM_ZERO && _fRight < LSM_ZERO); 00627 #endif // #if LSM_BASETYPE == LSM_FLOAT 00628 } 00629 00633 LSE_INLINE LSREAL LSE_FCALL CMathLib::FMod( LSREAL _fX, LSREAL _fMod ) { 00634 #if LSM_BASETYPE == LSM_FIXED 00635 return LSREAL::CFixedRawType( _fX.GetRawValue() % _fMod.GetRawValue() ); 00636 #else // #if LSM_BASETYPE == LSM_FIXED 00637 return LSMFMOD( _fX, _fMod ); 00638 #endif // #if LSM_BASETYPE == LSM_FIXED 00639 } 00640 00644 LSE_INLINE LSREAL LSE_FCALL CMathLib::Floor( LSREAL _fX ) { 00645 return LSMFLOOR( _fX ); 00646 } 00647 00654 LSE_INLINE LSREAL LSE_FCALL CMathLib::Ceil( LSREAL _fX ) { 00655 return LSMCEIL( _fX ); 00656 } 00657 00661 template <typename _tType> 00662 _tType LSE_FCALL CMathLib::Max( _tType _fX, _tType _fY ) { 00663 return _fX > _fY ? _fX : _fY; 00664 } 00665 00669 template <typename _tType> 00670 _tType LSE_FCALL CMathLib::Min( _tType _fX, _tType _fY ) { 00671 return _fX < _fY ? _fX : _fY; 00672 } 00673 00680 template <typename _tType> 00681 LSVOID LSE_FCALL CMathLib::Swap( LSE_UNALIGNED _tType &_fLeft, LSE_UNALIGNED _tType &_fRight ) { 00682 _tType fTemp = _fLeft; 00683 _fLeft = _fRight; 00684 _fRight = fTemp; 00685 } 00686 00695 template <typename _tType> 00696 _tType LSE_FCALL CMathLib::Clamp( _tType _fValue, _tType _fLow, _tType _fHigh ) { 00697 if ( _fValue < _fLow ) { return _fLow; } 00698 return (_fValue > _fHigh) ? _fHigh : _fValue; 00699 } 00700 00709 LSE_INLINE LSBOOL LSE_FCALL CMathLib::Equals( LSREAL _fX, LSREAL _fY, LSREAL _fEpsilon ) { 00710 LSREAL fMax = CMathLib::Max( CMathLib::Abs( _fX ), CMathLib::Abs( _fY ) ); 00711 return CMathLib::Abs( _fX - _fY ) <= _fEpsilon * CMathLib::Max( fMax, LSM_ONE ); 00712 } 00713 00722 template <typename _tType> 00723 LSBOOL LSE_FCALL CMathLib::EqualsT( _tType _fX, _tType _fY, _tType _fEpsilon ) { 00724 _tType fMax = CMathLib::Max<_tType>( CMathLib::AbsT( _fX ), CMathLib::AbsT( _fY ) ); 00725 return CMathLib::AbsT( _fX - _fY ) <= _fEpsilon * CMathLib::Max<_tType>( fMax, _tType( 1 ) ); 00726 } 00727 00728 } // namespace lsm 00729 00730 #pragma warning( pop ) 00731 00732 #endif // __LSM_MATHLIB_H__