Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/bullet/LinearMath/btScalar.h @ 2776

Last change on this file since 2776 was 2662, checked in by rgrieder, 16 years ago

Merged presentation branch back to trunk.

  • Property svn:eol-style set to native
File size: 13.4 KB
RevLine 
[1963]1/*
2Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  http://continuousphysics.com/Bullet/
3
4This software is provided 'as-is', without any express or implied warranty.
5In no event will the authors be held liable for any damages arising from the use of this software.
[2472]6Permission is granted to anyone to use this software for any purpose,
7including commercial applications, and to alter it and redistribute it freely,
[1963]8subject to the following restrictions:
9
101. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
112. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
123. This notice may not be removed or altered from any source distribution.
13*/
14
15
16
17#ifndef SIMD___SCALAR_H
18#define SIMD___SCALAR_H
19
20#include <math.h>
[2430]21
[1963]22#include <stdlib.h>//size_t for MSVC 6.0
23
24#include <cstdlib>
25#include <cfloat>
26#include <float.h>
27
[2430]28#define BT_BULLET_VERSION 273
[1963]29
30inline int      btGetVersion()
31{
32        return BT_BULLET_VERSION;
33}
34
35#if defined(DEBUG) || defined (_DEBUG)
36#define BT_DEBUG
37#endif
38
39
40#ifdef WIN32
41
42                #if defined(__MINGW32__) || defined(__CYGWIN__) || (defined (_MSC_VER) && _MSC_VER < 1300)
43
44                        #define SIMD_FORCE_INLINE inline
45                        #define ATTRIBUTE_ALIGNED16(a) a
46                        #define ATTRIBUTE_ALIGNED128(a) a
47                #else
48                        #define BT_HAS_ALIGNED_ALLOCATOR
49                        #pragma warning(disable : 4324) // disable padding warning
50//                      #pragma warning(disable:4530) // Disable the exception disable but used in MSCV Stl warning.
51//                      #pragma warning(disable:4996) //Turn off warnings about deprecated C routines
52//                      #pragma warning(disable:4786) // Disable the "debug name too long" warning
53
54                        #define SIMD_FORCE_INLINE __forceinline
55                        #define ATTRIBUTE_ALIGNED16(a) __declspec(align(16)) a
56                        #define ATTRIBUTE_ALIGNED128(a) __declspec (align(128)) a
57                #ifdef _XBOX
58                        #define BT_USE_VMX128
59
60                        #include <ppcintrinsics.h>
61                        #define BT_HAVE_NATIVE_FSEL
62                        #define btFsel(a,b,c) __fsel((a),(b),(c))
63                #else
64                        #define BT_USE_SSE
65                #endif
66                #endif //__MINGW32__
67
68                #include <assert.h>
[2430]69#ifdef BT_DEBUG
[1963]70                #define btAssert assert
71#else
72                #define btAssert(x)
73#endif
74                //btFullAssert is optional, slows down a lot
75                #define btFullAssert(x)
76
77                #define btLikely(_c)  _c
78                #define btUnlikely(_c) _c
79
80#else
[2472]81       
[1963]82#if defined     (__CELLOS_LV2__)
83                #define SIMD_FORCE_INLINE inline
84                #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
85                #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
86                #ifndef assert
87                #include <assert.h>
88                #endif
[2430]89#ifdef BT_DEBUG
[1963]90                #define btAssert assert
[2430]91#else
92                #define btAssert(x)
93#endif
[1963]94                //btFullAssert is optional, slows down a lot
95                #define btFullAssert(x)
96
97                #define btLikely(_c)  _c
98                #define btUnlikely(_c) _c
99
100#else
101
102#ifdef USE_LIBSPE2
103
104                #define SIMD_FORCE_INLINE __inline
105                #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
106                #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
107                #ifndef assert
108                #include <assert.h>
109                #endif
[2430]110#ifdef BT_DEBUG
[1963]111                #define btAssert assert
[2430]112#else
113                #define btAssert(x)
114#endif
[1963]115                //btFullAssert is optional, slows down a lot
116                #define btFullAssert(x)
117
118
119                #define btLikely(_c)   __builtin_expect((_c), 1)
120                #define btUnlikely(_c) __builtin_expect((_c), 0)
[2472]121               
[1963]122
123#else
124        //non-windows systems
125
126                #define SIMD_FORCE_INLINE inline
127                #define ATTRIBUTE_ALIGNED16(a) a
128                #define ATTRIBUTE_ALIGNED128(a) a
129                #ifndef assert
130                #include <assert.h>
131                #endif
132
133#if defined(DEBUG) || defined (_DEBUG)
134                #define btAssert assert
135#else
136                #define btAssert(x)
137#endif
138
139                //btFullAssert is optional, slows down a lot
140                #define btFullAssert(x)
141                #define btLikely(_c)  _c
142                #define btUnlikely(_c) _c
143
144
145#endif // LIBSPE2
146
147#endif  //__CELLOS_LV2__
148#endif
149
150/// older compilers (gcc 3.x) and Sun needs double version of sqrt etc.
151/// exclude Apple Intel (i's assumed to be a Macbook or new Intel Dual Core Processor)
152#if defined (__sun) || defined (__sun__) || defined (__sparc) || (defined (__APPLE__) && ! defined (__i386__))
153//use slow double float precision operation on those platforms
154#ifndef BT_USE_DOUBLE_PRECISION
155#define BT_FORCE_DOUBLE_FUNCTIONS
156#endif
157#endif
158
159///The btScalar type abstracts floating point numbers, to easily switch between double and single floating point precision.
160#if defined(BT_USE_DOUBLE_PRECISION)
161typedef double btScalar;
162#else
163typedef float btScalar;
164#endif
165
166
167
168#define BT_DECLARE_ALIGNED_ALLOCATOR() \
169   SIMD_FORCE_INLINE void* operator new(size_t sizeInBytes)   { return btAlignedAlloc(sizeInBytes,16); }   \
170   SIMD_FORCE_INLINE void  operator delete(void* ptr)         { btAlignedFree(ptr); }   \
171   SIMD_FORCE_INLINE void* operator new(size_t, void* ptr)   { return ptr; }   \
172   SIMD_FORCE_INLINE void  operator delete(void*, void*)      { }   \
173   SIMD_FORCE_INLINE void* operator new[](size_t sizeInBytes)   { return btAlignedAlloc(sizeInBytes,16); }   \
174   SIMD_FORCE_INLINE void  operator delete[](void* ptr)         { btAlignedFree(ptr); }   \
175   SIMD_FORCE_INLINE void* operator new[](size_t, void* ptr)   { return ptr; }   \
176   SIMD_FORCE_INLINE void  operator delete[](void*, void*)      { }   \
177
178
179
180#if defined(BT_USE_DOUBLE_PRECISION) || defined(BT_FORCE_DOUBLE_FUNCTIONS)
[2472]181               
[1963]182SIMD_FORCE_INLINE btScalar btSqrt(btScalar x) { return sqrt(x); }
183SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabs(x); }
184SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cos(x); }
185SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sin(x); }
186SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tan(x); }
187SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { return acos(x); }
188SIMD_FORCE_INLINE btScalar btAsin(btScalar x) { return asin(x); }
189SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atan(x); }
190SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2(x, y); }
191SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return exp(x); }
192SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return log(x); }
193SIMD_FORCE_INLINE btScalar btPow(btScalar x,btScalar y) { return pow(x,y); }
194
195#else
[2472]196               
197SIMD_FORCE_INLINE btScalar btSqrt(btScalar y) 
198{ 
[1963]199#ifdef USE_APPROXIMATION
200    double x, z, tempf;
201    unsigned long *tfptr = ((unsigned long *)&tempf) + 1;
202
203        tempf = y;
204        *tfptr = (0xbfcdd90a - *tfptr)>>1; /* estimate of 1/sqrt(y) */
205        x =  tempf;
206        z =  y*btScalar(0.5);                        /* hoist out the “/2”    */
207        x = (btScalar(1.5)*x)-(x*x)*(x*z);         /* iteration formula     */
208        x = (btScalar(1.5)*x)-(x*x)*(x*z);
209        x = (btScalar(1.5)*x)-(x*x)*(x*z);
210        x = (btScalar(1.5)*x)-(x*x)*(x*z);
211        x = (btScalar(1.5)*x)-(x*x)*(x*z);
212        return x*y;
213#else
[2472]214        return sqrtf(y); 
[1963]215#endif
216}
217SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabsf(x); }
218SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cosf(x); }
219SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sinf(x); }
220SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tanf(x); }
[2472]221SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { 
[1963]222        btAssert(x <= btScalar(1.));
[2472]223        return acosf(x); 
[1963]224}
225SIMD_FORCE_INLINE btScalar btAsin(btScalar x) { return asinf(x); }
226SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atanf(x); }
227SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2f(x, y); }
228SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return expf(x); }
229SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return logf(x); }
[2471]230  #if defined( __MINGW32__ )
231  SIMD_FORCE_INLINE btScalar btPow(btScalar x,btScalar y) { return pow(x,y); }
232  #else
233  SIMD_FORCE_INLINE btScalar btPow(btScalar x,btScalar y) { return powf(x,y); }
234  #endif
235
[1963]236#endif
237
238#define SIMD_2_PI         btScalar(6.283185307179586232)
239#define SIMD_PI           (SIMD_2_PI * btScalar(0.5))
240#define SIMD_HALF_PI      (SIMD_2_PI * btScalar(0.25))
241#define SIMD_RADS_PER_DEG (SIMD_2_PI / btScalar(360.0))
242#define SIMD_DEGS_PER_RAD  (btScalar(360.0) / SIMD_2_PI)
243
244#ifdef BT_USE_DOUBLE_PRECISION
245#define SIMD_EPSILON      DBL_EPSILON
246#define SIMD_INFINITY     DBL_MAX
247#else
248#define SIMD_EPSILON      FLT_EPSILON
249#define SIMD_INFINITY     FLT_MAX
250#endif
251
[2472]252SIMD_FORCE_INLINE btScalar btAtan2Fast(btScalar y, btScalar x) 
[1963]253{
254        btScalar coeff_1 = SIMD_PI / 4.0f;
255        btScalar coeff_2 = 3.0f * coeff_1;
256        btScalar abs_y = btFabs(y);
257        btScalar angle;
258        if (x >= 0.0f) {
259                btScalar r = (x - abs_y) / (x + abs_y);
260                angle = coeff_1 - coeff_1 * r;
261        } else {
262                btScalar r = (x + abs_y) / (abs_y - x);
263                angle = coeff_2 - coeff_1 * r;
264        }
265        return (y < 0.0f) ? -angle : angle;
266}
267
268SIMD_FORCE_INLINE bool      btFuzzyZero(btScalar x) { return btFabs(x) < SIMD_EPSILON; }
269
270SIMD_FORCE_INLINE bool  btEqual(btScalar a, btScalar eps) {
271        return (((a) <= eps) && !((a) < -eps));
272}
273SIMD_FORCE_INLINE bool  btGreaterEqual (btScalar a, btScalar eps) {
274        return (!((a) <= eps));
275}
276
277
278SIMD_FORCE_INLINE int       btIsNegative(btScalar x) {
279    return x < btScalar(0.0) ? 1 : 0;
280}
281
282SIMD_FORCE_INLINE btScalar btRadians(btScalar x) { return x * SIMD_RADS_PER_DEG; }
283SIMD_FORCE_INLINE btScalar btDegrees(btScalar x) { return x * SIMD_DEGS_PER_RAD; }
284
285#define BT_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
286
287#ifndef btFsel
288SIMD_FORCE_INLINE btScalar btFsel(btScalar a, btScalar b, btScalar c)
289{
290        return a >= 0 ? b : c;
291}
292#endif
293#define btFsels(a,b,c) (btScalar)btFsel(a,b,c)
294
295
296SIMD_FORCE_INLINE bool btMachineIsLittleEndian()
297{
298   long int i = 1;
299   const char *p = (const char *) &i;
300   if (p[0] == 1)  // Lowest address contains the least significant byte
301           return true;
302   else
303           return false;
304}
305
306
307
308///btSelect avoids branches, which makes performance much better for consoles like Playstation 3 and XBox 360
309///Thanks Phil Knight. See also http://www.cellperformance.com/articles/2006/04/more_techniques_for_eliminatin_1.html
[2472]310SIMD_FORCE_INLINE unsigned btSelect(unsigned condition, unsigned valueIfConditionNonZero, unsigned valueIfConditionZero) 
[1963]311{
312    // Set testNz to 0xFFFFFFFF if condition is nonzero, 0x00000000 if condition is zero
313    // Rely on positive value or'ed with its negative having sign bit on
[2472]314    // and zero value or'ed with its negative (which is still zero) having sign bit off
[1963]315    // Use arithmetic shift right, shifting the sign bit through all 32 bits
316    unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31);
317    unsigned testEqz = ~testNz;
[2472]318    return ((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz)); 
[1963]319}
320SIMD_FORCE_INLINE int btSelect(unsigned condition, int valueIfConditionNonZero, int valueIfConditionZero)
321{
322    unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31);
[2472]323    unsigned testEqz = ~testNz; 
[1963]324    return static_cast<int>((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz));
325}
326SIMD_FORCE_INLINE float btSelect(unsigned condition, float valueIfConditionNonZero, float valueIfConditionZero)
327{
328#ifdef BT_HAVE_NATIVE_FSEL
329    return (float)btFsel((btScalar)condition - btScalar(1.0f), valueIfConditionNonZero, valueIfConditionZero);
330#else
[2472]331    return (condition != 0) ? valueIfConditionNonZero : valueIfConditionZero; 
[1963]332#endif
333}
334
335template<typename T> SIMD_FORCE_INLINE void btSwap(T& a, T& b)
336{
337        T tmp = a;
338        a = b;
339        b = tmp;
340}
341
342
343//PCK: endian swapping functions
344SIMD_FORCE_INLINE unsigned btSwapEndian(unsigned val)
345{
346        return (((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8)  | ((val & 0x000000ff) << 24));
347}
348
349SIMD_FORCE_INLINE unsigned short btSwapEndian(unsigned short val)
350{
351        return static_cast<unsigned short>(((val & 0xff00) >> 8) | ((val & 0x00ff) << 8));
352}
353
354SIMD_FORCE_INLINE unsigned btSwapEndian(int val)
355{
356        return btSwapEndian((unsigned)val);
357}
358
359SIMD_FORCE_INLINE unsigned short btSwapEndian(short val)
360{
361        return btSwapEndian((unsigned short) val);
362}
363
364///btSwapFloat uses using char pointers to swap the endianness
365////btSwapFloat/btSwapDouble will NOT return a float, because the machine might 'correct' invalid floating point values
[2472]366///Not all values of sign/exponent/mantissa are valid floating point numbers according to IEEE 754.
367///When a floating point unit is faced with an invalid value, it may actually change the value, or worse, throw an exception.
368///In most systems, running user mode code, you wouldn't get an exception, but instead the hardware/os/runtime will 'fix' the number for you.
[1963]369///so instead of returning a float/double, we return integer/long long integer
370SIMD_FORCE_INLINE unsigned int  btSwapEndianFloat(float d)
371{
372    unsigned int a = 0;
373    unsigned char *dst = (unsigned char *)&a;
374    unsigned char *src = (unsigned char *)&d;
375
376    dst[0] = src[3];
377    dst[1] = src[2];
378    dst[2] = src[1];
379    dst[3] = src[0];
380    return a;
381}
382
383// unswap using char pointers
[2472]384SIMD_FORCE_INLINE float btUnswapEndianFloat(unsigned int a) 
[1963]385{
386    float d = 0.0f;
387    unsigned char *src = (unsigned char *)&a;
388    unsigned char *dst = (unsigned char *)&d;
389
390    dst[0] = src[3];
391    dst[1] = src[2];
392    dst[2] = src[1];
393    dst[3] = src[0];
394
395    return d;
396}
397
398
399// swap using char pointers
400SIMD_FORCE_INLINE void  btSwapEndianDouble(double d, unsigned char* dst)
401{
402    unsigned char *src = (unsigned char *)&d;
403
404    dst[0] = src[7];
405    dst[1] = src[6];
406    dst[2] = src[5];
407    dst[3] = src[4];
408    dst[4] = src[3];
409    dst[5] = src[2];
410    dst[6] = src[1];
411    dst[7] = src[0];
412
413}
414
415// unswap using char pointers
[2472]416SIMD_FORCE_INLINE double btUnswapEndianDouble(const unsigned char *src) 
[1963]417{
418    double d = 0.0;
419    unsigned char *dst = (unsigned char *)&d;
420
421    dst[0] = src[7];
422    dst[1] = src[6];
423    dst[2] = src[5];
424    dst[3] = src[4];
425    dst[4] = src[3];
426    dst[5] = src[2];
427    dst[6] = src[1];
428    dst[7] = src[0];
429
430        return d;
431}
432
433
434#endif //SIMD___SCALAR_H
Note: See TracBrowser for help on using the repository browser.