Line data Source code
1 : // Copyright (C) 2002-2012 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 : #ifndef FLT_MIN
35 : #define FLT_MIN 1.17549435e-38F
36 : #endif
37 :
38 : namespace irr
39 : {
40 : namespace core
41 : {
42 :
43 : //! Rounding error constant often used when comparing f32 values.
44 :
45 : const s32 ROUNDING_ERROR_S32 = 0;
46 : #ifdef __IRR_HAS_S64
47 : const s64 ROUNDING_ERROR_S64 = 0;
48 : #endif
49 : const f32 ROUNDING_ERROR_f32 = 0.000001f;
50 : const f64 ROUNDING_ERROR_f64 = 0.00000001;
51 :
52 : #ifdef PI // make sure we don't collide with a define
53 : #undef PI
54 : #endif
55 : //! Constant for PI.
56 : const f32 PI = 3.14159265359f;
57 :
58 : //! Constant for reciprocal of PI.
59 : const f32 RECIPROCAL_PI = 1.0f/PI;
60 :
61 : //! Constant for half of PI.
62 : const f32 HALF_PI = PI/2.0f;
63 :
64 : #ifdef PI64 // make sure we don't collide with a define
65 : #undef PI64
66 : #endif
67 : //! Constant for 64bit PI.
68 : const f64 PI64 = 3.1415926535897932384626433832795028841971693993751;
69 :
70 : //! Constant for 64bit reciprocal of PI.
71 : const f64 RECIPROCAL_PI64 = 1.0/PI64;
72 :
73 : //! 32bit Constant for converting from degrees to radians
74 : const f32 DEGTORAD = PI / 180.0f;
75 :
76 : //! 32bit constant for converting from radians to degrees (formally known as GRAD_PI)
77 : const f32 RADTODEG = 180.0f / PI;
78 :
79 : //! 64bit constant for converting from degrees to radians (formally known as GRAD_PI2)
80 : const f64 DEGTORAD64 = PI64 / 180.0;
81 :
82 : //! 64bit constant for converting from radians to degrees
83 : const f64 RADTODEG64 = 180.0 / PI64;
84 :
85 : //! Utility function to convert a radian value to degrees
86 : /** Provided as it can be clearer to write radToDeg(X) than RADTODEG * X
87 : \param radians The radians value to convert to degrees.
88 : */
89 : inline f32 radToDeg(f32 radians)
90 : {
91 : return RADTODEG * radians;
92 : }
93 :
94 : //! Utility function to convert a radian value to degrees
95 : /** Provided as it can be clearer to write radToDeg(X) than RADTODEG * X
96 : \param radians The radians value to convert to degrees.
97 : */
98 : inline f64 radToDeg(f64 radians)
99 : {
100 : return RADTODEG64 * radians;
101 : }
102 :
103 : //! Utility function to convert a degrees value to radians
104 : /** Provided as it can be clearer to write degToRad(X) than DEGTORAD * X
105 : \param degrees The degrees value to convert to radians.
106 : */
107 : inline f32 degToRad(f32 degrees)
108 : {
109 : return DEGTORAD * degrees;
110 : }
111 :
112 : //! Utility function to convert a degrees value to radians
113 : /** Provided as it can be clearer to write degToRad(X) than DEGTORAD * X
114 : \param degrees The degrees value to convert to radians.
115 : */
116 : inline f64 degToRad(f64 degrees)
117 : {
118 : return DEGTORAD64 * degrees;
119 : }
120 :
121 : //! returns minimum of two values. Own implementation to get rid of the STL (VS6 problems)
122 : template<class T>
123 27723084 : inline const T& min_(const T& a, const T& b)
124 : {
125 27723084 : return a < b ? a : b;
126 : }
127 :
128 : //! returns minimum of three values. Own implementation to get rid of the STL (VS6 problems)
129 : template<class T>
130 : inline const T& min_(const T& a, const T& b, const T& c)
131 : {
132 : return a < b ? min_(a, c) : min_(b, c);
133 : }
134 :
135 : //! returns maximum of two values. Own implementation to get rid of the STL (VS6 problems)
136 : template<class T>
137 27723338 : inline const T& max_(const T& a, const T& b)
138 : {
139 27723338 : return a < b ? b : a;
140 : }
141 :
142 : //! returns maximum of three values. Own implementation to get rid of the STL (VS6 problems)
143 : template<class T>
144 : inline const T& max_(const T& a, const T& b, const T& c)
145 : {
146 : return a < b ? max_(b, c) : max_(a, c);
147 : }
148 :
149 : //! returns abs of two values. Own implementation to get rid of STL (VS6 problems)
150 : template<class T>
151 : inline T abs_(const T& a)
152 : {
153 : return a < (T)0 ? -a : a;
154 : }
155 :
156 : //! returns linear interpolation of a and b with ratio t
157 : //! \return: a if t==0, b if t==1, and the linear interpolation else
158 : template<class T>
159 : inline T lerp(const T& a, const T& b, const f32 t)
160 : {
161 : return (T)(a*(1.f-t)) + (b*t);
162 : }
163 :
164 : //! clamps a value between low and high
165 : template <class T>
166 27723299 : inline const T clamp (const T& value, const T& low, const T& high)
167 : {
168 27723299 : return min_ (max_(value,low), high);
169 : }
170 :
171 : //! swaps the content of the passed parameters
172 : // Note: We use the same trick as boost and use two template arguments to
173 : // avoid ambiguity when swapping objects of an Irrlicht type that has not
174 : // it's own swap overload. Otherwise we get conflicts with some compilers
175 : // in combination with stl.
176 : template <class T1, class T2>
177 : inline void swap(T1& a, T2& b)
178 : {
179 : T1 c(a);
180 : a = b;
181 : b = c;
182 : }
183 :
184 : //! returns if a equals b, taking possible rounding errors into account
185 0 : inline bool equals(const f64 a, const f64 b, const f64 tolerance = ROUNDING_ERROR_f64)
186 : {
187 0 : return (a + tolerance >= b) && (a - tolerance <= b);
188 : }
189 :
190 : //! returns if a equals b, taking possible rounding errors into account
191 881622 : inline bool equals(const f32 a, const f32 b, const f32 tolerance = ROUNDING_ERROR_f32)
192 : {
193 881622 : return (a + tolerance >= b) && (a - tolerance <= b);
194 : }
195 :
196 : union FloatIntUnion32
197 : {
198 : FloatIntUnion32(float f1 = 0.0f) : f(f1) {}
199 : // Portable sign-extraction
200 : bool sign() const { return (i >> 31) != 0; }
201 :
202 : irr::s32 i;
203 : irr::f32 f;
204 : };
205 :
206 : //! We compare the difference in ULP's (spacing between floating-point numbers, aka ULP=1 means there exists no float between).
207 : //\result true when numbers have a ULP <= maxUlpDiff AND have the same sign.
208 : inline bool equalsByUlp(f32 a, f32 b, int maxUlpDiff)
209 : {
210 : // Based on the ideas and code from Bruce Dawson on
211 : // http://www.altdevblogaday.com/2012/02/22/comparing-floating-point-numbers-2012-edition/
212 : // When floats are interpreted as integers the two nearest possible float numbers differ just
213 : // by one integer number. Also works the other way round, an integer of 1 interpreted as float
214 : // is for example the smallest possible float number.
215 :
216 : FloatIntUnion32 fa(a);
217 : FloatIntUnion32 fb(b);
218 :
219 : // Different signs, we could maybe get difference to 0, but so close to 0 using epsilons is better.
220 : if ( fa.sign() != fb.sign() )
221 : {
222 : // Check for equality to make sure +0==-0
223 : if (fa.i == fb.i)
224 : return true;
225 : return false;
226 : }
227 :
228 : // Find the difference in ULPs.
229 : int ulpsDiff = abs_(fa.i- fb.i);
230 : if (ulpsDiff <= maxUlpDiff)
231 : return true;
232 :
233 : return false;
234 : }
235 :
236 : #if 0
237 : //! returns if a equals b, not using any rounding tolerance
238 : inline bool equals(const s32 a, const s32 b)
239 : {
240 : return (a == b);
241 : }
242 :
243 : //! returns if a equals b, not using any rounding tolerance
244 : inline bool equals(const u32 a, const u32 b)
245 : {
246 : return (a == b);
247 : }
248 : #endif
249 : //! returns if a equals b, taking an explicit rounding tolerance into account
250 125346872 : inline bool equals(const s32 a, const s32 b, const s32 tolerance = ROUNDING_ERROR_S32)
251 : {
252 125346872 : return (a + tolerance >= b) && (a - tolerance <= b);
253 : }
254 :
255 : //! returns if a equals b, taking an explicit rounding tolerance into account
256 4884 : inline bool equals(const u32 a, const u32 b, const s32 tolerance = ROUNDING_ERROR_S32)
257 : {
258 4884 : return (a + tolerance >= b) && (a - tolerance <= b);
259 : }
260 :
261 : #ifdef __IRR_HAS_S64
262 : //! returns if a equals b, taking an explicit rounding tolerance into account
263 : inline bool equals(const s64 a, const s64 b, const s64 tolerance = ROUNDING_ERROR_S64)
264 : {
265 : return (a + tolerance >= b) && (a - tolerance <= b);
266 : }
267 : #endif
268 :
269 : //! returns if a equals zero, taking rounding errors into account
270 : inline bool iszero(const f64 a, const f64 tolerance = ROUNDING_ERROR_f64)
271 : {
272 : return fabs(a) <= tolerance;
273 : }
274 :
275 : //! returns if a equals zero, taking rounding errors into account
276 1426243 : inline bool iszero(const f32 a, const f32 tolerance = ROUNDING_ERROR_f32)
277 : {
278 1426243 : return fabsf(a) <= tolerance;
279 : }
280 :
281 : //! returns if a equals not zero, taking rounding errors into account
282 : inline bool isnotzero(const f32 a, const f32 tolerance = ROUNDING_ERROR_f32)
283 : {
284 : return fabsf(a) > tolerance;
285 : }
286 :
287 : //! returns if a equals zero, taking rounding errors into account
288 : inline bool iszero(const s32 a, const s32 tolerance = 0)
289 : {
290 : return ( a & 0x7ffffff ) <= tolerance;
291 : }
292 :
293 : //! returns if a equals zero, taking rounding errors into account
294 : inline bool iszero(const u32 a, const u32 tolerance = 0)
295 : {
296 : return a <= tolerance;
297 : }
298 :
299 : #ifdef __IRR_HAS_S64
300 : //! returns if a equals zero, taking rounding errors into account
301 : inline bool iszero(const s64 a, const s64 tolerance = 0)
302 : {
303 : return abs_(a) <= tolerance;
304 : }
305 : #endif
306 :
307 : inline s32 s32_min(s32 a, s32 b)
308 : {
309 : const s32 mask = (a - b) >> 31;
310 : return (a & mask) | (b & ~mask);
311 : }
312 :
313 : inline s32 s32_max(s32 a, s32 b)
314 : {
315 : const s32 mask = (a - b) >> 31;
316 : return (b & mask) | (a & ~mask);
317 : }
318 :
319 : inline s32 s32_clamp (s32 value, s32 low, s32 high)
320 : {
321 : return s32_min(s32_max(value,low), high);
322 : }
323 :
324 : /*
325 : float IEEE-754 bit represenation
326 :
327 : 0 0x00000000
328 : 1.0 0x3f800000
329 : 0.5 0x3f000000
330 : 3 0x40400000
331 : +inf 0x7f800000
332 : -inf 0xff800000
333 : +NaN 0x7fc00000 or 0x7ff00000
334 : in general: number = (sign ? -1:1) * 2^(exponent) * 1.(mantissa bits)
335 : */
336 :
337 : typedef union { u32 u; s32 s; f32 f; } inttofloat;
338 :
339 : #define F32_AS_S32(f) (*((s32 *) &(f)))
340 : #define F32_AS_U32(f) (*((u32 *) &(f)))
341 : #define F32_AS_U32_POINTER(f) ( ((u32 *) &(f)))
342 :
343 : #define F32_VALUE_0 0x00000000
344 : #define F32_VALUE_1 0x3f800000
345 : #define F32_SIGN_BIT 0x80000000U
346 : #define F32_EXPON_MANTISSA 0x7FFFFFFFU
347 :
348 : //! code is taken from IceFPU
349 : //! Integer representation of a floating-point value.
350 : #ifdef IRRLICHT_FAST_MATH
351 : #define IR(x) ((u32&)(x))
352 : #else
353 : inline u32 IR(f32 x) {inttofloat tmp; tmp.f=x; return tmp.u;}
354 : #endif
355 :
356 : //! Absolute integer representation of a floating-point value
357 : #define AIR(x) (IR(x)&0x7fffffff)
358 :
359 : //! Floating-point representation of an integer value.
360 : #ifdef IRRLICHT_FAST_MATH
361 : #define FR(x) ((f32&)(x))
362 : #else
363 : inline f32 FR(u32 x) {inttofloat tmp; tmp.u=x; return tmp.f;}
364 : inline f32 FR(s32 x) {inttofloat tmp; tmp.s=x; return tmp.f;}
365 : #endif
366 :
367 : //! integer representation of 1.0
368 : #define IEEE_1_0 0x3f800000
369 : //! integer representation of 255.0
370 : #define IEEE_255_0 0x437f0000
371 :
372 : #ifdef IRRLICHT_FAST_MATH
373 : #define F32_LOWER_0(f) (F32_AS_U32(f) > F32_SIGN_BIT)
374 : #define F32_LOWER_EQUAL_0(f) (F32_AS_S32(f) <= F32_VALUE_0)
375 : #define F32_GREATER_0(f) (F32_AS_S32(f) > F32_VALUE_0)
376 : #define F32_GREATER_EQUAL_0(f) (F32_AS_U32(f) <= F32_SIGN_BIT)
377 : #define F32_EQUAL_1(f) (F32_AS_U32(f) == F32_VALUE_1)
378 : #define F32_EQUAL_0(f) ( (F32_AS_U32(f) & F32_EXPON_MANTISSA ) == F32_VALUE_0)
379 :
380 : // only same sign
381 : #define F32_A_GREATER_B(a,b) (F32_AS_S32((a)) > F32_AS_S32((b)))
382 :
383 : #else
384 :
385 : #define F32_LOWER_0(n) ((n) < 0.0f)
386 : #define F32_LOWER_EQUAL_0(n) ((n) <= 0.0f)
387 : #define F32_GREATER_0(n) ((n) > 0.0f)
388 : #define F32_GREATER_EQUAL_0(n) ((n) >= 0.0f)
389 : #define F32_EQUAL_1(n) ((n) == 1.0f)
390 : #define F32_EQUAL_0(n) ((n) == 0.0f)
391 : #define F32_A_GREATER_B(a,b) ((a) > (b))
392 : #endif
393 :
394 :
395 : #ifndef REALINLINE
396 : #ifdef _MSC_VER
397 : #define REALINLINE __forceinline
398 : #else
399 : #define REALINLINE inline
400 : #endif
401 : #endif
402 :
403 : #if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
404 :
405 : // 8-bit bools in borland builder
406 :
407 : //! conditional set based on mask and arithmetic shift
408 : REALINLINE u32 if_c_a_else_b ( const c8 condition, const u32 a, const u32 b )
409 : {
410 : return ( ( -condition >> 7 ) & ( a ^ b ) ) ^ b;
411 : }
412 :
413 : //! conditional set based on mask and arithmetic shift
414 : REALINLINE u32 if_c_a_else_0 ( const c8 condition, const u32 a )
415 : {
416 : return ( -condition >> 31 ) & a;
417 : }
418 : #else
419 :
420 : //! conditional set based on mask and arithmetic shift
421 : REALINLINE u32 if_c_a_else_b ( const s32 condition, const u32 a, const u32 b )
422 : {
423 : return ( ( -condition >> 31 ) & ( a ^ b ) ) ^ b;
424 : }
425 :
426 : //! conditional set based on mask and arithmetic shift
427 : REALINLINE u16 if_c_a_else_b ( const s16 condition, const u16 a, const u16 b )
428 : {
429 : return ( ( -condition >> 15 ) & ( a ^ b ) ) ^ b;
430 : }
431 :
432 : //! conditional set based on mask and arithmetic shift
433 : REALINLINE u32 if_c_a_else_0 ( const s32 condition, const u32 a )
434 : {
435 : return ( -condition >> 31 ) & a;
436 : }
437 : #endif
438 :
439 : /*
440 : if (condition) state |= m; else state &= ~m;
441 : */
442 : REALINLINE void setbit_cond ( u32 &state, s32 condition, u32 mask )
443 : {
444 : // 0, or any postive to mask
445 : //s32 conmask = -condition >> 31;
446 : state ^= ( ( -condition >> 31 ) ^ state ) & mask;
447 : }
448 :
449 83354372 : inline f32 round_( f32 x )
450 : {
451 83354372 : return floorf( x + 0.5f );
452 : }
453 :
454 : REALINLINE void clearFPUException ()
455 : {
456 : #ifdef IRRLICHT_FAST_MATH
457 : return;
458 : #ifdef feclearexcept
459 : feclearexcept(FE_ALL_EXCEPT);
460 : #elif defined(_MSC_VER)
461 : __asm fnclex;
462 : #elif defined(__GNUC__) && defined(__x86__)
463 : __asm__ __volatile__ ("fclex \n\t");
464 : #else
465 : # warn clearFPUException not supported.
466 : #endif
467 : #endif
468 : }
469 :
470 : // calculate: sqrt ( x )
471 3212705 : REALINLINE f32 squareroot(const f32 f)
472 : {
473 3212705 : return sqrtf(f);
474 : }
475 :
476 : // calculate: sqrt ( x )
477 : REALINLINE f64 squareroot(const f64 f)
478 : {
479 : return sqrt(f);
480 : }
481 :
482 : // calculate: sqrt ( x )
483 82897 : REALINLINE s32 squareroot(const s32 f)
484 : {
485 82897 : return static_cast<s32>(squareroot(static_cast<f32>(f)));
486 : }
487 :
488 : #ifdef __IRR_HAS_S64
489 : // calculate: sqrt ( x )
490 : REALINLINE s64 squareroot(const s64 f)
491 : {
492 : return static_cast<s64>(squareroot(static_cast<f64>(f)));
493 : }
494 : #endif
495 :
496 : // calculate: 1 / sqrt ( x )
497 8866291 : REALINLINE f64 reciprocal_squareroot(const f64 x)
498 : {
499 8866291 : return 1.0 / sqrt(x);
500 : }
501 :
502 : // calculate: 1 / sqrtf ( x )
503 0 : REALINLINE f32 reciprocal_squareroot(const f32 f)
504 : {
505 : #if defined ( IRRLICHT_FAST_MATH )
506 : #if defined(_MSC_VER)
507 : // SSE reciprocal square root estimate, accurate to 12 significant
508 : // bits of the mantissa
509 : f32 recsqrt;
510 : __asm rsqrtss xmm0, f // xmm0 = rsqrtss(f)
511 : __asm movss recsqrt, xmm0 // return xmm0
512 : return recsqrt;
513 :
514 : /*
515 : // comes from Nvidia
516 : u32 tmp = (u32(IEEE_1_0 << 1) + IEEE_1_0 - *(u32*)&x) >> 1;
517 : f32 y = *(f32*)&tmp;
518 : return y * (1.47f - 0.47f * x * y * y);
519 : */
520 : #else
521 : return 1.f / sqrtf(f);
522 : #endif
523 : #else // no fast math
524 0 : return 1.f / sqrtf(f);
525 : #endif
526 : }
527 :
528 : // calculate: 1 / sqrtf( x )
529 : REALINLINE s32 reciprocal_squareroot(const s32 x)
530 : {
531 : return static_cast<s32>(reciprocal_squareroot(static_cast<f32>(x)));
532 : }
533 :
534 : // calculate: 1 / x
535 1426243 : REALINLINE f32 reciprocal( const f32 f )
536 : {
537 : #if defined (IRRLICHT_FAST_MATH)
538 :
539 : // SSE Newton-Raphson reciprocal estimate, accurate to 23 significant
540 : // bi ts of the mantissa
541 : // One Newtown-Raphson Iteration:
542 : // f(i+1) = 2 * rcpss(f) - f * rcpss(f) * rcpss(f)
543 : f32 rec;
544 : __asm rcpss xmm0, f // xmm0 = rcpss(f)
545 : __asm movss xmm1, f // xmm1 = f
546 : __asm mulss xmm1, xmm0 // xmm1 = f * rcpss(f)
547 : __asm mulss xmm1, xmm0 // xmm2 = f * rcpss(f) * rcpss(f)
548 : __asm addss xmm0, xmm0 // xmm0 = 2 * rcpss(f)
549 : __asm subss xmm0, xmm1 // xmm0 = 2 * rcpss(f)
550 : // - f * rcpss(f) * rcpss(f)
551 : __asm movss rec, xmm0 // return xmm0
552 : return rec;
553 :
554 :
555 : //! i do not divide through 0.. (fpu expection)
556 : // instead set f to a high value to get a return value near zero..
557 : // -1000000000000.f.. is use minus to stay negative..
558 : // must test's here (plane.normal dot anything ) checks on <= 0.f
559 : //u32 x = (-(AIR(f) != 0 ) >> 31 ) & ( IR(f) ^ 0xd368d4a5 ) ^ 0xd368d4a5;
560 : //return 1.f / FR ( x );
561 :
562 : #else // no fast math
563 1426243 : return 1.f / f;
564 : #endif
565 : }
566 :
567 : // calculate: 1 / x
568 : REALINLINE f64 reciprocal ( const f64 f )
569 : {
570 : return 1.0 / f;
571 : }
572 :
573 :
574 : // calculate: 1 / x, low precision allowed
575 : REALINLINE f32 reciprocal_approxim ( const f32 f )
576 : {
577 : #if defined( IRRLICHT_FAST_MATH)
578 :
579 : // SSE Newton-Raphson reciprocal estimate, accurate to 23 significant
580 : // bi ts of the mantissa
581 : // One Newtown-Raphson Iteration:
582 : // f(i+1) = 2 * rcpss(f) - f * rcpss(f) * rcpss(f)
583 : f32 rec;
584 : __asm rcpss xmm0, f // xmm0 = rcpss(f)
585 : __asm movss xmm1, f // xmm1 = f
586 : __asm mulss xmm1, xmm0 // xmm1 = f * rcpss(f)
587 : __asm mulss xmm1, xmm0 // xmm2 = f * rcpss(f) * rcpss(f)
588 : __asm addss xmm0, xmm0 // xmm0 = 2 * rcpss(f)
589 : __asm subss xmm0, xmm1 // xmm0 = 2 * rcpss(f)
590 : // - f * rcpss(f) * rcpss(f)
591 : __asm movss rec, xmm0 // return xmm0
592 : return rec;
593 :
594 :
595 : /*
596 : // SSE reciprocal estimate, accurate to 12 significant bits of
597 : f32 rec;
598 : __asm rcpss xmm0, f // xmm0 = rcpss(f)
599 : __asm movss rec , xmm0 // return xmm0
600 : return rec;
601 : */
602 : /*
603 : register u32 x = 0x7F000000 - IR ( p );
604 : const f32 r = FR ( x );
605 : return r * (2.0f - p * r);
606 : */
607 : #else // no fast math
608 : return 1.f / f;
609 : #endif
610 : }
611 :
612 :
613 0 : REALINLINE s32 floor32(f32 x)
614 : {
615 : #ifdef IRRLICHT_FAST_MATH
616 : const f32 h = 0.5f;
617 :
618 : s32 t;
619 :
620 : #if defined(_MSC_VER)
621 : __asm
622 : {
623 : fld x
624 : fsub h
625 : fistp t
626 : }
627 : #elif defined(__GNUC__)
628 : __asm__ __volatile__ (
629 : "fsub %2 \n\t"
630 : "fistpl %0"
631 : : "=m" (t)
632 : : "t" (x), "f" (h)
633 : : "st"
634 : );
635 : #else
636 : # warn IRRLICHT_FAST_MATH not supported.
637 : return (s32) floorf ( x );
638 : #endif
639 : return t;
640 : #else // no fast math
641 0 : return (s32) floorf ( x );
642 : #endif
643 : }
644 :
645 :
646 : REALINLINE s32 ceil32 ( f32 x )
647 : {
648 : #ifdef IRRLICHT_FAST_MATH
649 : const f32 h = 0.5f;
650 :
651 : s32 t;
652 :
653 : #if defined(_MSC_VER)
654 : __asm
655 : {
656 : fld x
657 : fadd h
658 : fistp t
659 : }
660 : #elif defined(__GNUC__)
661 : __asm__ __volatile__ (
662 : "fadd %2 \n\t"
663 : "fistpl %0 \n\t"
664 : : "=m"(t)
665 : : "t"(x), "f"(h)
666 : : "st"
667 : );
668 : #else
669 : # warn IRRLICHT_FAST_MATH not supported.
670 : return (s32) ceilf ( x );
671 : #endif
672 : return t;
673 : #else // not fast math
674 : return (s32) ceilf ( x );
675 : #endif
676 : }
677 :
678 :
679 :
680 83354378 : REALINLINE s32 round32(f32 x)
681 : {
682 : #if defined(IRRLICHT_FAST_MATH)
683 : s32 t;
684 :
685 : #if defined(_MSC_VER)
686 : __asm
687 : {
688 : fld x
689 : fistp t
690 : }
691 : #elif defined(__GNUC__)
692 : __asm__ __volatile__ (
693 : "fistpl %0 \n\t"
694 : : "=m"(t)
695 : : "t"(x)
696 : : "st"
697 : );
698 : #else
699 : # warn IRRLICHT_FAST_MATH not supported.
700 : return (s32) round_(x);
701 : #endif
702 : return t;
703 : #else // no fast math
704 83354378 : return (s32) round_(x);
705 : #endif
706 : }
707 :
708 : inline f32 f32_max3(const f32 a, const f32 b, const f32 c)
709 : {
710 : return a > b ? (a > c ? a : c) : (b > c ? b : c);
711 : }
712 :
713 : inline f32 f32_min3(const f32 a, const f32 b, const f32 c)
714 : {
715 : return a < b ? (a < c ? a : c) : (b < c ? b : c);
716 : }
717 :
718 : inline f32 fract ( f32 x )
719 : {
720 : return x - floorf ( x );
721 : }
722 :
723 : } // end namespace core
724 : } // end namespace irr
725 :
726 : #ifndef IRRLICHT_FAST_MATH
727 : using irr::core::IR;
728 : using irr::core::FR;
729 : #endif
730 :
731 : #endif
732 :
|