aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/ode-0.9/OPCODE/Ice/IceFPU.h
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/ode-0.9/OPCODE/Ice/IceFPU.h')
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceFPU.h337
1 files changed, 337 insertions, 0 deletions
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceFPU.h b/libraries/ode-0.9/OPCODE/Ice/IceFPU.h
new file mode 100644
index 0000000..0cae4cb
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceFPU.h
@@ -0,0 +1,337 @@
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&)y = (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__