Home | Namespaces | Hierarchy | Alphabetical List | Class list | Files | Namespace Members | Class members | File members | Tutorials

irrMath.h

Go to the documentation of this file.
00001 // Copyright (C) 2002-2009 Nikolaus Gebhardt
00002 // This file is part of the "Irrlicht Engine".
00003 // For conditions of distribution and use, see copyright notice in irrlicht.h
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> // for abs() etc.
00013 #include <limits.h> // For INT_MAX / UINT_MAX
00014 
00015 #if defined(_IRR_SOLARIS_PLATFORM_) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) || defined (_WIN32_WCE)
00016         #define sqrtf(X) (f32)sqrt((f64)(X))
00017         #define sinf(X) (f32)sin((f64)(X))
00018         #define cosf(X) (f32)cos((f64)(X))
00019         #define asinf(X) (f32)asin((f64)(X))
00020         #define acosf(X) (f32)acos((f64)(X))
00021         #define atan2f(X,Y) (f32)atan2((f64)(X),(f64)(Y))
00022         #define ceilf(X) (f32)ceil((f64)(X))
00023         #define floorf(X) (f32)floor((f64)(X))
00024         #define powf(X,Y) (f32)pow((f64)(X),(f64)(Y))
00025         #define fmodf(X,Y) (f32)fmod((f64)(X),(f64)(Y))
00026         #define fabsf(X) (f32)fabs((f64)(X))
00027         #define logf(X) (f32)log((f64)(X))
00028 #endif
00029 
00030 #ifndef FLT_MAX
00031 #define FLT_MAX 3.402823466E+38F
00032 #endif
00033 
00034 namespace irr
00035 {
00036 namespace core
00037 {
00038 
00040 
00041         const s32 ROUNDING_ERROR_S32 = 0;
00042         const f32 ROUNDING_ERROR_f32 = 0.000001f;
00043         const f64 ROUNDING_ERROR_f64 = 0.00000001;
00044 
00045 #ifdef PI // make sure we don't collide with a define
00046 #undef PI
00047 #endif
00049         const f32 PI            = 3.14159265359f;
00050 
00052         const f32 RECIPROCAL_PI = 1.0f/PI;
00053 
00055         const f32 HALF_PI       = PI/2.0f;
00056 
00057 #ifdef PI64 // make sure we don't collide with a define
00058 #undef PI64
00059 #endif
00061         const f64 PI64          = 3.1415926535897932384626433832795028841971693993751;
00062 
00064         const f64 RECIPROCAL_PI64 = 1.0/PI64;
00065 
00067         const f32 DEGTORAD = PI / 180.0f;
00068 
00070         const f32 RADTODEG   = 180.0f / PI;
00071 
00073         const f64 DEGTORAD64 = PI64 / 180.0;
00074 
00076         const f64 RADTODEG64 = 180.0 / PI64;
00077 
00079 
00082         inline f32 radToDeg(f32 radians)
00083         {
00084                 return RADTODEG * radians;
00085         }
00086 
00088 
00091         inline f64 radToDeg(f64 radians)
00092         {
00093                 return RADTODEG64 * radians;
00094         }
00095 
00097 
00100         inline f32 degToRad(f32 degrees)
00101         {
00102                 return DEGTORAD * degrees;
00103         }
00104 
00106 
00109         inline f64 degToRad(f64 degrees)
00110         {
00111                 return DEGTORAD64 * degrees;
00112         }
00113 
00115         template<class T>
00116         inline const T& min_(const T& a, const T& b)
00117         {
00118                 return a < b ? a : b;
00119         }
00120 
00122         template<class T>
00123         inline const T& min_(const T& a, const T& b, const T& c)
00124         {
00125                 return a < b ? min_(a, c) : min_(b, c);
00126         }
00127 
00129         template<class T>
00130         inline const T& max_(const T& a, const T& b)
00131         {
00132                 return a < b ? b : a;
00133         }
00134 
00136         template<class T>
00137         inline const T& max_(const T& a, const T& b, const T& c)
00138         {
00139                 return a < b ? max_(b, c) : max_(a, c);
00140         }
00141 
00143         template<class T>
00144         inline T abs_(const T& a)
00145         {
00146                 return a < (T)0 ? -a : a;
00147         }
00148 
00151         template<class T>
00152         inline T lerp(const T& a, const T& b, const f32 t)
00153         {
00154                 return (T)(a*(1.f-t)) + (b*t);
00155         }
00156 
00158         template <class T>
00159         inline const T clamp (const T& value, const T& low, const T& high)
00160         {
00161                 return min_ (max_(value,low), high);
00162         }
00163 
00165         template <class T>
00166         inline void swap(T& a, T& b)
00167         {
00168                 T c(a);
00169                 a = b;
00170                 b = c;
00171         }
00172 
00174         inline bool equals(const f64 a, const f64 b, const f64 tolerance = ROUNDING_ERROR_f64)
00175         {
00176                 return (a + tolerance >= b) && (a - tolerance <= b);
00177         }
00178 
00180         inline bool equals(const f32 a, const f32 b, const f32 tolerance = ROUNDING_ERROR_f32)
00181         {
00182                 return (a + tolerance >= b) && (a - tolerance <= b);
00183         }
00184 #if 0
00186         inline bool equals(const s32 a, const s32 b)
00187         {
00188                 return (a == b);
00189         }
00190 
00192         inline bool equals(const u32 a, const u32 b)
00193         {
00194                 return (a == b);
00195         }
00196 #endif
00198         inline bool equals(const s32 a, const s32 b, const s32 tolerance = ROUNDING_ERROR_S32)
00199         {
00200                 return (a + tolerance >= b) && (a - tolerance <= b);
00201         }
00202 
00204         inline bool equals(const u32 a, const u32 b, const s32 tolerance = ROUNDING_ERROR_S32)
00205         {
00206                 return (a + tolerance >= b) && (a - tolerance <= b);
00207         }
00208 
00209 
00211         inline bool iszero(const f64 a, const f64 tolerance = ROUNDING_ERROR_f64)
00212         {
00213                 return fabs(a) <= tolerance;
00214         }
00215 
00217         inline bool iszero(const f32 a, const f32 tolerance = ROUNDING_ERROR_f32)
00218         {
00219                 return fabsf(a) <= tolerance;
00220         }
00221 
00223         inline bool isnotzero(const f32 a, const f32 tolerance = ROUNDING_ERROR_f32)
00224         {
00225                 return fabsf(a) > tolerance;
00226         }
00227 
00229         inline bool iszero(const s32 a, const s32 tolerance = 0)
00230         {
00231                 return ( a & 0x7ffffff ) <= tolerance;
00232         }
00233 
00235         inline bool iszero(const u32 a, const u32 tolerance = 0)
00236         {
00237                 return a <= tolerance;
00238         }
00239 
00240         inline s32 s32_min(s32 a, s32 b)
00241         {
00242                 const s32 mask = (a - b) >> 31;
00243                 return (a & mask) | (b & ~mask);
00244         }
00245 
00246         inline s32 s32_max(s32 a, s32 b)
00247         {
00248                 const s32 mask = (a - b) >> 31;
00249                 return (b & mask) | (a & ~mask);
00250         }
00251 
00252         inline s32 s32_clamp (s32 value, s32 low, s32 high)
00253         {
00254                 return s32_min(s32_max(value,low), high);
00255         }
00256 
00257         /*
00258                 float IEEE-754 bit represenation
00259 
00260                 0      0x00000000
00261                 1.0    0x3f800000
00262                 0.5    0x3f000000
00263                 3      0x40400000
00264                 +inf   0x7f800000
00265                 -inf   0xff800000
00266                 +NaN   0x7fc00000 or 0x7ff00000
00267                 in general: number = (sign ? -1:1) * 2^(exponent) * 1.(mantissa bits)
00268         */
00269 
00270         typedef union { u32 u; s32 s; f32 f; } inttofloat;
00271 
00272         #define F32_AS_S32(f)           (*((s32 *) &(f)))
00273         #define F32_AS_U32(f)           (*((u32 *) &(f)))
00274         #define F32_AS_U32_POINTER(f)   ( ((u32 *) &(f)))
00275 
00276         #define F32_VALUE_0             0x00000000
00277         #define F32_VALUE_1             0x3f800000
00278         #define F32_SIGN_BIT            0x80000000U
00279         #define F32_EXPON_MANTISSA      0x7FFFFFFFU
00280 
00283 #ifdef IRRLICHT_FAST_MATH
00284         #define IR(x)                           ((u32&)(x))
00285 #else
00286         inline u32 IR(f32 x) {inttofloat tmp; tmp.f=x; return tmp.u;}
00287 #endif
00288 
00290         #define AIR(x)                          (IR(x)&0x7fffffff)
00291 
00293 #ifdef IRRLICHT_FAST_MATH
00294         #define FR(x)                           ((f32&)(x))
00295 #else
00296         inline f32 FR(u32 x) {inttofloat tmp; tmp.u=x; return tmp.f;}
00297         inline f32 FR(s32 x) {inttofloat tmp; tmp.s=x; return tmp.f;}
00298 #endif
00299 
00301         #define IEEE_1_0                        0x3f800000
00303         #define IEEE_255_0                      0x437f0000
00304 
00305 #ifdef IRRLICHT_FAST_MATH
00306         #define F32_LOWER_0(f)          (F32_AS_U32(f) >  F32_SIGN_BIT)
00307         #define F32_LOWER_EQUAL_0(f)    (F32_AS_S32(f) <= F32_VALUE_0)
00308         #define F32_GREATER_0(f)        (F32_AS_S32(f) >  F32_VALUE_0)
00309         #define F32_GREATER_EQUAL_0(f)  (F32_AS_U32(f) <= F32_SIGN_BIT)
00310         #define F32_EQUAL_1(f)          (F32_AS_U32(f) == F32_VALUE_1)
00311         #define F32_EQUAL_0(f)          ( (F32_AS_U32(f) & F32_EXPON_MANTISSA ) == F32_VALUE_0)
00312 
00313         // only same sign
00314         #define F32_A_GREATER_B(a,b)    (F32_AS_S32((a)) > F32_AS_S32((b)))
00315 
00316 #else
00317 
00318         #define F32_LOWER_0(n)          ((n) <  0.0f)
00319         #define F32_LOWER_EQUAL_0(n)    ((n) <= 0.0f)
00320         #define F32_GREATER_0(n)        ((n) >  0.0f)
00321         #define F32_GREATER_EQUAL_0(n)  ((n) >= 0.0f)
00322         #define F32_EQUAL_1(n)          ((n) == 1.0f)
00323         #define F32_EQUAL_0(n)          ((n) == 0.0f)
00324         #define F32_A_GREATER_B(a,b)    ((a) > (b))
00325 #endif
00326 
00327 
00328 #ifndef REALINLINE
00329         #ifdef _MSC_VER
00330                 #define REALINLINE __forceinline
00331         #else
00332                 #define REALINLINE inline
00333         #endif
00334 #endif
00335 
00336 #if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
00337 
00338         // 8-bit bools in borland builder
00339 
00341         REALINLINE u32 if_c_a_else_b ( const c8 condition, const u32 a, const u32 b )
00342         {
00343                 return ( ( -condition >> 7 ) & ( a ^ b ) ) ^ b;
00344         }
00345 
00347         REALINLINE u32 if_c_a_else_0 ( const c8 condition, const u32 a )
00348         {
00349                 return ( -condition >> 31 ) & a;
00350         }
00351 #else
00352 
00354         REALINLINE u32 if_c_a_else_b ( const s32 condition, const u32 a, const u32 b )
00355         {
00356                 return ( ( -condition >> 31 ) & ( a ^ b ) ) ^ b;
00357         }
00358 
00360         REALINLINE u16 if_c_a_else_b ( const s16 condition, const u16 a, const u16 b )
00361         {
00362                 return ( ( -condition >> 15 ) & ( a ^ b ) ) ^ b;
00363         }
00364 
00366         REALINLINE u32 if_c_a_else_0 ( const s32 condition, const u32 a )
00367         {
00368                 return ( -condition >> 31 ) & a;
00369         }
00370 #endif
00371 
00372         /*
00373                 if (condition) state |= m; else state &= ~m;
00374         */
00375         REALINLINE void setbit_cond ( u32 &state, s32 condition, u32 mask )
00376         {
00377                 // 0, or any postive to mask
00378                 //s32 conmask = -condition >> 31;
00379                 state ^= ( ( -condition >> 31 ) ^ state ) & mask;
00380         }
00381 
00382         inline f32 round_( f32 x )
00383         {
00384                 return floorf( x + 0.5f );
00385         }
00386 
00387         REALINLINE void clearFPUException ()
00388         {
00389 #ifdef IRRLICHT_FAST_MATH
00390                 return;
00391 #ifdef feclearexcept
00392                 feclearexcept(FE_ALL_EXCEPT);
00393 #elif defined(_MSC_VER)
00394                 __asm fnclex;
00395 #elif defined(__GNUC__) && defined(__x86__)
00396                 __asm__ __volatile__ ("fclex \n\t");
00397 #else
00398 #  warn clearFPUException not supported.
00399 #endif
00400 #endif
00401         }
00402 
00403         // calculate: sqrt ( x )
00404         REALINLINE f32 squareroot(const f32 f)
00405         {
00406                 return sqrtf(f);
00407         }
00408 
00409         // calculate: sqrt ( x )
00410         REALINLINE f64 squareroot(const f64 f)
00411         {
00412                 return sqrt(f);
00413         }
00414 
00415         // calculate: sqrt ( x )
00416         REALINLINE s32 squareroot(const s32 f)
00417         {
00418                 return static_cast<s32>(squareroot(static_cast<f32>(f)));
00419         }
00420 
00421         // calculate: 1 / sqrt ( x )
00422         REALINLINE f64 reciprocal_squareroot(const f64 x)
00423         {
00424                 return 1.0 / sqrt(x);
00425         }
00426 
00427         // calculate: 1 / sqrtf ( x )
00428         REALINLINE f32 reciprocal_squareroot(const f32 f)
00429         {
00430 #if defined ( IRRLICHT_FAST_MATH )
00431         #if defined(_MSC_VER)
00432                 // SSE reciprocal square root estimate, accurate to 12 significant
00433                 // bits of the mantissa
00434                 f32 recsqrt;
00435                 __asm rsqrtss xmm0, f           // xmm0 = rsqrtss(f)
00436                 __asm movss recsqrt, xmm0       // return xmm0
00437                 return recsqrt;
00438 
00439 /*
00440                 // comes from Nvidia
00441                 u32 tmp = (u32(IEEE_1_0 << 1) + IEEE_1_0 - *(u32*)&x) >> 1;
00442                 f32 y = *(f32*)&tmp;
00443                 return y * (1.47f - 0.47f * x * y * y);
00444 */
00445         #else
00446                 return 1.f / sqrtf(f);
00447         #endif
00448 #else // no fast math
00449                 return 1.f / sqrtf(f);
00450 #endif
00451         }
00452 
00453         // calculate: 1 / sqrtf( x )
00454         REALINLINE s32 reciprocal_squareroot(const s32 x)
00455         {
00456                 return static_cast<s32>(reciprocal_squareroot(static_cast<f32>(x)));
00457         }
00458 
00459         // calculate: 1 / x
00460         REALINLINE f32 reciprocal( const f32 f )
00461         {
00462 #if defined (IRRLICHT_FAST_MATH)
00463 
00464                 // SSE Newton-Raphson reciprocal estimate, accurate to 23 significant
00465                 // bi ts of the mantissa
00466                 // One Newtown-Raphson Iteration:
00467                 // f(i+1) = 2 * rcpss(f) - f * rcpss(f) * rcpss(f)
00468                 f32 rec;
00469                 __asm rcpss xmm0, f               // xmm0 = rcpss(f)
00470                 __asm movss xmm1, f               // xmm1 = f
00471                 __asm mulss xmm1, xmm0            // xmm1 = f * rcpss(f)
00472                 __asm mulss xmm1, xmm0            // xmm2 = f * rcpss(f) * rcpss(f)
00473                 __asm addss xmm0, xmm0            // xmm0 = 2 * rcpss(f)
00474                 __asm subss xmm0, xmm1            // xmm0 = 2 * rcpss(f)
00475                                                                                   //        - f * rcpss(f) * rcpss(f)
00476                 __asm movss rec, xmm0             // return xmm0
00477                 return rec;
00478 
00479 
00481                 // instead set f to a high value to get a return value near zero..
00482                 // -1000000000000.f.. is use minus to stay negative..
00483                 // must test's here (plane.normal dot anything ) checks on <= 0.f
00484                 //u32 x = (-(AIR(f) != 0 ) >> 31 ) & ( IR(f) ^ 0xd368d4a5 ) ^ 0xd368d4a5;
00485                 //return 1.f / FR ( x );
00486 
00487 #else // no fast math
00488                 return 1.f / f;
00489 #endif
00490         }
00491 
00492         // calculate: 1 / x
00493         REALINLINE f64 reciprocal ( const f64 f )
00494         {
00495                 return 1.0 / f;
00496         }
00497 
00498 
00499         // calculate: 1 / x, low precision allowed
00500         REALINLINE f32 reciprocal_approxim ( const f32 f )
00501         {
00502 #if defined( IRRLICHT_FAST_MATH)
00503 
00504                 // SSE Newton-Raphson reciprocal estimate, accurate to 23 significant
00505                 // bi ts of the mantissa
00506                 // One Newtown-Raphson Iteration:
00507                 // f(i+1) = 2 * rcpss(f) - f * rcpss(f) * rcpss(f)
00508                 f32 rec;
00509                 __asm rcpss xmm0, f               // xmm0 = rcpss(f)
00510                 __asm movss xmm1, f               // xmm1 = f
00511                 __asm mulss xmm1, xmm0            // xmm1 = f * rcpss(f)
00512                 __asm mulss xmm1, xmm0            // xmm2 = f * rcpss(f) * rcpss(f)
00513                 __asm addss xmm0, xmm0            // xmm0 = 2 * rcpss(f)
00514                 __asm subss xmm0, xmm1            // xmm0 = 2 * rcpss(f)
00515                                                                                   //        - f * rcpss(f) * rcpss(f)
00516                 __asm movss rec, xmm0             // return xmm0
00517                 return rec;
00518 
00519 
00520 /*
00521                 // SSE reciprocal estimate, accurate to 12 significant bits of
00522                 f32 rec;
00523                 __asm rcpss xmm0, f             // xmm0 = rcpss(f)
00524                 __asm movss rec , xmm0          // return xmm0
00525                 return rec;
00526 */
00527 /*
00528                 register u32 x = 0x7F000000 - IR ( p );
00529                 const f32 r = FR ( x );
00530                 return r * (2.0f - p * r);
00531 */
00532 #else // no fast math
00533                 return 1.f / f;
00534 #endif
00535         }
00536 
00537 
00538         REALINLINE s32 floor32(f32 x)
00539         {
00540 #ifdef IRRLICHT_FAST_MATH
00541                 const f32 h = 0.5f;
00542 
00543                 s32 t;
00544 
00545 #if defined(_MSC_VER)
00546                 __asm
00547                 {
00548                         fld     x
00549                         fsub    h
00550                         fistp   t
00551                 }
00552 #elif defined(__GNUC__)
00553                 __asm__ __volatile__ (
00554                         "fsub %2 \n\t"
00555                         "fistpl %0"
00556                         : "=m" (t)
00557                         : "t" (x), "f" (h)
00558                         : "st"
00559                         );
00560 #else
00561 #  warn IRRLICHT_FAST_MATH not supported.
00562                 return (s32) floorf ( x );
00563 #endif
00564                 return t;
00565 #else // no fast math
00566                 return (s32) floorf ( x );
00567 #endif
00568         }
00569 
00570 
00571         REALINLINE s32 ceil32 ( f32 x )
00572         {
00573 #ifdef IRRLICHT_FAST_MATH
00574                 const f32 h = 0.5f;
00575 
00576                 s32 t;
00577 
00578 #if defined(_MSC_VER)
00579                 __asm
00580                 {
00581                         fld     x
00582                         fadd    h
00583                         fistp   t
00584                 }
00585 #elif defined(__GNUC__)
00586                 __asm__ __volatile__ (
00587                         "fadd %2 \n\t"
00588                         "fistpl %0 \n\t"
00589                         : "=m"(t)
00590                         : "t"(x), "f"(h)
00591                         : "st"
00592                         );
00593 #else
00594 #  warn IRRLICHT_FAST_MATH not supported.
00595                 return (s32) ceilf ( x );
00596 #endif
00597                 return t;
00598 #else // not fast math
00599                 return (s32) ceilf ( x );
00600 #endif
00601         }
00602 
00603 
00604 
00605         REALINLINE s32 round32(f32 x)
00606         {
00607 #if defined(IRRLICHT_FAST_MATH)
00608                 s32 t;
00609 
00610 #if defined(_MSC_VER)
00611                 __asm
00612                 {
00613                         fld   x
00614                         fistp t
00615                 }
00616 #elif defined(__GNUC__)
00617                 __asm__ __volatile__ (
00618                         "fistpl %0 \n\t"
00619                         : "=m"(t)
00620                         : "t"(x)
00621                         : "st"
00622                         );
00623 #else
00624 #  warn IRRLICHT_FAST_MATH not supported.
00625                 return (s32) round_(x);
00626 #endif
00627                 return t;
00628 #else // no fast math
00629                 return (s32) round_(x);
00630 #endif
00631         }
00632 
00633         inline f32 f32_max3(const f32 a, const f32 b, const f32 c)
00634         {
00635                 return a > b ? (a > c ? a : c) : (b > c ? b : c);
00636         }
00637 
00638         inline f32 f32_min3(const f32 a, const f32 b, const f32 c)
00639         {
00640                 return a < b ? (a < c ? a : c) : (b < c ? b : c);
00641         }
00642 
00643         inline f32 fract ( f32 x )
00644         {
00645                 return x - floorf ( x );
00646         }
00647 
00648 } // end namespace core
00649 } // end namespace irr
00650 
00651 #ifndef IRRLICHT_FAST_MATH
00652         using irr::core::IR;
00653         using irr::core::FR;
00654 #endif
00655 
00656 #endif
00657 

The Irrlicht Engine
The Irrlicht Engine Documentation © 2003-2010 by Nikolaus Gebhardt. Generated on Sun Jan 31 16:45:17 2010 by Doxygen (1.6.2)