diff options
Diffstat (limited to 'libraries/ode-0.9/OPCODE/Ice/IceFPU.h')
-rw-r--r-- | libraries/ode-0.9/OPCODE/Ice/IceFPU.h | 337 |
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__ | ||