1 // Copyright (C) 2002-2007 Nikolaus Gebhardt
2 // This file is part of the "Irrlicht Engine".
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
5 #ifndef __IRR_MATH_H_INCLUDED__
6 #define __IRR_MATH_H_INCLUDED__
8 #include "IrrCompileConfig.h"
12 #if defined(_IRR_SOLARIS_PLATFORM_) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
13 #define sqrtf(X) (f32)sqrt((f64)(X))
14 #define sinf(X) (f32)sin((f64)(X))
15 #define cosf(X) (f32)cos((f64)(X))
16 #define ceilf(X) (f32)ceil((f64)(X))
17 #define floorf(X) (f32)floor((f64)(X))
18 #define powf(X,Y) (f32)pow((f64)(X),(f64)(Y))
19 #define fmodf(X,Y) (f32)fmod((f64)(X),(f64)(Y))
20 #define fabsf(X) (f32)fabs((f64)(X))
28 //! Rounding error constant often used when comparing f32 values.
30 #ifdef IRRLICHT_FAST_MATH
31 const f32 ROUNDING_ERROR_32
= 0.00005f
;
32 const f64 ROUNDING_ERROR_64
= 0.000005f
;
34 const f32 ROUNDING_ERROR_32
= 0.000001f
;
35 const f64 ROUNDING_ERROR_64
= 0.00000001f
;
39 const f32 PI
= 3.14159265359f
;
41 //! Constant for reciprocal of PI.
42 const f32 RECIPROCAL_PI
= 1.0f
/PI
;
44 //! Constant for half of PI.
45 const f32 HALF_PI
= PI
/2.0f
;
47 //! Constant for 64bit PI.
48 const f64 PI64
= 3.1415926535897932384626433832795028841971693993751;
50 //! Constant for 64bit reciprocal of PI.
51 const f64 RECIPROCAL_PI64
= 1.0/PI64
;
53 //! 32bit Constant for converting from degrees to radians
54 const f32 DEGTORAD
= PI
/ 180.0f
;
56 //! 32bit constant for converting from radians to degrees (formally known as GRAD_PI)
57 const f32 RADTODEG
= 180.0f
/ PI
;
59 //! 64bit constant for converting from degrees to radians (formally known as GRAD_PI2)
60 const f64 DEGTORAD64
= PI64
/ 180.0;
62 //! 64bit constant for converting from radians to degrees
63 const f64 RADTODEG64
= 180.0 / PI64
;
65 //! returns minimum of two values. Own implementation to get rid of the STL (VS6 problems)
67 inline const T
& min_(const T
& a
, const T
& b
)
72 //! returns minimum of three values. Own implementation to get rid of the STL (VS6 problems)
74 inline const T
& min_(const T
& a
, const T
& b
, const T
& c
)
76 return a
< b
? min_(a
, c
) : min_(b
, c
);
79 //! returns maximum of two values. Own implementation to get rid of the STL (VS6 problems)
81 inline const T
& max_(const T
& a
, const T
& b
)
86 //! returns maximum of three values. Own implementation to get rid of the STL (VS6 problems)
88 inline const T
& max_(const T
& a
, const T
& b
, const T
& c
)
90 return a
< b
? max_(b
, c
) : max_(a
, c
);
93 //! returns abs of two values. Own implementation to get rid of STL (VS6 problems)
95 inline T
abs_(const T
& a
)
97 return a
< (T
)0 ? -a
: a
;
100 //! returns linear interpolation of a and b with ratio t
101 //! \return: a if t==0, b if t==1, and the linear interpolation else
103 inline T
lerp(const T
& a
, const T
& b
, const f32 t
)
105 return (a
*(1.f
-t
)) + (b
*t
);
108 //! clamps a value between low and high
110 inline const T
clamp (const T
& value
, const T
& low
, const T
& high
)
112 return min_ (max_(value
,low
), high
);
115 //! returns if a equals b, taking possible rounding errors into account
116 inline bool equals(const f32 a
, const f32 b
, const f32 tolerance
= ROUNDING_ERROR_32
)
118 return (a
+ tolerance
>= b
) && (a
- tolerance
<= b
);
121 //! returns if a equals b, taking possible rounding errors into account
122 inline bool equals(const s32 a
, const s32 b
, const s32 tolerance
= 0)
124 return (a
+ tolerance
>= b
) && (a
- tolerance
<= b
);
127 //! returns if a equals b, taking possible rounding errors into account
128 inline bool equals(const u32 a
, const u32 b
, const u32 tolerance
= 0)
130 return (a
+ tolerance
>= b
) && (a
- tolerance
<= b
);
133 //! returns if a equals zero, taking rounding errors into account
134 inline bool iszero(const f32 a
, const f32 tolerance
= ROUNDING_ERROR_32
)
136 return fabsf ( a
) <= tolerance
;
139 //! returns if a equals zero, taking rounding errors into account
140 inline bool iszero(const s32 a
, const s32 tolerance
= 0)
142 return ( a
& 0x7ffffff ) <= tolerance
;
145 //! returns if a equals zero, taking rounding errors into account
146 inline bool iszero(const u32 a
, const u32 tolerance
= 0)
148 return a
<= tolerance
;
151 inline s32
s32_min ( s32 a
, s32 b
)
153 s32 mask
= (a
- b
) >> 31;
154 return (a
& mask
) | (b
& ~mask
);
157 inline s32
s32_max ( s32 a
, s32 b
)
159 s32 mask
= (a
- b
) >> 31;
160 return (b
& mask
) | (a
& ~mask
);
163 inline s32
s32_clamp (s32 value
, s32 low
, s32 high
)
165 return s32_min (s32_max(value
,low
), high
);
170 float IEEE-754 bit represenation
178 +NaN 0x7fc00000 or 0x7ff00000
179 in general: number = (sign ? -1:1) * 2^(exponent) * 1.(mantissa bits)
182 #define F32_AS_S32(f) (*((s32 *) &(f)))
183 #define F32_AS_U32(f) (*((u32 *) &(f)))
184 #define F32_AS_U32_POINTER(f) ( ((u32 *) &(f)))
186 #define F32_VALUE_0 0x00000000
187 #define F32_VALUE_1 0x3f800000
188 #define F32_SIGN_BIT 0x80000000U
189 #define F32_EXPON_MANTISSA 0x7FFFFFFFU
191 //! code is taken from IceFPU
192 //! Integer representation of a floating-point value.
193 #define IR(x) ((u32&)(x))
195 //! Absolute integer representation of a floating-point value
196 #define AIR(x) (IR(x)&0x7fffffff)
198 //! Floating-point representation of an integer value.
199 #define FR(x) ((f32&)(x))
201 #define IEEE_1_0 0x3f800000 //!< integer representation of 1.0
202 #define IEEE_255_0 0x437f0000 //!< integer representation of 255.0
204 #ifdef IRRLICHT_FAST_MATH
205 #define F32_LOWER_0(f) (F32_AS_U32(f) > F32_SIGN_BIT)
206 #define F32_LOWER_EQUAL_0(f) (F32_AS_S32(f) <= F32_VALUE_0)
207 #define F32_GREATER_0(f) (F32_AS_S32(f) > F32_VALUE_0)
208 #define F32_GREATER_EQUAL_0(f) (F32_AS_U32(f) <= F32_SIGN_BIT)
209 #define F32_EQUAL_1(f) (F32_AS_U32(f) == F32_VALUE_1)
210 #define F32_EQUAL_0(f) ( (F32_AS_U32(f) & F32_EXPON_MANTISSA ) == F32_VALUE_0)
213 #define F32_A_GREATER_B(a,b) (F32_AS_S32((a)) > F32_AS_S32((b)))
215 #define F32_LOWER_0(n) ((n) < 0.0f)
216 #define F32_LOWER_EQUAL_0(n) ((n) <= 0.0f)
217 #define F32_GREATER_0(n) ((n) > 0.0f)
218 #define F32_GREATER_EQUAL_0(n) ((n) >= 0.0f)
219 #define F32_EQUAL_1(n) ((n) == 1.0f)
220 #define F32_EQUAL_0(n) ((n) == 0.0f)
221 #define F32_A_GREATER_B(a,b) ((a) > (b))
227 #define REALINLINE __forceinline
229 #define REALINLINE inline
234 //! conditional set based on mask and arithmetic shift
235 REALINLINE u32
if_c_a_else_b ( const s32 condition
, const u32 a
, const u32 b
)
237 return ( ( -condition
>> 31 ) & ( a
^ b
) ) ^ b
;
240 //! conditional set based on mask and arithmetic shift
241 REALINLINE u32
if_c_a_else_0 ( const s32 condition
, const u32 a
)
243 return ( -condition
>> 31 ) & a
;
247 if (condition) state |= m; else state &= ~m;
249 REALINLINE
void setbit ( u32
&state
, s32 condition
, u32 mask
)
251 // 0, or any postive to mask
252 //s32 conmask = -condition >> 31;
253 state
^= ( ( -condition
>> 31 ) ^ state
) & mask
;
258 inline f32
round_( f32 x
)
260 return floorf( x
+ 0.5f
);
263 REALINLINE
void clearFPUException ()
265 #ifdef IRRLICHT_FAST_MATH
267 feclearexcept(FE_ALL_EXCEPT
);
268 #elif defined(_MSC_VER)
270 #elif defined(__GNUC__) && defined(__x86__)
271 __asm__
__volatile__ ("fclex \n\t");
273 # warn clearFPUException not supported.
278 REALINLINE f32
reciprocal_squareroot(const f32 x
)
280 #ifdef IRRLICHT_FAST_MATH
283 u32 tmp
= (u32(IEEE_1_0
<< 1) + IEEE_1_0
- *(u32
*)&x
) >> 1;
285 return y
* (1.47f
- 0.47f
* x
* y
* y
);
286 #elif defined(_MSC_VER)
296 #else // no fast math
297 return 1.f
/ sqrtf ( x
);
303 REALINLINE f32
reciprocal ( const f32 f
)
305 #ifdef IRRLICHT_FAST_MATH
306 //! i do not divide through 0.. (fpu expection)
307 // instead set f to a high value to get a return value near zero..
308 // -1000000000000.f.. is use minus to stay negative..
309 // must test's here (plane.normal dot anything ) checks on <= 0.f
311 //u32 x = (-(AIR(f) != 0 ) >> 31 ) & ( IR(f) ^ 0xd368d4a5 ) ^ 0xd368d4a5;
312 //return 1.f / FR ( x );
313 #else // no fast math
319 REALINLINE f32
reciprocal_approxim ( const f32 p
)
321 #ifdef IRRLICHT_FAST_MATH
322 register u32 x
= 0x7F000000 - IR ( p
);
323 const f32 r
= FR ( x
);
324 return r
* (2.0f
- p
* r
);
325 #else // no fast math
331 REALINLINE s32
floor32(f32 x
)
333 #ifdef IRRLICHT_FAST_MATH
338 #if defined(_MSC_VER)
345 #elif defined(__GNUC__)
346 __asm__
__volatile__ (
354 # warn IRRLICHT_FAST_MATH not supported.
355 return (s32
) floorf ( x
);
358 #else // no fast math
359 return (s32
) floorf ( x
);
364 REALINLINE s32
ceil32 ( f32 x
)
366 #ifdef IRRLICHT_FAST_MATH
371 #if defined(_MSC_VER)
378 #elif defined(__GNUC__)
379 __asm__
__volatile__ (
387 # warn IRRLICHT_FAST_MATH not supported.
388 return (s32
) ceilf ( x
);
391 #else // not fast math
392 return (s32
) ceilf ( x
);
398 REALINLINE s32
round32(f32 x
)
400 #if defined(IRRLICHT_FAST_MATH)
403 #if defined(_MSC_VER)
409 #elif defined(__GNUC__)
410 __asm__
__volatile__ (
417 # warn IRRLICHT_FAST_MATH not supported.
418 return (s32
) round_(x
);
421 #else // no fast math
422 return (s32
) round_(x
);
426 inline f32
f32_max3(const f32 a
, const f32 b
, const f32 c
)
428 return a
> b
? (a
> c
? a
: c
) : (b
> c
? b
: c
);
431 inline f32
f32_min3(const f32 a
, const f32 b
, const f32 c
)
433 return a
< b
? (a
< c
? a
: c
) : (b
< c
? b
: c
);
436 inline f32
fract ( f32 x
)
438 return x
- floorf ( x
);
441 } // end namespace core
442 } // end namespace irr