Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/physics/src/bullet/LinearMath/btScalar.h @ 1963

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

Added Bullet physics engine.

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