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