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