Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/ode/ode-0.9/OPCODE/Ice/IceFPU.h @ 216

Last change on this file since 216 was 216, checked in by mathiask, 16 years ago

[Physik] add ode-0.9

File size: 9.2 KB
Line 
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 *      Contains FPU related code.
4 *      \file           IceFPU.h
5 *      \author         Pierre Terdiman
6 *      \date           April, 4, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11// Include Guard
12#ifndef __ICEFPU_H__
13#define __ICEFPU_H__
14
15        #define SIGN_BITMASK                    0x80000000
16
17        //! Integer representation of a floating-point value.
18        #define IR(x)                                   ((udword&)(x))
19
20        //! Signed integer representation of a floating-point value.
21        #define SIR(x)                                  ((sdword&)(x))
22
23        //! Absolute integer representation of a floating-point value
24        #define AIR(x)                                  (IR(x)&0x7fffffff)
25
26        //! Floating-point representation of an integer value.
27        #define FR(x)                                   ((float&)(x))
28
29        //! Integer-based comparison of a floating point value.
30        //! Don't use it blindly, it can be faster or slower than the FPU comparison, depends on the context.
31        #define IS_NEGATIVE_FLOAT(x)    (IR(x)&0x80000000)
32
33        //! Fast fabs for floating-point values. It just clears the sign bit.
34        //! Don't use it blindy, it can be faster or slower than the FPU comparison, depends on the context.
35        inline_ float FastFabs(float x)
36        {
37                udword FloatBits = IR(x)&0x7fffffff;
38                return FR(FloatBits);
39        }
40
41        //! Fast square root for floating-point values.
42        inline_ float FastSqrt(float square)
43        {
44#ifdef _MSC_VER
45                        float retval;
46
47                        __asm {
48                                        mov             eax, square
49                                        sub             eax, 0x3F800000
50                                        sar             eax, 1
51                                        add             eax, 0x3F800000
52                                        mov             [retval], eax
53                        }
54                        return retval;
55#else
56                        return sqrt(square);
57#endif
58        }
59
60        //! Saturates positive to zero.
61        inline_ float fsat(float f)
62        {
63                udword y = (udword&)f & ~((sdword&)f >>31);
64                return (float&)y;
65        }
66
67        //! Computes 1.0f / sqrtf(x).
68        inline_ float frsqrt(float f)
69        {
70                float x = f * 0.5f;
71                udword y = 0x5f3759df - ((udword&)f >> 1);
72                // Iteration...
73                (float&)= (float&)y * ( 1.5f - ( x * (float&)y * (float&)y ) );
74                // Result
75                return (float&)y;
76        }
77
78        //! Computes 1.0f / sqrtf(x). Comes from NVIDIA.
79        inline_ float InvSqrt(const float& x)
80        {
81                udword tmp = (udword(IEEE_1_0 << 1) + IEEE_1_0 - *(udword*)&x) >> 1;   
82                float y = *(float*)&tmp;                                             
83                return y * (1.47f - 0.47f * x * y * y);
84        }
85
86        //! Computes 1.0f / sqrtf(x). Comes from Quake3. Looks like the first one I had above.
87        //! See http://www.magic-software.com/3DGEDInvSqrt.html
88        inline_ float RSqrt(float number)
89        {
90                long i;
91                float x2, y;
92                const float threehalfs = 1.5f;
93
94                x2 = number * 0.5f;
95                y  = number;
96                i  = * (long *) &y;
97                i  = 0x5f3759df - (i >> 1);
98                y  = * (float *) &i;
99                y  = y * (threehalfs - (x2 * y * y));
100
101                return y;
102        }
103
104        //! TO BE DOCUMENTED
105        inline_ float fsqrt(float f)
106        {
107                udword y = ( ( (sdword&)f - 0x3f800000 ) >> 1 ) + 0x3f800000;
108                // Iteration...?
109                // (float&)y = (3.0f - ((float&)y * (float&)y) / f) * (float&)y * 0.5f;
110                // Result
111                return (float&)y;
112        }
113
114        //! Returns the float ranged espilon value.
115        inline_ float fepsilon(float f)
116        {
117                udword b = (udword&)f & 0xff800000;
118                udword a = b | 0x00000001;
119                (float&)a -= (float&)b;
120                // Result
121                return (float&)a;
122        }
123
124        //! Is the float valid ?
125        inline_ bool IsNAN(float value)                         { return (IR(value)&0x7f800000) == 0x7f800000;  }
126        inline_ bool IsIndeterminate(float value)       { return IR(value) == 0xffc00000;                               }
127        inline_ bool IsPlusInf(float value)                     { return IR(value) == 0x7f800000;                               }
128        inline_ bool IsMinusInf(float value)            { return IR(value) == 0xff800000;                               }
129
130        inline_ bool IsValidFloat(float value)
131        {
132                if(IsNAN(value))                        return false;
133                if(IsIndeterminate(value))      return false;
134                if(IsPlusInf(value))            return false;
135                if(IsMinusInf(value))           return false;
136                return true;
137        }
138
139        #define CHECK_VALID_FLOAT(x)    ASSERT(IsValidFloat(x));
140
141/*
142        //! FPU precision setting function.
143        inline_ void SetFPU()
144        {
145                // This function evaluates whether the floating-point
146                // control word is set to single precision/round to nearest/
147                // exceptions disabled. If these conditions don't hold, the
148                // function changes the control word to set them and returns
149                // TRUE, putting the old control word value in the passback
150                // location pointed to by pwOldCW.
151                {
152                        uword wTemp, wSave;
153 
154                        __asm fstcw wSave
155                        if (wSave & 0x300 ||            // Not single mode
156                                0x3f != (wSave & 0x3f) ||   // Exceptions enabled
157                                wSave & 0xC00)              // Not round to nearest mode
158                        {
159                                __asm
160                                {
161                                        mov ax, wSave
162                                        and ax, not 300h    ;; single mode
163                                        or  ax, 3fh         ;; disable all exceptions
164                                        and ax, not 0xC00   ;; round to nearest mode
165                                        mov wTemp, ax
166                                        fldcw   wTemp
167                                }
168                        }
169                }
170        }
171*/
172        //! This function computes the slowest possible floating-point value (you can also directly use FLT_EPSILON)
173        inline_ float ComputeFloatEpsilon()
174        {
175                float f = 1.0f;
176                ((udword&)f)^=1;
177                return f - 1.0f;        // You can check it's the same as FLT_EPSILON
178        }
179
180        inline_ bool IsFloatZero(float x, float epsilon=1e-6f)
181        {
182                return x*x < epsilon;
183        }
184
185        #define FCOMI_ST0       _asm    _emit   0xdb    _asm    _emit   0xf0
186        #define FCOMIP_ST0      _asm    _emit   0xdf    _asm    _emit   0xf0
187        #define FCMOVB_ST0      _asm    _emit   0xda    _asm    _emit   0xc0
188        #define FCMOVNB_ST0     _asm    _emit   0xdb    _asm    _emit   0xc0
189
190        #define FCOMI_ST1       _asm    _emit   0xdb    _asm    _emit   0xf1
191        #define FCOMIP_ST1      _asm    _emit   0xdf    _asm    _emit   0xf1
192        #define FCMOVB_ST1      _asm    _emit   0xda    _asm    _emit   0xc1
193        #define FCMOVNB_ST1     _asm    _emit   0xdb    _asm    _emit   0xc1
194
195        #define FCOMI_ST2       _asm    _emit   0xdb    _asm    _emit   0xf2
196        #define FCOMIP_ST2      _asm    _emit   0xdf    _asm    _emit   0xf2
197        #define FCMOVB_ST2      _asm    _emit   0xda    _asm    _emit   0xc2
198        #define FCMOVNB_ST2     _asm    _emit   0xdb    _asm    _emit   0xc2
199
200        #define FCOMI_ST3       _asm    _emit   0xdb    _asm    _emit   0xf3
201        #define FCOMIP_ST3      _asm    _emit   0xdf    _asm    _emit   0xf3
202        #define FCMOVB_ST3      _asm    _emit   0xda    _asm    _emit   0xc3
203        #define FCMOVNB_ST3     _asm    _emit   0xdb    _asm    _emit   0xc3
204
205        #define FCOMI_ST4       _asm    _emit   0xdb    _asm    _emit   0xf4
206        #define FCOMIP_ST4      _asm    _emit   0xdf    _asm    _emit   0xf4
207        #define FCMOVB_ST4      _asm    _emit   0xda    _asm    _emit   0xc4
208        #define FCMOVNB_ST4     _asm    _emit   0xdb    _asm    _emit   0xc4
209
210        #define FCOMI_ST5       _asm    _emit   0xdb    _asm    _emit   0xf5
211        #define FCOMIP_ST5      _asm    _emit   0xdf    _asm    _emit   0xf5
212        #define FCMOVB_ST5      _asm    _emit   0xda    _asm    _emit   0xc5
213        #define FCMOVNB_ST5     _asm    _emit   0xdb    _asm    _emit   0xc5
214
215        #define FCOMI_ST6       _asm    _emit   0xdb    _asm    _emit   0xf6
216        #define FCOMIP_ST6      _asm    _emit   0xdf    _asm    _emit   0xf6
217        #define FCMOVB_ST6      _asm    _emit   0xda    _asm    _emit   0xc6
218        #define FCMOVNB_ST6     _asm    _emit   0xdb    _asm    _emit   0xc6
219
220        #define FCOMI_ST7       _asm    _emit   0xdb    _asm    _emit   0xf7
221        #define FCOMIP_ST7      _asm    _emit   0xdf    _asm    _emit   0xf7
222        #define FCMOVB_ST7      _asm    _emit   0xda    _asm    _emit   0xc7
223        #define FCMOVNB_ST7     _asm    _emit   0xdb    _asm    _emit   0xc7
224
225        //! A global function to find MAX(a,b) using FCOMI/FCMOV
226        inline_ float FCMax2(float a, float b)
227        {
228#ifdef _MSC_VER
229                float Res;
230                _asm    fld             [a]
231                _asm    fld             [b]
232                FCOMI_ST1
233                FCMOVB_ST1
234                _asm    fstp    [Res]
235                _asm    fcomp
236                return Res;
237#else
238                return (a > b) ? a : b;
239#endif
240        }
241
242        //! A global function to find MIN(a,b) using FCOMI/FCMOV
243        inline_ float FCMin2(float a, float b)
244        {
245#ifdef _MSC_VER
246                float Res;
247                _asm    fld             [a]
248                _asm    fld             [b]
249                FCOMI_ST1
250                FCMOVNB_ST1
251                _asm    fstp    [Res]
252                _asm    fcomp
253                return Res;
254#else
255                return (a < b) ? a : b;
256#endif
257        }
258
259        //! A global function to find MAX(a,b,c) using FCOMI/FCMOV
260        inline_ float FCMax3(float a, float b, float c)
261        {
262#ifdef _MSC_VER
263                float Res;
264                _asm    fld             [a]
265                _asm    fld             [b]
266                _asm    fld             [c]
267                FCOMI_ST1
268                FCMOVB_ST1
269                FCOMI_ST2
270                FCMOVB_ST2
271                _asm    fstp    [Res]
272                _asm    fcompp
273                return Res;
274#else
275                return (a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c);
276#endif
277        }
278
279        //! A global function to find MIN(a,b,c) using FCOMI/FCMOV
280        inline_ float FCMin3(float a, float b, float c)
281        {
282#ifdef _MSC_VER
283                float Res;
284                _asm    fld             [a]
285                _asm    fld             [b]
286                _asm    fld             [c]
287                FCOMI_ST1
288                FCMOVNB_ST1
289                FCOMI_ST2
290                FCMOVNB_ST2
291                _asm    fstp    [Res]
292                _asm    fcompp
293                return Res;
294#else
295                return (a < b) ? ((a < c) ? a : c) : ((b < c) ? b : c);
296#endif
297        }
298
299        inline_ int ConvertToSortable(float f)
300        {
301                int& Fi = (int&)f;
302                int Fmask = (Fi>>31);
303                Fi ^= Fmask;
304                Fmask &= ~(1<<31);
305                Fi -= Fmask;
306                return Fi;
307        }
308
309        enum FPUMode
310        {
311                FPU_FLOOR               = 0,
312                FPU_CEIL                = 1,
313                FPU_BEST                = 2,
314
315                FPU_FORCE_DWORD = 0x7fffffff
316        };
317
318        FUNCTION ICECORE_API FPUMode    GetFPUMode();
319        FUNCTION ICECORE_API void               SaveFPU();
320        FUNCTION ICECORE_API void               RestoreFPU();
321        FUNCTION ICECORE_API void               SetFPUFloorMode();
322        FUNCTION ICECORE_API void               SetFPUCeilMode();
323        FUNCTION ICECORE_API void               SetFPUBestMode();
324
325        FUNCTION ICECORE_API void               SetFPUPrecision24();
326        FUNCTION ICECORE_API void               SetFPUPrecision53();
327        FUNCTION ICECORE_API void               SetFPUPrecision64();
328        FUNCTION ICECORE_API void               SetFPURoundingChop();
329        FUNCTION ICECORE_API void               SetFPURoundingUp();
330        FUNCTION ICECORE_API void               SetFPURoundingDown();
331        FUNCTION ICECORE_API void               SetFPURoundingNear();
332
333        FUNCTION ICECORE_API int                intChop(const float& f);
334        FUNCTION ICECORE_API int                intFloor(const float& f);
335        FUNCTION ICECORE_API int                intCeil(const float& f);
336
337#endif // __ICEFPU_H__
Note: See TracBrowser for help on using the repository browser.