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 = 1;
    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         inline bool equals(const f64 a, const f64 b, const f64 tolerance = ROUNDING_ERROR_f64)
    00166         {
    00167                 return (a + tolerance >= b) && (a - tolerance <= b);
    00168         }
    00169
    00171         inline bool equals(const f32 a, const f32 b, const f32 tolerance = ROUNDING_ERROR_f32)
    00172         {
    00173                 return (a + tolerance >= b) && (a - tolerance <= b);
    00174         }
    00175 #if 0
    00177         inline bool equals(const s32 a, const s32 b)
    00178         {
    00179                 return (a == b);
    00180         }
    00181
    00183         inline bool equals(const u32 a, const u32 b)
    00184         {
    00185                 return (a == b);
    00186         }
    00187 #endif
    00189         inline bool equals(const s32 a, const s32 b, const s32 tolerance = ROUNDING_ERROR_S32)
    00190         {
    00191                 return (a + tolerance >= b) && (a - tolerance <= b);
    00192         }
    00193
    00195         inline bool equals(const u32 a, const u32 b, const s32 tolerance = ROUNDING_ERROR_S32)
    00196         {
    00197                 return (a + tolerance >= b) && (a - tolerance <= b);
    00198         }
    00199
    00200
    00202         inline bool iszero(const f64 a, const f64 tolerance = ROUNDING_ERROR_f64)
    00203         {
    00204                 return fabs(a) <= tolerance;
    00205         }
    00206
    00208         inline bool iszero(const f32 a, const f32 tolerance = ROUNDING_ERROR_f32)
    00209         {
    00210                 return fabsf(a) <= tolerance;
    00211         }
    00212
    00214         inline bool isnotzero(const f32 a, const f32 tolerance = ROUNDING_ERROR_f32)
    00215         {
    00216                 return fabsf(a) > tolerance;
    00217         }
    00218
    00220         inline bool iszero(const s32 a, const s32 tolerance = 0)
    00221         {
    00222                 return ( a & 0x7ffffff ) <= tolerance;
    00223         }
    00224
    00226         inline bool iszero(const u32 a, const u32 tolerance = 0)
    00227         {
    00228                 return a <= tolerance;
    00229         }
    00230
    00231         inline s32 s32_min(s32 a, s32 b)
    00232         {
    00233                 const s32 mask = (a - b) >> 31;
    00234                 return (a & mask) | (b & ~mask);
    00235         }
    00236
    00237         inline s32 s32_max(s32 a, s32 b)
    00238         {
    00239                 const s32 mask = (a - b) >> 31;
    00240                 return (b & mask) | (a & ~mask);
    00241         }
    00242
    00243         inline s32 s32_clamp (s32 value, s32 low, s32 high)
    00244         {
    00245                 return s32_min(s32_max(value,low), high);
    00246         }
    00247
    00248         /*
    00249                 float IEEE-754 bit represenation
    00250
    00251                 0      0x00000000
    00252                 1.0    0x3f800000
    00253                 0.5    0x3f000000
    00254                 3      0x40400000
    00255                 +inf   0x7f800000
    00256                 -inf   0xff800000
    00257                 +NaN   0x7fc00000 or 0x7ff00000
    00258                 in general: number = (sign ? -1:1) * 2^(exponent) * 1.(mantissa bits)
    00259         */
    00260
    00261         typedef union { u32 u; s32 s; f32 f; } inttofloat;
    00262
    00263         #define F32_AS_S32(f)           (*((s32 *) &(f)))
    00264         #define F32_AS_U32(f)           (*((u32 *) &(f)))
    00265         #define F32_AS_U32_POINTER(f)   ( ((u32 *) &(f)))
    00266
    00267         #define F32_VALUE_0             0x00000000
    00268         #define F32_VALUE_1             0x3f800000
    00269         #define F32_SIGN_BIT            0x80000000U
    00270         #define F32_EXPON_MANTISSA      0x7FFFFFFFU
    00271
    00274 #ifdef IRRLICHT_FAST_MATH
    00275         #define IR(x)                           ((u32&)(x))
    00276 #else
    00277         inline u32 IR(f32 x) {inttofloat tmp; tmp.f=x; return tmp.u;}
    00278 #endif
    00279
    00281         #define AIR(x)                          (IR(x)&0x7fffffff)
    00282
    00284 #ifdef IRRLICHT_FAST_MATH
    00285         #define FR(x)                           ((f32&)(x))
    00286 #else
    00287         inline f32 FR(u32 x) {inttofloat tmp; tmp.u=x; return tmp.f;}
    00288         inline f32 FR(s32 x) {inttofloat tmp; tmp.s=x; return tmp.f;}
    00289 #endif
    00290
    00292         #define IEEE_1_0                        0x3f800000
    00294         #define IEEE_255_0                      0x437f0000
    00295
    00296 #ifdef IRRLICHT_FAST_MATH
    00297         #define F32_LOWER_0(f)          (F32_AS_U32(f) >  F32_SIGN_BIT)
    00298         #define F32_LOWER_EQUAL_0(f)    (F32_AS_S32(f) <= F32_VALUE_0)
    00299         #define F32_GREATER_0(f)        (F32_AS_S32(f) >  F32_VALUE_0)
    00300         #define F32_GREATER_EQUAL_0(f)  (F32_AS_U32(f) <= F32_SIGN_BIT)
    00301         #define F32_EQUAL_1(f)          (F32_AS_U32(f) == F32_VALUE_1)
    00302         #define F32_EQUAL_0(f)          ( (F32_AS_U32(f) & F32_EXPON_MANTISSA ) == F32_VALUE_0)
    00303
    00304         // only same sign
    00305         #define F32_A_GREATER_B(a,b)    (F32_AS_S32((a)) > F32_AS_S32((b)))
    00306
    00307 #else
    00308
    00309         #define F32_LOWER_0(n)          ((n) <  0.0f)
    00310         #define F32_LOWER_EQUAL_0(n)    ((n) <= 0.0f)
    00311         #define F32_GREATER_0(n)        ((n) >  0.0f)
    00312         #define F32_GREATER_EQUAL_0(n)  ((n) >= 0.0f)
    00313         #define F32_EQUAL_1(n)          ((n) == 1.0f)
    00314         #define F32_EQUAL_0(n)          ((n) == 0.0f)
    00315         #define F32_A_GREATER_B(a,b)    ((a) > (b))
    00316 #endif
    00317
    00318
    00319 #ifndef REALINLINE
    00320         #ifdef _MSC_VER
    00321                 #define REALINLINE __forceinline
    00322         #else
    00323                 #define REALINLINE inline
    00324         #endif
    00325 #endif
    00326
    00327 #if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
    00328
    00329         // 8-bit bools in borland builder
    00330
    00332         REALINLINE u32 if_c_a_else_b ( const c8 condition, const u32 a, const u32 b )
    00333         {
    00334                 return ( ( -condition >> 7 ) & ( a ^ b ) ) ^ b;
    00335         }
    00336
    00338         REALINLINE u32 if_c_a_else_0 ( const c8 condition, const u32 a )
    00339         {
    00340                 return ( -condition >> 31 ) & a;
    00341         }
    00342 #else
    00343
    00345         REALINLINE u32 if_c_a_else_b ( const s32 condition, const u32 a, const u32 b )
    00346         {
    00347                 return ( ( -condition >> 31 ) & ( a ^ b ) ) ^ b;
    00348         }
    00349
    00351         REALINLINE u16 if_c_a_else_b ( const s16 condition, const u16 a, const u16 b )
    00352         {
    00353                 return ( ( -condition >> 15 ) & ( a ^ b ) ) ^ b;
    00354         }
    00355
    00357         REALINLINE u32 if_c_a_else_0 ( const s32 condition, const u32 a )
    00358         {
    00359                 return ( -condition >> 31 ) & a;
    00360         }
    00361 #endif
    00362
    00363         /*
    00364                 if (condition) state |= m; else state &= ~m;
    00365         */
    00366         REALINLINE void setbit_cond ( u32 &state, s32 condition, u32 mask )
    00367         {
    00368                 // 0, or any postive to mask
    00369                 //s32 conmask = -condition >> 31;
    00370                 state ^= ( ( -condition >> 31 ) ^ state ) & mask;
    00371         }
    00372
    00373         inline f32 round_( f32 x )
    00374         {
    00375                 return floorf( x + 0.5f );
    00376         }
    00377
    00378         REALINLINE void clearFPUException ()
    00379         {
    00380 #ifdef IRRLICHT_FAST_MATH
    00381                 return;
    00382 #ifdef feclearexcept
    00383                 feclearexcept(FE_ALL_EXCEPT);
    00384 #elif defined(_MSC_VER)
    00385                 __asm fnclex;
    00386 #elif defined(__GNUC__) && defined(__x86__)
    00387                 __asm__ __volatile__ ("fclex \n\t");
    00388 #else
    00389 #  warn clearFPUException not supported.
    00390 #endif
    00391 #endif
    00392         }
    00393
    00394         // calculate: sqrt ( x )
    00395         REALINLINE f32 squareroot(const f32 f)
    00396         {
    00397                 return sqrtf(f);
    00398         }
    00399
    00400         // calculate: sqrt ( x )
    00401         REALINLINE f64 squareroot(const f64 f)
    00402         {
    00403                 return sqrt(f);
    00404         }
    00405
    00406         // calculate: sqrt ( x )
    00407         REALINLINE s32 squareroot(const s32 f)
    00408         {
    00409                 return static_cast<s32>(squareroot(static_cast<f32>(f)));
    00410         }
    00411
    00412         // calculate: 1 / sqrt ( x )
    00413         REALINLINE f64 reciprocal_squareroot(const f64 x)
    00414         {
    00415                 return 1.0 / sqrt(x);
    00416         }
    00417
    00418         // calculate: 1 / sqrtf ( x )
    00419         REALINLINE f32 reciprocal_squareroot(const f32 f)
    00420         {
    00421 #if defined ( IRRLICHT_FAST_MATH )
    00422         #if defined(_MSC_VER)
    00423                 // SSE reciprocal square root estimate, accurate to 12 significant
    00424                 // bits of the mantissa
    00425                 f32 recsqrt;
    00426                 __asm rsqrtss xmm0, f           // xmm0 = rsqrtss(f)
    00427                 __asm movss recsqrt, xmm0       // return xmm0
    00428                 return recsqrt;
    00429
    00430 /*
    00431                 // comes from Nvidia
    00432                 u32 tmp = (u32(IEEE_1_0 << 1) + IEEE_1_0 - *(u32*)&x) >> 1;
    00433                 f32 y = *(f32*)&tmp;
    00434                 return y * (1.47f - 0.47f * x * y * y);
    00435 */
    00436         #else
    00437                 return 1.f / sqrtf(f);
    00438         #endif
    00439 #else // no fast math
    00440                 return 1.f / sqrtf(f);
    00441 #endif
    00442         }
    00443
    00444         // calculate: 1 / sqrtf( x )
    00445         REALINLINE s32 reciprocal_squareroot(const s32 x)
    00446         {
    00447                 return static_cast<s32>(reciprocal_squareroot(static_cast<f32>(x)));
    00448         }
    00449
    00450         // calculate: 1 / x
    00451         REALINLINE f32 reciprocal( const f32 f )
    00452         {
    00453 #if defined (IRRLICHT_FAST_MATH)
    00454
    00455                 // SSE Newton-Raphson reciprocal estimate, accurate to 23 significant
    00456                 // bi ts of the mantissa
    00457                 // One Newtown-Raphson Iteration:
    00458                 // f(i+1) = 2 * rcpss(f) - f * rcpss(f) * rcpss(f)
    00459                 f32 rec;
    00460                 __asm rcpss xmm0, f               // xmm0 = rcpss(f)
    00461                 __asm movss xmm1, f               // xmm1 = f
    00462                 __asm mulss xmm1, xmm0            // xmm1 = f * rcpss(f)
    00463                 __asm mulss xmm1, xmm0            // xmm2 = f * rcpss(f) * rcpss(f)
    00464                 __asm addss xmm0, xmm0            // xmm0 = 2 * rcpss(f)
    00465                 __asm subss xmm0, xmm1            // xmm0 = 2 * rcpss(f)
    00466                                                                                   //        - f * rcpss(f) * rcpss(f)
    00467                 __asm movss rec, xmm0             // return xmm0
    00468                 return rec;
    00469
    00470
    00472                 // instead set f to a high value to get a return value near zero..
    00473                 // -1000000000000.f.. is use minus to stay negative..
    00474                 // must test's here (plane.normal dot anything ) checks on <= 0.f
    00475                 //u32 x = (-(AIR(f) != 0 ) >> 31 ) & ( IR(f) ^ 0xd368d4a5 ) ^ 0xd368d4a5;
    00476                 //return 1.f / FR ( x );
    00477
    00478 #else // no fast math
    00479                 return 1.f / f;
    00480 #endif
    00481         }
    00482
    00483         // calculate: 1 / x
    00484         REALINLINE f64 reciprocal ( const f64 f )
    00485         {
    00486                 return 1.0 / f;
    00487         }
    00488
    00489
    00490         // calculate: 1 / x, low precision allowed
    00491         REALINLINE f32 reciprocal_approxim ( const f32 f )
    00492         {
    00493 #if defined( IRRLICHT_FAST_MATH)
    00494
    00495                 // SSE Newton-Raphson reciprocal estimate, accurate to 23 significant
    00496                 // bi ts of the mantissa
    00497                 // One Newtown-Raphson Iteration:
    00498                 // f(i+1) = 2 * rcpss(f) - f * rcpss(f) * rcpss(f)
    00499                 f32 rec;
    00500                 __asm rcpss xmm0, f               // xmm0 = rcpss(f)
    00501                 __asm movss xmm1, f               // xmm1 = f
    00502                 __asm mulss xmm1, xmm0            // xmm1 = f * rcpss(f)
    00503                 __asm mulss xmm1, xmm0            // xmm2 = f * rcpss(f) * rcpss(f)
    00504                 __asm addss xmm0, xmm0            // xmm0 = 2 * rcpss(f)
    00505                 __asm subss xmm0, xmm1            // xmm0 = 2 * rcpss(f)
    00506                                                                                   //        - f * rcpss(f) * rcpss(f)
    00507                 __asm movss rec, xmm0             // return xmm0
    00508                 return rec;
    00509
    00510
    00511 /*
    00512                 // SSE reciprocal estimate, accurate to 12 significant bits of
    00513                 f32 rec;
    00514                 __asm rcpss xmm0, f             // xmm0 = rcpss(f)
    00515                 __asm movss rec , xmm0          // return xmm0
    00516                 return rec;
    00517 */
    00518 /*
    00519                 register u32 x = 0x7F000000 - IR ( p );
    00520                 const f32 r = FR ( x );
    00521                 return r * (2.0f - p * r);
    00522 */
    00523 #else // no fast math
    00524                 return 1.f / f;
    00525 #endif
    00526         }
    00527
    00528
    00529         REALINLINE s32 floor32(f32 x)
    00530         {
    00531 #ifdef IRRLICHT_FAST_MATH
    00532                 const f32 h = 0.5f;
    00533
    00534                 s32 t;
    00535
    00536 #if defined(_MSC_VER)
    00537                 __asm
    00538                 {
    00539                         fld     x
    00540                         fsub    h
    00541                         fistp   t
    00542                 }
    00543 #elif defined(__GNUC__)
    00544                 __asm__ __volatile__ (
    00545                         "fsub %2 \n\t"
    00546                         "fistpl %0"
    00547                         : "=m" (t)
    00548                         : "t" (x), "f" (h)
    00549                         : "st"
    00550                         );
    00551 #else
    00552 #  warn IRRLICHT_FAST_MATH not supported.
    00553                 return (s32) floorf ( x );
    00554 #endif
    00555                 return t;
    00556 #else // no fast math
    00557                 return (s32) floorf ( x );
    00558 #endif
    00559         }
    00560
    00561
    00562         REALINLINE s32 ceil32 ( f32 x )
    00563         {
    00564 #ifdef IRRLICHT_FAST_MATH
    00565                 const f32 h = 0.5f;
    00566
    00567                 s32 t;
    00568
    00569 #if defined(_MSC_VER)
    00570                 __asm
    00571                 {
    00572                         fld     x
    00573                         fadd    h
    00574                         fistp   t
    00575                 }
    00576 #elif defined(__GNUC__)
    00577                 __asm__ __volatile__ (
    00578                         "fadd %2 \n\t"
    00579                         "fistpl %0 \n\t"
    00580                         : "=m"(t)
    00581                         : "t"(x), "f"(h)
    00582                         : "st"
    00583                         );
    00584 #else
    00585 #  warn IRRLICHT_FAST_MATH not supported.
    00586                 return (s32) ceilf ( x );
    00587 #endif
    00588                 return t;
    00589 #else // not fast math
    00590                 return (s32) ceilf ( x );
    00591 #endif
    00592         }
    00593
    00594
    00595
    00596         REALINLINE s32 round32(f32 x)
    00597         {
    00598 #if defined(IRRLICHT_FAST_MATH)
    00599                 s32 t;
    00600
    00601 #if defined(_MSC_VER)
    00602                 __asm
    00603                 {
    00604                         fld   x
    00605                         fistp t
    00606                 }
    00607 #elif defined(__GNUC__)
    00608                 __asm__ __volatile__ (
    00609                         "fistpl %0 \n\t"
    00610                         : "=m"(t)
    00611                         : "t"(x)
    00612                         : "st"
    00613                         );
    00614 #else
    00615 #  warn IRRLICHT_FAST_MATH not supported.
    00616                 return (s32) round_(x);
    00617 #endif
    00618                 return t;
    00619 #else // no fast math
    00620                 return (s32) round_(x);
    00621 #endif
    00622         }
    00623
    00624         inline f32 f32_max3(const f32 a, const f32 b, const f32 c)
    00625         {
    00626                 return a > b ? (a > c ? a : c) : (b > c ? b : c);
    00627         }
    00628
    00629         inline f32 f32_min3(const f32 a, const f32 b, const f32 c)
    00630         {
    00631                 return a < b ? (a < c ? a : c) : (b < c ? b : c);
    00632         }
    00633
    00634         inline f32 fract ( f32 x )
    00635         {
    00636                 return x - floorf ( x );
    00637         }
    00638
    00639 } // end namespace core
    00640 } // end namespace irr
    00641
    00642 #ifndef IRRLICHT_FAST_MATH
    00643         using irr::core::IR;
    00644         using irr::core::FR;
    00645 #endif
    00646
    00647 #endif
    00648

| The Irrlicht Engine Documentation © 2003-2009 by Nikolaus Gebhardt. Generated on Sun Jan 10 09:24:04 2010 by Doxygen (1.5.6)