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
00197
00198 inline bool equalsByUlp(f32 a, f32 b, int maxUlpDiff)
00199 {
00200
00201
00202
00203
00204
00205 union Float_t
00206 {
00207 Float_t(float f1 = 0.0f) : f(f1) {}
00208
00209 bool sign() const { return (i >> 31) != 0; }
00210
00211 int i;
00212 float f;
00213 };
00214
00215 Float_t fa(a);
00216 Float_t fb(b);
00217
00218
00219 if ( fa.sign() != fb.sign() )
00220 {
00221
00222 if (fa.i == fb.i)
00223 return true;
00224 return false;
00225 }
00226
00227
00228 int ulpsDiff = abs_(fa.i- fb.i);
00229 if (ulpsDiff <= maxUlpDiff)
00230 return true;
00231
00232 return false;
00233 }
00234
00235 #if 0
00236
00237 inline bool equals(const s32 a, const s32 b)
00238 {
00239 return (a == b);
00240 }
00241
00243 inline bool equals(const u32 a, const u32 b)
00244 {
00245 return (a == b);
00246 }
00247 #endif
00248
00249 inline bool equals(const s32 a, const s32 b, const s32 tolerance = ROUNDING_ERROR_S32)
00250 {
00251 return (a + tolerance >= b) && (a - tolerance <= b);
00252 }
00253
00255 inline bool equals(const u32 a, const u32 b, const s32 tolerance = ROUNDING_ERROR_S32)
00256 {
00257 return (a + tolerance >= b) && (a - tolerance <= b);
00258 }
00259
00260 #ifdef __IRR_HAS_S64
00261
00262 inline bool equals(const s64 a, const s64 b, const s64 tolerance = ROUNDING_ERROR_S64)
00263 {
00264 return (a + tolerance >= b) && (a - tolerance <= b);
00265 }
00266 #endif
00267
00269 inline bool iszero(const f64 a, const f64 tolerance = ROUNDING_ERROR_f64)
00270 {
00271 return fabs(a) <= tolerance;
00272 }
00273
00275 inline bool iszero(const f32 a, const f32 tolerance = ROUNDING_ERROR_f32)
00276 {
00277 return fabsf(a) <= tolerance;
00278 }
00279
00281 inline bool isnotzero(const f32 a, const f32 tolerance = ROUNDING_ERROR_f32)
00282 {
00283 return fabsf(a) > tolerance;
00284 }
00285
00287 inline bool iszero(const s32 a, const s32 tolerance = 0)
00288 {
00289 return ( a & 0x7ffffff ) <= tolerance;
00290 }
00291
00293 inline bool iszero(const u32 a, const u32 tolerance = 0)
00294 {
00295 return a <= tolerance;
00296 }
00297
00298 #ifdef __IRR_HAS_S64
00299
00300 inline bool iszero(const s64 a, const s64 tolerance = 0)
00301 {
00302 return abs_(a) > tolerance;
00303 }
00304 #endif
00305
00306 inline s32 s32_min(s32 a, s32 b)
00307 {
00308 const s32 mask = (a - b) >> 31;
00309 return (a & mask) | (b & ~mask);
00310 }
00311
00312 inline s32 s32_max(s32 a, s32 b)
00313 {
00314 const s32 mask = (a - b) >> 31;
00315 return (b & mask) | (a & ~mask);
00316 }
00317
00318 inline s32 s32_clamp (s32 value, s32 low, s32 high)
00319 {
00320 return s32_min(s32_max(value,low), high);
00321 }
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336 typedef union { u32 u; s32 s; f32 f; } inttofloat;
00337
00338 #define F32_AS_S32(f) (*((s32 *) &(f)))
00339 #define F32_AS_U32(f) (*((u32 *) &(f)))
00340 #define F32_AS_U32_POINTER(f) ( ((u32 *) &(f)))
00341
00342 #define F32_VALUE_0 0x00000000
00343 #define F32_VALUE_1 0x3f800000
00344 #define F32_SIGN_BIT 0x80000000U
00345 #define F32_EXPON_MANTISSA 0x7FFFFFFFU
00346
00349 #ifdef IRRLICHT_FAST_MATH
00350 #define IR(x) ((u32&)(x))
00351 #else
00352 inline u32 IR(f32 x) {inttofloat tmp; tmp.f=x; return tmp.u;}
00353 #endif
00354
00356 #define AIR(x) (IR(x)&0x7fffffff)
00357
00359 #ifdef IRRLICHT_FAST_MATH
00360 #define FR(x) ((f32&)(x))
00361 #else
00362 inline f32 FR(u32 x) {inttofloat tmp; tmp.u=x; return tmp.f;}
00363 inline f32 FR(s32 x) {inttofloat tmp; tmp.s=x; return tmp.f;}
00364 #endif
00365
00367 #define IEEE_1_0 0x3f800000
00368
00369 #define IEEE_255_0 0x437f0000
00370
00371 #ifdef IRRLICHT_FAST_MATH
00372 #define F32_LOWER_0(f) (F32_AS_U32(f) > F32_SIGN_BIT)
00373 #define F32_LOWER_EQUAL_0(f) (F32_AS_S32(f) <= F32_VALUE_0)
00374 #define F32_GREATER_0(f) (F32_AS_S32(f) > F32_VALUE_0)
00375 #define F32_GREATER_EQUAL_0(f) (F32_AS_U32(f) <= F32_SIGN_BIT)
00376 #define F32_EQUAL_1(f) (F32_AS_U32(f) == F32_VALUE_1)
00377 #define F32_EQUAL_0(f) ( (F32_AS_U32(f) & F32_EXPON_MANTISSA ) == F32_VALUE_0)
00378
00379
00380 #define F32_A_GREATER_B(a,b) (F32_AS_S32((a)) > F32_AS_S32((b)))
00381
00382 #else
00383
00384 #define F32_LOWER_0(n) ((n) < 0.0f)
00385 #define F32_LOWER_EQUAL_0(n) ((n) <= 0.0f)
00386 #define F32_GREATER_0(n) ((n) > 0.0f)
00387 #define F32_GREATER_EQUAL_0(n) ((n) >= 0.0f)
00388 #define F32_EQUAL_1(n) ((n) == 1.0f)
00389 #define F32_EQUAL_0(n) ((n) == 0.0f)
00390 #define F32_A_GREATER_B(a,b) ((a) > (b))
00391 #endif
00392
00393
00394 #ifndef REALINLINE
00395 #ifdef _MSC_VER
00396 #define REALINLINE __forceinline
00397 #else
00398 #define REALINLINE inline
00399 #endif
00400 #endif
00401
00402 #if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
00403
00404
00405
00407 REALINLINE u32 if_c_a_else_b ( const c8 condition, const u32 a, const u32 b )
00408 {
00409 return ( ( -condition >> 7 ) & ( a ^ b ) ) ^ b;
00410 }
00411
00413 REALINLINE u32 if_c_a_else_0 ( const c8 condition, const u32 a )
00414 {
00415 return ( -condition >> 31 ) & a;
00416 }
00417 #else
00418
00420 REALINLINE u32 if_c_a_else_b ( const s32 condition, const u32 a, const u32 b )
00421 {
00422 return ( ( -condition >> 31 ) & ( a ^ b ) ) ^ b;
00423 }
00424
00426 REALINLINE u16 if_c_a_else_b ( const s16 condition, const u16 a, const u16 b )
00427 {
00428 return ( ( -condition >> 15 ) & ( a ^ b ) ) ^ b;
00429 }
00430
00432 REALINLINE u32 if_c_a_else_0 ( const s32 condition, const u32 a )
00433 {
00434 return ( -condition >> 31 ) & a;
00435 }
00436 #endif
00437
00438
00439
00440
00441 REALINLINE void setbit_cond ( u32 &state, s32 condition, u32 mask )
00442 {
00443
00444
00445 state ^= ( ( -condition >> 31 ) ^ state ) & mask;
00446 }
00447
00448 inline f32 round_( f32 x )
00449 {
00450 return floorf( x + 0.5f );
00451 }
00452
00453 REALINLINE void clearFPUException ()
00454 {
00455 #ifdef IRRLICHT_FAST_MATH
00456 return;
00457 #ifdef feclearexcept
00458 feclearexcept(FE_ALL_EXCEPT);
00459 #elif defined(_MSC_VER)
00460 __asm fnclex;
00461 #elif defined(__GNUC__) && defined(__x86__)
00462 __asm__ __volatile__ ("fclex \n\t");
00463 #else
00464 # warn clearFPUException not supported.
00465 #endif
00466 #endif
00467 }
00468
00469
00470 REALINLINE f32 squareroot(const f32 f)
00471 {
00472 return sqrtf(f);
00473 }
00474
00475
00476 REALINLINE f64 squareroot(const f64 f)
00477 {
00478 return sqrt(f);
00479 }
00480
00481
00482 REALINLINE s32 squareroot(const s32 f)
00483 {
00484 return static_cast<s32>(squareroot(static_cast<f32>(f)));
00485 }
00486
00487 #ifdef __IRR_HAS_S64
00488
00489 REALINLINE s64 squareroot(const s64 f)
00490 {
00491 return static_cast<s64>(squareroot(static_cast<f64>(f)));
00492 }
00493 #endif
00494
00495
00496 REALINLINE f64 reciprocal_squareroot(const f64 x)
00497 {
00498 return 1.0 / sqrt(x);
00499 }
00500
00501
00502 REALINLINE f32 reciprocal_squareroot(const f32 f)
00503 {
00504 #if defined ( IRRLICHT_FAST_MATH )
00505 #if defined(_MSC_VER)
00506
00507
00508 f32 recsqrt;
00509 __asm rsqrtss xmm0, f
00510 __asm movss recsqrt, xmm0
00511 return recsqrt;
00512
00513
00514
00515
00516
00517
00518
00519 #else
00520 return 1.f / sqrtf(f);
00521 #endif
00522 #else // no fast math
00523 return 1.f / sqrtf(f);
00524 #endif
00525 }
00526
00527
00528 REALINLINE s32 reciprocal_squareroot(const s32 x)
00529 {
00530 return static_cast<s32>(reciprocal_squareroot(static_cast<f32>(x)));
00531 }
00532
00533
00534 REALINLINE f32 reciprocal( const f32 f )
00535 {
00536 #if defined (IRRLICHT_FAST_MATH)
00537
00538
00539
00540
00541
00542 f32 rec;
00543 __asm rcpss xmm0, f
00544 __asm movss xmm1, f
00545 __asm mulss xmm1, xmm0
00546 __asm mulss xmm1, xmm0
00547 __asm addss xmm0, xmm0
00548 __asm subss xmm0, xmm1
00549
00550 __asm movss rec, xmm0
00551 return rec;
00552
00553
00555
00556
00557
00558
00559
00560
00561 #else // no fast math
00562 return 1.f / f;
00563 #endif
00564 }
00565
00566
00567 REALINLINE f64 reciprocal ( const f64 f )
00568 {
00569 return 1.0 / f;
00570 }
00571
00572
00573
00574 REALINLINE f32 reciprocal_approxim ( const f32 f )
00575 {
00576 #if defined( IRRLICHT_FAST_MATH)
00577
00578
00579
00580
00581
00582 f32 rec;
00583 __asm rcpss xmm0, f
00584 __asm movss xmm1, f
00585 __asm mulss xmm1, xmm0
00586 __asm mulss xmm1, xmm0
00587 __asm addss xmm0, xmm0
00588 __asm subss xmm0, xmm1
00589
00590 __asm movss rec, xmm0
00591 return rec;
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606 #else // no fast math
00607 return 1.f / f;
00608 #endif
00609 }
00610
00611
00612 REALINLINE s32 floor32(f32 x)
00613 {
00614 #ifdef IRRLICHT_FAST_MATH
00615 const f32 h = 0.5f;
00616
00617 s32 t;
00618
00619 #if defined(_MSC_VER)
00620 __asm
00621 {
00622 fld x
00623 fsub h
00624 fistp t
00625 }
00626 #elif defined(__GNUC__)
00627 __asm__ __volatile__ (
00628 "fsub %2 \n\t"
00629 "fistpl %0"
00630 : "=m" (t)
00631 : "t" (x), "f" (h)
00632 : "st"
00633 );
00634 #else
00635 # warn IRRLICHT_FAST_MATH not supported.
00636 return (s32) floorf ( x );
00637 #endif
00638 return t;
00639 #else // no fast math
00640 return (s32) floorf ( x );
00641 #endif
00642 }
00643
00644
00645 REALINLINE s32 ceil32 ( f32 x )
00646 {
00647 #ifdef IRRLICHT_FAST_MATH
00648 const f32 h = 0.5f;
00649
00650 s32 t;
00651
00652 #if defined(_MSC_VER)
00653 __asm
00654 {
00655 fld x
00656 fadd h
00657 fistp t
00658 }
00659 #elif defined(__GNUC__)
00660 __asm__ __volatile__ (
00661 "fadd %2 \n\t"
00662 "fistpl %0 \n\t"
00663 : "=m"(t)
00664 : "t"(x), "f"(h)
00665 : "st"
00666 );
00667 #else
00668 # warn IRRLICHT_FAST_MATH not supported.
00669 return (s32) ceilf ( x );
00670 #endif
00671 return t;
00672 #else // not fast math
00673 return (s32) ceilf ( x );
00674 #endif
00675 }
00676
00677
00678
00679 REALINLINE s32 round32(f32 x)
00680 {
00681 #if defined(IRRLICHT_FAST_MATH)
00682 s32 t;
00683
00684 #if defined(_MSC_VER)
00685 __asm
00686 {
00687 fld x
00688 fistp t
00689 }
00690 #elif defined(__GNUC__)
00691 __asm__ __volatile__ (
00692 "fistpl %0 \n\t"
00693 : "=m"(t)
00694 : "t"(x)
00695 : "st"
00696 );
00697 #else
00698 # warn IRRLICHT_FAST_MATH not supported.
00699 return (s32) round_(x);
00700 #endif
00701 return t;
00702 #else // no fast math
00703 return (s32) round_(x);
00704 #endif
00705 }
00706
00707 inline f32 f32_max3(const f32 a, const f32 b, const f32 c)
00708 {
00709 return a > b ? (a > c ? a : c) : (b > c ? b : c);
00710 }
00711
00712 inline f32 f32_min3(const f32 a, const f32 b, const f32 c)
00713 {
00714 return a < b ? (a < c ? a : c) : (b < c ? b : c);
00715 }
00716
00717 inline f32 fract ( f32 x )
00718 {
00719 return x - floorf ( x );
00720 }
00721
00722 }
00723 }
00724
00725 #ifndef IRRLICHT_FAST_MATH
00726 using irr::core::IR;
00727 using irr::core::FR;
00728 #endif
00729
00730 #endif
00731