Home | Namespaces | Hierarchy | Alphabetical List | Class list | Files | Namespace Members | Class members | File members | Tutorials
irrMath.h
Go to the documentation of this file.
1 // Copyright (C) 2002-2010 Nikolaus Gebhardt
2 // This file is part of the "Irrlicht Engine".
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
4 
5 #ifndef __IRR_MATH_H_INCLUDED__
6 #define __IRR_MATH_H_INCLUDED__
7 
8 #include "IrrCompileConfig.h"
9 #include "irrTypes.h"
10 #include <math.h>
11 #include <float.h>
12 #include <stdlib.h> // for abs() etc.
13 #include <limits.h> // For INT_MAX / UINT_MAX
14 
15 #if defined(_IRR_SOLARIS_PLATFORM_) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) || defined (_WIN32_WCE)
16  #define sqrtf(X) (irr::f32)sqrt((irr::f64)(X))
17  #define sinf(X) (irr::f32)sin((irr::f64)(X))
18  #define cosf(X) (irr::f32)cos((irr::f64)(X))
19  #define asinf(X) (irr::f32)asin((irr::f64)(X))
20  #define acosf(X) (irr::f32)acos((irr::f64)(X))
21  #define atan2f(X,Y) (irr::f32)atan2((irr::f64)(X),(irr::f64)(Y))
22  #define ceilf(X) (irr::f32)ceil((irr::f64)(X))
23  #define floorf(X) (irr::f32)floor((irr::f64)(X))
24  #define powf(X,Y) (irr::f32)pow((irr::f64)(X),(irr::f64)(Y))
25  #define fmodf(X,Y) (irr::f32)fmod((irr::f64)(X),(irr::f64)(Y))
26  #define fabsf(X) (irr::f32)fabs((irr::f64)(X))
27  #define logf(X) (irr::f32)log((irr::f64)(X))
28 #endif
29 
30 #ifndef FLT_MAX
31 #define FLT_MAX 3.402823466E+38F
32 #endif
33 
34 namespace irr
35 {
36 namespace core
37 {
38 
40 
42  const f32 ROUNDING_ERROR_f32 = 0.000001f;
43  const f64 ROUNDING_ERROR_f64 = 0.00000001;
44 
45 #ifdef PI // make sure we don't collide with a define
46 #undef PI
47 #endif
48 
49  const f32 PI = 3.14159265359f;
50 
52  const f32 RECIPROCAL_PI = 1.0f/PI;
53 
55  const f32 HALF_PI = PI/2.0f;
56 
57 #ifdef PI64 // make sure we don't collide with a define
58 #undef PI64
59 #endif
60 
61  const f64 PI64 = 3.1415926535897932384626433832795028841971693993751;
62 
64  const f64 RECIPROCAL_PI64 = 1.0/PI64;
65 
67  const f32 DEGTORAD = PI / 180.0f;
68 
70  const f32 RADTODEG = 180.0f / PI;
71 
73  const f64 DEGTORAD64 = PI64 / 180.0;
74 
76  const f64 RADTODEG64 = 180.0 / PI64;
77 
79 
82  inline f32 radToDeg(f32 radians)
83  {
84  return RADTODEG * radians;
85  }
86 
88 
91  inline f64 radToDeg(f64 radians)
92  {
93  return RADTODEG64 * radians;
94  }
95 
97 
100  inline f32 degToRad(f32 degrees)
101  {
102  return DEGTORAD * degrees;
103  }
104 
106 
109  inline f64 degToRad(f64 degrees)
110  {
111  return DEGTORAD64 * degrees;
112  }
113 
115  template<class T>
116  inline const T& min_(const T& a, const T& b)
117  {
118  return a < b ? a : b;
119  }
120 
122  template<class T>
123  inline const T& min_(const T& a, const T& b, const T& c)
124  {
125  return a < b ? min_(a, c) : min_(b, c);
126  }
127 
129  template<class T>
130  inline const T& max_(const T& a, const T& b)
131  {
132  return a < b ? b : a;
133  }
134 
136  template<class T>
137  inline const T& max_(const T& a, const T& b, const T& c)
138  {
139  return a < b ? max_(b, c) : max_(a, c);
140  }
141 
143  template<class T>
144  inline T abs_(const T& a)
145  {
146  return a < (T)0 ? -a : a;
147  }
148 
151  template<class T>
152  inline T lerp(const T& a, const T& b, const f32 t)
153  {
154  return (T)(a*(1.f-t)) + (b*t);
155  }
156 
158  template <class T>
159  inline const T clamp (const T& value, const T& low, const T& high)
160  {
161  return min_ (max_(value,low), high);
162  }
163 
165  // Note: We use the same trick as boost and use two template arguments to
166  // avoid ambiguity when swapping objects of an Irrlicht type that has not
167  // it's own swap overload. Otherwise we get conflicts with some compilers
168  // in combination with stl.
169  template <class T1, class T2>
170  inline void swap(T1& a, T2& b)
171  {
172  T1 c(a);
173  a = b;
174  b = c;
175  }
176 
178  inline bool equals(const f64 a, const f64 b, const f64 tolerance = ROUNDING_ERROR_f64)
179  {
180  return (a + tolerance >= b) && (a - tolerance <= b);
181  }
182 
184  inline bool equals(const f32 a, const f32 b, const f32 tolerance = ROUNDING_ERROR_f32)
185  {
186  return (a + tolerance >= b) && (a - tolerance <= b);
187  }
188 #if 0
189 
190  inline bool equals(const s32 a, const s32 b)
191  {
192  return (a == b);
193  }
194 
196  inline bool equals(const u32 a, const u32 b)
197  {
198  return (a == b);
199  }
200 #endif
201 
202  inline bool equals(const s32 a, const s32 b, const s32 tolerance = ROUNDING_ERROR_S32)
203  {
204  return (a + tolerance >= b) && (a - tolerance <= b);
205  }
206 
208  inline bool equals(const u32 a, const u32 b, const s32 tolerance = ROUNDING_ERROR_S32)
209  {
210  return (a + tolerance >= b) && (a - tolerance <= b);
211  }
212 
213 
215  inline bool iszero(const f64 a, const f64 tolerance = ROUNDING_ERROR_f64)
216  {
217  return fabs(a) <= tolerance;
218  }
219 
221  inline bool iszero(const f32 a, const f32 tolerance = ROUNDING_ERROR_f32)
222  {
223  return fabsf(a) <= tolerance;
224  }
225 
227  inline bool isnotzero(const f32 a, const f32 tolerance = ROUNDING_ERROR_f32)
228  {
229  return fabsf(a) > tolerance;
230  }
231 
233  inline bool iszero(const s32 a, const s32 tolerance = 0)
234  {
235  return ( a & 0x7ffffff ) <= tolerance;
236  }
237 
239  inline bool iszero(const u32 a, const u32 tolerance = 0)
240  {
241  return a <= tolerance;
242  }
243 
244  inline s32 s32_min(s32 a, s32 b)
245  {
246  const s32 mask = (a - b) >> 31;
247  return (a & mask) | (b & ~mask);
248  }
249 
250  inline s32 s32_max(s32 a, s32 b)
251  {
252  const s32 mask = (a - b) >> 31;
253  return (b & mask) | (a & ~mask);
254  }
255 
256  inline s32 s32_clamp (s32 value, s32 low, s32 high)
257  {
258  return s32_min(s32_max(value,low), high);
259  }
260 
261  /*
262  float IEEE-754 bit represenation
263 
264  0 0x00000000
265  1.0 0x3f800000
266  0.5 0x3f000000
267  3 0x40400000
268  +inf 0x7f800000
269  -inf 0xff800000
270  +NaN 0x7fc00000 or 0x7ff00000
271  in general: number = (sign ? -1:1) * 2^(exponent) * 1.(mantissa bits)
272  */
273 
274  typedef union { u32 u; s32 s; f32 f; } inttofloat;
275 
276  #define F32_AS_S32(f) (*((s32 *) &(f)))
277  #define F32_AS_U32(f) (*((u32 *) &(f)))
278  #define F32_AS_U32_POINTER(f) ( ((u32 *) &(f)))
279 
280  #define F32_VALUE_0 0x00000000
281  #define F32_VALUE_1 0x3f800000
282  #define F32_SIGN_BIT 0x80000000U
283  #define F32_EXPON_MANTISSA 0x7FFFFFFFU
284 
287 #ifdef IRRLICHT_FAST_MATH
288  #define IR(x) ((u32&)(x))
289 #else
290  inline u32 IR(f32 x) {inttofloat tmp; tmp.f=x; return tmp.u;}
291 #endif
292 
294  #define AIR(x) (IR(x)&0x7fffffff)
295 
297 #ifdef IRRLICHT_FAST_MATH
298  #define FR(x) ((f32&)(x))
299 #else
300  inline f32 FR(u32 x) {inttofloat tmp; tmp.u=x; return tmp.f;}
301  inline f32 FR(s32 x) {inttofloat tmp; tmp.s=x; return tmp.f;}
302 #endif
303 
305  #define IEEE_1_0 0x3f800000
306 
307  #define IEEE_255_0 0x437f0000
308 
309 #ifdef IRRLICHT_FAST_MATH
310  #define F32_LOWER_0(f) (F32_AS_U32(f) > F32_SIGN_BIT)
311  #define F32_LOWER_EQUAL_0(f) (F32_AS_S32(f) <= F32_VALUE_0)
312  #define F32_GREATER_0(f) (F32_AS_S32(f) > F32_VALUE_0)
313  #define F32_GREATER_EQUAL_0(f) (F32_AS_U32(f) <= F32_SIGN_BIT)
314  #define F32_EQUAL_1(f) (F32_AS_U32(f) == F32_VALUE_1)
315  #define F32_EQUAL_0(f) ( (F32_AS_U32(f) & F32_EXPON_MANTISSA ) == F32_VALUE_0)
316 
317  // only same sign
318  #define F32_A_GREATER_B(a,b) (F32_AS_S32((a)) > F32_AS_S32((b)))
319 
320 #else
321 
322  #define F32_LOWER_0(n) ((n) < 0.0f)
323  #define F32_LOWER_EQUAL_0(n) ((n) <= 0.0f)
324  #define F32_GREATER_0(n) ((n) > 0.0f)
325  #define F32_GREATER_EQUAL_0(n) ((n) >= 0.0f)
326  #define F32_EQUAL_1(n) ((n) == 1.0f)
327  #define F32_EQUAL_0(n) ((n) == 0.0f)
328  #define F32_A_GREATER_B(a,b) ((a) > (b))
329 #endif
330 
331 
332 #ifndef REALINLINE
333  #ifdef _MSC_VER
334  #define REALINLINE __forceinline
335  #else
336  #define REALINLINE inline
337  #endif
338 #endif
339 
340 #if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
341 
342  // 8-bit bools in borland builder
343 
345  REALINLINE u32 if_c_a_else_b ( const c8 condition, const u32 a, const u32 b )
346  {
347  return ( ( -condition >> 7 ) & ( a ^ b ) ) ^ b;
348  }
349 
351  REALINLINE u32 if_c_a_else_0 ( const c8 condition, const u32 a )
352  {
353  return ( -condition >> 31 ) & a;
354  }
355 #else
356 
358  REALINLINE u32 if_c_a_else_b ( const s32 condition, const u32 a, const u32 b )
359  {
360  return ( ( -condition >> 31 ) & ( a ^ b ) ) ^ b;
361  }
362 
364  REALINLINE u16 if_c_a_else_b ( const s16 condition, const u16 a, const u16 b )
365  {
366  return ( ( -condition >> 15 ) & ( a ^ b ) ) ^ b;
367  }
368 
370  REALINLINE u32 if_c_a_else_0 ( const s32 condition, const u32 a )
371  {
372  return ( -condition >> 31 ) & a;
373  }
374 #endif
375 
376  /*
377  if (condition) state |= m; else state &= ~m;
378  */
379  REALINLINE void setbit_cond ( u32 &state, s32 condition, u32 mask )
380  {
381  // 0, or any postive to mask
382  //s32 conmask = -condition >> 31;
383  state ^= ( ( -condition >> 31 ) ^ state ) & mask;
384  }
385 
386  inline f32 round_( f32 x )
387  {
388  return floorf( x + 0.5f );
389  }
390 
392  {
393 #ifdef IRRLICHT_FAST_MATH
394  return;
395 #ifdef feclearexcept
396  feclearexcept(FE_ALL_EXCEPT);
397 #elif defined(_MSC_VER)
398  __asm fnclex;
399 #elif defined(__GNUC__) && defined(__x86__)
400  __asm__ __volatile__ ("fclex \n\t");
401 #else
402 # warn clearFPUException not supported.
403 #endif
404 #endif
405  }
406 
407  // calculate: sqrt ( x )
409  {
410  return sqrtf(f);
411  }
412 
413  // calculate: sqrt ( x )
415  {
416  return sqrt(f);
417  }
418 
419  // calculate: sqrt ( x )
421  {
422  return static_cast<s32>(squareroot(static_cast<f32>(f)));
423  }
424 
425  // calculate: 1 / sqrt ( x )
427  {
428  return 1.0 / sqrt(x);
429  }
430 
431  // calculate: 1 / sqrtf ( x )
433  {
434 #if defined ( IRRLICHT_FAST_MATH )
435  #if defined(_MSC_VER)
436  // SSE reciprocal square root estimate, accurate to 12 significant
437  // bits of the mantissa
438  f32 recsqrt;
439  __asm rsqrtss xmm0, f // xmm0 = rsqrtss(f)
440  __asm movss recsqrt, xmm0 // return xmm0
441  return recsqrt;
442 
443 /*
444  // comes from Nvidia
445  u32 tmp = (u32(IEEE_1_0 << 1) + IEEE_1_0 - *(u32*)&x) >> 1;
446  f32 y = *(f32*)&tmp;
447  return y * (1.47f - 0.47f * x * y * y);
448 */
449  #else
450  return 1.f / sqrtf(f);
451  #endif
452 #else // no fast math
453  return 1.f / sqrtf(f);
454 #endif
455  }
456 
457  // calculate: 1 / sqrtf( x )
459  {
460  return static_cast<s32>(reciprocal_squareroot(static_cast<f32>(x)));
461  }
462 
463  // calculate: 1 / x
465  {
466 #if defined (IRRLICHT_FAST_MATH)
467 
468  // SSE Newton-Raphson reciprocal estimate, accurate to 23 significant
469  // bi ts of the mantissa
470  // One Newtown-Raphson Iteration:
471  // f(i+1) = 2 * rcpss(f) - f * rcpss(f) * rcpss(f)
472  f32 rec;
473  __asm rcpss xmm0, f // xmm0 = rcpss(f)
474  __asm movss xmm1, f // xmm1 = f
475  __asm mulss xmm1, xmm0 // xmm1 = f * rcpss(f)
476  __asm mulss xmm1, xmm0 // xmm2 = f * rcpss(f) * rcpss(f)
477  __asm addss xmm0, xmm0 // xmm0 = 2 * rcpss(f)
478  __asm subss xmm0, xmm1 // xmm0 = 2 * rcpss(f)
479  // - f * rcpss(f) * rcpss(f)
480  __asm movss rec, xmm0 // return xmm0
481  return rec;
482 
483 
485  // instead set f to a high value to get a return value near zero..
486  // -1000000000000.f.. is use minus to stay negative..
487  // must test's here (plane.normal dot anything ) checks on <= 0.f
488  //u32 x = (-(AIR(f) != 0 ) >> 31 ) & ( IR(f) ^ 0xd368d4a5 ) ^ 0xd368d4a5;
489  //return 1.f / FR ( x );
490 
491 #else // no fast math
492  return 1.f / f;
493 #endif
494  }
495 
496  // calculate: 1 / x
498  {
499  return 1.0 / f;
500  }
501 
502 
503  // calculate: 1 / x, low precision allowed
505  {
506 #if defined( IRRLICHT_FAST_MATH)
507 
508  // SSE Newton-Raphson reciprocal estimate, accurate to 23 significant
509  // bi ts of the mantissa
510  // One Newtown-Raphson Iteration:
511  // f(i+1) = 2 * rcpss(f) - f * rcpss(f) * rcpss(f)
512  f32 rec;
513  __asm rcpss xmm0, f // xmm0 = rcpss(f)
514  __asm movss xmm1, f // xmm1 = f
515  __asm mulss xmm1, xmm0 // xmm1 = f * rcpss(f)
516  __asm mulss xmm1, xmm0 // xmm2 = f * rcpss(f) * rcpss(f)
517  __asm addss xmm0, xmm0 // xmm0 = 2 * rcpss(f)
518  __asm subss xmm0, xmm1 // xmm0 = 2 * rcpss(f)
519  // - f * rcpss(f) * rcpss(f)
520  __asm movss rec, xmm0 // return xmm0
521  return rec;
522 
523 
524 /*
525  // SSE reciprocal estimate, accurate to 12 significant bits of
526  f32 rec;
527  __asm rcpss xmm0, f // xmm0 = rcpss(f)
528  __asm movss rec , xmm0 // return xmm0
529  return rec;
530 */
531 /*
532  register u32 x = 0x7F000000 - IR ( p );
533  const f32 r = FR ( x );
534  return r * (2.0f - p * r);
535 */
536 #else // no fast math
537  return 1.f / f;
538 #endif
539  }
540 
541 
543  {
544 #ifdef IRRLICHT_FAST_MATH
545  const f32 h = 0.5f;
546 
547  s32 t;
548 
549 #if defined(_MSC_VER)
550  __asm
551  {
552  fld x
553  fsub h
554  fistp t
555  }
556 #elif defined(__GNUC__)
557  __asm__ __volatile__ (
558  "fsub %2 \n\t"
559  "fistpl %0"
560  : "=m" (t)
561  : "t" (x), "f" (h)
562  : "st"
563  );
564 #else
565 # warn IRRLICHT_FAST_MATH not supported.
566  return (s32) floorf ( x );
567 #endif
568  return t;
569 #else // no fast math
570  return (s32) floorf ( x );
571 #endif
572  }
573 
574 
576  {
577 #ifdef IRRLICHT_FAST_MATH
578  const f32 h = 0.5f;
579 
580  s32 t;
581 
582 #if defined(_MSC_VER)
583  __asm
584  {
585  fld x
586  fadd h
587  fistp t
588  }
589 #elif defined(__GNUC__)
590  __asm__ __volatile__ (
591  "fadd %2 \n\t"
592  "fistpl %0 \n\t"
593  : "=m"(t)
594  : "t"(x), "f"(h)
595  : "st"
596  );
597 #else
598 # warn IRRLICHT_FAST_MATH not supported.
599  return (s32) ceilf ( x );
600 #endif
601  return t;
602 #else // not fast math
603  return (s32) ceilf ( x );
604 #endif
605  }
606 
607 
608 
610  {
611 #if defined(IRRLICHT_FAST_MATH)
612  s32 t;
613 
614 #if defined(_MSC_VER)
615  __asm
616  {
617  fld x
618  fistp t
619  }
620 #elif defined(__GNUC__)
621  __asm__ __volatile__ (
622  "fistpl %0 \n\t"
623  : "=m"(t)
624  : "t"(x)
625  : "st"
626  );
627 #else
628 # warn IRRLICHT_FAST_MATH not supported.
629  return (s32) round_(x);
630 #endif
631  return t;
632 #else // no fast math
633  return (s32) round_(x);
634 #endif
635  }
636 
637  inline f32 f32_max3(const f32 a, const f32 b, const f32 c)
638  {
639  return a > b ? (a > c ? a : c) : (b > c ? b : c);
640  }
641 
642  inline f32 f32_min3(const f32 a, const f32 b, const f32 c)
643  {
644  return a < b ? (a < c ? a : c) : (b < c ? b : c);
645  }
646 
647  inline f32 fract ( f32 x )
648  {
649  return x - floorf ( x );
650  }
651 
652 } // end namespace core
653 } // end namespace irr
654 
655 #ifndef IRRLICHT_FAST_MATH
656  using irr::core::IR;
657  using irr::core::FR;
658 #endif
659 
660 #endif
661 

The Irrlicht Engine
The Irrlicht Engine Documentation © 2003-2010 by Nikolaus Gebhardt. Generated on Fri Mar 21 2014 04:40:17 by Doxygen (1.8.1.2)