00001 
00002 
00003 
00004 
00005 #ifndef __IRR_MATH_H_INCLUDED__
00006 #define __IRR_MATH_H_INCLUDED__
00007 
00008 #include "IrrCompileConfig.h"
00009 #include "irrTypes.h"
00010 #include <math.h>
00011 #include <float.h>
00012 #include <stdlib.h> 
00013 #include <limits.h> 
00014 
00015 #if defined(_IRR_SOLARIS_PLATFORM_) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) || defined (_WIN32_WCE)
00016     #define sqrtf(X) (irr::f32)sqrt((irr::f64)(X))
00017     #define sinf(X) (irr::f32)sin((irr::f64)(X))
00018     #define cosf(X) (irr::f32)cos((irr::f64)(X))
00019     #define asinf(X) (irr::f32)asin((irr::f64)(X))
00020     #define acosf(X) (irr::f32)acos((irr::f64)(X))
00021     #define atan2f(X,Y) (irr::f32)atan2((irr::f64)(X),(irr::f64)(Y))
00022     #define ceilf(X) (irr::f32)ceil((irr::f64)(X))
00023     #define floorf(X) (irr::f32)floor((irr::f64)(X))
00024     #define powf(X,Y) (irr::f32)pow((irr::f64)(X),(irr::f64)(Y))
00025     #define fmodf(X,Y) (irr::f32)fmod((irr::f64)(X),(irr::f64)(Y))
00026     #define fabsf(X) (irr::f32)fabs((irr::f64)(X))
00027     #define logf(X) (irr::f32)log((irr::f64)(X))
00028 #endif
00029 
00030 #ifndef FLT_MAX
00031 #define FLT_MAX 3.402823466E+38F
00032 #endif
00033 
00034 #ifndef FLT_MIN
00035 #define FLT_MIN 1.17549435e-38F
00036 #endif
00037 
00038 namespace irr
00039 {
00040 namespace core
00041 {
00042 
00044 
00045     const s32 ROUNDING_ERROR_S32 = 0;
00046 #ifdef __IRR_HAS_S64
00047     const s64 ROUNDING_ERROR_S64 = 0;
00048 #endif
00049     const f32 ROUNDING_ERROR_f32 = 0.000001f;
00050     const f64 ROUNDING_ERROR_f64 = 0.00000001;
00051 
00052 #ifdef PI // make sure we don't collide with a define
00053 #undef PI
00054 #endif
00055 
00056     const f32 PI        = 3.14159265359f;
00057 
00059     const f32 RECIPROCAL_PI = 1.0f/PI;
00060 
00062     const f32 HALF_PI   = PI/2.0f;
00063 
00064 #ifdef PI64 // make sure we don't collide with a define
00065 #undef PI64
00066 #endif
00067 
00068     const f64 PI64      = 3.1415926535897932384626433832795028841971693993751;
00069 
00071     const f64 RECIPROCAL_PI64 = 1.0/PI64;
00072 
00074     const f32 DEGTORAD = PI / 180.0f;
00075 
00077     const f32 RADTODEG   = 180.0f / PI;
00078 
00080     const f64 DEGTORAD64 = PI64 / 180.0;
00081 
00083     const f64 RADTODEG64 = 180.0 / PI64;
00084 
00086 
00089     inline f32 radToDeg(f32 radians)
00090     {
00091         return RADTODEG * radians;
00092     }
00093 
00095 
00098     inline f64 radToDeg(f64 radians)
00099     {
00100         return RADTODEG64 * radians;
00101     }
00102 
00104 
00107     inline f32 degToRad(f32 degrees)
00108     {
00109         return DEGTORAD * degrees;
00110     }
00111 
00113 
00116     inline f64 degToRad(f64 degrees)
00117     {
00118         return DEGTORAD64 * degrees;
00119     }
00120 
00122     template<class T>
00123     inline const T& min_(const T& a, const T& b)
00124     {
00125         return a < b ? a : b;
00126     }
00127 
00129     template<class T>
00130     inline const T& min_(const T& a, const T& b, const T& c)
00131     {
00132         return a < b ? min_(a, c) : min_(b, c);
00133     }
00134 
00136     template<class T>
00137     inline const T& max_(const T& a, const T& b)
00138     {
00139         return a < b ? b : a;
00140     }
00141 
00143     template<class T>
00144     inline const T& max_(const T& a, const T& b, const T& c)
00145     {
00146         return a < b ? max_(b, c) : max_(a, c);
00147     }
00148 
00150     template<class T>
00151     inline T abs_(const T& a)
00152     {
00153         return a < (T)0 ? -a : a;
00154     }
00155 
00158     template<class T>
00159     inline T lerp(const T& a, const T& b, const f32 t)
00160     {
00161         return (T)(a*(1.f-t)) + (b*t);
00162     }
00163 
00165     template <class T>
00166     inline const T clamp (const T& value, const T& low, const T& high)
00167     {
00168         return min_ (max_(value,low), high);
00169     }
00170 
00172     
00173     
00174     
00175     
00176     template <class T1, class T2>
00177     inline void swap(T1& a, T2& b)
00178     {
00179         T1 c(a);
00180         a = b;
00181         b = c;
00182     }
00183 
00185     inline bool equals(const f64 a, const f64 b, const f64 tolerance = ROUNDING_ERROR_f64)
00186     {
00187         return (a + tolerance >= b) && (a - tolerance <= b);
00188     }
00189 
00191     inline bool equals(const f32 a, const f32 b, const f32 tolerance = ROUNDING_ERROR_f32)
00192     {
00193         return (a + tolerance >= b) && (a - tolerance <= b);
00194     }
00195 
00196     union FloatIntUnion32
00197     {
00198         FloatIntUnion32(float f1 = 0.0f) : f(f1) {}
00199         
00200         bool sign() const { return (i >> 31) != 0; }
00201 
00202         irr::s32 i;
00203         irr::f32 f;
00204     };
00205 
00207     
00208     inline bool equalsByUlp(f32 a, f32 b, int maxUlpDiff)
00209     {
00210         
00211         
00212         
00213         
00214         
00215 
00216         FloatIntUnion32 fa(a);
00217         FloatIntUnion32 fb(b);
00218 
00219         
00220         if ( fa.sign() != fb.sign() )
00221         {
00222             
00223             if (fa.i == fb.i)
00224                 return true;
00225             return false;
00226         }
00227 
00228         
00229         int ulpsDiff = abs_(fa.i- fb.i);
00230         if (ulpsDiff <= maxUlpDiff)
00231             return true;
00232 
00233         return false;
00234     }
00235 
00236 #if 0
00237 
00238     inline bool equals(const s32 a, const s32 b)
00239     {
00240         return (a == b);
00241     }
00242 
00244     inline bool equals(const u32 a, const u32 b)
00245     {
00246         return (a == b);
00247     }
00248 #endif
00249 
00250     inline bool equals(const s32 a, const s32 b, const s32 tolerance = ROUNDING_ERROR_S32)
00251     {
00252         return (a + tolerance >= b) && (a - tolerance <= b);
00253     }
00254 
00256     inline bool equals(const u32 a, const u32 b, const s32 tolerance = ROUNDING_ERROR_S32)
00257     {
00258         return (a + tolerance >= b) && (a - tolerance <= b);
00259     }
00260 
00261 #ifdef __IRR_HAS_S64
00262 
00263     inline bool equals(const s64 a, const s64 b, const s64 tolerance = ROUNDING_ERROR_S64)
00264     {
00265         return (a + tolerance >= b) && (a - tolerance <= b);
00266     }
00267 #endif
00268 
00270     inline bool iszero(const f64 a, const f64 tolerance = ROUNDING_ERROR_f64)
00271     {
00272         return fabs(a) <= tolerance;
00273     }
00274 
00276     inline bool iszero(const f32 a, const f32 tolerance = ROUNDING_ERROR_f32)
00277     {
00278         return fabsf(a) <= tolerance;
00279     }
00280 
00282     inline bool isnotzero(const f32 a, const f32 tolerance = ROUNDING_ERROR_f32)
00283     {
00284         return fabsf(a) > tolerance;
00285     }
00286 
00288     inline bool iszero(const s32 a, const s32 tolerance = 0)
00289     {
00290         return ( a & 0x7ffffff ) <= tolerance;
00291     }
00292 
00294     inline bool iszero(const u32 a, const u32 tolerance = 0)
00295     {
00296         return a <= tolerance;
00297     }
00298 
00299 #ifdef __IRR_HAS_S64
00300 
00301     inline bool iszero(const s64 a, const s64 tolerance = 0)
00302     {
00303         return abs_(a) <= tolerance;
00304     }
00305 #endif
00306 
00307     inline s32 s32_min(s32 a, s32 b)
00308     {
00309         const s32 mask = (a - b) >> 31;
00310         return (a & mask) | (b & ~mask);
00311     }
00312 
00313     inline s32 s32_max(s32 a, s32 b)
00314     {
00315         const s32 mask = (a - b) >> 31;
00316         return (b & mask) | (a & ~mask);
00317     }
00318 
00319     inline s32 s32_clamp (s32 value, s32 low, s32 high)
00320     {
00321         return s32_min(s32_max(value,low), high);
00322     }
00323 
00324     
00325 
00326 
00327 
00328 
00329 
00330 
00331 
00332 
00333 
00334 
00335 
00336 
00337     typedef union { u32 u; s32 s; f32 f; } inttofloat;
00338 
00339     #define F32_AS_S32(f)       (*((s32 *) &(f)))
00340     #define F32_AS_U32(f)       (*((u32 *) &(f)))
00341     #define F32_AS_U32_POINTER(f)   ( ((u32 *) &(f)))
00342 
00343     #define F32_VALUE_0     0x00000000
00344     #define F32_VALUE_1     0x3f800000
00345     #define F32_SIGN_BIT        0x80000000U
00346     #define F32_EXPON_MANTISSA  0x7FFFFFFFU
00347 
00350 #ifdef IRRLICHT_FAST_MATH
00351     #define IR(x)                           ((u32&)(x))
00352 #else
00353     inline u32 IR(f32 x) {inttofloat tmp; tmp.f=x; return tmp.u;}
00354 #endif
00355 
00357     #define AIR(x)              (IR(x)&0x7fffffff)
00358 
00360 #ifdef IRRLICHT_FAST_MATH
00361     #define FR(x)                           ((f32&)(x))
00362 #else
00363     inline f32 FR(u32 x) {inttofloat tmp; tmp.u=x; return tmp.f;}
00364     inline f32 FR(s32 x) {inttofloat tmp; tmp.s=x; return tmp.f;}
00365 #endif
00366 
00368     #define IEEE_1_0            0x3f800000
00369 
00370     #define IEEE_255_0          0x437f0000
00371 
00372 #ifdef IRRLICHT_FAST_MATH
00373     #define F32_LOWER_0(f)      (F32_AS_U32(f) >  F32_SIGN_BIT)
00374     #define F32_LOWER_EQUAL_0(f)    (F32_AS_S32(f) <= F32_VALUE_0)
00375     #define F32_GREATER_0(f)    (F32_AS_S32(f) >  F32_VALUE_0)
00376     #define F32_GREATER_EQUAL_0(f)  (F32_AS_U32(f) <= F32_SIGN_BIT)
00377     #define F32_EQUAL_1(f)      (F32_AS_U32(f) == F32_VALUE_1)
00378     #define F32_EQUAL_0(f)      ( (F32_AS_U32(f) & F32_EXPON_MANTISSA ) == F32_VALUE_0)
00379 
00380     
00381     #define F32_A_GREATER_B(a,b)    (F32_AS_S32((a)) > F32_AS_S32((b)))
00382 
00383 #else
00384 
00385     #define F32_LOWER_0(n)      ((n) <  0.0f)
00386     #define F32_LOWER_EQUAL_0(n)    ((n) <= 0.0f)
00387     #define F32_GREATER_0(n)    ((n) >  0.0f)
00388     #define F32_GREATER_EQUAL_0(n)  ((n) >= 0.0f)
00389     #define F32_EQUAL_1(n)      ((n) == 1.0f)
00390     #define F32_EQUAL_0(n)      ((n) == 0.0f)
00391     #define F32_A_GREATER_B(a,b)    ((a) > (b))
00392 #endif
00393 
00394 
00395 #ifndef REALINLINE
00396     #ifdef _MSC_VER
00397         #define REALINLINE __forceinline
00398     #else
00399         #define REALINLINE inline
00400     #endif
00401 #endif
00402 
00403 #if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
00404 
00405     
00406 
00408     REALINLINE u32 if_c_a_else_b ( const c8 condition, const u32 a, const u32 b )
00409     {
00410         return ( ( -condition >> 7 ) & ( a ^ b ) ) ^ b;
00411     }
00412 
00414     REALINLINE u32 if_c_a_else_0 ( const c8 condition, const u32 a )
00415     {
00416         return ( -condition >> 31 ) & a;
00417     }
00418 #else
00419 
00421     REALINLINE u32 if_c_a_else_b ( const s32 condition, const u32 a, const u32 b )
00422     {
00423         return ( ( -condition >> 31 ) & ( a ^ b ) ) ^ b;
00424     }
00425 
00427     REALINLINE u16 if_c_a_else_b ( const s16 condition, const u16 a, const u16 b )
00428     {
00429         return ( ( -condition >> 15 ) & ( a ^ b ) ) ^ b;
00430     }
00431 
00433     REALINLINE u32 if_c_a_else_0 ( const s32 condition, const u32 a )
00434     {
00435         return ( -condition >> 31 ) & a;
00436     }
00437 #endif
00438 
00439     
00440 
00441 
00442     REALINLINE void setbit_cond ( u32 &state, s32 condition, u32 mask )
00443     {
00444         
00445         
00446         state ^= ( ( -condition >> 31 ) ^ state ) & mask;
00447     }
00448 
00449     inline f32 round_( f32 x )
00450     {
00451         return floorf( x + 0.5f );
00452     }
00453 
00454     REALINLINE void clearFPUException ()
00455     {
00456 #ifdef IRRLICHT_FAST_MATH
00457         return;
00458 #ifdef feclearexcept
00459         feclearexcept(FE_ALL_EXCEPT);
00460 #elif defined(_MSC_VER)
00461         __asm fnclex;
00462 #elif defined(__GNUC__) && defined(__x86__)
00463         __asm__ __volatile__ ("fclex \n\t");
00464 #else
00465 #  warn clearFPUException not supported.
00466 #endif
00467 #endif
00468     }
00469 
00470     
00471     REALINLINE f32 squareroot(const f32 f)
00472     {
00473         return sqrtf(f);
00474     }
00475 
00476     
00477     REALINLINE f64 squareroot(const f64 f)
00478     {
00479         return sqrt(f);
00480     }
00481 
00482     
00483     REALINLINE s32 squareroot(const s32 f)
00484     {
00485         return static_cast<s32>(squareroot(static_cast<f32>(f)));
00486     }
00487 
00488 #ifdef __IRR_HAS_S64
00489     
00490     REALINLINE s64 squareroot(const s64 f)
00491     {
00492         return static_cast<s64>(squareroot(static_cast<f64>(f)));
00493     }
00494 #endif
00495 
00496     
00497     REALINLINE f64 reciprocal_squareroot(const f64 x)
00498     {
00499         return 1.0 / sqrt(x);
00500     }
00501 
00502     
00503     REALINLINE f32 reciprocal_squareroot(const f32 f)
00504     {
00505 #if defined ( IRRLICHT_FAST_MATH )
00506     #if defined(_MSC_VER)
00507         
00508         
00509         f32 recsqrt;
00510         __asm rsqrtss xmm0, f           
00511         __asm movss recsqrt, xmm0       
00512         return recsqrt;
00513 
00514 
00515 
00516 
00517 
00518 
00519 
00520     #else
00521         return 1.f / sqrtf(f);
00522     #endif
00523 #else // no fast math
00524         return 1.f / sqrtf(f);
00525 #endif
00526     }
00527 
00528     
00529     REALINLINE s32 reciprocal_squareroot(const s32 x)
00530     {
00531         return static_cast<s32>(reciprocal_squareroot(static_cast<f32>(x)));
00532     }
00533 
00534     
00535     REALINLINE f32 reciprocal( const f32 f )
00536     {
00537 #if defined (IRRLICHT_FAST_MATH)
00538 
00539         
00540         
00541         
00542         
00543         f32 rec;
00544         __asm rcpss xmm0, f               
00545         __asm movss xmm1, f               
00546         __asm mulss xmm1, xmm0            
00547         __asm mulss xmm1, xmm0            
00548         __asm addss xmm0, xmm0            
00549         __asm subss xmm0, xmm1            
00550                                           
00551         __asm movss rec, xmm0             
00552         return rec;
00553 
00554 
00556         
00557         
00558         
00559         
00560         
00561 
00562 #else // no fast math
00563         return 1.f / f;
00564 #endif
00565     }
00566 
00567     
00568     REALINLINE f64 reciprocal ( const f64 f )
00569     {
00570         return 1.0 / f;
00571     }
00572 
00573 
00574     
00575     REALINLINE f32 reciprocal_approxim ( const f32 f )
00576     {
00577 #if defined( IRRLICHT_FAST_MATH)
00578 
00579         
00580         
00581         
00582         
00583         f32 rec;
00584         __asm rcpss xmm0, f               
00585         __asm movss xmm1, f               
00586         __asm mulss xmm1, xmm0            
00587         __asm mulss xmm1, xmm0            
00588         __asm addss xmm0, xmm0            
00589         __asm subss xmm0, xmm1            
00590                                           
00591         __asm movss rec, xmm0             
00592         return rec;
00593 
00594 
00595 
00596 
00597 
00598 
00599 
00600 
00601 
00602 
00603 
00604 
00605 
00606 
00607 #else // no fast math
00608         return 1.f / f;
00609 #endif
00610     }
00611 
00612 
00613     REALINLINE s32 floor32(f32 x)
00614     {
00615 #ifdef IRRLICHT_FAST_MATH
00616         const f32 h = 0.5f;
00617 
00618         s32 t;
00619 
00620 #if defined(_MSC_VER)
00621         __asm
00622         {
00623             fld x
00624             fsub    h
00625             fistp   t
00626         }
00627 #elif defined(__GNUC__)
00628         __asm__ __volatile__ (
00629             "fsub %2 \n\t"
00630             "fistpl %0"
00631             : "=m" (t)
00632             : "t" (x), "f" (h)
00633             : "st"
00634             );
00635 #else
00636 #  warn IRRLICHT_FAST_MATH not supported.
00637         return (s32) floorf ( x );
00638 #endif
00639         return t;
00640 #else // no fast math
00641         return (s32) floorf ( x );
00642 #endif
00643     }
00644 
00645 
00646     REALINLINE s32 ceil32 ( f32 x )
00647     {
00648 #ifdef IRRLICHT_FAST_MATH
00649         const f32 h = 0.5f;
00650 
00651         s32 t;
00652 
00653 #if defined(_MSC_VER)
00654         __asm
00655         {
00656             fld x
00657             fadd    h
00658             fistp   t
00659         }
00660 #elif defined(__GNUC__)
00661         __asm__ __volatile__ (
00662             "fadd %2 \n\t"
00663             "fistpl %0 \n\t"
00664             : "=m"(t)
00665             : "t"(x), "f"(h)
00666             : "st"
00667             );
00668 #else
00669 #  warn IRRLICHT_FAST_MATH not supported.
00670         return (s32) ceilf ( x );
00671 #endif
00672         return t;
00673 #else // not fast math
00674         return (s32) ceilf ( x );
00675 #endif
00676     }
00677 
00678 
00679 
00680     REALINLINE s32 round32(f32 x)
00681     {
00682 #if defined(IRRLICHT_FAST_MATH)
00683         s32 t;
00684 
00685 #if defined(_MSC_VER)
00686         __asm
00687         {
00688             fld   x
00689             fistp t
00690         }
00691 #elif defined(__GNUC__)
00692         __asm__ __volatile__ (
00693             "fistpl %0 \n\t"
00694             : "=m"(t)
00695             : "t"(x)
00696             : "st"
00697             );
00698 #else
00699 #  warn IRRLICHT_FAST_MATH not supported.
00700         return (s32) round_(x);
00701 #endif
00702         return t;
00703 #else // no fast math
00704         return (s32) round_(x);
00705 #endif
00706     }
00707 
00708     inline f32 f32_max3(const f32 a, const f32 b, const f32 c)
00709     {
00710         return a > b ? (a > c ? a : c) : (b > c ? b : c);
00711     }
00712 
00713     inline f32 f32_min3(const f32 a, const f32 b, const f32 c)
00714     {
00715         return a < b ? (a < c ? a : c) : (b < c ? b : c);
00716     }
00717 
00718     inline f32 fract ( f32 x )
00719     {
00720         return x - floorf ( x );
00721     }
00722 
00723 } 
00724 } 
00725 
00726 #ifndef IRRLICHT_FAST_MATH
00727     using irr::core::IR;
00728     using irr::core::FR;
00729 #endif
00730 
00731 #endif
00732