Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/OgreMain/include/asm_math.h @ 1

Last change on this file since 1 was 1, checked in by landauf, 17 years ago
File size: 7.9 KB
Line 
1#ifndef __asm_math_H__
2#define __asm_math_H__
3
4#include "OgrePrerequisites.h"
5
6namespace Ogre
7{
8
9/*=============================================================================
10 ASM math routines posted by davepermen et al on flipcode forums
11=============================================================================*/
12const float pi = 4.0 * atan( 1.0 );
13const float half_pi = 0.5 * pi;
14
15/*=============================================================================
16        NO EXPLICIT RETURN REQUIRED FROM THESE METHODS!!
17=============================================================================*/
18#if  OGRE_COMPILER == OGRE_COMPILER_MSVC && OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_32
19#       pragma warning( push )
20#       pragma warning( disable: 4035 )
21#endif
22
23float asm_arccos( float r ) {
24    // return half_pi + arctan( r / -sqr( 1.f - r * r ) );
25       
26#if  OGRE_COMPILER == OGRE_COMPILER_MSVC &&  OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_32
27
28    float asm_one = 1.f;
29    float asm_half_pi = half_pi;
30    __asm {
31        fld r // r0 = r
32        fld r // r1 = r0, r0 = r
33        fmul r // r0 = r0 * r
34        fsubr asm_one // r0 = r0 - 1.f
35        fsqrt // r0 = sqrtf( r0 )
36        fchs // r0 = - r0
37        fdiv // r0 = r1 / r0
38        fld1 // {{ r0 = atan( r0 )
39        fpatan // }}
40        fadd asm_half_pi // r0 = r0 + pi / 2
41    } // returns r0
42
43#else
44
45        return float( acos( r ) );
46
47#endif
48}
49
50float asm_arcsin( float r ) {
51    // return arctan( r / sqr( 1.f - r * r ) );
52
53#if  OGRE_COMPILER == OGRE_COMPILER_MSVC &&  OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_32
54
55    const float asm_one = 1.f;
56    __asm {
57        fld r // r0 = r
58        fld r // r1 = r0, r0 = r
59        fmul r // r0 = r0 * r
60        fsubr asm_one // r0 = r0 - 1.f
61        fsqrt // r0 = sqrtf( r0 )
62        fdiv // r0 = r1 / r0
63        fld1 // {{ r0 = atan( r0 )
64        fpatan // }}
65    } // returns r0
66
67#else
68
69        return float( asin( r ) );
70
71#endif
72
73}
74
75float asm_arctan( float r ) {
76
77#if  OGRE_COMPILER == OGRE_COMPILER_MSVC &&  OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_32
78
79    __asm {
80        fld r // r0 = r
81        fld1 // {{ r0 = atan( r0 )
82        fpatan // }}
83    } // returns r0
84
85#else
86
87        return float( atan( r ) );
88
89#endif
90
91}
92
93float asm_sin( float r ) {
94
95#if  OGRE_COMPILER == OGRE_COMPILER_MSVC &&  OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_32
96
97    __asm {
98        fld r // r0 = r
99        fsin // r0 = sinf( r0 )
100    } // returns r0
101
102#else
103
104        return sin( r );
105
106#endif
107
108}
109
110float asm_cos( float r ) {
111
112#if  OGRE_COMPILER == OGRE_COMPILER_MSVC &&  OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_32
113
114    __asm {
115        fld r // r0 = r
116        fcos // r0 = cosf( r0 )
117    } // returns r0
118
119#else
120       
121        return cos( r );
122
123#endif
124}
125
126float asm_tan( float r ) {
127
128#if  OGRE_COMPILER == OGRE_COMPILER_MSVC &&  OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_32
129
130    // return sin( r ) / cos( r );
131    __asm {
132        fld r // r0 = r
133        fsin // r0 = sinf( r0 )
134        fld r // r1 = r0, r0 = r
135        fcos // r0 = cosf( r0 )
136        fdiv // r0 = r1 / r0
137    } // returns r0
138
139#else
140       
141        return tan( r );
142
143#endif
144}
145
146// returns a for a * a = r
147float asm_sqrt( float r )
148{
149#if  OGRE_COMPILER == OGRE_COMPILER_MSVC &&  OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_32
150
151    __asm {
152        fld r // r0 = r
153        fsqrt // r0 = sqrtf( r0 )
154    } // returns r0
155
156#else
157
158        return sqrt( r );
159
160#endif
161}
162
163// returns 1 / a for a * a = r
164// -- Use this for Vector normalisation!!!
165float asm_rsq( float r )
166{
167#if  OGRE_COMPILER == OGRE_COMPILER_MSVC &&  OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_32
168
169    __asm {
170        fld1 // r0 = 1.f
171        fld r // r1 = r0, r0 = r
172        fsqrt // r0 = sqrtf( r0 )
173        fdiv // r0 = r1 / r0
174    } // returns r0
175
176#else
177
178        return 1. / sqrt( r );
179
180#endif
181}
182
183// returns 1 / a for a * a = r
184// Another version
185float apx_rsq( float r ) {
186
187#if  OGRE_COMPILER == OGRE_COMPILER_MSVC &&  OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_32
188
189    const float asm_dot5 = 0.5f;
190    const float asm_1dot5 = 1.5f;
191
192    __asm {
193        fld r // r0 = r
194        fmul asm_dot5 // r0 = r0 * .5f
195        mov eax, r // eax = r
196        shr eax, 0x1 // eax = eax >> 1
197        neg eax // eax = -eax
198        add eax, 0x5F400000 // eax = eax & MAGICAL NUMBER
199        mov r, eax // r = eax
200        fmul r // r0 = r0 * r
201        fmul r // r0 = r0 * r
202        fsubr asm_1dot5 // r0 = 1.5f - r0
203        fmul r // r0 = r0 * r
204    } // returns r0
205
206#else
207
208        return 1. / sqrt( r );
209
210#endif
211}
212
213/* very MS-specific, commented out for now
214   Finally the best InvSqrt implementation?
215   Use for vector normalisation instead of 1/length() * x,y,z
216*/
217#if  OGRE_COMPILER == OGRE_COMPILER_MSVC &&  OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_32
218
219__declspec(naked) float __fastcall InvSqrt(float fValue)
220{
221    __asm
222    {
223        mov        eax, 0be6eb508h
224        mov        dword ptr[esp-12],03fc00000h
225        sub        eax, dword ptr[esp + 4]
226        sub        dword ptr[esp+4], 800000h
227        shr        eax, 1
228        mov        dword ptr[esp -  8], eax
229
230        fld        dword ptr[esp -  8]
231        fmul    st, st
232        fld        dword ptr[esp -  8]
233        fxch    st(1)
234        fmul    dword ptr[esp +  4]
235        fld        dword ptr[esp - 12]
236        fld        st(0)
237        fsub    st,st(2)
238
239        fld        st(1)
240        fxch    st(1)
241        fmul    st(3),st
242        fmul    st(3),st
243        fmulp    st(4),st
244        fsub    st,st(2)
245
246        fmul    st(2),st
247        fmul    st(3),st
248        fmulp    st(2),st
249        fxch    st(1)
250        fsubp    st(1),st
251
252        fmulp    st(1), st
253        ret 4
254    }
255}
256
257#endif
258
259// returns a random number
260FORCEINLINE float asm_rand()
261{
262
263#if  OGRE_COMPILER == OGRE_COMPILER_MSVC &&  OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_32
264  #if 0
265    #if OGRE_COMP_VER >= 1300
266
267        static unsigned __int64 q = time( NULL );
268
269        _asm {
270                movq mm0, q
271
272                // do the magic MMX thing
273                pshufw mm1, mm0, 0x1E
274                paddd mm0, mm1
275
276                // move to integer memory location and free MMX
277                movq q, mm0
278                emms
279        }
280
281        return float( q );
282    #endif
283  #else
284    // VC6 does not support pshufw
285    return float( rand() );
286  #endif
287#else
288    // GCC etc
289
290        return float( rand() );
291
292#endif
293}
294
295// returns the maximum random number
296FORCEINLINE float asm_rand_max()
297{
298
299#if  OGRE_COMPILER == OGRE_COMPILER_MSVC &&  OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_32
300  #if 0
301    #if OGRE_COMP_VER >= 1300
302
303        return (std::numeric_limits< unsigned __int64 >::max)();
304        return 9223372036854775807.0f;
305    #endif
306  #else
307    // VC6 does not support unsigned __int64
308    return float( RAND_MAX );
309  #endif
310
311#else
312    // GCC etc
313        return float( RAND_MAX );
314
315#endif
316}
317
318// returns log2( r ) / log2( e )
319float asm_ln( float r ) {   
320
321#if  OGRE_COMPILER == OGRE_COMPILER_MSVC &&  OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_32
322
323    const float asm_e = 2.71828182846f;
324    const float asm_1_div_log2_e = .693147180559f;
325    const float asm_neg1_div_3 = -.33333333333333333333333333333f;
326    const float asm_neg2_div_3 = -.66666666666666666666666666667f;
327    const float asm_2 = 2.f;
328
329    int log_2 = 0;
330
331    __asm {
332        // log_2 = ( ( r >> 0x17 ) & 0xFF ) - 0x80;
333        mov eax, r
334        sar eax, 0x17
335        and eax, 0xFF
336        sub eax, 0x80
337        mov log_2, eax
338
339        // r = ( r & 0x807fffff ) + 0x3f800000;
340        mov ebx, r
341        and ebx, 0x807FFFFF
342        add ebx, 0x3F800000
343        mov r, ebx
344
345        // r = ( asm_neg1_div_3 * r + asm_2 ) * r + asm_neg2_div_3;   // (1)
346        fld r
347        fmul asm_neg1_div_3
348        fadd asm_2
349        fmul r
350        fadd asm_neg2_div_3
351        fild log_2
352        fadd
353        fmul asm_1_div_log2_e
354    }
355
356#else
357
358        return log( r );
359
360#endif
361}
362
363#if  OGRE_COMPILER == OGRE_COMPILER_MSVC &&  OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_32
364#       pragma warning( pop )
365#endif
366} // namespace
367#endif
Note: See TracBrowser for help on using the repository browser.