Tizen 2.1 base
[platform/upstream/libbullet.git] / Extras / vectormathlibrary / include / vectormath / SSE / cpp / vec_aos.h
1 /*
2    Copyright (C) 2006, 2010 Sony Computer Entertainment Inc.
3    All rights reserved.
4
5    Redistribution and use in source and binary forms,
6    with or without modification, are permitted provided that the
7    following conditions are met:
8     * Redistributions of source code must retain the above copyright
9       notice, this list of conditions and the following disclaimer.
10     * Redistributions in binary form must reproduce the above copyright
11       notice, this list of conditions and the following disclaimer in the
12       documentation and/or other materials provided with the distribution.
13     * Neither the name of the Sony Computer Entertainment Inc nor the names
14       of its contributors may be used to endorse or promote products derived
15       from this software without specific prior written permission.
16
17    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27    POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #ifndef _VECTORMATH_VEC_AOS_CPP_H
31 #define _VECTORMATH_VEC_AOS_CPP_H
32
33 //-----------------------------------------------------------------------------
34 // Constants
35 // for permutes words are labeled [x,y,z,w] [a,b,c,d]
36
37 #define _VECTORMATH_PERM_X 0x00010203
38 #define _VECTORMATH_PERM_Y 0x04050607
39 #define _VECTORMATH_PERM_Z 0x08090a0b
40 #define _VECTORMATH_PERM_W 0x0c0d0e0f
41 #define _VECTORMATH_PERM_A 0x10111213
42 #define _VECTORMATH_PERM_B 0x14151617
43 #define _VECTORMATH_PERM_C 0x18191a1b
44 #define _VECTORMATH_PERM_D 0x1c1d1e1f
45 #define _VECTORMATH_PERM_XYZA (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A }
46 #define _VECTORMATH_PERM_ZXYW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_W }
47 #define _VECTORMATH_PERM_YZXW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_W }
48 #define _VECTORMATH_PERM_YZAB (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A, _VECTORMATH_PERM_B }
49 #define _VECTORMATH_PERM_ZABC (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A, _VECTORMATH_PERM_B, _VECTORMATH_PERM_C }
50 #define _VECTORMATH_PERM_XYAW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A, _VECTORMATH_PERM_W }
51 #define _VECTORMATH_PERM_XAZW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_A, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_W }
52 #define _VECTORMATH_MASK_0xF000 (vec_uint4){ 0xffffffff, 0, 0, 0 }
53 #define _VECTORMATH_MASK_0x0F00 (vec_uint4){ 0, 0xffffffff, 0, 0 }
54 #define _VECTORMATH_MASK_0x00F0 (vec_uint4){ 0, 0, 0xffffffff, 0 }
55 #define _VECTORMATH_MASK_0x000F (vec_uint4){ 0, 0, 0, 0xffffffff }
56 #define _VECTORMATH_UNIT_1000 _mm_setr_ps(1.0f,0.0f,0.0f,0.0f) // (__m128){ 1.0f, 0.0f, 0.0f, 0.0f }
57 #define _VECTORMATH_UNIT_0100 _mm_setr_ps(0.0f,1.0f,0.0f,0.0f) // (__m128){ 0.0f, 1.0f, 0.0f, 0.0f }
58 #define _VECTORMATH_UNIT_0010 _mm_setr_ps(0.0f,0.0f,1.0f,0.0f) // (__m128){ 0.0f, 0.0f, 1.0f, 0.0f }
59 #define _VECTORMATH_UNIT_0001 _mm_setr_ps(0.0f,0.0f,0.0f,1.0f) // (__m128){ 0.0f, 0.0f, 0.0f, 1.0f }
60 #define _VECTORMATH_SLERP_TOL 0.999f
61 //_VECTORMATH_SLERP_TOLF
62
63 //-----------------------------------------------------------------------------
64 // Definitions
65
66 #ifndef _VECTORMATH_INTERNAL_FUNCTIONS
67 #define _VECTORMATH_INTERNAL_FUNCTIONS
68
69 #define     _vmath_shufps(a, b, immx, immy, immz, immw) _mm_shuffle_ps(a, b, _MM_SHUFFLE(immw, immz, immy, immx))
70 static __forceinline __m128 _vmathVfDot3( __m128 vec0, __m128 vec1 )
71 {
72         __m128 result = _mm_mul_ps( vec0, vec1);
73     return _mm_add_ps( vec_splat( result, 0 ), _mm_add_ps( vec_splat( result, 1 ), vec_splat( result, 2 ) ) );
74 }
75
76 static __forceinline __m128 _vmathVfDot4( __m128 vec0, __m128 vec1 )
77 {
78     __m128 result = _mm_mul_ps(vec0, vec1);
79         return _mm_add_ps(_mm_shuffle_ps(result, result, _MM_SHUFFLE(0,0,0,0)),
80                         _mm_add_ps(_mm_shuffle_ps(result, result, _MM_SHUFFLE(1,1,1,1)),
81                         _mm_add_ps(_mm_shuffle_ps(result, result, _MM_SHUFFLE(2,2,2,2)), _mm_shuffle_ps(result, result, _MM_SHUFFLE(3,3,3,3)))));
82 }
83
84 static __forceinline __m128 _vmathVfCross( __m128 vec0, __m128 vec1 )
85 {
86     __m128 tmp0, tmp1, tmp2, tmp3, result;
87     tmp0 = _mm_shuffle_ps( vec0, vec0, _MM_SHUFFLE(3,0,2,1) );
88     tmp1 = _mm_shuffle_ps( vec1, vec1, _MM_SHUFFLE(3,1,0,2) );
89     tmp2 = _mm_shuffle_ps( vec0, vec0, _MM_SHUFFLE(3,1,0,2) );
90     tmp3 = _mm_shuffle_ps( vec1, vec1, _MM_SHUFFLE(3,0,2,1) );
91     result = vec_mul( tmp0, tmp1 );
92     result = vec_nmsub( tmp2, tmp3, result );
93     return result;
94 }
95 /*
96 static __forceinline vec_uint4 _vmathVfToHalfFloatsUnpacked(__m128 v)
97 {
98 #if 0
99     vec_int4 bexp;
100     vec_uint4 mant, sign, hfloat;
101     vec_uint4 notZero, isInf;
102     const vec_uint4 hfloatInf = (vec_uint4)(0x00007c00u);
103     const vec_uint4 mergeMant = (vec_uint4)(0x000003ffu);
104     const vec_uint4 mergeSign = (vec_uint4)(0x00008000u);
105
106     sign = vec_sr((vec_uint4)v, (vec_uint4)16);
107     mant = vec_sr((vec_uint4)v, (vec_uint4)13);
108     bexp = vec_and(vec_sr((vec_int4)v, (vec_uint4)23), (vec_int4)0xff);
109
110     notZero = (vec_uint4)vec_cmpgt(bexp, (vec_int4)112);
111     isInf = (vec_uint4)vec_cmpgt(bexp, (vec_int4)142);
112
113     bexp = _mm_add_ps(bexp, (vec_int4)-112);
114     bexp = vec_sl(bexp, (vec_uint4)10);
115
116     hfloat = vec_sel((vec_uint4)bexp, mant, mergeMant);
117     hfloat = vec_sel((vec_uint4)(0), hfloat, notZero);
118     hfloat = vec_sel(hfloat, hfloatInf, isInf);
119     hfloat = vec_sel(hfloat, sign, mergeSign);
120
121     return hfloat;
122 #else
123         assert(0);
124         return _mm_setzero_ps();
125 #endif
126 }
127
128 static __forceinline vec_ushort8 _vmath2VfToHalfFloats(__m128 u, __m128 v)
129 {
130 #if 0
131     vec_uint4 hfloat_u, hfloat_v;
132     const vec_uchar16 pack = (vec_uchar16){2,3,6,7,10,11,14,15,18,19,22,23,26,27,30,31};
133     hfloat_u = _vmathVfToHalfFloatsUnpacked(u);
134     hfloat_v = _vmathVfToHalfFloatsUnpacked(v);
135     return (vec_ushort8)vec_perm(hfloat_u, hfloat_v, pack);
136 #else
137         assert(0);
138         return _mm_setzero_si128();
139 #endif
140 }
141 */
142
143 static __forceinline __m128 _vmathVfInsert(__m128 dst, __m128 src, int slot)
144 {
145         SSEFloat s;
146         s.m128 = src;
147         SSEFloat d;
148         d.m128 = dst;
149         d.f[slot] = s.f[slot];
150         return d.m128;
151 }
152
153 #define _vmathVfSetElement(vec, scalar, slot) ((float *)&(vec))[slot] = scalar
154
155 static __forceinline __m128 _vmathVfSplatScalar(float scalar)
156 {
157         return _mm_set1_ps(scalar);
158 }
159
160 #endif
161
162 namespace Vectormath {
163 namespace Aos {
164
165         
166 #ifdef _VECTORMATH_NO_SCALAR_CAST
167 __forceinline VecIdx::operator floatInVec() const
168 {
169     return floatInVec(ref, i);
170 }
171
172 __forceinline float VecIdx::getAsFloat() const
173 #else
174 __forceinline VecIdx::operator float() const
175 #endif
176 {
177     return ((float *)&ref)[i];
178 }
179
180 __forceinline float VecIdx::operator =( float scalar )
181 {
182     _vmathVfSetElement(ref, scalar, i);
183     return scalar;
184 }
185
186 __forceinline floatInVec VecIdx::operator =( const floatInVec &scalar )
187 {
188     ref = _vmathVfInsert(ref, scalar.get128(), i);
189     return scalar;
190 }
191
192 __forceinline floatInVec VecIdx::operator =( const VecIdx& scalar )
193 {
194     return *this = floatInVec(scalar.ref, scalar.i);
195 }
196
197 __forceinline floatInVec VecIdx::operator *=( float scalar )
198 {
199     return *this *= floatInVec(scalar);
200 }
201
202 __forceinline floatInVec VecIdx::operator *=( const floatInVec &scalar )
203 {
204     return *this = floatInVec(ref, i) * scalar;
205 }
206
207 __forceinline floatInVec VecIdx::operator /=( float scalar )
208 {
209     return *this /= floatInVec(scalar);
210 }
211
212 inline floatInVec VecIdx::operator /=( const floatInVec &scalar )
213 {
214     return *this = floatInVec(ref, i) / scalar;
215 }
216
217 __forceinline floatInVec VecIdx::operator +=( float scalar )
218 {
219     return *this += floatInVec(scalar);
220 }
221
222 __forceinline floatInVec VecIdx::operator +=( const floatInVec &scalar )
223 {
224     return *this = floatInVec(ref, i) + scalar;
225 }
226
227 __forceinline floatInVec VecIdx::operator -=( float scalar )
228 {
229     return *this -= floatInVec(scalar);
230 }
231
232 __forceinline floatInVec VecIdx::operator -=( const floatInVec &scalar )
233 {
234     return *this = floatInVec(ref, i) - scalar;
235 }
236
237 __forceinline Vector3::Vector3(const Vector3& vec)
238 {
239     set128(vec.get128());
240 }
241
242 __forceinline void Vector3::set128(vec_float4 vec)
243 {
244     mVec128 = vec;
245 }
246
247
248 __forceinline Vector3::Vector3( float _x, float _y, float _z )
249 {
250     mVec128 = _mm_setr_ps(_x, _y, _z, 0.0f);
251 }
252
253 __forceinline Vector3::Vector3( const floatInVec &_x, const floatInVec &_y, const floatInVec &_z )
254 {
255         __m128 xz = _mm_unpacklo_ps( _x.get128(), _z.get128() );
256         mVec128 = _mm_unpacklo_ps( xz, _y.get128() );
257 }
258
259 __forceinline Vector3::Vector3( const Point3 &pnt )
260 {
261     mVec128 = pnt.get128();
262 }
263
264 __forceinline Vector3::Vector3( float scalar )
265 {
266     mVec128 = floatInVec(scalar).get128();
267 }
268
269 __forceinline Vector3::Vector3( const floatInVec &scalar )
270 {
271     mVec128 = scalar.get128();
272 }
273
274 __forceinline Vector3::Vector3( __m128 vf4 )
275 {
276     mVec128 = vf4;
277 }
278
279 __forceinline const Vector3 Vector3::xAxis( )
280 {
281     return Vector3( _VECTORMATH_UNIT_1000 );
282 }
283
284 __forceinline const Vector3 Vector3::yAxis( )
285 {
286     return Vector3( _VECTORMATH_UNIT_0100 );
287 }
288
289 __forceinline const Vector3 Vector3::zAxis( )
290 {
291     return Vector3( _VECTORMATH_UNIT_0010 );
292 }
293
294 __forceinline const Vector3 lerp( float t, const Vector3 &vec0, const Vector3 &vec1 )
295 {
296     return lerp( floatInVec(t), vec0, vec1 );
297 }
298
299 __forceinline const Vector3 lerp( const floatInVec &t, const Vector3 &vec0, const Vector3 &vec1 )
300 {
301     return ( vec0 + ( ( vec1 - vec0 ) * t ) );
302 }
303
304 __forceinline const Vector3 slerp( float t, const Vector3 &unitVec0, const Vector3 &unitVec1 )
305 {
306     return slerp( floatInVec(t), unitVec0, unitVec1 );
307 }
308
309 __forceinline const Vector3 slerp( const floatInVec &t, const Vector3 &unitVec0, const Vector3 &unitVec1 )
310 {
311     __m128 scales, scale0, scale1, cosAngle, angle, tttt, oneMinusT, angles, sines;
312     cosAngle = _vmathVfDot3( unitVec0.get128(), unitVec1.get128() );
313     __m128 selectMask = _mm_cmpgt_ps( _mm_set1_ps(_VECTORMATH_SLERP_TOL), cosAngle );
314     angle = acosf4( cosAngle );
315     tttt = t.get128();
316     oneMinusT = _mm_sub_ps( _mm_set1_ps(1.0f), tttt );
317     angles = _mm_unpacklo_ps( _mm_set1_ps(1.0f), tttt ); // angles = 1, t, 1, t
318     angles = _mm_unpacklo_ps( angles, oneMinusT );              // angles = 1, 1-t, t, 1-t
319     angles = _mm_mul_ps( angles, angle );
320     sines = sinf4( angles );
321     scales = _mm_div_ps( sines, vec_splat( sines, 0 ) );
322     scale0 = vec_sel( oneMinusT, vec_splat( scales, 1 ), selectMask );
323     scale1 = vec_sel( tttt, vec_splat( scales, 2 ), selectMask );
324     return Vector3( vec_madd( unitVec0.get128(), scale0, _mm_mul_ps( unitVec1.get128(), scale1 ) ) );
325 }
326
327 __forceinline __m128 Vector3::get128( ) const
328 {
329     return mVec128;
330 }
331
332 __forceinline void loadXYZ(Vector3& vec, const float* fptr)
333 {
334 #ifdef USE_SSE2_LDDQU
335         vec = Vector3(  SSEFloat(_mm_lddqu_si128((const __m128i*)((float*)(fptr)))).m128 );
336 #else
337         SSEFloat fl;
338         fl.f[0] = fptr[0];
339         fl.f[1] = fptr[1];
340         fl.f[2] = fptr[2];
341         fl.f[3] = fptr[3];
342     vec = Vector3(      fl.m128);
343 #endif //USE_SSE2_LDDQU
344         
345 }
346
347 __forceinline void storeXYZ( const Vector3 &vec, __m128 * quad )
348 {
349     __m128 dstVec = *quad;
350         __declspec(align(16)) unsigned int sw[4] = {0, 0, 0, 0xffffffff}; // TODO: Centralize
351     dstVec = vec_sel(vec.get128(), dstVec, sw);
352     *quad = dstVec;
353 }
354
355 __forceinline void storeXYZ(const Vector3& vec, float* fptr)
356 {
357         fptr[0] = vec.getX();
358         fptr[1] = vec.getY();
359         fptr[2] = vec.getZ();
360 }
361
362
363 __forceinline void loadXYZArray( Vector3 & vec0, Vector3 & vec1, Vector3 & vec2, Vector3 & vec3, const __m128 * threeQuads )
364 {
365         const float *quads = (float *)threeQuads;
366     vec0 = Vector3(  _mm_load_ps(quads) );
367     vec1 = Vector3( _mm_loadu_ps(quads + 3) );
368     vec2 = Vector3( _mm_loadu_ps(quads + 6) );
369     vec3 = Vector3( _mm_loadu_ps(quads + 9) );
370 }
371
372 __forceinline void storeXYZArray( const Vector3 &vec0, const Vector3 &vec1, const Vector3 &vec2, const Vector3 &vec3, __m128 * threeQuads )
373 {
374         __m128 xxxx = _mm_shuffle_ps( vec1.get128(), vec1.get128(), _MM_SHUFFLE(0, 0, 0, 0) );
375         __m128 zzzz = _mm_shuffle_ps( vec2.get128(), vec2.get128(), _MM_SHUFFLE(2, 2, 2, 2) );
376         __declspec(align(16)) unsigned int xsw[4] = {0, 0, 0, 0xffffffff};
377         __declspec(align(16)) unsigned int zsw[4] = {0xffffffff, 0, 0, 0};
378         threeQuads[0] = vec_sel( vec0.get128(), xxxx, xsw );
379     threeQuads[1] = _mm_shuffle_ps( vec1.get128(), vec2.get128(), _MM_SHUFFLE(1, 0, 2, 1) );
380     threeQuads[2] = vec_sel( _mm_shuffle_ps( vec3.get128(), vec3.get128(), _MM_SHUFFLE(2, 1, 0, 3) ), zzzz, zsw );
381 }
382 /*
383 __forceinline void storeHalfFloats( const Vector3 &vec0, const Vector3 &vec1, const Vector3 &vec2, const Vector3 &vec3, const Vector3 &vec4, const Vector3 &vec5, const Vector3 &vec6, const Vector3 &vec7, vec_ushort8 * threeQuads )
384 {
385         assert(0);
386 #if 0
387     __m128 xyz0[3];
388     __m128 xyz1[3];
389     storeXYZArray( vec0, vec1, vec2, vec3, xyz0 );
390     storeXYZArray( vec4, vec5, vec6, vec7, xyz1 );
391     threeQuads[0] = _vmath2VfToHalfFloats(xyz0[0], xyz0[1]);
392     threeQuads[1] = _vmath2VfToHalfFloats(xyz0[2], xyz1[0]);
393     threeQuads[2] = _vmath2VfToHalfFloats(xyz1[1], xyz1[2]);
394 #endif
395 }
396 */
397 __forceinline Vector3 & Vector3::operator =( const Vector3 &vec )
398 {
399     mVec128 = vec.mVec128;
400     return *this;
401 }
402
403 __forceinline Vector3 & Vector3::setX( float _x )
404 {
405     _vmathVfSetElement(mVec128, _x, 0);
406     return *this;
407 }
408
409 __forceinline Vector3 & Vector3::setX( const floatInVec &_x )
410 {
411     mVec128 = _vmathVfInsert(mVec128, _x.get128(), 0);
412     return *this;
413 }
414
415 __forceinline const floatInVec Vector3::getX( ) const
416 {
417     return floatInVec( mVec128, 0 );
418 }
419
420 __forceinline Vector3 & Vector3::setY( float _y )
421 {
422     _vmathVfSetElement(mVec128, _y, 1);
423     return *this;
424 }
425
426 __forceinline Vector3 & Vector3::setY( const floatInVec &_y )
427 {
428     mVec128 = _vmathVfInsert(mVec128, _y.get128(), 1);
429     return *this;
430 }
431
432 __forceinline const floatInVec Vector3::getY( ) const
433 {
434     return floatInVec( mVec128, 1 );
435 }
436
437 __forceinline Vector3 & Vector3::setZ( float _z )
438 {
439     _vmathVfSetElement(mVec128, _z, 2);
440     return *this;
441 }
442
443 __forceinline Vector3 & Vector3::setZ( const floatInVec &_z )
444 {
445     mVec128 = _vmathVfInsert(mVec128, _z.get128(), 2);
446     return *this;
447 }
448
449 __forceinline const floatInVec Vector3::getZ( ) const
450 {
451     return floatInVec( mVec128, 2 );
452 }
453
454 __forceinline Vector3 & Vector3::setElem( int idx, float value )
455 {
456     _vmathVfSetElement(mVec128, value, idx);
457     return *this;
458 }
459
460 __forceinline Vector3 & Vector3::setElem( int idx, const floatInVec &value )
461 {
462     mVec128 = _vmathVfInsert(mVec128, value.get128(), idx);
463     return *this;
464 }
465
466 __forceinline const floatInVec Vector3::getElem( int idx ) const
467 {
468     return floatInVec( mVec128, idx );
469 }
470
471 __forceinline VecIdx Vector3::operator []( int idx )
472 {
473     return VecIdx( mVec128, idx );
474 }
475
476 __forceinline const floatInVec Vector3::operator []( int idx ) const
477 {
478     return floatInVec( mVec128, idx );
479 }
480
481 __forceinline const Vector3 Vector3::operator +( const Vector3 &vec ) const
482 {
483     return Vector3( _mm_add_ps( mVec128, vec.mVec128 ) );
484 }
485
486 __forceinline const Vector3 Vector3::operator -( const Vector3 &vec ) const
487 {
488     return Vector3( _mm_sub_ps( mVec128, vec.mVec128 ) );
489 }
490
491 __forceinline const Point3 Vector3::operator +( const Point3 &pnt ) const
492 {
493     return Point3( _mm_add_ps( mVec128, pnt.get128() ) );
494 }
495
496 __forceinline const Vector3 Vector3::operator *( float scalar ) const
497 {
498     return *this * floatInVec(scalar);
499 }
500
501 __forceinline const Vector3 Vector3::operator *( const floatInVec &scalar ) const
502 {
503     return Vector3( _mm_mul_ps( mVec128, scalar.get128() ) );
504 }
505
506 __forceinline Vector3 & Vector3::operator +=( const Vector3 &vec )
507 {
508     *this = *this + vec;
509     return *this;
510 }
511
512 __forceinline Vector3 & Vector3::operator -=( const Vector3 &vec )
513 {
514     *this = *this - vec;
515     return *this;
516 }
517
518 __forceinline Vector3 & Vector3::operator *=( float scalar )
519 {
520     *this = *this * scalar;
521     return *this;
522 }
523
524 __forceinline Vector3 & Vector3::operator *=( const floatInVec &scalar )
525 {
526     *this = *this * scalar;
527     return *this;
528 }
529
530 __forceinline const Vector3 Vector3::operator /( float scalar ) const
531 {
532     return *this / floatInVec(scalar);
533 }
534
535 __forceinline const Vector3 Vector3::operator /( const floatInVec &scalar ) const
536 {
537     return Vector3( _mm_div_ps( mVec128, scalar.get128() ) );
538 }
539
540 __forceinline Vector3 & Vector3::operator /=( float scalar )
541 {
542     *this = *this / scalar;
543     return *this;
544 }
545
546 __forceinline Vector3 & Vector3::operator /=( const floatInVec &scalar )
547 {
548     *this = *this / scalar;
549     return *this;
550 }
551
552 __forceinline const Vector3 Vector3::operator -( ) const
553 {
554         //return Vector3(_mm_sub_ps( _mm_setzero_ps(), mVec128 ) );
555
556         __declspec(align(16)) static const int array[] = {0x80000000, 0x80000000, 0x80000000, 0x80000000};
557         __m128 NEG_MASK = SSEFloat(*(const vec_float4*)array).vf;
558         return Vector3(_mm_xor_ps(get128(),NEG_MASK));
559 }
560
561 __forceinline const Vector3 operator *( float scalar, const Vector3 &vec )
562 {
563     return floatInVec(scalar) * vec;
564 }
565
566 __forceinline const Vector3 operator *( const floatInVec &scalar, const Vector3 &vec )
567 {
568     return vec * scalar;
569 }
570
571 __forceinline const Vector3 mulPerElem( const Vector3 &vec0, const Vector3 &vec1 )
572 {
573     return Vector3( _mm_mul_ps( vec0.get128(), vec1.get128() ) );
574 }
575
576 __forceinline const Vector3 divPerElem( const Vector3 &vec0, const Vector3 &vec1 )
577 {
578     return Vector3( _mm_div_ps( vec0.get128(), vec1.get128() ) );
579 }
580
581 __forceinline const Vector3 recipPerElem( const Vector3 &vec )
582 {
583     return Vector3( _mm_rcp_ps( vec.get128() ) );
584 }
585
586 __forceinline const Vector3 absPerElem( const Vector3 &vec )
587 {
588     return Vector3( fabsf4( vec.get128() ) );
589 }
590
591 __forceinline const Vector3 copySignPerElem( const Vector3 &vec0, const Vector3 &vec1 )
592 {
593         __m128 vmask = toM128(0x7fffffff);
594         return Vector3( _mm_or_ps(
595                 _mm_and_ps   ( vmask, vec0.get128() ),                  // Value
596                 _mm_andnot_ps( vmask, vec1.get128() ) ) );              // Signs
597 }
598
599 __forceinline const Vector3 maxPerElem( const Vector3 &vec0, const Vector3 &vec1 )
600 {
601     return Vector3( _mm_max_ps( vec0.get128(), vec1.get128() ) );
602 }
603
604 __forceinline const floatInVec maxElem( const Vector3 &vec )
605 {
606     return floatInVec( _mm_max_ps( _mm_max_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ), vec_splat( vec.get128(), 2 ) ) );
607 }
608
609 __forceinline const Vector3 minPerElem( const Vector3 &vec0, const Vector3 &vec1 )
610 {
611     return Vector3( _mm_min_ps( vec0.get128(), vec1.get128() ) );
612 }
613
614 __forceinline const floatInVec minElem( const Vector3 &vec )
615 {
616     return floatInVec( _mm_min_ps( _mm_min_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ), vec_splat( vec.get128(), 2 ) ) );
617 }
618
619 __forceinline const floatInVec sum( const Vector3 &vec )
620 {
621     return floatInVec( _mm_add_ps( _mm_add_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ), vec_splat( vec.get128(), 2 ) ) );
622 }
623
624 __forceinline const floatInVec dot( const Vector3 &vec0, const Vector3 &vec1 )
625 {
626     return floatInVec( _vmathVfDot3( vec0.get128(), vec1.get128() ), 0 );
627 }
628
629 __forceinline const floatInVec lengthSqr( const Vector3 &vec )
630 {
631     return floatInVec(  _vmathVfDot3( vec.get128(), vec.get128() ), 0 );
632 }
633
634 __forceinline const floatInVec length( const Vector3 &vec )
635 {
636     return floatInVec(  _mm_sqrt_ps(_vmathVfDot3( vec.get128(), vec.get128() )), 0 );
637 }
638
639
640 __forceinline const Vector3 normalizeApprox( const Vector3 &vec )
641 {
642     return Vector3( _mm_mul_ps( vec.get128(), _mm_rsqrt_ps( _vmathVfDot3( vec.get128(), vec.get128() ) ) ) );
643 }
644
645 __forceinline const Vector3 normalize( const Vector3 &vec )
646 {
647         return Vector3( _mm_mul_ps( vec.get128(), newtonrapson_rsqrt4( _vmathVfDot3( vec.get128(), vec.get128() ) ) ) );
648 }
649
650 __forceinline const Vector3 cross( const Vector3 &vec0, const Vector3 &vec1 )
651 {
652     return Vector3( _vmathVfCross( vec0.get128(), vec1.get128() ) );
653 }
654
655 __forceinline const Vector3 select( const Vector3 &vec0, const Vector3 &vec1, bool select1 )
656 {
657     return select( vec0, vec1, boolInVec(select1) );
658 }
659
660
661 __forceinline  const Vector4 select(const Vector4& vec0, const Vector4& vec1, const boolInVec& select1)
662 {
663     return Vector4(vec_sel(vec0.get128(), vec1.get128(), select1.get128()));
664 }
665
666 #ifdef _VECTORMATH_DEBUG
667
668 __forceinline void print( const Vector3 &vec )
669 {
670     union { __m128 v; float s[4]; } tmp;
671     tmp.v = vec.get128();
672     printf( "( %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2] );
673 }
674
675 __forceinline void print( const Vector3 &vec, const char * name )
676 {
677     union { __m128 v; float s[4]; } tmp;
678     tmp.v = vec.get128();
679     printf( "%s: ( %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2] );
680 }
681
682 #endif
683
684 __forceinline Vector4::Vector4( float _x, float _y, float _z, float _w )
685 {
686     mVec128 = _mm_setr_ps(_x, _y, _z, _w); 
687  }
688
689 __forceinline Vector4::Vector4( const floatInVec &_x, const floatInVec &_y, const floatInVec &_z, const floatInVec &_w )
690 {
691         mVec128 = _mm_unpacklo_ps(
692                 _mm_unpacklo_ps( _x.get128(), _z.get128() ),
693                 _mm_unpacklo_ps( _y.get128(), _w.get128() ) );
694 }
695
696 __forceinline Vector4::Vector4( const Vector3 &xyz, float _w )
697 {
698     mVec128 = xyz.get128();
699     _vmathVfSetElement(mVec128, _w, 3);
700 }
701
702 __forceinline Vector4::Vector4( const Vector3 &xyz, const floatInVec &_w )
703 {
704     mVec128 = xyz.get128();
705     mVec128 = _vmathVfInsert(mVec128, _w.get128(), 3);
706 }
707
708 __forceinline Vector4::Vector4( const Vector3 &vec )
709 {
710     mVec128 = vec.get128();
711     mVec128 = _vmathVfInsert(mVec128, _mm_setzero_ps(), 3);
712 }
713
714 __forceinline Vector4::Vector4( const Point3 &pnt )
715 {
716     mVec128 = pnt.get128();
717     mVec128 = _vmathVfInsert(mVec128, _mm_set1_ps(1.0f), 3);
718 }
719
720 __forceinline Vector4::Vector4( const Quat &quat )
721 {
722     mVec128 = quat.get128();
723 }
724
725 __forceinline Vector4::Vector4( float scalar )
726 {
727     mVec128 = floatInVec(scalar).get128();
728 }
729
730 __forceinline Vector4::Vector4( const floatInVec &scalar )
731 {
732     mVec128 = scalar.get128();
733 }
734
735 __forceinline Vector4::Vector4( __m128 vf4 )
736 {
737     mVec128 = vf4;
738 }
739
740 __forceinline const Vector4 Vector4::xAxis( )
741 {
742     return Vector4( _VECTORMATH_UNIT_1000 );
743 }
744
745 __forceinline const Vector4 Vector4::yAxis( )
746 {
747     return Vector4( _VECTORMATH_UNIT_0100 );
748 }
749
750 __forceinline const Vector4 Vector4::zAxis( )
751 {
752     return Vector4( _VECTORMATH_UNIT_0010 );
753 }
754
755 __forceinline const Vector4 Vector4::wAxis( )
756 {
757     return Vector4( _VECTORMATH_UNIT_0001 );
758 }
759
760 __forceinline const Vector4 lerp( float t, const Vector4 &vec0, const Vector4 &vec1 )
761 {
762     return lerp( floatInVec(t), vec0, vec1 );
763 }
764
765 __forceinline const Vector4 lerp( const floatInVec &t, const Vector4 &vec0, const Vector4 &vec1 )
766 {
767     return ( vec0 + ( ( vec1 - vec0 ) * t ) );
768 }
769
770 __forceinline const Vector4 slerp( float t, const Vector4 &unitVec0, const Vector4 &unitVec1 )
771 {
772     return slerp( floatInVec(t), unitVec0, unitVec1 );
773 }
774
775 __forceinline const Vector4 slerp( const floatInVec &t, const Vector4 &unitVec0, const Vector4 &unitVec1 )
776 {
777     __m128 scales, scale0, scale1, cosAngle, angle, tttt, oneMinusT, angles, sines;
778     cosAngle = _vmathVfDot4( unitVec0.get128(), unitVec1.get128() );
779     __m128 selectMask = _mm_cmpgt_ps( _mm_set1_ps(_VECTORMATH_SLERP_TOL), cosAngle );
780     angle = acosf4( cosAngle );
781     tttt = t.get128();
782     oneMinusT = _mm_sub_ps( _mm_set1_ps(1.0f), tttt );
783     angles = _mm_unpacklo_ps( _mm_set1_ps(1.0f), tttt ); // angles = 1, t, 1, t
784     angles = _mm_unpacklo_ps( angles, oneMinusT );              // angles = 1, 1-t, t, 1-t
785     angles = _mm_mul_ps( angles, angle );
786     sines = sinf4( angles );
787     scales = _mm_div_ps( sines, vec_splat( sines, 0 ) );
788     scale0 = vec_sel( oneMinusT, vec_splat( scales, 1 ), selectMask );
789     scale1 = vec_sel( tttt, vec_splat( scales, 2 ), selectMask );
790     return Vector4( vec_madd( unitVec0.get128(), scale0, _mm_mul_ps( unitVec1.get128(), scale1 ) ) );
791 }
792
793 __forceinline __m128 Vector4::get128( ) const
794 {
795     return mVec128;
796 }
797 /*
798 __forceinline void storeHalfFloats( const Vector4 &vec0, const Vector4 &vec1, const Vector4 &vec2, const Vector4 &vec3, vec_ushort8 * twoQuads )
799 {
800     twoQuads[0] = _vmath2VfToHalfFloats(vec0.get128(), vec1.get128());
801     twoQuads[1] = _vmath2VfToHalfFloats(vec2.get128(), vec3.get128());
802 }
803 */
804 __forceinline Vector4 & Vector4::operator =( const Vector4 &vec )
805 {
806     mVec128 = vec.mVec128;
807     return *this;
808 }
809
810 __forceinline Vector4 & Vector4::setXYZ( const Vector3 &vec )
811 {
812         __declspec(align(16)) unsigned int sw[4] = {0, 0, 0, 0xffffffff};
813         mVec128 = vec_sel( vec.get128(), mVec128, sw );
814     return *this;
815 }
816
817 __forceinline const Vector3 Vector4::getXYZ( ) const
818 {
819     return Vector3( mVec128 );
820 }
821
822 __forceinline Vector4 & Vector4::setX( float _x )
823 {
824     _vmathVfSetElement(mVec128, _x, 0);
825     return *this;
826 }
827
828 __forceinline Vector4 & Vector4::setX( const floatInVec &_x )
829 {
830     mVec128 = _vmathVfInsert(mVec128, _x.get128(), 0);
831     return *this;
832 }
833
834 __forceinline const floatInVec Vector4::getX( ) const
835 {
836     return floatInVec( mVec128, 0 );
837 }
838
839 __forceinline Vector4 & Vector4::setY( float _y )
840 {
841     _vmathVfSetElement(mVec128, _y, 1);
842     return *this;
843 }
844
845 __forceinline Vector4 & Vector4::setY( const floatInVec &_y )
846 {
847     mVec128 = _vmathVfInsert(mVec128, _y.get128(), 1);
848     return *this;
849 }
850
851 __forceinline const floatInVec Vector4::getY( ) const
852 {
853     return floatInVec( mVec128, 1 );
854 }
855
856 __forceinline Vector4 & Vector4::setZ( float _z )
857 {
858     _vmathVfSetElement(mVec128, _z, 2);
859     return *this;
860 }
861
862 __forceinline Vector4 & Vector4::setZ( const floatInVec &_z )
863 {
864     mVec128 = _vmathVfInsert(mVec128, _z.get128(), 2);
865     return *this;
866 }
867
868 __forceinline const floatInVec Vector4::getZ( ) const
869 {
870     return floatInVec( mVec128, 2 );
871 }
872
873 __forceinline Vector4 & Vector4::setW( float _w )
874 {
875     _vmathVfSetElement(mVec128, _w, 3);
876     return *this;
877 }
878
879 __forceinline Vector4 & Vector4::setW( const floatInVec &_w )
880 {
881     mVec128 = _vmathVfInsert(mVec128, _w.get128(), 3);
882     return *this;
883 }
884
885 __forceinline const floatInVec Vector4::getW( ) const
886 {
887     return floatInVec( mVec128, 3 );
888 }
889
890 __forceinline Vector4 & Vector4::setElem( int idx, float value )
891 {
892     _vmathVfSetElement(mVec128, value, idx);
893     return *this;
894 }
895
896 __forceinline Vector4 & Vector4::setElem( int idx, const floatInVec &value )
897 {
898     mVec128 = _vmathVfInsert(mVec128, value.get128(), idx);
899     return *this;
900 }
901
902 __forceinline const floatInVec Vector4::getElem( int idx ) const
903 {
904     return floatInVec( mVec128, idx );
905 }
906
907 __forceinline VecIdx Vector4::operator []( int idx )
908 {
909     return VecIdx( mVec128, idx );
910 }
911
912 __forceinline const floatInVec Vector4::operator []( int idx ) const
913 {
914     return floatInVec( mVec128, idx );
915 }
916
917 __forceinline const Vector4 Vector4::operator +( const Vector4 &vec ) const
918 {
919     return Vector4( _mm_add_ps( mVec128, vec.mVec128 ) );
920 }
921
922 __forceinline const Vector4 Vector4::operator -( const Vector4 &vec ) const
923 {
924     return Vector4( _mm_sub_ps( mVec128, vec.mVec128 ) );
925 }
926
927 __forceinline const Vector4 Vector4::operator *( float scalar ) const
928 {
929     return *this * floatInVec(scalar);
930 }
931
932 __forceinline const Vector4 Vector4::operator *( const floatInVec &scalar ) const
933 {
934     return Vector4( _mm_mul_ps( mVec128, scalar.get128() ) );
935 }
936
937 __forceinline Vector4 & Vector4::operator +=( const Vector4 &vec )
938 {
939     *this = *this + vec;
940     return *this;
941 }
942
943 __forceinline Vector4 & Vector4::operator -=( const Vector4 &vec )
944 {
945     *this = *this - vec;
946     return *this;
947 }
948
949 __forceinline Vector4 & Vector4::operator *=( float scalar )
950 {
951     *this = *this * scalar;
952     return *this;
953 }
954
955 __forceinline Vector4 & Vector4::operator *=( const floatInVec &scalar )
956 {
957     *this = *this * scalar;
958     return *this;
959 }
960
961 __forceinline const Vector4 Vector4::operator /( float scalar ) const
962 {
963     return *this / floatInVec(scalar);
964 }
965
966 __forceinline const Vector4 Vector4::operator /( const floatInVec &scalar ) const
967 {
968     return Vector4( _mm_div_ps( mVec128, scalar.get128() ) );
969 }
970
971 __forceinline Vector4 & Vector4::operator /=( float scalar )
972 {
973     *this = *this / scalar;
974     return *this;
975 }
976
977 __forceinline Vector4 & Vector4::operator /=( const floatInVec &scalar )
978 {
979     *this = *this / scalar;
980     return *this;
981 }
982
983 __forceinline const Vector4 Vector4::operator -( ) const
984 {
985         return Vector4(_mm_sub_ps( _mm_setzero_ps(), mVec128 ) );
986 }
987
988 __forceinline const Vector4 operator *( float scalar, const Vector4 &vec )
989 {
990     return floatInVec(scalar) * vec;
991 }
992
993 __forceinline const Vector4 operator *( const floatInVec &scalar, const Vector4 &vec )
994 {
995     return vec * scalar;
996 }
997
998 __forceinline const Vector4 mulPerElem( const Vector4 &vec0, const Vector4 &vec1 )
999 {
1000     return Vector4( _mm_mul_ps( vec0.get128(), vec1.get128() ) );
1001 }
1002
1003 __forceinline const Vector4 divPerElem( const Vector4 &vec0, const Vector4 &vec1 )
1004 {
1005     return Vector4( _mm_div_ps( vec0.get128(), vec1.get128() ) );
1006 }
1007
1008 __forceinline const Vector4 recipPerElem( const Vector4 &vec )
1009 {
1010     return Vector4( _mm_rcp_ps( vec.get128() ) );
1011 }
1012
1013 __forceinline const Vector4 absPerElem( const Vector4 &vec )
1014 {
1015     return Vector4( fabsf4( vec.get128() ) );
1016 }
1017
1018 __forceinline const Vector4 copySignPerElem( const Vector4 &vec0, const Vector4 &vec1 )
1019 {
1020         __m128 vmask = toM128(0x7fffffff);
1021         return Vector4( _mm_or_ps(
1022                 _mm_and_ps   ( vmask, vec0.get128() ),                  // Value
1023                 _mm_andnot_ps( vmask, vec1.get128() ) ) );              // Signs
1024 }
1025
1026 __forceinline const Vector4 maxPerElem( const Vector4 &vec0, const Vector4 &vec1 )
1027 {
1028     return Vector4( _mm_max_ps( vec0.get128(), vec1.get128() ) );
1029 }
1030
1031 __forceinline const floatInVec maxElem( const Vector4 &vec )
1032 {
1033     return floatInVec( _mm_max_ps(
1034                 _mm_max_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ),
1035                 _mm_max_ps( vec_splat( vec.get128(), 2 ), vec_splat( vec.get128(), 3 ) ) ) );
1036 }
1037
1038 __forceinline const Vector4 minPerElem( const Vector4 &vec0, const Vector4 &vec1 )
1039 {
1040     return Vector4( _mm_min_ps( vec0.get128(), vec1.get128() ) );
1041 }
1042
1043 __forceinline const floatInVec minElem( const Vector4 &vec )
1044 {
1045     return floatInVec( _mm_min_ps(
1046                 _mm_min_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ),
1047                 _mm_min_ps( vec_splat( vec.get128(), 2 ), vec_splat( vec.get128(), 3 ) ) ) );
1048 }
1049
1050 __forceinline const floatInVec sum( const Vector4 &vec )
1051 {
1052     return floatInVec( _mm_add_ps(
1053                 _mm_add_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ),
1054                 _mm_add_ps( vec_splat( vec.get128(), 2 ), vec_splat( vec.get128(), 3 ) ) ) );
1055 }
1056
1057 __forceinline const floatInVec dot( const Vector4 &vec0, const Vector4 &vec1 )
1058 {
1059     return floatInVec( _vmathVfDot4( vec0.get128(), vec1.get128() ), 0 );
1060 }
1061
1062 __forceinline const floatInVec lengthSqr( const Vector4 &vec )
1063 {
1064     return floatInVec(  _vmathVfDot4( vec.get128(), vec.get128() ), 0 );
1065 }
1066
1067 __forceinline const floatInVec length( const Vector4 &vec )
1068 {
1069     return floatInVec(  _mm_sqrt_ps(_vmathVfDot4( vec.get128(), vec.get128() )), 0 );
1070 }
1071
1072 __forceinline const Vector4 normalizeApprox( const Vector4 &vec )
1073 {
1074     return Vector4( _mm_mul_ps( vec.get128(), _mm_rsqrt_ps( _vmathVfDot4( vec.get128(), vec.get128() ) ) ) );
1075 }
1076
1077 __forceinline const Vector4 normalize( const Vector4 &vec )
1078 {
1079     return Vector4( _mm_mul_ps( vec.get128(), newtonrapson_rsqrt4( _vmathVfDot4( vec.get128(), vec.get128() ) ) ) );
1080 }
1081
1082 __forceinline const Vector4 select( const Vector4 &vec0, const Vector4 &vec1, bool select1 )
1083 {
1084     return select( vec0, vec1, boolInVec(select1) );
1085 }
1086
1087
1088 #ifdef _VECTORMATH_DEBUG
1089
1090 __forceinline void print( const Vector4 &vec )
1091 {
1092     union { __m128 v; float s[4]; } tmp;
1093     tmp.v = vec.get128();
1094     printf( "( %f %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] );
1095 }
1096
1097 __forceinline void print( const Vector4 &vec, const char * name )
1098 {
1099     union { __m128 v; float s[4]; } tmp;
1100     tmp.v = vec.get128();
1101     printf( "%s: ( %f %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] );
1102 }
1103
1104 #endif
1105
1106 __forceinline Point3::Point3( float _x, float _y, float _z )
1107 {
1108     mVec128 = _mm_setr_ps(_x, _y, _z, 0.0f);
1109 }
1110
1111 __forceinline Point3::Point3( const floatInVec &_x, const floatInVec &_y, const floatInVec &_z )
1112 {
1113         mVec128 = _mm_unpacklo_ps( _mm_unpacklo_ps( _x.get128(), _z.get128() ), _y.get128() );
1114 }
1115
1116 __forceinline Point3::Point3( const Vector3 &vec )
1117 {
1118     mVec128 = vec.get128();
1119 }
1120
1121 __forceinline Point3::Point3( float scalar )
1122 {
1123     mVec128 = floatInVec(scalar).get128();
1124 }
1125
1126 __forceinline Point3::Point3( const floatInVec &scalar )
1127 {
1128     mVec128 = scalar.get128();
1129 }
1130
1131 __forceinline Point3::Point3( __m128 vf4 )
1132 {
1133     mVec128 = vf4;
1134 }
1135
1136 __forceinline const Point3 lerp( float t, const Point3 &pnt0, const Point3 &pnt1 )
1137 {
1138     return lerp( floatInVec(t), pnt0, pnt1 );
1139 }
1140
1141 __forceinline const Point3 lerp( const floatInVec &t, const Point3 &pnt0, const Point3 &pnt1 )
1142 {
1143     return ( pnt0 + ( ( pnt1 - pnt0 ) * t ) );
1144 }
1145
1146 __forceinline __m128 Point3::get128( ) const
1147 {
1148     return mVec128;
1149 }
1150
1151 __forceinline void storeXYZ( const Point3 &pnt, __m128 * quad )
1152 {
1153     __m128 dstVec = *quad;
1154         __declspec(align(16)) unsigned int sw[4] = {0, 0, 0, 0xffffffff}; // TODO: Centralize
1155     dstVec = vec_sel(pnt.get128(), dstVec, sw);
1156     *quad = dstVec;
1157 }
1158
1159 __forceinline void loadXYZArray( Point3 & pnt0, Point3 & pnt1, Point3 & pnt2, Point3 & pnt3, const __m128 * threeQuads )
1160 {
1161         const float *quads = (float *)threeQuads;
1162     pnt0 = Point3(  _mm_load_ps(quads) );
1163     pnt1 = Point3( _mm_loadu_ps(quads + 3) );
1164     pnt2 = Point3( _mm_loadu_ps(quads + 6) );
1165     pnt3 = Point3( _mm_loadu_ps(quads + 9) );
1166 }
1167
1168 __forceinline void storeXYZArray( const Point3 &pnt0, const Point3 &pnt1, const Point3 &pnt2, const Point3 &pnt3, __m128 * threeQuads )
1169 {
1170         __m128 xxxx = _mm_shuffle_ps( pnt1.get128(), pnt1.get128(), _MM_SHUFFLE(0, 0, 0, 0) );
1171         __m128 zzzz = _mm_shuffle_ps( pnt2.get128(), pnt2.get128(), _MM_SHUFFLE(2, 2, 2, 2) );
1172         __declspec(align(16)) unsigned int xsw[4] = {0, 0, 0, 0xffffffff};
1173         __declspec(align(16)) unsigned int zsw[4] = {0xffffffff, 0, 0, 0};
1174         threeQuads[0] = vec_sel( pnt0.get128(), xxxx, xsw );
1175     threeQuads[1] = _mm_shuffle_ps( pnt1.get128(), pnt2.get128(), _MM_SHUFFLE(1, 0, 2, 1) );
1176     threeQuads[2] = vec_sel( _mm_shuffle_ps( pnt3.get128(), pnt3.get128(), _MM_SHUFFLE(2, 1, 0, 3) ), zzzz, zsw );
1177 }
1178 /*
1179 __forceinline void storeHalfFloats( const Point3 &pnt0, const Point3 &pnt1, const Point3 &pnt2, const Point3 &pnt3, const Point3 &pnt4, const Point3 &pnt5, const Point3 &pnt6, const Point3 &pnt7, vec_ushort8 * threeQuads )
1180 {
1181 #if 0
1182     __m128 xyz0[3];
1183     __m128 xyz1[3];
1184     storeXYZArray( pnt0, pnt1, pnt2, pnt3, xyz0 );
1185     storeXYZArray( pnt4, pnt5, pnt6, pnt7, xyz1 );
1186     threeQuads[0] = _vmath2VfToHalfFloats(xyz0[0], xyz0[1]);
1187     threeQuads[1] = _vmath2VfToHalfFloats(xyz0[2], xyz1[0]);
1188     threeQuads[2] = _vmath2VfToHalfFloats(xyz1[1], xyz1[2]);
1189 #else
1190         assert(0);
1191 #endif
1192 }
1193 */
1194 __forceinline Point3 & Point3::operator =( const Point3 &pnt )
1195 {
1196     mVec128 = pnt.mVec128;
1197     return *this;
1198 }
1199
1200 __forceinline Point3 & Point3::setX( float _x )
1201 {
1202     _vmathVfSetElement(mVec128, _x, 0);
1203     return *this;
1204 }
1205
1206 __forceinline Point3 & Point3::setX( const floatInVec &_x )
1207 {
1208     mVec128 = _vmathVfInsert(mVec128, _x.get128(), 0);
1209     return *this;
1210 }
1211
1212 __forceinline const floatInVec Point3::getX( ) const
1213 {
1214     return floatInVec( mVec128, 0 );
1215 }
1216
1217 __forceinline Point3 & Point3::setY( float _y )
1218 {
1219     _vmathVfSetElement(mVec128, _y, 1);
1220     return *this;
1221 }
1222
1223 __forceinline Point3 & Point3::setY( const floatInVec &_y )
1224 {
1225     mVec128 = _vmathVfInsert(mVec128, _y.get128(), 1);
1226     return *this;
1227 }
1228
1229 __forceinline const floatInVec Point3::getY( ) const
1230 {
1231     return floatInVec( mVec128, 1 );
1232 }
1233
1234 __forceinline Point3 & Point3::setZ( float _z )
1235 {
1236     _vmathVfSetElement(mVec128, _z, 2);
1237     return *this;
1238 }
1239
1240 __forceinline Point3 & Point3::setZ( const floatInVec &_z )
1241 {
1242     mVec128 = _vmathVfInsert(mVec128, _z.get128(), 2);
1243     return *this;
1244 }
1245
1246 __forceinline const floatInVec Point3::getZ( ) const
1247 {
1248     return floatInVec( mVec128, 2 );
1249 }
1250
1251 __forceinline Point3 & Point3::setElem( int idx, float value )
1252 {
1253     _vmathVfSetElement(mVec128, value, idx);
1254     return *this;
1255 }
1256
1257 __forceinline Point3 & Point3::setElem( int idx, const floatInVec &value )
1258 {
1259     mVec128 = _vmathVfInsert(mVec128, value.get128(), idx);
1260     return *this;
1261 }
1262
1263 __forceinline const floatInVec Point3::getElem( int idx ) const
1264 {
1265     return floatInVec( mVec128, idx );
1266 }
1267
1268 __forceinline VecIdx Point3::operator []( int idx )
1269 {
1270     return VecIdx( mVec128, idx );
1271 }
1272
1273 __forceinline const floatInVec Point3::operator []( int idx ) const
1274 {
1275     return floatInVec( mVec128, idx );
1276 }
1277
1278 __forceinline const Vector3 Point3::operator -( const Point3 &pnt ) const
1279 {
1280     return Vector3( _mm_sub_ps( mVec128, pnt.mVec128 ) );
1281 }
1282
1283 __forceinline const Point3 Point3::operator +( const Vector3 &vec ) const
1284 {
1285     return Point3( _mm_add_ps( mVec128, vec.get128() ) );
1286 }
1287
1288 __forceinline const Point3 Point3::operator -( const Vector3 &vec ) const
1289 {
1290     return Point3( _mm_sub_ps( mVec128, vec.get128() ) );
1291 }
1292
1293 __forceinline Point3 & Point3::operator +=( const Vector3 &vec )
1294 {
1295     *this = *this + vec;
1296     return *this;
1297 }
1298
1299 __forceinline Point3 & Point3::operator -=( const Vector3 &vec )
1300 {
1301     *this = *this - vec;
1302     return *this;
1303 }
1304
1305 __forceinline const Point3 mulPerElem( const Point3 &pnt0, const Point3 &pnt1 )
1306 {
1307     return Point3( _mm_mul_ps( pnt0.get128(), pnt1.get128() ) );
1308 }
1309
1310 __forceinline const Point3 divPerElem( const Point3 &pnt0, const Point3 &pnt1 )
1311 {
1312     return Point3( _mm_div_ps( pnt0.get128(), pnt1.get128() ) );
1313 }
1314
1315 __forceinline const Point3 recipPerElem( const Point3 &pnt )
1316 {
1317     return Point3( _mm_rcp_ps( pnt.get128() ) );
1318 }
1319
1320 __forceinline const Point3 absPerElem( const Point3 &pnt )
1321 {
1322     return Point3( fabsf4( pnt.get128() ) );
1323 }
1324
1325 __forceinline const Point3 copySignPerElem( const Point3 &pnt0, const Point3 &pnt1 )
1326 {
1327         __m128 vmask = toM128(0x7fffffff);
1328         return Point3( _mm_or_ps(
1329                 _mm_and_ps   ( vmask, pnt0.get128() ),                  // Value
1330                 _mm_andnot_ps( vmask, pnt1.get128() ) ) );              // Signs
1331 }
1332
1333 __forceinline const Point3 maxPerElem( const Point3 &pnt0, const Point3 &pnt1 )
1334 {
1335     return Point3( _mm_max_ps( pnt0.get128(), pnt1.get128() ) );
1336 }
1337
1338 __forceinline const floatInVec maxElem( const Point3 &pnt )
1339 {
1340     return floatInVec( _mm_max_ps( _mm_max_ps( vec_splat( pnt.get128(), 0 ), vec_splat( pnt.get128(), 1 ) ), vec_splat( pnt.get128(), 2 ) ) );
1341 }
1342
1343 __forceinline const Point3 minPerElem( const Point3 &pnt0, const Point3 &pnt1 )
1344 {
1345     return Point3( _mm_min_ps( pnt0.get128(), pnt1.get128() ) );
1346 }
1347
1348 __forceinline const floatInVec minElem( const Point3 &pnt )
1349 {
1350     return floatInVec( _mm_min_ps( _mm_min_ps( vec_splat( pnt.get128(), 0 ), vec_splat( pnt.get128(), 1 ) ), vec_splat( pnt.get128(), 2 ) ) );
1351 }
1352
1353 __forceinline const floatInVec sum( const Point3 &pnt )
1354 {
1355     return floatInVec( _mm_add_ps( _mm_add_ps( vec_splat( pnt.get128(), 0 ), vec_splat( pnt.get128(), 1 ) ), vec_splat( pnt.get128(), 2 ) ) );
1356 }
1357
1358 __forceinline const Point3 scale( const Point3 &pnt, float scaleVal )
1359 {
1360     return scale( pnt, floatInVec( scaleVal ) );
1361 }
1362
1363 __forceinline const Point3 scale( const Point3 &pnt, const floatInVec &scaleVal )
1364 {
1365     return mulPerElem( pnt, Point3( scaleVal ) );
1366 }
1367
1368 __forceinline const Point3 scale( const Point3 &pnt, const Vector3 &scaleVec )
1369 {
1370     return mulPerElem( pnt, Point3( scaleVec ) );
1371 }
1372
1373 __forceinline const floatInVec projection( const Point3 &pnt, const Vector3 &unitVec )
1374 {
1375     return floatInVec( _vmathVfDot3( pnt.get128(), unitVec.get128() ), 0 );
1376 }
1377
1378 __forceinline const floatInVec distSqrFromOrigin( const Point3 &pnt )
1379 {
1380     return lengthSqr( Vector3( pnt ) );
1381 }
1382
1383 __forceinline const floatInVec distFromOrigin( const Point3 &pnt )
1384 {
1385     return length( Vector3( pnt ) );
1386 }
1387
1388 __forceinline const floatInVec distSqr( const Point3 &pnt0, const Point3 &pnt1 )
1389 {
1390     return lengthSqr( ( pnt1 - pnt0 ) );
1391 }
1392
1393 __forceinline const floatInVec dist( const Point3 &pnt0, const Point3 &pnt1 )
1394 {
1395     return length( ( pnt1 - pnt0 ) );
1396 }
1397
1398 __forceinline const Point3 select( const Point3 &pnt0, const Point3 &pnt1, bool select1 )
1399 {
1400     return select( pnt0, pnt1, boolInVec(select1) );
1401 }
1402
1403 __forceinline const Point3 select( const Point3 &pnt0, const Point3 &pnt1, const boolInVec &select1 )
1404 {
1405     return Point3( vec_sel( pnt0.get128(), pnt1.get128(), select1.get128() ) );
1406 }
1407
1408
1409
1410 #ifdef _VECTORMATH_DEBUG
1411
1412 __forceinline void print( const Point3 &pnt )
1413 {
1414     union { __m128 v; float s[4]; } tmp;
1415     tmp.v = pnt.get128();
1416     printf( "( %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2] );
1417 }
1418
1419 __forceinline void print( const Point3 &pnt, const char * name )
1420 {
1421     union { __m128 v; float s[4]; } tmp;
1422     tmp.v = pnt.get128();
1423     printf( "%s: ( %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2] );
1424 }
1425
1426 #endif
1427
1428 } // namespace Aos
1429 } // namespace Vectormath
1430
1431 #endif