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