1 /*
2    Copyright (C) 2006, 2007 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_QUAT_AOS_CPP_H
31 #define _VECTORMATH_QUAT_AOS_CPP_H
32 
33 //-----------------------------------------------------------------------------
34 // Definitions
35 
36 #ifndef _VECTORMATH_INTERNAL_FUNCTIONS
37 #define _VECTORMATH_INTERNAL_FUNCTIONS
38 
39 #endif
40 
41 namespace Vectormath
42 {
43 namespace Aos
44 {
set128(vec_float4 vec)45 VECTORMATH_FORCE_INLINE void Quat::set128(vec_float4 vec)
46 {
47 	mVec128 = vec;
48 }
49 
Quat(const floatInVec & _x,const floatInVec & _y,const floatInVec & _z,const floatInVec & _w)50 VECTORMATH_FORCE_INLINE Quat::Quat(const floatInVec &_x, const floatInVec &_y, const floatInVec &_z, const floatInVec &_w)
51 {
52 	mVec128 = _mm_unpacklo_ps(
53 		_mm_unpacklo_ps(_x.get128(), _z.get128()),
54 		_mm_unpacklo_ps(_y.get128(), _w.get128()));
55 }
56 
Quat(const Vector3 & xyz,float _w)57 VECTORMATH_FORCE_INLINE Quat::Quat(const Vector3 &xyz, float _w)
58 {
59 	mVec128 = xyz.get128();
60 	_vmathVfSetElement(mVec128, _w, 3);
61 }
62 
Quat(const Quat & quat)63 VECTORMATH_FORCE_INLINE Quat::Quat(const Quat &quat)
64 {
65 	mVec128 = quat.get128();
66 }
67 
Quat(float _x,float _y,float _z,float _w)68 VECTORMATH_FORCE_INLINE Quat::Quat(float _x, float _y, float _z, float _w)
69 {
70 	mVec128 = _mm_setr_ps(_x, _y, _z, _w);
71 }
72 
Quat(const Vector3 & xyz,const floatInVec & _w)73 VECTORMATH_FORCE_INLINE Quat::Quat(const Vector3 &xyz, const floatInVec &_w)
74 {
75 	mVec128 = xyz.get128();
76 	mVec128 = _vmathVfInsert(mVec128, _w.get128(), 3);
77 }
78 
Quat(const Vector4 & vec)79 VECTORMATH_FORCE_INLINE Quat::Quat(const Vector4 &vec)
80 {
81 	mVec128 = vec.get128();
82 }
83 
Quat(float scalar)84 VECTORMATH_FORCE_INLINE Quat::Quat(float scalar)
85 {
86 	mVec128 = floatInVec(scalar).get128();
87 }
88 
Quat(const floatInVec & scalar)89 VECTORMATH_FORCE_INLINE Quat::Quat(const floatInVec &scalar)
90 {
91 	mVec128 = scalar.get128();
92 }
93 
Quat(__m128 vf4)94 VECTORMATH_FORCE_INLINE Quat::Quat(__m128 vf4)
95 {
96 	mVec128 = vf4;
97 }
98 
identity()99 VECTORMATH_FORCE_INLINE const Quat Quat::identity()
100 {
101 	return Quat(_VECTORMATH_UNIT_0001);
102 }
103 
lerp(float t,const Quat & quat0,const Quat & quat1)104 VECTORMATH_FORCE_INLINE const Quat lerp(float t, const Quat &quat0, const Quat &quat1)
105 {
106 	return lerp(floatInVec(t), quat0, quat1);
107 }
108 
lerp(const floatInVec & t,const Quat & quat0,const Quat & quat1)109 VECTORMATH_FORCE_INLINE const Quat lerp(const floatInVec &t, const Quat &quat0, const Quat &quat1)
110 {
111 	return (quat0 + ((quat1 - quat0) * t));
112 }
113 
slerp(float t,const Quat & unitQuat0,const Quat & unitQuat1)114 VECTORMATH_FORCE_INLINE const Quat slerp(float t, const Quat &unitQuat0, const Quat &unitQuat1)
115 {
116 	return slerp(floatInVec(t), unitQuat0, unitQuat1);
117 }
118 
slerp(const floatInVec & t,const Quat & unitQuat0,const Quat & unitQuat1)119 VECTORMATH_FORCE_INLINE const Quat slerp(const floatInVec &t, const Quat &unitQuat0, const Quat &unitQuat1)
120 {
121 	Quat start;
122 	vec_float4 scales, scale0, scale1, cosAngle, angle, tttt, oneMinusT, angles, sines;
123 	__m128 selectMask;
124 	cosAngle = _vmathVfDot4(unitQuat0.get128(), unitQuat1.get128());
125 	selectMask = (__m128)vec_cmpgt(_mm_setzero_ps(), cosAngle);
126 	cosAngle = vec_sel(cosAngle, negatef4(cosAngle), selectMask);
127 	start = Quat(vec_sel(unitQuat0.get128(), negatef4(unitQuat0.get128()), selectMask));
128 	selectMask = (__m128)vec_cmpgt(_mm_set1_ps(_VECTORMATH_SLERP_TOL), cosAngle);
129 	angle = acosf4(cosAngle);
130 	tttt = t.get128();
131 	oneMinusT = vec_sub(_mm_set1_ps(1.0f), tttt);
132 	angles = vec_mergeh(_mm_set1_ps(1.0f), tttt);
133 	angles = vec_mergeh(angles, oneMinusT);
134 	angles = vec_madd(angles, angle, _mm_setzero_ps());
135 	sines = sinf4(angles);
136 	scales = _mm_div_ps(sines, vec_splat(sines, 0));
137 	scale0 = vec_sel(oneMinusT, vec_splat(scales, 1), selectMask);
138 	scale1 = vec_sel(tttt, vec_splat(scales, 2), selectMask);
139 	return Quat(vec_madd(start.get128(), scale0, vec_mul(unitQuat1.get128(), scale1)));
140 }
141 
squad(float t,const Quat & unitQuat0,const Quat & unitQuat1,const Quat & unitQuat2,const Quat & unitQuat3)142 VECTORMATH_FORCE_INLINE const Quat squad(float t, const Quat &unitQuat0, const Quat &unitQuat1, const Quat &unitQuat2, const Quat &unitQuat3)
143 {
144 	return squad(floatInVec(t), unitQuat0, unitQuat1, unitQuat2, unitQuat3);
145 }
146 
squad(const floatInVec & t,const Quat & unitQuat0,const Quat & unitQuat1,const Quat & unitQuat2,const Quat & unitQuat3)147 VECTORMATH_FORCE_INLINE const Quat squad(const floatInVec &t, const Quat &unitQuat0, const Quat &unitQuat1, const Quat &unitQuat2, const Quat &unitQuat3)
148 {
149 	return slerp(((floatInVec(2.0f) * t) * (floatInVec(1.0f) - t)), slerp(t, unitQuat0, unitQuat3), slerp(t, unitQuat1, unitQuat2));
150 }
151 
get128()152 VECTORMATH_FORCE_INLINE __m128 Quat::get128() const
153 {
154 	return mVec128;
155 }
156 
157 VECTORMATH_FORCE_INLINE Quat &Quat::operator=(const Quat &quat)
158 {
159 	mVec128 = quat.mVec128;
160 	return *this;
161 }
162 
setXYZ(const Vector3 & vec)163 VECTORMATH_FORCE_INLINE Quat &Quat::setXYZ(const Vector3 &vec)
164 {
165 	VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff};
166 	mVec128 = vec_sel(vec.get128(), mVec128, sw);
167 	return *this;
168 }
169 
getXYZ()170 VECTORMATH_FORCE_INLINE const Vector3 Quat::getXYZ() const
171 {
172 	return Vector3(mVec128);
173 }
174 
setX(float _x)175 VECTORMATH_FORCE_INLINE Quat &Quat::setX(float _x)
176 {
177 	_vmathVfSetElement(mVec128, _x, 0);
178 	return *this;
179 }
180 
setX(const floatInVec & _x)181 VECTORMATH_FORCE_INLINE Quat &Quat::setX(const floatInVec &_x)
182 {
183 	mVec128 = _vmathVfInsert(mVec128, _x.get128(), 0);
184 	return *this;
185 }
186 
getX()187 VECTORMATH_FORCE_INLINE const floatInVec Quat::getX() const
188 {
189 	return floatInVec(mVec128, 0);
190 }
191 
setY(float _y)192 VECTORMATH_FORCE_INLINE Quat &Quat::setY(float _y)
193 {
194 	_vmathVfSetElement(mVec128, _y, 1);
195 	return *this;
196 }
197 
setY(const floatInVec & _y)198 VECTORMATH_FORCE_INLINE Quat &Quat::setY(const floatInVec &_y)
199 {
200 	mVec128 = _vmathVfInsert(mVec128, _y.get128(), 1);
201 	return *this;
202 }
203 
getY()204 VECTORMATH_FORCE_INLINE const floatInVec Quat::getY() const
205 {
206 	return floatInVec(mVec128, 1);
207 }
208 
setZ(float _z)209 VECTORMATH_FORCE_INLINE Quat &Quat::setZ(float _z)
210 {
211 	_vmathVfSetElement(mVec128, _z, 2);
212 	return *this;
213 }
214 
setZ(const floatInVec & _z)215 VECTORMATH_FORCE_INLINE Quat &Quat::setZ(const floatInVec &_z)
216 {
217 	mVec128 = _vmathVfInsert(mVec128, _z.get128(), 2);
218 	return *this;
219 }
220 
getZ()221 VECTORMATH_FORCE_INLINE const floatInVec Quat::getZ() const
222 {
223 	return floatInVec(mVec128, 2);
224 }
225 
setW(float _w)226 VECTORMATH_FORCE_INLINE Quat &Quat::setW(float _w)
227 {
228 	_vmathVfSetElement(mVec128, _w, 3);
229 	return *this;
230 }
231 
setW(const floatInVec & _w)232 VECTORMATH_FORCE_INLINE Quat &Quat::setW(const floatInVec &_w)
233 {
234 	mVec128 = _vmathVfInsert(mVec128, _w.get128(), 3);
235 	return *this;
236 }
237 
getW()238 VECTORMATH_FORCE_INLINE const floatInVec Quat::getW() const
239 {
240 	return floatInVec(mVec128, 3);
241 }
242 
setElem(int idx,float value)243 VECTORMATH_FORCE_INLINE Quat &Quat::setElem(int idx, float value)
244 {
245 	_vmathVfSetElement(mVec128, value, idx);
246 	return *this;
247 }
248 
setElem(int idx,const floatInVec & value)249 VECTORMATH_FORCE_INLINE Quat &Quat::setElem(int idx, const floatInVec &value)
250 {
251 	mVec128 = _vmathVfInsert(mVec128, value.get128(), idx);
252 	return *this;
253 }
254 
getElem(int idx)255 VECTORMATH_FORCE_INLINE const floatInVec Quat::getElem(int idx) const
256 {
257 	return floatInVec(mVec128, idx);
258 }
259 
260 VECTORMATH_FORCE_INLINE VecIdx Quat::operator[](int idx)
261 {
262 	return VecIdx(mVec128, idx);
263 }
264 
265 VECTORMATH_FORCE_INLINE const floatInVec Quat::operator[](int idx) const
266 {
267 	return floatInVec(mVec128, idx);
268 }
269 
270 VECTORMATH_FORCE_INLINE const Quat Quat::operator+(const Quat &quat) const
271 {
272 	return Quat(_mm_add_ps(mVec128, quat.mVec128));
273 }
274 
275 VECTORMATH_FORCE_INLINE const Quat Quat::operator-(const Quat &quat) const
276 {
277 	return Quat(_mm_sub_ps(mVec128, quat.mVec128));
278 }
279 
280 VECTORMATH_FORCE_INLINE const Quat Quat::operator*(float scalar) const
281 {
282 	return *this * floatInVec(scalar);
283 }
284 
285 VECTORMATH_FORCE_INLINE const Quat Quat::operator*(const floatInVec &scalar) const
286 {
287 	return Quat(_mm_mul_ps(mVec128, scalar.get128()));
288 }
289 
290 VECTORMATH_FORCE_INLINE Quat &Quat::operator+=(const Quat &quat)
291 {
292 	*this = *this + quat;
293 	return *this;
294 }
295 
296 VECTORMATH_FORCE_INLINE Quat &Quat::operator-=(const Quat &quat)
297 {
298 	*this = *this - quat;
299 	return *this;
300 }
301 
302 VECTORMATH_FORCE_INLINE Quat &Quat::operator*=(float scalar)
303 {
304 	*this = *this * scalar;
305 	return *this;
306 }
307 
308 VECTORMATH_FORCE_INLINE Quat &Quat::operator*=(const floatInVec &scalar)
309 {
310 	*this = *this * scalar;
311 	return *this;
312 }
313 
314 VECTORMATH_FORCE_INLINE const Quat Quat::operator/(float scalar) const
315 {
316 	return *this / floatInVec(scalar);
317 }
318 
319 VECTORMATH_FORCE_INLINE const Quat Quat::operator/(const floatInVec &scalar) const
320 {
321 	return Quat(_mm_div_ps(mVec128, scalar.get128()));
322 }
323 
324 VECTORMATH_FORCE_INLINE Quat &Quat::operator/=(float scalar)
325 {
326 	*this = *this / scalar;
327 	return *this;
328 }
329 
330 VECTORMATH_FORCE_INLINE Quat &Quat::operator/=(const floatInVec &scalar)
331 {
332 	*this = *this / scalar;
333 	return *this;
334 }
335 
336 VECTORMATH_FORCE_INLINE const Quat Quat::operator-() const
337 {
338 	return Quat(_mm_sub_ps(_mm_setzero_ps(), mVec128));
339 }
340 
341 VECTORMATH_FORCE_INLINE const Quat operator*(float scalar, const Quat &quat)
342 {
343 	return floatInVec(scalar) * quat;
344 }
345 
346 VECTORMATH_FORCE_INLINE const Quat operator*(const floatInVec &scalar, const Quat &quat)
347 {
348 	return quat * scalar;
349 }
350 
dot(const Quat & quat0,const Quat & quat1)351 VECTORMATH_FORCE_INLINE const floatInVec dot(const Quat &quat0, const Quat &quat1)
352 {
353 	return floatInVec(_vmathVfDot4(quat0.get128(), quat1.get128()), 0);
354 }
355 
norm(const Quat & quat)356 VECTORMATH_FORCE_INLINE const floatInVec norm(const Quat &quat)
357 {
358 	return floatInVec(_vmathVfDot4(quat.get128(), quat.get128()), 0);
359 }
360 
length(const Quat & quat)361 VECTORMATH_FORCE_INLINE const floatInVec length(const Quat &quat)
362 {
363 	return floatInVec(_mm_sqrt_ps(_vmathVfDot4(quat.get128(), quat.get128())), 0);
364 }
365 
normalize(const Quat & quat)366 VECTORMATH_FORCE_INLINE const Quat normalize(const Quat &quat)
367 {
368 	vec_float4 dot = _vmathVfDot4(quat.get128(), quat.get128());
369 	return Quat(_mm_mul_ps(quat.get128(), newtonrapson_rsqrt4(dot)));
370 }
371 
rotation(const Vector3 & unitVec0,const Vector3 & unitVec1)372 VECTORMATH_FORCE_INLINE const Quat Quat::rotation(const Vector3 &unitVec0, const Vector3 &unitVec1)
373 {
374 	Vector3 crossVec;
375 	__m128 cosAngle, cosAngleX2Plus2, recipCosHalfAngleX2, cosHalfAngleX2, res;
376 	cosAngle = _vmathVfDot3(unitVec0.get128(), unitVec1.get128());
377 	cosAngleX2Plus2 = vec_madd(cosAngle, _mm_set1_ps(2.0f), _mm_set1_ps(2.0f));
378 	recipCosHalfAngleX2 = _mm_rsqrt_ps(cosAngleX2Plus2);
379 	cosHalfAngleX2 = vec_mul(recipCosHalfAngleX2, cosAngleX2Plus2);
380 	crossVec = cross(unitVec0, unitVec1);
381 	res = vec_mul(crossVec.get128(), recipCosHalfAngleX2);
382 	VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff};
383 	res = vec_sel(res, vec_mul(cosHalfAngleX2, _mm_set1_ps(0.5f)), sw);
384 	return Quat(res);
385 }
386 
rotation(float radians,const Vector3 & unitVec)387 VECTORMATH_FORCE_INLINE const Quat Quat::rotation(float radians, const Vector3 &unitVec)
388 {
389 	return rotation(floatInVec(radians), unitVec);
390 }
391 
rotation(const floatInVec & radians,const Vector3 & unitVec)392 VECTORMATH_FORCE_INLINE const Quat Quat::rotation(const floatInVec &radians, const Vector3 &unitVec)
393 {
394 	__m128 s, c, angle, res;
395 	angle = vec_mul(radians.get128(), _mm_set1_ps(0.5f));
396 	sincosf4(angle, &s, &c);
397 	VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff};
398 	res = vec_sel(vec_mul(unitVec.get128(), s), c, sw);
399 	return Quat(res);
400 }
401 
rotationX(float radians)402 VECTORMATH_FORCE_INLINE const Quat Quat::rotationX(float radians)
403 {
404 	return rotationX(floatInVec(radians));
405 }
406 
rotationX(const floatInVec & radians)407 VECTORMATH_FORCE_INLINE const Quat Quat::rotationX(const floatInVec &radians)
408 {
409 	__m128 s, c, angle, res;
410 	angle = vec_mul(radians.get128(), _mm_set1_ps(0.5f));
411 	sincosf4(angle, &s, &c);
412 	VM_ATTRIBUTE_ALIGN16 unsigned int xsw[4] = {0xffffffff, 0, 0, 0};
413 	VM_ATTRIBUTE_ALIGN16 unsigned int wsw[4] = {0, 0, 0, 0xffffffff};
414 	res = vec_sel(_mm_setzero_ps(), s, xsw);
415 	res = vec_sel(res, c, wsw);
416 	return Quat(res);
417 }
418 
rotationY(float radians)419 VECTORMATH_FORCE_INLINE const Quat Quat::rotationY(float radians)
420 {
421 	return rotationY(floatInVec(radians));
422 }
423 
rotationY(const floatInVec & radians)424 VECTORMATH_FORCE_INLINE const Quat Quat::rotationY(const floatInVec &radians)
425 {
426 	__m128 s, c, angle, res;
427 	angle = vec_mul(radians.get128(), _mm_set1_ps(0.5f));
428 	sincosf4(angle, &s, &c);
429 	VM_ATTRIBUTE_ALIGN16 unsigned int ysw[4] = {0, 0xffffffff, 0, 0};
430 	VM_ATTRIBUTE_ALIGN16 unsigned int wsw[4] = {0, 0, 0, 0xffffffff};
431 	res = vec_sel(_mm_setzero_ps(), s, ysw);
432 	res = vec_sel(res, c, wsw);
433 	return Quat(res);
434 }
435 
rotationZ(float radians)436 VECTORMATH_FORCE_INLINE const Quat Quat::rotationZ(float radians)
437 {
438 	return rotationZ(floatInVec(radians));
439 }
440 
rotationZ(const floatInVec & radians)441 VECTORMATH_FORCE_INLINE const Quat Quat::rotationZ(const floatInVec &radians)
442 {
443 	__m128 s, c, angle, res;
444 	angle = vec_mul(radians.get128(), _mm_set1_ps(0.5f));
445 	sincosf4(angle, &s, &c);
446 	VM_ATTRIBUTE_ALIGN16 unsigned int zsw[4] = {0, 0, 0xffffffff, 0};
447 	VM_ATTRIBUTE_ALIGN16 unsigned int wsw[4] = {0, 0, 0, 0xffffffff};
448 	res = vec_sel(_mm_setzero_ps(), s, zsw);
449 	res = vec_sel(res, c, wsw);
450 	return Quat(res);
451 }
452 
453 VECTORMATH_FORCE_INLINE const Quat Quat::operator*(const Quat &quat) const
454 {
455 	__m128 ldata, rdata, qv, tmp0, tmp1, tmp2, tmp3;
456 	__m128 product, l_wxyz, r_wxyz, xy, qw;
457 	ldata = mVec128;
458 	rdata = quat.mVec128;
459 	tmp0 = _mm_shuffle_ps(ldata, ldata, _MM_SHUFFLE(3, 0, 2, 1));
460 	tmp1 = _mm_shuffle_ps(rdata, rdata, _MM_SHUFFLE(3, 1, 0, 2));
461 	tmp2 = _mm_shuffle_ps(ldata, ldata, _MM_SHUFFLE(3, 1, 0, 2));
462 	tmp3 = _mm_shuffle_ps(rdata, rdata, _MM_SHUFFLE(3, 0, 2, 1));
463 	qv = vec_mul(vec_splat(ldata, 3), rdata);
464 	qv = vec_madd(vec_splat(rdata, 3), ldata, qv);
465 	qv = vec_madd(tmp0, tmp1, qv);
466 	qv = vec_nmsub(tmp2, tmp3, qv);
467 	product = vec_mul(ldata, rdata);
468 	l_wxyz = vec_sld(ldata, ldata, 12);
469 	r_wxyz = vec_sld(rdata, rdata, 12);
470 	qw = vec_nmsub(l_wxyz, r_wxyz, product);
471 	xy = vec_madd(l_wxyz, r_wxyz, product);
472 	qw = vec_sub(qw, vec_sld(xy, xy, 8));
473 	VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff};
474 	return Quat(vec_sel(qv, qw, sw));
475 }
476 
477 VECTORMATH_FORCE_INLINE Quat &Quat::operator*=(const Quat &quat)
478 {
479 	*this = *this * quat;
480 	return *this;
481 }
482 
rotate(const Quat & quat,const Vector3 & vec)483 VECTORMATH_FORCE_INLINE const Vector3 rotate(const Quat &quat, const Vector3 &vec)
484 {
485 	__m128 qdata, vdata, product, tmp0, tmp1, tmp2, tmp3, wwww, qv, qw, res;
486 	qdata = quat.get128();
487 	vdata = vec.get128();
488 	tmp0 = _mm_shuffle_ps(qdata, qdata, _MM_SHUFFLE(3, 0, 2, 1));
489 	tmp1 = _mm_shuffle_ps(vdata, vdata, _MM_SHUFFLE(3, 1, 0, 2));
490 	tmp2 = _mm_shuffle_ps(qdata, qdata, _MM_SHUFFLE(3, 1, 0, 2));
491 	tmp3 = _mm_shuffle_ps(vdata, vdata, _MM_SHUFFLE(3, 0, 2, 1));
492 	wwww = vec_splat(qdata, 3);
493 	qv = vec_mul(wwww, vdata);
494 	qv = vec_madd(tmp0, tmp1, qv);
495 	qv = vec_nmsub(tmp2, tmp3, qv);
496 	product = vec_mul(qdata, vdata);
497 	qw = vec_madd(vec_sld(qdata, qdata, 4), vec_sld(vdata, vdata, 4), product);
498 	qw = vec_add(vec_sld(product, product, 8), qw);
499 	tmp1 = _mm_shuffle_ps(qv, qv, _MM_SHUFFLE(3, 1, 0, 2));
500 	tmp3 = _mm_shuffle_ps(qv, qv, _MM_SHUFFLE(3, 0, 2, 1));
501 	res = vec_mul(vec_splat(qw, 0), qdata);
502 	res = vec_madd(wwww, qv, res);
503 	res = vec_madd(tmp0, tmp1, res);
504 	res = vec_nmsub(tmp2, tmp3, res);
505 	return Vector3(res);
506 }
507 
conj(const Quat & quat)508 VECTORMATH_FORCE_INLINE const Quat conj(const Quat &quat)
509 {
510 	VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0x80000000, 0x80000000, 0x80000000, 0};
511 	return Quat(vec_xor(quat.get128(), _mm_load_ps((float *)sw)));
512 }
513 
select(const Quat & quat0,const Quat & quat1,bool select1)514 VECTORMATH_FORCE_INLINE const Quat select(const Quat &quat0, const Quat &quat1, bool select1)
515 {
516 	return select(quat0, quat1, boolInVec(select1));
517 }
518 
519 //VECTORMATH_FORCE_INLINE const Quat select( const Quat &quat0, const Quat &quat1, const boolInVec &select1 )
520 //{
521 //    return Quat( vec_sel( quat0.get128(), quat1.get128(), select1.get128() ) );
522 //}
523 
loadXYZW(Quat & quat,const float * fptr)524 VECTORMATH_FORCE_INLINE void loadXYZW(Quat &quat, const float *fptr)
525 {
526 #ifdef USE_SSE3_LDDQU
527 	quat = Quat(SSEFloat(_mm_lddqu_si128((const __m128i *)((float *)(fptr)))).m128);
528 #else
529 	SSEFloat fl;
530 	fl.f[0] = fptr[0];
531 	fl.f[1] = fptr[1];
532 	fl.f[2] = fptr[2];
533 	fl.f[3] = fptr[3];
534 	quat = Quat(fl.m128);
535 #endif
536 }
537 
storeXYZW(const Quat & quat,float * fptr)538 VECTORMATH_FORCE_INLINE void storeXYZW(const Quat &quat, float *fptr)
539 {
540 	fptr[0] = quat.getX();
541 	fptr[1] = quat.getY();
542 	fptr[2] = quat.getZ();
543 	fptr[3] = quat.getW();
544 	//    _mm_storeu_ps((float*)quat.get128(),fptr);
545 }
546 
547 #ifdef _VECTORMATH_DEBUG
548 
print(const Quat & quat)549 VECTORMATH_FORCE_INLINE void print(const Quat &quat)
550 {
551 	union {
552 		__m128 v;
553 		float s[4];
554 	} tmp;
555 	tmp.v = quat.get128();
556 	printf("( %f %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3]);
557 }
558 
print(const Quat & quat,const char * name)559 VECTORMATH_FORCE_INLINE void print(const Quat &quat, const char *name)
560 {
561 	union {
562 		__m128 v;
563 		float s[4];
564 	} tmp;
565 	tmp.v = quat.get128();
566 	printf("%s: ( %f %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3]);
567 }
568 
569 #endif
570 
571 }  // namespace Aos
572 }  // namespace Vectormath
573 
574 #endif
575