RavEngine
Loading...
Searching...
No Matches
PxWindowsInlineAoS.h
1// Redistribution and use in source and binary forms, with or without
2// modification, are permitted provided that the following conditions
3// are met:
4// * Redistributions of source code must retain the above copyright
5// notice, this list of conditions and the following disclaimer.
6// * Redistributions in binary form must reproduce the above copyright
7// notice, this list of conditions and the following disclaimer in the
8// documentation and/or other materials provided with the distribution.
9// * Neither the name of NVIDIA CORPORATION nor the names of its
10// contributors may be used to endorse or promote products derived
11// from this software without specific prior written permission.
12//
13// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
14// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24//
25// Copyright (c) 2008-2022 NVIDIA Corporation. All rights reserved.
26// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
27// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
28
29#ifndef PX_WINDOWS_INLINE_AOS_H
30#define PX_WINDOWS_INLINE_AOS_H
31
32#if !COMPILE_VECTOR_INTRINSICS
33#error Vector intrinsics should not be included when using scalar implementation.
34#endif
35
36#include "../PxVecMathSSE.h"
37
38namespace physx
39{
40namespace aos
41{
42
44//Test that Vec3V and FloatV are legal
46
47#define FLOAT_COMPONENTS_EQUAL_THRESHOLD 0.01f
48PX_FORCE_INLINE bool isValidFloatV(const FloatV a)
49{
50 const PxF32 x = V4ReadX(a);
51 const PxF32 y = V4ReadY(a);
52 const PxF32 z = V4ReadZ(a);
53 const PxF32 w = V4ReadW(a);
54
55 return (!(x != y || x != z || x != w));
56
57 /*if (
58 (PxAbs(x - y) < FLOAT_COMPONENTS_EQUAL_THRESHOLD) &&
59 (PxAbs(x - z) < FLOAT_COMPONENTS_EQUAL_THRESHOLD) &&
60 (PxAbs(x - w) < FLOAT_COMPONENTS_EQUAL_THRESHOLD)
61 )
62 {
63 return true;
64 }
65
66 if (
67 (PxAbs((x - y) / x) < FLOAT_COMPONENTS_EQUAL_THRESHOLD) &&
68 (PxAbs((x - z) / x) < FLOAT_COMPONENTS_EQUAL_THRESHOLD) &&
69 (PxAbs((x - w) / x) < FLOAT_COMPONENTS_EQUAL_THRESHOLD)
70 )
71 {
72 return true;
73 }
74 return false;*/
75}
76
77PX_FORCE_INLINE bool isValidVec3V(const Vec3V a)
78{
79 //using _mm_comieq_ss to do the comparison doesn't work for NaN.
80 PX_ALIGN(16, PxF32 f[4]);
81 V4StoreA((const Vec4V&)a, f);
82 return f[3] == 0.0f;
83}
84
85PX_FORCE_INLINE bool isFiniteLength(const Vec3V a)
86{
87 return !FAllEq(V4LengthSq(a), FZero());
88}
89
90PX_FORCE_INLINE bool isAligned16(void* a)
91{
92 return(0 == ((size_t)a & 0x0f));
93}
94
95//ASSERT_FINITELENGTH is deactivated because there is a lot of code that calls a simd normalisation function with zero length but then ignores the result.
96
97#if PX_DEBUG
98#define ASSERT_ISVALIDVEC3V(a) PX_ASSERT(isValidVec3V(a))
99#define ASSERT_ISVALIDFLOATV(a) PX_ASSERT(isValidFloatV(a))
100#define ASSERT_ISALIGNED16(a) PX_ASSERT(isAligned16((void*)a))
101#define ASSERT_ISFINITELENGTH(a) //PX_ASSERT(isFiniteLength(a))
102#else
103#define ASSERT_ISVALIDVEC3V(a)
104#define ASSERT_ISVALIDFLOATV(a)
105#define ASSERT_ISALIGNED16(a)
106#define ASSERT_ISFINITELENGTH(a)
107#endif
111
113// USED ONLY INTERNALLY
115
116namespace internalWindowsSimd
117{
118PX_FORCE_INLINE __m128 m128_I2F(__m128i n)
119{
120 return _mm_castsi128_ps(n);
121}
122
123PX_FORCE_INLINE __m128i m128_F2I(__m128 n)
124{
125 return _mm_castps_si128(n);
126}
127
128PX_FORCE_INLINE PxU32 BAllTrue4_R(const BoolV a)
129{
130 const PxI32 moveMask = _mm_movemask_ps(a);
131 return PxU32(moveMask == 0xf);
132}
133
134PX_FORCE_INLINE PxU32 BAllTrue3_R(const BoolV a)
135{
136 const PxI32 moveMask = _mm_movemask_ps(a);
137 return PxU32((moveMask & 0x7) == 0x7);
138}
139
140PX_FORCE_INLINE PxU32 BAnyTrue4_R(const BoolV a)
141{
142 const PxI32 moveMask = _mm_movemask_ps(a);
143 return PxU32(moveMask != 0x0);
144}
145
146PX_FORCE_INLINE PxU32 BAnyTrue3_R(const BoolV a)
147{
148 const PxI32 moveMask = _mm_movemask_ps(a);
149 return PxU32(((moveMask & 0x7) != 0x0));
150}
151
152PX_FORCE_INLINE PxU32 FiniteTestEq(const Vec4V a, const Vec4V b)
153{
154 // This is a bit of a bodge.
155 //_mm_comieq_ss returns 1 if either value is nan so we need to re-cast a and b with true encoded as a non-nan
156 // number.
157 // There must be a better way of doing this in sse.
158 const BoolV one = FOne();
159 const BoolV zero = FZero();
160 const BoolV a1 = V4Sel(a, one, zero);
161 const BoolV b1 = V4Sel(b, one, zero);
162 return (PxU32(
163 _mm_comieq_ss(a1, b1) &&
164 _mm_comieq_ss(_mm_shuffle_ps(a1, a1, _MM_SHUFFLE(1, 1, 1, 1)), _mm_shuffle_ps(b1, b1, _MM_SHUFFLE(1, 1, 1, 1))) &&
165 _mm_comieq_ss(_mm_shuffle_ps(a1, a1, _MM_SHUFFLE(2, 2, 2, 2)), _mm_shuffle_ps(b1, b1, _MM_SHUFFLE(2, 2, 2, 2))) &&
166 _mm_comieq_ss(_mm_shuffle_ps(a1, a1, _MM_SHUFFLE(3, 3, 3, 3)), _mm_shuffle_ps(b1, b1, _MM_SHUFFLE(3, 3, 3, 3)))));
167}
168
169PX_FORCE_INLINE bool hasZeroElementinFloatV(const FloatV a)
170{
171 ASSERT_ISVALIDFLOATV(a);
172 return _mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0)), FZero()) ? true : false;
173}
174
175PX_FORCE_INLINE bool hasZeroElementInVec3V(const Vec3V a)
176{
177 return (_mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0)), FZero()) ||
178 _mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 1, 1, 1)), FZero()) ||
179 _mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2)), FZero()));
180}
181
182PX_FORCE_INLINE bool hasZeroElementInVec4V(const Vec4V a)
183{
184 return (_mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0)), FZero()) ||
185 _mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 1, 1, 1)), FZero()) ||
186 _mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2)), FZero()) ||
187 _mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 3, 3, 3)), FZero()));
188}
189
190const PX_ALIGN(16, PxU32 gMaskXYZ[4]) = { 0xffffffff, 0xffffffff, 0xffffffff, 0 };
191} //internalWindowsSimd
192
193namespace vecMathTests
194{
195// PT: this function returns an invalid Vec3V (W!=0.0f) just for unit-testing 'isValidVec3V'
196PX_FORCE_INLINE Vec3V getInvalidVec3V()
197{
198 const float f = 1.0f;
199 return _mm_load1_ps(&f);
200}
201
202PX_FORCE_INLINE bool allElementsEqualFloatV(const FloatV a, const FloatV b)
203{
204 ASSERT_ISVALIDFLOATV(a);
205 ASSERT_ISVALIDFLOATV(b);
206 return _mm_comieq_ss(a, b) != 0;
207}
208
209PX_FORCE_INLINE bool allElementsEqualVec3V(const Vec3V a, const Vec3V b)
210{
211 return V3AllEq(a, b) != 0;
212}
213
214PX_FORCE_INLINE bool allElementsEqualVec4V(const Vec4V a, const Vec4V b)
215{
216 return V4AllEq(a, b) != 0;
217}
218
219PX_FORCE_INLINE bool allElementsEqualBoolV(const BoolV a, const BoolV b)
220{
221 return internalWindowsSimd::BAllTrue4_R(VecI32V_IsEq(a, b)) != 0;
222}
223
224PX_FORCE_INLINE bool allElementsEqualVecU32V(const VecU32V a, const VecU32V b)
225{
226 return internalWindowsSimd::BAllTrue4_R(V4IsEqU32(a, b)) != 0;
227}
228
229PX_FORCE_INLINE bool allElementsEqualVecI32V(const VecI32V a, const VecI32V b)
230{
231 BoolV c = internalWindowsSimd::m128_I2F(
232 _mm_cmpeq_epi32(internalWindowsSimd::m128_F2I(a), internalWindowsSimd::m128_F2I(b)));
233 return internalWindowsSimd::BAllTrue4_R(c) != 0;
234}
235
236#define VECMATH_AOS_EPSILON (1e-3f)
237static const FloatV minFError = FLoad(-VECMATH_AOS_EPSILON);
238static const FloatV maxFError = FLoad(VECMATH_AOS_EPSILON);
239static const Vec3V minV3Error = V3Load(-VECMATH_AOS_EPSILON);
240static const Vec3V maxV3Error = V3Load(VECMATH_AOS_EPSILON);
241static const Vec4V minV4Error = V4Load(-VECMATH_AOS_EPSILON);
242static const Vec4V maxV4Error = V4Load(VECMATH_AOS_EPSILON);
243
244PX_FORCE_INLINE bool allElementsNearEqualFloatV(const FloatV a, const FloatV b)
245{
246 ASSERT_ISVALIDFLOATV(a);
247 ASSERT_ISVALIDFLOATV(b);
248 const FloatV c = FSub(a, b);
249 return _mm_comigt_ss(c, minFError) && _mm_comilt_ss(c, maxFError);
250}
251
252PX_FORCE_INLINE bool allElementsNearEqualVec3V(const Vec3V a, const Vec3V b)
253{
254 const Vec3V c = V3Sub(a, b);
255 return (_mm_comigt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(0, 0, 0, 0)), minV3Error) &&
256 _mm_comilt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(0, 0, 0, 0)), maxV3Error) &&
257 _mm_comigt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(1, 1, 1, 1)), minV3Error) &&
258 _mm_comilt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(1, 1, 1, 1)), maxV3Error) &&
259 _mm_comigt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(2, 2, 2, 2)), minV3Error) &&
260 _mm_comilt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(2, 2, 2, 2)), maxV3Error));
261}
262
263PX_FORCE_INLINE bool allElementsNearEqualVec4V(const Vec4V a, const Vec4V b)
264{
265 const Vec4V c = V4Sub(a, b);
266 return (_mm_comigt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(0, 0, 0, 0)), minV4Error) &&
267 _mm_comilt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(0, 0, 0, 0)), maxV4Error) &&
268 _mm_comigt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(1, 1, 1, 1)), minV4Error) &&
269 _mm_comilt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(1, 1, 1, 1)), maxV4Error) &&
270 _mm_comigt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(2, 2, 2, 2)), minV4Error) &&
271 _mm_comilt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(2, 2, 2, 2)), maxV4Error) &&
272 _mm_comigt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(3, 3, 3, 3)), minV4Error) &&
273 _mm_comilt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(3, 3, 3, 3)), maxV4Error));
274}
275} //vecMathTests
276
277PX_FORCE_INLINE bool isFiniteFloatV(const FloatV a)
278{
279 PxF32 f;
280 FStore(a, &f);
281 return PxIsFinite(f);
282 /*
283 const PxU32 badNumber = (_FPCLASS_SNAN | _FPCLASS_QNAN | _FPCLASS_NINF | _FPCLASS_PINF);
284 const FloatV vBadNum = FloatV_From_F32((PxF32&)badNumber);
285 const BoolV vMask = BAnd(vBadNum, a);
286 return FiniteTestEq(vMask, BFFFF()) == 1;
287 */
288}
289
290PX_FORCE_INLINE bool isFiniteVec3V(const Vec3V a)
291{
292 PX_ALIGN(16, PxF32 f[4]);
293 V4StoreA((Vec4V&)a, f);
294 return PxIsFinite(f[0]) && PxIsFinite(f[1]) && PxIsFinite(f[2]);
295
296 /*
297 const PxU32 badNumber = (_FPCLASS_SNAN | _FPCLASS_QNAN | _FPCLASS_NINF | _FPCLASS_PINF);
298 const Vec3V vBadNum = Vec3V_From_F32((PxF32&)badNumber);
299 const BoolV vMask = BAnd(BAnd(vBadNum, a), BTTTF());
300 return FiniteTestEq(vMask, BFFFF()) == 1;
301 */
302}
303
304PX_FORCE_INLINE bool isFiniteVec4V(const Vec4V a)
305{
306 PX_ALIGN(16, PxF32 f[4]);
307 V4StoreA(a, f);
308 return PxIsFinite(f[0]) && PxIsFinite(f[1]) && PxIsFinite(f[2]) && PxIsFinite(f[3]);
309
310 /*
311 const PxU32 badNumber = (_FPCLASS_SNAN | _FPCLASS_QNAN | _FPCLASS_NINF | _FPCLASS_PINF);
312 const Vec4V vBadNum = Vec4V_From_U32((PxF32&)badNumber);
313 const BoolV vMask = BAnd(vBadNum, a);
314
315 return FiniteTestEq(vMask, BFFFF()) == 1;
316 */
317}
318
322
323PX_FORCE_INLINE FloatV FLoad(const PxF32 f)
324{
325 return _mm_load1_ps(&f);
326}
327
328PX_FORCE_INLINE Vec3V V3Load(const PxF32 f)
329{
330 return _mm_set_ps(0.0f, f, f, f);
331}
332
333PX_FORCE_INLINE Vec4V V4Load(const PxF32 f)
334{
335 return _mm_load1_ps(&f);
336}
337
338PX_FORCE_INLINE BoolV BLoad(const bool f)
339{
340 const PxU32 i = PxU32(-(PxI32)f);
341 return _mm_load1_ps((float*)&i);
342}
343
344PX_FORCE_INLINE Vec3V V3LoadA(const PxVec3& f)
345{
346 ASSERT_ISALIGNED16(&f);
347 return _mm_and_ps(_mm_load_ps(&f.x), reinterpret_cast<const Vec4V&>(internalWindowsSimd::gMaskXYZ));
348}
349
350PX_FORCE_INLINE Vec3V V3LoadU(const PxVec3& f)
351{
352 return _mm_set_ps(0.0f, f.z, f.y, f.x);
353}
354
355// w component of result is undefined
356PX_FORCE_INLINE Vec3V V3LoadUnsafeA(const PxVec3& f)
357{
358 ASSERT_ISALIGNED16(&f);
359 return _mm_load_ps(&f.x);
360}
361
362PX_FORCE_INLINE Vec3V V3LoadA(const PxF32* const f)
363{
364 ASSERT_ISALIGNED16(f);
365 return V4ClearW(_mm_load_ps(f));
366}
367
368PX_FORCE_INLINE Vec3V V3LoadU(const PxF32* const i)
369{
370 return _mm_set_ps(0.0f, i[2], i[1], i[0]);
371}
372
373PX_FORCE_INLINE Vec3V Vec3V_From_Vec4V(Vec4V v)
374{
375 return V4ClearW(v);
376}
377
378PX_FORCE_INLINE Vec3V Vec3V_From_Vec4V_WUndefined(const Vec4V v)
379{
380 return v;
381}
382
383PX_FORCE_INLINE Vec4V Vec4V_From_Vec3V(Vec3V f)
384{
385 return f; // ok if it is implemented as the same type.
386}
387
388PX_FORCE_INLINE Vec4V Vec4V_From_FloatV(FloatV f)
389{
390 return f;
391}
392
393PX_FORCE_INLINE Vec3V Vec3V_From_FloatV(FloatV f)
394{
395 return Vec3V_From_Vec4V(Vec4V_From_FloatV(f));
396}
397
398PX_FORCE_INLINE Vec3V Vec3V_From_FloatV_WUndefined(FloatV f)
399{
400 return Vec3V_From_Vec4V_WUndefined(Vec4V_From_FloatV(f));
401}
402
403PX_FORCE_INLINE Vec4V Vec4V_From_PxVec3_WUndefined(const PxVec3& f)
404{
405 return _mm_set_ps(0.0f, f.z, f.y, f.x);
406}
407
408PX_FORCE_INLINE Vec4V V4LoadA(const PxF32* const f)
409{
410 ASSERT_ISALIGNED16(f);
411 return _mm_load_ps(f);
412}
413
414PX_FORCE_INLINE void V4StoreA(const Vec4V a, PxF32* f)
415{
416 ASSERT_ISALIGNED16(f);
417 _mm_store_ps(f, a);
418}
419
420PX_FORCE_INLINE void V4StoreU(const Vec4V a, PxF32* f)
421{
422 _mm_storeu_ps(f, a);
423}
424
425PX_FORCE_INLINE void BStoreA(const BoolV a, PxU32* f)
426{
427 ASSERT_ISALIGNED16(f);
428 _mm_store_ps((PxF32*)f, a);
429}
430
431PX_FORCE_INLINE void U4StoreA(const VecU32V uv, PxU32* u)
432{
433 ASSERT_ISALIGNED16(u);
434 _mm_store_ps((PxF32*)u, uv);
435}
436
437PX_FORCE_INLINE void I4StoreA(const VecI32V iv, PxI32* i)
438{
439 ASSERT_ISALIGNED16(i);
440 _mm_store_ps((PxF32*)i, iv);
441}
442
443PX_FORCE_INLINE Vec4V V4LoadU(const PxF32* const f)
444{
445 return _mm_loadu_ps(f);
446}
447
448PX_FORCE_INLINE BoolV BLoad(const bool* const f)
449{
450 const PX_ALIGN(16, PxU32 b[4]) = { PxU32(-(PxI32)f[0]), PxU32(-(PxI32)f[1]),
451 PxU32(-(PxI32)f[2]), PxU32(-(PxI32)f[3]) };
452 return _mm_load_ps((float*)&b);
453}
454
455PX_FORCE_INLINE void FStore(const FloatV a, PxF32* PX_RESTRICT f)
456{
457 ASSERT_ISVALIDFLOATV(a);
458 _mm_store_ss(f, a);
459}
460
461PX_FORCE_INLINE void V3StoreA(const Vec3V a, PxVec3& f)
462{
463 ASSERT_ISALIGNED16(&f);
464 PX_ALIGN(16, PxF32 f2[4]);
465 _mm_store_ps(f2, a);
466 f = PxVec3(f2[0], f2[1], f2[2]);
467}
468
469PX_FORCE_INLINE void Store_From_BoolV(const BoolV b, PxU32* b2)
470{
471 _mm_store_ss((PxF32*)b2, b);
472}
473
474PX_FORCE_INLINE void V3StoreU(const Vec3V a, PxVec3& f)
475{
476 PX_ALIGN(16, PxF32 f2[4]);
477 _mm_store_ps(f2, a);
478 f = PxVec3(f2[0], f2[1], f2[2]);
479}
480
481PX_FORCE_INLINE Mat33V Mat33V_From_PxMat33(const PxMat33& m)
482{
483 return Mat33V(V3LoadU(m.column0), V3LoadU(m.column1), V3LoadU(m.column2));
484}
485
486PX_FORCE_INLINE void PxMat33_From_Mat33V(const Mat33V& m, PxMat33& out)
487{
488 ASSERT_ISALIGNED16(&out);
489 V3StoreU(m.col0, out.column0);
490 V3StoreU(m.col1, out.column1);
491 V3StoreU(m.col2, out.column2);
492}
493
495// FLOATV
497
498PX_FORCE_INLINE FloatV FZero()
499{
500 return _mm_setzero_ps();
501}
502
503PX_FORCE_INLINE FloatV FOne()
504{
505 return FLoad(1.0f);
506}
507
508PX_FORCE_INLINE FloatV FHalf()
509{
510 return FLoad(0.5f);
511}
512
513PX_FORCE_INLINE FloatV FEps()
514{
515 return FLoad(PX_EPS_REAL);
516}
517
518PX_FORCE_INLINE FloatV FEps6()
519{
520 return FLoad(1e-6f);
521}
522
523PX_FORCE_INLINE FloatV FMax()
524{
525 return FLoad(PX_MAX_REAL);
526}
527
528PX_FORCE_INLINE FloatV FNegMax()
529{
530 return FLoad(-PX_MAX_REAL);
531}
532
533PX_FORCE_INLINE FloatV IZero()
534{
535 const PxU32 zero = 0;
536 return _mm_load1_ps((PxF32*)&zero);
537}
538
539PX_FORCE_INLINE FloatV IOne()
540{
541 const PxU32 one = 1;
542 return _mm_load1_ps((PxF32*)&one);
543}
544
545PX_FORCE_INLINE FloatV ITwo()
546{
547 const PxU32 two = 2;
548 return _mm_load1_ps((PxF32*)&two);
549}
550
551PX_FORCE_INLINE FloatV IThree()
552{
553 const PxU32 three = 3;
554 return _mm_load1_ps((PxF32*)&three);
555}
556
557PX_FORCE_INLINE FloatV IFour()
558{
559 const PxU32 four = 4;
560 return _mm_load1_ps((PxF32*)&four);
561}
562
563PX_FORCE_INLINE FloatV FNeg(const FloatV f)
564{
565 ASSERT_ISVALIDFLOATV(f);
566 return _mm_sub_ps(_mm_setzero_ps(), f);
567}
568
569PX_FORCE_INLINE FloatV FAdd(const FloatV a, const FloatV b)
570{
571 ASSERT_ISVALIDFLOATV(a);
572 ASSERT_ISVALIDFLOATV(b);
573 return _mm_add_ps(a, b);
574}
575
576PX_FORCE_INLINE FloatV FSub(const FloatV a, const FloatV b)
577{
578 ASSERT_ISVALIDFLOATV(a);
579 ASSERT_ISVALIDFLOATV(b);
580 return _mm_sub_ps(a, b);
581}
582
583PX_FORCE_INLINE FloatV FMul(const FloatV a, const FloatV b)
584{
585 ASSERT_ISVALIDFLOATV(a);
586 ASSERT_ISVALIDFLOATV(b);
587 return _mm_mul_ps(a, b);
588}
589
590PX_FORCE_INLINE FloatV FDiv(const FloatV a, const FloatV b)
591{
592 ASSERT_ISVALIDFLOATV(a);
593 ASSERT_ISVALIDFLOATV(b);
594 return _mm_div_ps(a, b);
595}
596
597PX_FORCE_INLINE FloatV FDivFast(const FloatV a, const FloatV b)
598{
599 ASSERT_ISVALIDFLOATV(a);
600 ASSERT_ISVALIDFLOATV(b);
601 return _mm_mul_ps(a, _mm_rcp_ps(b));
602}
603
604PX_FORCE_INLINE FloatV FRecip(const FloatV a)
605{
606 ASSERT_ISVALIDFLOATV(a);
607 return _mm_div_ps(FOne(), a);
608}
609
610PX_FORCE_INLINE FloatV FRecipFast(const FloatV a)
611{
612 return _mm_rcp_ps(a);
613}
614
615PX_FORCE_INLINE FloatV FRsqrt(const FloatV a)
616{
617 ASSERT_ISVALIDFLOATV(a);
618 return _mm_div_ps(FOne(), _mm_sqrt_ps(a));
619}
620
621PX_FORCE_INLINE FloatV FSqrt(const FloatV a)
622{
623 ASSERT_ISVALIDFLOATV(a);
624 return _mm_sqrt_ps(a);
625}
626
627PX_FORCE_INLINE FloatV FRsqrtFast(const FloatV a)
628{
629 ASSERT_ISVALIDFLOATV(a);
630 return _mm_rsqrt_ps(a);
631}
632
633PX_FORCE_INLINE FloatV FScaleAdd(const FloatV a, const FloatV b, const FloatV c)
634{
635 ASSERT_ISVALIDFLOATV(a);
636 ASSERT_ISVALIDFLOATV(b);
637 ASSERT_ISVALIDFLOATV(c);
638 return FAdd(FMul(a, b), c);
639}
640
641PX_FORCE_INLINE FloatV FNegScaleSub(const FloatV a, const FloatV b, const FloatV c)
642{
643 ASSERT_ISVALIDFLOATV(a);
644 ASSERT_ISVALIDFLOATV(b);
645 ASSERT_ISVALIDFLOATV(c);
646 return FSub(c, FMul(a, b));
647}
648
649PX_FORCE_INLINE FloatV FAbs(const FloatV a)
650{
651 ASSERT_ISVALIDFLOATV(a);
652 PX_ALIGN(16, const static PxU32 absMask[4]) = { 0x7fFFffFF, 0x7fFFffFF, 0x7fFFffFF, 0x7fFFffFF };
653 return _mm_and_ps(a, _mm_load_ps((PxF32*)absMask));
654}
655
656PX_FORCE_INLINE FloatV FSel(const BoolV c, const FloatV a, const FloatV b)
657{
658 PX_ASSERT(vecMathTests::allElementsEqualBoolV(c, BTTTT()) ||
659 vecMathTests::allElementsEqualBoolV(c, BFFFF()));
660 ASSERT_ISVALIDFLOATV(_mm_or_ps(_mm_andnot_ps(c, b), _mm_and_ps(c, a)));
661 return _mm_or_ps(_mm_andnot_ps(c, b), _mm_and_ps(c, a));
662}
663
664PX_FORCE_INLINE BoolV FIsGrtr(const FloatV a, const FloatV b)
665{
666 ASSERT_ISVALIDFLOATV(a);
667 ASSERT_ISVALIDFLOATV(b);
668 return _mm_cmpgt_ps(a, b);
669}
670
671PX_FORCE_INLINE BoolV FIsGrtrOrEq(const FloatV a, const FloatV b)
672{
673 ASSERT_ISVALIDFLOATV(a);
674 ASSERT_ISVALIDFLOATV(b);
675 return _mm_cmpge_ps(a, b);
676}
677
678PX_FORCE_INLINE BoolV FIsEq(const FloatV a, const FloatV b)
679{
680 ASSERT_ISVALIDFLOATV(a);
681 ASSERT_ISVALIDFLOATV(b);
682 return _mm_cmpeq_ps(a, b);
683}
684
685PX_FORCE_INLINE FloatV FMax(const FloatV a, const FloatV b)
686{
687 ASSERT_ISVALIDFLOATV(a);
688 ASSERT_ISVALIDFLOATV(b);
689 return _mm_max_ps(a, b);
690}
691
692PX_FORCE_INLINE FloatV FMin(const FloatV a, const FloatV b)
693{
694 ASSERT_ISVALIDFLOATV(a);
695 ASSERT_ISVALIDFLOATV(b);
696 return _mm_min_ps(a, b);
697}
698
699PX_FORCE_INLINE FloatV FClamp(const FloatV a, const FloatV minV, const FloatV maxV)
700{
701 ASSERT_ISVALIDFLOATV(minV);
702 ASSERT_ISVALIDFLOATV(maxV);
703 return _mm_max_ps(_mm_min_ps(a, maxV), minV);
704}
705
706PX_FORCE_INLINE PxU32 FAllGrtr(const FloatV a, const FloatV b)
707{
708 ASSERT_ISVALIDFLOATV(a);
709 ASSERT_ISVALIDFLOATV(b);
710 return PxU32(_mm_comigt_ss(a, b));
711}
712
713PX_FORCE_INLINE PxU32 FAllGrtrOrEq(const FloatV a, const FloatV b)
714{
715 ASSERT_ISVALIDFLOATV(a);
716 ASSERT_ISVALIDFLOATV(b);
717 return PxU32(_mm_comige_ss(a, b));
718}
719
720PX_FORCE_INLINE PxU32 FAllEq(const FloatV a, const FloatV b)
721{
722 ASSERT_ISVALIDFLOATV(a);
723 ASSERT_ISVALIDFLOATV(b);
724 return PxU32(_mm_comieq_ss(a, b));
725}
726
727PX_FORCE_INLINE FloatV FRound(const FloatV a)
728{
729 ASSERT_ISVALIDFLOATV(a);
730 // return _mm_round_ps(a, 0x0);
731 const FloatV half = FLoad(0.5f);
732 const __m128 signBit = _mm_cvtepi32_ps(_mm_srli_epi32(_mm_cvtps_epi32(a), 31));
733 const FloatV aRound = FSub(FAdd(a, half), signBit);
734 __m128i tmp = _mm_cvttps_epi32(aRound);
735 return _mm_cvtepi32_ps(tmp);
736}
737
738PX_FORCE_INLINE FloatV FSin(const FloatV a)
739{
740 ASSERT_ISVALIDFLOATV(a);
741 // Modulo the range of the given angles such that -XM_2PI <= Angles < XM_2PI
742 const FloatV recipTwoPi = V4LoadA(g_PXReciprocalTwoPi.f);
743 const FloatV twoPi = V4LoadA(g_PXTwoPi.f);
744 const FloatV tmp = FMul(a, recipTwoPi);
745 const FloatV b = FRound(tmp);
746 const FloatV V1 = FNegScaleSub(twoPi, b, a);
747
748 // sin(V) ~= V - V^3 / 3! + V^5 / 5! - V^7 / 7! + V^9 / 9! - V^11 / 11! + V^13 / 13! -
749 // V^15 / 15! + V^17 / 17! - V^19 / 19! + V^21 / 21! - V^23 / 23! (for -PI <= V < PI)
750 const FloatV V2 = FMul(V1, V1);
751 const FloatV V3 = FMul(V2, V1);
752 const FloatV V5 = FMul(V3, V2);
753 const FloatV V7 = FMul(V5, V2);
754 const FloatV V9 = FMul(V7, V2);
755 const FloatV V11 = FMul(V9, V2);
756 const FloatV V13 = FMul(V11, V2);
757 const FloatV V15 = FMul(V13, V2);
758 const FloatV V17 = FMul(V15, V2);
759 const FloatV V19 = FMul(V17, V2);
760 const FloatV V21 = FMul(V19, V2);
761 const FloatV V23 = FMul(V21, V2);
762
763 const Vec4V sinCoefficients0 = V4LoadA(g_PXSinCoefficients0.f);
764 const Vec4V sinCoefficients1 = V4LoadA(g_PXSinCoefficients1.f);
765 const Vec4V sinCoefficients2 = V4LoadA(g_PXSinCoefficients2.f);
766
767 const FloatV S1 = V4GetY(sinCoefficients0);
768 const FloatV S2 = V4GetZ(sinCoefficients0);
769 const FloatV S3 = V4GetW(sinCoefficients0);
770 const FloatV S4 = V4GetX(sinCoefficients1);
771 const FloatV S5 = V4GetY(sinCoefficients1);
772 const FloatV S6 = V4GetZ(sinCoefficients1);
773 const FloatV S7 = V4GetW(sinCoefficients1);
774 const FloatV S8 = V4GetX(sinCoefficients2);
775 const FloatV S9 = V4GetY(sinCoefficients2);
776 const FloatV S10 = V4GetZ(sinCoefficients2);
777 const FloatV S11 = V4GetW(sinCoefficients2);
778
779 FloatV Result;
780 Result = FScaleAdd(S1, V3, V1);
781 Result = FScaleAdd(S2, V5, Result);
782 Result = FScaleAdd(S3, V7, Result);
783 Result = FScaleAdd(S4, V9, Result);
784 Result = FScaleAdd(S5, V11, Result);
785 Result = FScaleAdd(S6, V13, Result);
786 Result = FScaleAdd(S7, V15, Result);
787 Result = FScaleAdd(S8, V17, Result);
788 Result = FScaleAdd(S9, V19, Result);
789 Result = FScaleAdd(S10, V21, Result);
790 Result = FScaleAdd(S11, V23, Result);
791
792 return Result;
793}
794
795PX_FORCE_INLINE FloatV FCos(const FloatV a)
796{
797 ASSERT_ISVALIDFLOATV(a);
798
799 // Modulo the range of the given angles such that -XM_2PI <= Angles < XM_2PI
800 const FloatV recipTwoPi = V4LoadA(g_PXReciprocalTwoPi.f);
801 const FloatV twoPi = V4LoadA(g_PXTwoPi.f);
802 const FloatV tmp = FMul(a, recipTwoPi);
803 const FloatV b = FRound(tmp);
804 const FloatV V1 = FNegScaleSub(twoPi, b, a);
805
806 // cos(V) ~= 1 - V^2 / 2! + V^4 / 4! - V^6 / 6! + V^8 / 8! - V^10 / 10! + V^12 / 12! -
807 // V^14 / 14! + V^16 / 16! - V^18 / 18! + V^20 / 20! - V^22 / 22! (for -PI <= V < PI)
808 const FloatV V2 = FMul(V1, V1);
809 const FloatV V4 = FMul(V2, V2);
810 const FloatV V6 = FMul(V4, V2);
811 const FloatV V8 = FMul(V4, V4);
812 const FloatV V10 = FMul(V6, V4);
813 const FloatV V12 = FMul(V6, V6);
814 const FloatV V14 = FMul(V8, V6);
815 const FloatV V16 = FMul(V8, V8);
816 const FloatV V18 = FMul(V10, V8);
817 const FloatV V20 = FMul(V10, V10);
818 const FloatV V22 = FMul(V12, V10);
819
820 const Vec4V cosCoefficients0 = V4LoadA(g_PXCosCoefficients0.f);
821 const Vec4V cosCoefficients1 = V4LoadA(g_PXCosCoefficients1.f);
822 const Vec4V cosCoefficients2 = V4LoadA(g_PXCosCoefficients2.f);
823
824 const FloatV C1 = V4GetY(cosCoefficients0);
825 const FloatV C2 = V4GetZ(cosCoefficients0);
826 const FloatV C3 = V4GetW(cosCoefficients0);
827 const FloatV C4 = V4GetX(cosCoefficients1);
828 const FloatV C5 = V4GetY(cosCoefficients1);
829 const FloatV C6 = V4GetZ(cosCoefficients1);
830 const FloatV C7 = V4GetW(cosCoefficients1);
831 const FloatV C8 = V4GetX(cosCoefficients2);
832 const FloatV C9 = V4GetY(cosCoefficients2);
833 const FloatV C10 = V4GetZ(cosCoefficients2);
834 const FloatV C11 = V4GetW(cosCoefficients2);
835
836 FloatV Result;
837 Result = FScaleAdd(C1, V2, V4One());
838 Result = FScaleAdd(C2, V4, Result);
839 Result = FScaleAdd(C3, V6, Result);
840 Result = FScaleAdd(C4, V8, Result);
841 Result = FScaleAdd(C5, V10, Result);
842 Result = FScaleAdd(C6, V12, Result);
843 Result = FScaleAdd(C7, V14, Result);
844 Result = FScaleAdd(C8, V16, Result);
845 Result = FScaleAdd(C9, V18, Result);
846 Result = FScaleAdd(C10, V20, Result);
847 Result = FScaleAdd(C11, V22, Result);
848
849 return Result;
850}
851
852PX_FORCE_INLINE PxU32 FOutOfBounds(const FloatV a, const FloatV min, const FloatV max)
853{
854 ASSERT_ISVALIDFLOATV(a);
855 ASSERT_ISVALIDFLOATV(min);
856 ASSERT_ISVALIDFLOATV(max);
857 const BoolV c = BOr(FIsGrtr(a, max), FIsGrtr(min, a));
858 return PxU32(!BAllEqFFFF(c));
859}
860
861PX_FORCE_INLINE PxU32 FInBounds(const FloatV a, const FloatV min, const FloatV max)
862{
863 ASSERT_ISVALIDFLOATV(a);
864 ASSERT_ISVALIDFLOATV(min);
865 ASSERT_ISVALIDFLOATV(max);
866 const BoolV c = BAnd(FIsGrtrOrEq(a, min), FIsGrtrOrEq(max, a));
867 return BAllEqTTTT(c);
868}
869
870PX_FORCE_INLINE PxU32 FOutOfBounds(const FloatV a, const FloatV bounds)
871{
872 ASSERT_ISVALIDFLOATV(a);
873 ASSERT_ISVALIDFLOATV(bounds);
874 return FOutOfBounds(a, FNeg(bounds), bounds);
875}
876
877PX_FORCE_INLINE PxU32 FInBounds(const FloatV a, const FloatV bounds)
878{
879 ASSERT_ISVALIDFLOATV(a);
880 ASSERT_ISVALIDFLOATV(bounds);
881 return FInBounds(a, FNeg(bounds), bounds);
882}
883
885// VEC3V
887
888PX_FORCE_INLINE Vec3V V3Splat(const FloatV f)
889{
890 ASSERT_ISVALIDFLOATV(f);
891 const __m128 zero = V3Zero();
892 const __m128 fff0 = _mm_move_ss(f, zero);
893 return _mm_shuffle_ps(fff0, fff0, _MM_SHUFFLE(0, 1, 2, 3));
894}
895
896PX_FORCE_INLINE Vec3V V3Merge(const FloatVArg x, const FloatVArg y, const FloatVArg z)
897{
898 ASSERT_ISVALIDFLOATV(x);
899 ASSERT_ISVALIDFLOATV(y);
900 ASSERT_ISVALIDFLOATV(z);
901 // static on zero causes compiler crash on x64 debug_opt
902 const __m128 zero = V3Zero();
903 const __m128 xy = _mm_move_ss(x, y);
904 const __m128 z0 = _mm_move_ss(zero, z);
905
906 return _mm_shuffle_ps(xy, z0, _MM_SHUFFLE(1, 0, 0, 1));
907}
908
909PX_FORCE_INLINE Vec3V V3UnitX()
910{
911 const PX_ALIGN(16, PxF32 x[4]) = { 1.0f, 0.0f, 0.0f, 0.0f };
912 const __m128 x128 = _mm_load_ps(x);
913 return x128;
914}
915
916PX_FORCE_INLINE Vec3V V3UnitY()
917{
918 const PX_ALIGN(16, PxF32 y[4]) = { 0.0f, 1.0f, 0.0f, 0.0f };
919 const __m128 y128 = _mm_load_ps(y);
920 return y128;
921}
922
923PX_FORCE_INLINE Vec3V V3UnitZ()
924{
925 const PX_ALIGN(16, PxF32 z[4]) = { 0.0f, 0.0f, 1.0f, 0.0f };
926 const __m128 z128 = _mm_load_ps(z);
927 return z128;
928}
929
930PX_FORCE_INLINE FloatV V3GetX(const Vec3V f)
931{
932 ASSERT_ISVALIDVEC3V(f);
933 return _mm_shuffle_ps(f, f, _MM_SHUFFLE(0, 0, 0, 0));
934}
935
936PX_FORCE_INLINE FloatV V3GetY(const Vec3V f)
937{
938 ASSERT_ISVALIDVEC3V(f);
939 return _mm_shuffle_ps(f, f, _MM_SHUFFLE(1, 1, 1, 1));
940}
941
942PX_FORCE_INLINE FloatV V3GetZ(const Vec3V f)
943{
944 ASSERT_ISVALIDVEC3V(f);
945 return _mm_shuffle_ps(f, f, _MM_SHUFFLE(2, 2, 2, 2));
946}
947
948PX_FORCE_INLINE Vec3V V3SetX(const Vec3V v, const FloatV f)
949{
950 ASSERT_ISVALIDVEC3V(v);
951 ASSERT_ISVALIDFLOATV(f);
952 return V4Sel(BFTTT(), v, f);
953}
954
955PX_FORCE_INLINE Vec3V V3SetY(const Vec3V v, const FloatV f)
956{
957 ASSERT_ISVALIDVEC3V(v);
958 ASSERT_ISVALIDFLOATV(f);
959 return V4Sel(BTFTT(), v, f);
960}
961
962PX_FORCE_INLINE Vec3V V3SetZ(const Vec3V v, const FloatV f)
963{
964 ASSERT_ISVALIDVEC3V(v);
965 ASSERT_ISVALIDFLOATV(f);
966 return V4Sel(BTTFT(), v, f);
967}
968
969PX_FORCE_INLINE Vec3V V3ColX(const Vec3V a, const Vec3V b, const Vec3V c)
970{
971 ASSERT_ISVALIDVEC3V(a);
972 ASSERT_ISVALIDVEC3V(b);
973 ASSERT_ISVALIDVEC3V(c);
974 Vec3V r = _mm_shuffle_ps(a, c, _MM_SHUFFLE(3, 0, 3, 0));
975 return V3SetY(r, V3GetX(b));
976}
977
978PX_FORCE_INLINE Vec3V V3ColY(const Vec3V a, const Vec3V b, const Vec3V c)
979{
980 ASSERT_ISVALIDVEC3V(a);
981 ASSERT_ISVALIDVEC3V(b);
982 ASSERT_ISVALIDVEC3V(c);
983 Vec3V r = _mm_shuffle_ps(a, c, _MM_SHUFFLE(3, 1, 3, 1));
984 return V3SetY(r, V3GetY(b));
985}
986
987PX_FORCE_INLINE Vec3V V3ColZ(const Vec3V a, const Vec3V b, const Vec3V c)
988{
989 ASSERT_ISVALIDVEC3V(a);
990 ASSERT_ISVALIDVEC3V(b);
991 ASSERT_ISVALIDVEC3V(c);
992 Vec3V r = _mm_shuffle_ps(a, c, _MM_SHUFFLE(3, 2, 3, 2));
993 return V3SetY(r, V3GetZ(b));
994}
995
996PX_FORCE_INLINE Vec3V V3Zero()
997{
998 return _mm_setzero_ps();
999}
1000
1001PX_FORCE_INLINE Vec3V V3One()
1002{
1003 return V3Load(1.0f);
1004}
1005
1006PX_FORCE_INLINE Vec3V V3Eps()
1007{
1008 return V3Load(PX_EPS_REAL);
1009}
1010
1011PX_FORCE_INLINE Vec3V V3Neg(const Vec3V f)
1012{
1013 ASSERT_ISVALIDVEC3V(f);
1014 return _mm_sub_ps(_mm_setzero_ps(), f);
1015}
1016
1017PX_FORCE_INLINE Vec3V V3Add(const Vec3V a, const Vec3V b)
1018{
1019 ASSERT_ISVALIDVEC3V(a);
1020 ASSERT_ISVALIDVEC3V(b);
1021 return _mm_add_ps(a, b);
1022}
1023
1024PX_FORCE_INLINE Vec3V V3Sub(const Vec3V a, const Vec3V b)
1025{
1026 ASSERT_ISVALIDVEC3V(a);
1027 ASSERT_ISVALIDVEC3V(b);
1028 return _mm_sub_ps(a, b);
1029}
1030
1031PX_FORCE_INLINE Vec3V V3Scale(const Vec3V a, const FloatV b)
1032{
1033 ASSERT_ISVALIDVEC3V(a);
1034 ASSERT_ISVALIDFLOATV(b);
1035 return _mm_mul_ps(a, b);
1036}
1037
1038PX_FORCE_INLINE Vec3V V3Mul(const Vec3V a, const Vec3V b)
1039{
1040 ASSERT_ISVALIDVEC3V(a);
1041 ASSERT_ISVALIDVEC3V(b);
1042 return _mm_mul_ps(a, b);
1043}
1044
1045PX_FORCE_INLINE Vec3V V3ScaleInv(const Vec3V a, const FloatV b)
1046{
1047 ASSERT_ISVALIDVEC3V(a);
1048 ASSERT_ISVALIDFLOATV(b);
1049 return _mm_div_ps(a, b);
1050}
1051
1052PX_FORCE_INLINE Vec3V V3Div(const Vec3V a, const Vec3V b)
1053{
1054 ASSERT_ISVALIDVEC3V(a);
1055 ASSERT_ISVALIDVEC3V(b);
1056 return V4ClearW(_mm_div_ps(a, b));
1057}
1058
1059PX_FORCE_INLINE Vec3V V3ScaleInvFast(const Vec3V a, const FloatV b)
1060{
1061 ASSERT_ISVALIDVEC3V(a);
1062 ASSERT_ISVALIDFLOATV(b);
1063 return _mm_mul_ps(a, _mm_rcp_ps(b));
1064}
1065
1066PX_FORCE_INLINE Vec3V V3DivFast(const Vec3V a, const Vec3V b)
1067{
1068 ASSERT_ISVALIDVEC3V(a);
1069 ASSERT_ISVALIDVEC3V(b);
1070 return V4ClearW(_mm_mul_ps(a, _mm_rcp_ps(b)));
1071}
1072
1073PX_FORCE_INLINE Vec3V V3Recip(const Vec3V a)
1074{
1075 ASSERT_ISVALIDVEC3V(a);
1076 const __m128 zero = V3Zero();
1077 const __m128 tttf = BTTTF();
1078 const __m128 recipA = _mm_div_ps(V3One(), a);
1079 return V4Sel(tttf, recipA, zero);
1080}
1081
1082PX_FORCE_INLINE Vec3V V3RecipFast(const Vec3V a)
1083{
1084 ASSERT_ISVALIDVEC3V(a);
1085 const __m128 zero = V3Zero();
1086 const __m128 tttf = BTTTF();
1087 const __m128 recipA = _mm_rcp_ps(a);
1088 return V4Sel(tttf, recipA, zero);
1089}
1090
1091PX_FORCE_INLINE Vec3V V3Rsqrt(const Vec3V a)
1092{
1093 ASSERT_ISVALIDVEC3V(a);
1094 const __m128 zero = V3Zero();
1095 const __m128 tttf = BTTTF();
1096 const __m128 recipA = _mm_div_ps(V3One(), _mm_sqrt_ps(a));
1097 return V4Sel(tttf, recipA, zero);
1098}
1099
1100PX_FORCE_INLINE Vec3V V3RsqrtFast(const Vec3V a)
1101{
1102 ASSERT_ISVALIDVEC3V(a);
1103 const __m128 zero = V3Zero();
1104 const __m128 tttf = BTTTF();
1105 const __m128 recipA = _mm_rsqrt_ps(a);
1106 return V4Sel(tttf, recipA, zero);
1107}
1108
1109PX_FORCE_INLINE Vec3V V3ScaleAdd(const Vec3V a, const FloatV b, const Vec3V c)
1110{
1111 ASSERT_ISVALIDVEC3V(a);
1112 ASSERT_ISVALIDFLOATV(b);
1113 ASSERT_ISVALIDVEC3V(c);
1114 return V3Add(V3Scale(a, b), c);
1115}
1116
1117PX_FORCE_INLINE Vec3V V3NegScaleSub(const Vec3V a, const FloatV b, const Vec3V c)
1118{
1119 ASSERT_ISVALIDVEC3V(a);
1120 ASSERT_ISVALIDFLOATV(b);
1121 ASSERT_ISVALIDVEC3V(c);
1122 return V3Sub(c, V3Scale(a, b));
1123}
1124
1125PX_FORCE_INLINE Vec3V V3MulAdd(const Vec3V a, const Vec3V b, const Vec3V c)
1126{
1127 ASSERT_ISVALIDVEC3V(a);
1128 ASSERT_ISVALIDVEC3V(b);
1129 ASSERT_ISVALIDVEC3V(c);
1130 return V3Add(V3Mul(a, b), c);
1131}
1132
1133PX_FORCE_INLINE Vec3V V3NegMulSub(const Vec3V a, const Vec3V b, const Vec3V c)
1134{
1135 ASSERT_ISVALIDVEC3V(a);
1136 ASSERT_ISVALIDVEC3V(b);
1137 ASSERT_ISVALIDVEC3V(c);
1138 return V3Sub(c, V3Mul(a, b));
1139}
1140
1141PX_FORCE_INLINE Vec3V V3Abs(const Vec3V a)
1142{
1143 ASSERT_ISVALIDVEC3V(a);
1144 return V3Max(a, V3Neg(a));
1145}
1146
1147PX_FORCE_INLINE FloatV V3Dot(const Vec3V a, const Vec3V b)
1148{
1149 ASSERT_ISVALIDVEC3V(a);
1150 ASSERT_ISVALIDVEC3V(b);
1151
1152 const __m128 t0 = _mm_mul_ps(a, b); // aw*bw | az*bz | ay*by | ax*bx
1153 const __m128 t1 = _mm_shuffle_ps(t0, t0, _MM_SHUFFLE(1,0,3,2)); // ay*by | ax*bx | aw*bw | az*bz
1154 const __m128 t2 = _mm_add_ps(t0, t1); // ay*by + aw*bw | ax*bx + az*bz | aw*bw + ay*by | az*bz + ax*bx
1155 const __m128 t3 = _mm_shuffle_ps(t2, t2, _MM_SHUFFLE(2,3,0,1)); // ax*bx + az*bz | ay*by + aw*bw | az*bz + ax*bx | aw*bw + ay*by
1156 return _mm_add_ps(t3, t2); // ax*bx + az*bz + ay*by + aw*bw
1157 // ay*by + aw*bw + ax*bx + az*bz
1158 // az*bz + ax*bx + aw*bw + ay*by
1159 // aw*bw + ay*by + az*bz + ax*bx
1160}
1161
1162PX_FORCE_INLINE Vec3V V3Cross(const Vec3V a, const Vec3V b)
1163{
1164 ASSERT_ISVALIDVEC3V(a);
1165 ASSERT_ISVALIDVEC3V(b);
1166/* if(0)
1167 {
1168 const __m128 r1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 1, 0, 2)); // z,x,y,w
1169 const __m128 r2 = _mm_shuffle_ps(b, b, _MM_SHUFFLE(3, 0, 2, 1)); // y,z,x,w
1170 const __m128 l1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 0, 2, 1)); // y,z,x,w
1171 const __m128 l2 = _mm_shuffle_ps(b, b, _MM_SHUFFLE(3, 1, 0, 2)); // z,x,y,w
1172 return _mm_sub_ps(_mm_mul_ps(l1, l2), _mm_mul_ps(r1, r2));
1173 }
1174 else*/
1175 {
1176 const __m128 b0 = _mm_shuffle_ps(b, b, _MM_SHUFFLE(3,0,2,1));
1177 const __m128 a1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(3,0,2,1));
1178 __m128 v = _mm_mul_ps(a1, b);
1179 v = _mm_sub_ps(_mm_mul_ps(a, b0), v);
1180 __m128 res = _mm_shuffle_ps(v, v, _MM_SHUFFLE(3,0,2,1));
1181 ASSERT_ISVALIDVEC3V(res);
1182 return res;
1183 }
1184}
1185
1186PX_FORCE_INLINE VecCrossV V3PrepareCross(const Vec3V a)
1187{
1188 ASSERT_ISVALIDVEC3V(a);
1189 VecCrossV v;
1190 v.mR1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 1, 0, 2)); // z,x,y,w
1191 v.mL1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 0, 2, 1)); // y,z,x,w
1192 return v;
1193}
1194
1195PX_FORCE_INLINE Vec3V V3Cross(const VecCrossV& a, const Vec3V b)
1196{
1197 ASSERT_ISVALIDVEC3V(b);
1198 const __m128 r2 = _mm_shuffle_ps(b, b, _MM_SHUFFLE(3, 0, 2, 1)); // y,z,x,w
1199 const __m128 l2 = _mm_shuffle_ps(b, b, _MM_SHUFFLE(3, 1, 0, 2)); // z,x,y,w
1200 return _mm_sub_ps(_mm_mul_ps(a.mL1, l2), _mm_mul_ps(a.mR1, r2));
1201}
1202
1203PX_FORCE_INLINE Vec3V V3Cross(const Vec3V a, const VecCrossV& b)
1204{
1205 ASSERT_ISVALIDVEC3V(a);
1206 const __m128 r2 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 0, 2, 1)); // y,z,x,w
1207 const __m128 l2 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 1, 0, 2)); // z,x,y,w
1208 return _mm_sub_ps(_mm_mul_ps(b.mR1, r2), _mm_mul_ps(b.mL1, l2));
1209}
1210
1211PX_FORCE_INLINE Vec3V V3Cross(const VecCrossV& a, const VecCrossV& b)
1212{
1213 return _mm_sub_ps(_mm_mul_ps(a.mL1, b.mR1), _mm_mul_ps(a.mR1, b.mL1));
1214}
1215
1216PX_FORCE_INLINE FloatV V3Length(const Vec3V a)
1217{
1218 ASSERT_ISVALIDVEC3V(a);
1219 return _mm_sqrt_ps(V3Dot(a, a));
1220}
1221
1222PX_FORCE_INLINE FloatV V3LengthSq(const Vec3V a)
1223{
1224 ASSERT_ISVALIDVEC3V(a);
1225 return V3Dot(a, a);
1226}
1227
1228PX_FORCE_INLINE Vec3V V3Normalize(const Vec3V a)
1229{
1230 ASSERT_ISVALIDVEC3V(a);
1231 ASSERT_ISFINITELENGTH(a);
1232 return V3ScaleInv(a, _mm_sqrt_ps(V3Dot(a, a)));
1233}
1234
1235PX_FORCE_INLINE Vec3V V3NormalizeFast(const Vec3V a)
1236{
1237 ASSERT_ISVALIDVEC3V(a);
1238 ASSERT_ISFINITELENGTH(a);
1239 return V3Scale(a, _mm_rsqrt_ps(V3Dot(a, a)));
1240}
1241
1242PX_FORCE_INLINE Vec3V V3NormalizeSafe(const Vec3V a, const Vec3V unsafeReturnValue)
1243{
1244 ASSERT_ISVALIDVEC3V(a);
1245 const __m128 eps = FEps();
1246 const __m128 length = V3Length(a);
1247 const __m128 isGreaterThanZero = FIsGrtr(length, eps);
1248 return V3Sel(isGreaterThanZero, V3ScaleInv(a, length), unsafeReturnValue);
1249}
1250
1251PX_FORCE_INLINE Vec3V V3Sel(const BoolV c, const Vec3V a, const Vec3V b)
1252{
1253 ASSERT_ISVALIDVEC3V(_mm_or_ps(_mm_andnot_ps(c, b), _mm_and_ps(c, a)));
1254 return _mm_or_ps(_mm_andnot_ps(c, b), _mm_and_ps(c, a));
1255}
1256
1257PX_FORCE_INLINE BoolV V3IsGrtr(const Vec3V a, const Vec3V b)
1258{
1259 ASSERT_ISVALIDVEC3V(a);
1260 ASSERT_ISVALIDVEC3V(b);
1261 return _mm_cmpgt_ps(a, b);
1262}
1263
1264PX_FORCE_INLINE BoolV V3IsGrtrOrEq(const Vec3V a, const Vec3V b)
1265{
1266 ASSERT_ISVALIDVEC3V(a);
1267 ASSERT_ISVALIDVEC3V(b);
1268 return _mm_cmpge_ps(a, b);
1269}
1270
1271PX_FORCE_INLINE BoolV V3IsEq(const Vec3V a, const Vec3V b)
1272{
1273 ASSERT_ISVALIDVEC3V(a);
1274 ASSERT_ISVALIDVEC3V(b);
1275 return _mm_cmpeq_ps(a, b);
1276}
1277
1278PX_FORCE_INLINE Vec3V V3Max(const Vec3V a, const Vec3V b)
1279{
1280 ASSERT_ISVALIDVEC3V(a);
1281 ASSERT_ISVALIDVEC3V(b);
1282 return _mm_max_ps(a, b);
1283}
1284
1285PX_FORCE_INLINE Vec3V V3Min(const Vec3V a, const Vec3V b)
1286{
1287 ASSERT_ISVALIDVEC3V(a);
1288 ASSERT_ISVALIDVEC3V(b);
1289 return _mm_min_ps(a, b);
1290}
1291
1292PX_FORCE_INLINE FloatV V3ExtractMax(const Vec3V a)
1293{
1294 ASSERT_ISVALIDVEC3V(a);
1295 const __m128 shuf1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0));
1296 const __m128 shuf2 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 1, 1, 1));
1297 const __m128 shuf3 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2));
1298 return _mm_max_ps(_mm_max_ps(shuf1, shuf2), shuf3);
1299}
1300
1301PX_FORCE_INLINE FloatV V3ExtractMin(const Vec3V a)
1302{
1303 ASSERT_ISVALIDVEC3V(a);
1304 const __m128 shuf1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0));
1305 const __m128 shuf2 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 1, 1, 1));
1306 const __m128 shuf3 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2));
1307 return _mm_min_ps(_mm_min_ps(shuf1, shuf2), shuf3);
1308}
1309
1311// PX_FORCE_INLINE Vec3V V3MathSign(const Vec3V a)
1312//{
1313// VECMATHAOS_ASSERT(isValidVec3V(a));
1314//
1315// const __m128i ai = _mm_cvtps_epi32(a);
1316// const __m128i bi = _mm_cvtps_epi32(V3Neg(a));
1317// const __m128 aa = _mm_cvtepi32_ps(_mm_srai_epi32(ai, 31));
1318// const __m128 bb = _mm_cvtepi32_ps(_mm_srai_epi32(bi, 31));
1319// return _mm_or_ps(aa, bb);
1320//}
1321
1322// return (a >= 0.0f) ? 1.0f : -1.0f;
1323PX_FORCE_INLINE Vec3V V3Sign(const Vec3V a)
1324{
1325 ASSERT_ISVALIDVEC3V(a);
1326 const __m128 zero = V3Zero();
1327 const __m128 one = V3One();
1328 const __m128 none = V3Neg(one);
1329 return V3Sel(V3IsGrtrOrEq(a, zero), one, none);
1330}
1331
1332PX_FORCE_INLINE Vec3V V3Clamp(const Vec3V a, const Vec3V minV, const Vec3V maxV)
1333{
1334 ASSERT_ISVALIDVEC3V(a);
1335 ASSERT_ISVALIDVEC3V(minV);
1336 ASSERT_ISVALIDVEC3V(maxV);
1337 return V3Max(V3Min(a, maxV), minV);
1338}
1339
1340PX_FORCE_INLINE PxU32 V3AllGrtr(const Vec3V a, const Vec3V b)
1341{
1342 ASSERT_ISVALIDVEC3V(a);
1343 ASSERT_ISVALIDVEC3V(b);
1344 return internalWindowsSimd::BAllTrue3_R(V4IsGrtr(a, b));
1345}
1346
1347PX_FORCE_INLINE PxU32 V3AllGrtrOrEq(const Vec3V a, const Vec3V b)
1348{
1349 ASSERT_ISVALIDVEC3V(a);
1350 ASSERT_ISVALIDVEC3V(b);
1351 return internalWindowsSimd::BAllTrue3_R(V4IsGrtrOrEq(a, b));
1352}
1353
1354PX_FORCE_INLINE PxU32 V3AllEq(const Vec3V a, const Vec3V b)
1355{
1356 ASSERT_ISVALIDVEC3V(a);
1357 ASSERT_ISVALIDVEC3V(b);
1358 return internalWindowsSimd::BAllTrue3_R(V4IsEq(a, b));
1359}
1360
1361PX_FORCE_INLINE Vec3V V3Round(const Vec3V a)
1362{
1363 ASSERT_ISVALIDVEC3V(a);
1364
1365 // return _mm_round_ps(a, 0x0);
1366 const Vec3V half = V3Load(0.5f);
1367 const __m128 signBit = _mm_cvtepi32_ps(_mm_srli_epi32(_mm_cvtps_epi32(a), 31));
1368 const Vec3V aRound = V3Sub(V3Add(a, half), signBit);
1369 __m128i tmp = _mm_cvttps_epi32(aRound);
1370 return _mm_cvtepi32_ps(tmp);
1371}
1372
1373PX_FORCE_INLINE Vec3V V3Sin(const Vec3V a)
1374{
1375 ASSERT_ISVALIDVEC3V(a);
1376
1377 // Modulo the range of the given angles such that -XM_2PI <= Angles < XM_2PI
1378 const Vec4V recipTwoPi = V4LoadA(g_PXReciprocalTwoPi.f);
1379 const Vec4V twoPi = V4LoadA(g_PXTwoPi.f);
1380 const Vec3V tmp = V3Scale(a, recipTwoPi);
1381 const Vec3V b = V3Round(tmp);
1382 const Vec3V V1 = V3NegScaleSub(b, twoPi, a);
1383
1384 // sin(V) ~= V - V^3 / 3! + V^5 / 5! - V^7 / 7! + V^9 / 9! - V^11 / 11! + V^13 / 13! -
1385 // V^15 / 15! + V^17 / 17! - V^19 / 19! + V^21 / 21! - V^23 / 23! (for -PI <= V < PI)
1386 const Vec3V V2 = V3Mul(V1, V1);
1387 const Vec3V V3 = V3Mul(V2, V1);
1388 const Vec3V V5 = V3Mul(V3, V2);
1389 const Vec3V V7 = V3Mul(V5, V2);
1390 const Vec3V V9 = V3Mul(V7, V2);
1391 const Vec3V V11 = V3Mul(V9, V2);
1392 const Vec3V V13 = V3Mul(V11, V2);
1393 const Vec3V V15 = V3Mul(V13, V2);
1394 const Vec3V V17 = V3Mul(V15, V2);
1395 const Vec3V V19 = V3Mul(V17, V2);
1396 const Vec3V V21 = V3Mul(V19, V2);
1397 const Vec3V V23 = V3Mul(V21, V2);
1398
1399 const Vec4V sinCoefficients0 = V4LoadA(g_PXSinCoefficients0.f);
1400 const Vec4V sinCoefficients1 = V4LoadA(g_PXSinCoefficients1.f);
1401 const Vec4V sinCoefficients2 = V4LoadA(g_PXSinCoefficients2.f);
1402
1403 const FloatV S1 = V4GetY(sinCoefficients0);
1404 const FloatV S2 = V4GetZ(sinCoefficients0);
1405 const FloatV S3 = V4GetW(sinCoefficients0);
1406 const FloatV S4 = V4GetX(sinCoefficients1);
1407 const FloatV S5 = V4GetY(sinCoefficients1);
1408 const FloatV S6 = V4GetZ(sinCoefficients1);
1409 const FloatV S7 = V4GetW(sinCoefficients1);
1410 const FloatV S8 = V4GetX(sinCoefficients2);
1411 const FloatV S9 = V4GetY(sinCoefficients2);
1412 const FloatV S10 = V4GetZ(sinCoefficients2);
1413 const FloatV S11 = V4GetW(sinCoefficients2);
1414
1415 Vec3V Result;
1416 Result = V3ScaleAdd(V3, S1, V1);
1417 Result = V3ScaleAdd(V5, S2, Result);
1418 Result = V3ScaleAdd(V7, S3, Result);
1419 Result = V3ScaleAdd(V9, S4, Result);
1420 Result = V3ScaleAdd(V11, S5, Result);
1421 Result = V3ScaleAdd(V13, S6, Result);
1422 Result = V3ScaleAdd(V15, S7, Result);
1423 Result = V3ScaleAdd(V17, S8, Result);
1424 Result = V3ScaleAdd(V19, S9, Result);
1425 Result = V3ScaleAdd(V21, S10, Result);
1426 Result = V3ScaleAdd(V23, S11, Result);
1427
1428 ASSERT_ISVALIDVEC3V(Result);
1429 return Result;
1430}
1431
1432PX_FORCE_INLINE Vec3V V3Cos(const Vec3V a)
1433{
1434 ASSERT_ISVALIDVEC3V(a);
1435
1436 // Modulo the range of the given angles such that -XM_2PI <= Angles < XM_2PI
1437 const Vec4V recipTwoPi = V4LoadA(g_PXReciprocalTwoPi.f);
1438 const Vec4V twoPi = V4LoadA(g_PXTwoPi.f);
1439 const Vec3V tmp = V3Scale(a, recipTwoPi);
1440 const Vec3V b = V3Round(tmp);
1441 const Vec3V V1 = V3NegScaleSub(b, twoPi, a);
1442
1443 // cos(V) ~= 1 - V^2 / 2! + V^4 / 4! - V^6 / 6! + V^8 / 8! - V^10 / 10! + V^12 / 12! -
1444 // V^14 / 14! + V^16 / 16! - V^18 / 18! + V^20 / 20! - V^22 / 22! (for -PI <= V < PI)
1445 const Vec3V V2 = V3Mul(V1, V1);
1446 const Vec3V V4 = V3Mul(V2, V2);
1447 const Vec3V V6 = V3Mul(V4, V2);
1448 const Vec3V V8 = V3Mul(V4, V4);
1449 const Vec3V V10 = V3Mul(V6, V4);
1450 const Vec3V V12 = V3Mul(V6, V6);
1451 const Vec3V V14 = V3Mul(V8, V6);
1452 const Vec3V V16 = V3Mul(V8, V8);
1453 const Vec3V V18 = V3Mul(V10, V8);
1454 const Vec3V V20 = V3Mul(V10, V10);
1455 const Vec3V V22 = V3Mul(V12, V10);
1456
1457 const Vec4V cosCoefficients0 = V4LoadA(g_PXCosCoefficients0.f);
1458 const Vec4V cosCoefficients1 = V4LoadA(g_PXCosCoefficients1.f);
1459 const Vec4V cosCoefficients2 = V4LoadA(g_PXCosCoefficients2.f);
1460
1461 const FloatV C1 = V4GetY(cosCoefficients0);
1462 const FloatV C2 = V4GetZ(cosCoefficients0);
1463 const FloatV C3 = V4GetW(cosCoefficients0);
1464 const FloatV C4 = V4GetX(cosCoefficients1);
1465 const FloatV C5 = V4GetY(cosCoefficients1);
1466 const FloatV C6 = V4GetZ(cosCoefficients1);
1467 const FloatV C7 = V4GetW(cosCoefficients1);
1468 const FloatV C8 = V4GetX(cosCoefficients2);
1469 const FloatV C9 = V4GetY(cosCoefficients2);
1470 const FloatV C10 = V4GetZ(cosCoefficients2);
1471 const FloatV C11 = V4GetW(cosCoefficients2);
1472
1473 Vec3V Result;
1474 Result = V3ScaleAdd(V2, C1, V3One());
1475 Result = V3ScaleAdd(V4, C2, Result);
1476 Result = V3ScaleAdd(V6, C3, Result);
1477 Result = V3ScaleAdd(V8, C4, Result);
1478 Result = V3ScaleAdd(V10, C5, Result);
1479 Result = V3ScaleAdd(V12, C6, Result);
1480 Result = V3ScaleAdd(V14, C7, Result);
1481 Result = V3ScaleAdd(V16, C8, Result);
1482 Result = V3ScaleAdd(V18, C9, Result);
1483 Result = V3ScaleAdd(V20, C10, Result);
1484 Result = V3ScaleAdd(V22, C11, Result);
1485
1486 ASSERT_ISVALIDVEC3V(Result);
1487 return Result;
1488}
1489
1490PX_FORCE_INLINE Vec3V V3PermYZZ(const Vec3V a)
1491{
1492 ASSERT_ISVALIDVEC3V(a);
1493 return _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 2, 2, 1));
1494}
1495
1496PX_FORCE_INLINE Vec3V V3PermXYX(const Vec3V a)
1497{
1498 ASSERT_ISVALIDVEC3V(a);
1499 return _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 0, 1, 0));
1500}
1501
1502PX_FORCE_INLINE Vec3V V3PermYZX(const Vec3V a)
1503{
1504 ASSERT_ISVALIDVEC3V(a);
1505 return _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 0, 2, 1));
1506}
1507
1508PX_FORCE_INLINE Vec3V V3PermZXY(const Vec3V a)
1509{
1510 ASSERT_ISVALIDVEC3V(a);
1511 return _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 1, 0, 2));
1512}
1513
1514PX_FORCE_INLINE Vec3V V3PermZZY(const Vec3V a)
1515{
1516 ASSERT_ISVALIDVEC3V(a);
1517 return _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 1, 2, 2));
1518}
1519
1520PX_FORCE_INLINE Vec3V V3PermYXX(const Vec3V a)
1521{
1522 ASSERT_ISVALIDVEC3V(a);
1523 return _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 0, 0, 1));
1524}
1525
1526PX_FORCE_INLINE Vec3V V3Perm_Zero_1Z_0Y(const Vec3V v0, const Vec3V v1)
1527{
1528 ASSERT_ISVALIDVEC3V(v0);
1529 ASSERT_ISVALIDVEC3V(v1);
1530 return _mm_shuffle_ps(v1, v0, _MM_SHUFFLE(3, 1, 2, 3));
1531}
1532
1533PX_FORCE_INLINE Vec3V V3Perm_0Z_Zero_1X(const Vec3V v0, const Vec3V v1)
1534{
1535 ASSERT_ISVALIDVEC3V(v0);
1536 ASSERT_ISVALIDVEC3V(v1);
1537 return _mm_shuffle_ps(v0, v1, _MM_SHUFFLE(3, 0, 3, 2));
1538}
1539
1540PX_FORCE_INLINE Vec3V V3Perm_1Y_0X_Zero(const Vec3V v0, const Vec3V v1)
1541{
1542 ASSERT_ISVALIDVEC3V(v0);
1543 ASSERT_ISVALIDVEC3V(v1);
1544 // There must be a better way to do this.
1545 Vec3V v2 = V3Zero();
1546 FloatV y1 = V3GetY(v1);
1547 FloatV x0 = V3GetX(v0);
1548 v2 = V3SetX(v2, y1);
1549 return V3SetY(v2, x0);
1550}
1551
1552PX_FORCE_INLINE FloatV V3SumElems(const Vec3V a)
1553{
1554 ASSERT_ISVALIDVEC3V(a);
1555 const __m128 shuf1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0)); // z,y,x,w
1556 const __m128 shuf2 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 1, 1, 1)); // y,x,w,z
1557 const __m128 shuf3 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2)); // x,w,z,y
1558 return _mm_add_ps(_mm_add_ps(shuf1, shuf2), shuf3);
1559}
1560
1561PX_FORCE_INLINE PxU32 V3OutOfBounds(const Vec3V a, const Vec3V min, const Vec3V max)
1562{
1563 ASSERT_ISVALIDVEC3V(a);
1564 ASSERT_ISVALIDVEC3V(min);
1565 ASSERT_ISVALIDVEC3V(max);
1566 const BoolV c = BOr(V3IsGrtr(a, max), V3IsGrtr(min, a));
1567 return PxU32(!BAllEqFFFF(c));
1568}
1569
1570PX_FORCE_INLINE PxU32 V3InBounds(const Vec3V a, const Vec3V min, const Vec3V max)
1571{
1572 ASSERT_ISVALIDVEC3V(a);
1573 ASSERT_ISVALIDVEC3V(min);
1574 ASSERT_ISVALIDVEC3V(max);
1575 const BoolV c = BAnd(V3IsGrtrOrEq(a, min), V3IsGrtrOrEq(max, a));
1576 return BAllEqTTTT(c);
1577}
1578
1579PX_FORCE_INLINE PxU32 V3OutOfBounds(const Vec3V a, const Vec3V bounds)
1580{
1581 ASSERT_ISVALIDVEC3V(a);
1582 ASSERT_ISVALIDVEC3V(bounds);
1583 return V3OutOfBounds(a, V3Neg(bounds), bounds);
1584}
1585
1586PX_FORCE_INLINE PxU32 V3InBounds(const Vec3V a, const Vec3V bounds)
1587{
1588 ASSERT_ISVALIDVEC3V(a);
1589 ASSERT_ISVALIDVEC3V(bounds);
1590 return V3InBounds(a, V3Neg(bounds), bounds);
1591}
1592
1593PX_FORCE_INLINE void V3Transpose(Vec3V& col0, Vec3V& col1, Vec3V& col2)
1594{
1595 ASSERT_ISVALIDVEC3V(col0);
1596 ASSERT_ISVALIDVEC3V(col1);
1597 ASSERT_ISVALIDVEC3V(col2);
1598 const Vec3V col3 = _mm_setzero_ps();
1599 Vec3V tmp0 = _mm_unpacklo_ps(col0, col1);
1600 Vec3V tmp2 = _mm_unpacklo_ps(col2, col3);
1601 Vec3V tmp1 = _mm_unpackhi_ps(col0, col1);
1602 Vec3V tmp3 = _mm_unpackhi_ps(col2, col3);
1603 col0 = _mm_movelh_ps(tmp0, tmp2);
1604 col1 = _mm_movehl_ps(tmp2, tmp0);
1605 col2 = _mm_movelh_ps(tmp1, tmp3);
1606}
1607
1609// VEC4V
1611
1612PX_FORCE_INLINE Vec4V V4Splat(const FloatV f)
1613{
1614 ASSERT_ISVALIDFLOATV(f);
1615 // return _mm_shuffle_ps(f, f, _MM_SHUFFLE(0,0,0,0));
1616 return f;
1617}
1618
1619PX_FORCE_INLINE Vec4V V4Merge(const FloatV* const floatVArray)
1620{
1621 ASSERT_ISVALIDFLOATV(floatVArray[0]);
1622 ASSERT_ISVALIDFLOATV(floatVArray[1]);
1623 ASSERT_ISVALIDFLOATV(floatVArray[2]);
1624 ASSERT_ISVALIDFLOATV(floatVArray[3]);
1625 const __m128 xw = _mm_move_ss(floatVArray[1], floatVArray[0]); // y, y, y, x
1626 const __m128 yz = _mm_move_ss(floatVArray[2], floatVArray[3]); // z, z, z, w
1627 return _mm_shuffle_ps(xw, yz, _MM_SHUFFLE(0, 2, 1, 0));
1628}
1629
1630PX_FORCE_INLINE Vec4V V4Merge(const FloatVArg x, const FloatVArg y, const FloatVArg z, const FloatVArg w)
1631{
1632 ASSERT_ISVALIDFLOATV(x);
1633 ASSERT_ISVALIDFLOATV(y);
1634 ASSERT_ISVALIDFLOATV(z);
1635 ASSERT_ISVALIDFLOATV(w);
1636 const __m128 xw = _mm_move_ss(y, x); // y, y, y, x
1637 const __m128 yz = _mm_move_ss(z, w); // z, z, z, w
1638 return _mm_shuffle_ps(xw, yz, _MM_SHUFFLE(0, 2, 1, 0));
1639}
1640
1641PX_FORCE_INLINE Vec4V V4MergeW(const Vec4VArg x, const Vec4VArg y, const Vec4VArg z, const Vec4VArg w)
1642{
1643 const Vec4V xz = _mm_unpackhi_ps(x, z);
1644 const Vec4V yw = _mm_unpackhi_ps(y, w);
1645 return _mm_unpackhi_ps(xz, yw);
1646}
1647
1648PX_FORCE_INLINE Vec4V V4MergeZ(const Vec4VArg x, const Vec4VArg y, const Vec4VArg z, const Vec4VArg w)
1649{
1650 const Vec4V xz = _mm_unpackhi_ps(x, z);
1651 const Vec4V yw = _mm_unpackhi_ps(y, w);
1652 return _mm_unpacklo_ps(xz, yw);
1653}
1654
1655PX_FORCE_INLINE Vec4V V4MergeY(const Vec4VArg x, const Vec4VArg y, const Vec4VArg z, const Vec4VArg w)
1656{
1657 const Vec4V xz = _mm_unpacklo_ps(x, z);
1658 const Vec4V yw = _mm_unpacklo_ps(y, w);
1659 return _mm_unpackhi_ps(xz, yw);
1660}
1661
1662PX_FORCE_INLINE Vec4V V4MergeX(const Vec4VArg x, const Vec4VArg y, const Vec4VArg z, const Vec4VArg w)
1663{
1664 const Vec4V xz = _mm_unpacklo_ps(x, z);
1665 const Vec4V yw = _mm_unpacklo_ps(y, w);
1666 return _mm_unpacklo_ps(xz, yw);
1667}
1668
1669PX_FORCE_INLINE Vec4V V4UnpackXY(const Vec4VArg a, const Vec4VArg b)
1670{
1671 return _mm_unpacklo_ps(a, b);
1672}
1673
1674PX_FORCE_INLINE Vec4V V4UnpackZW(const Vec4VArg a, const Vec4VArg b)
1675{
1676 return _mm_unpackhi_ps(a, b);
1677}
1678
1679PX_FORCE_INLINE Vec4V V4PermYXWZ(const Vec4V a)
1680{
1681 return _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 3, 0, 1));
1682}
1683
1684PX_FORCE_INLINE Vec4V V4PermXZXZ(const Vec4V a)
1685{
1686 return _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 0, 2, 0));
1687}
1688
1689PX_FORCE_INLINE Vec4V V4PermYWYW(const Vec4V a)
1690{
1691 return _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 1, 3, 1));
1692}
1693
1694PX_FORCE_INLINE Vec4V V4PermYZXW(const Vec4V a)
1695{
1696 return _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 0, 2, 1));
1697}
1698
1699PX_FORCE_INLINE Vec4V V4PermZWXY(const Vec4V a)
1700{
1701 return _mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 0, 3, 2));
1702}
1703
1704template <PxU8 x, PxU8 y, PxU8 z, PxU8 w>
1705PX_FORCE_INLINE Vec4V V4Perm(const Vec4V a)
1706{
1707 return _mm_shuffle_ps(a, a, _MM_SHUFFLE(w, z, y, x));
1708}
1709
1710PX_FORCE_INLINE Vec4V V4UnitW()
1711{
1712 const PX_ALIGN(16, PxF32 w[4]) = { 0.0f, 0.0f, 0.0f, 1.0f };
1713 const __m128 w128 = _mm_load_ps(w);
1714 return w128;
1715}
1716
1717PX_FORCE_INLINE Vec4V V4UnitX()
1718{
1719 const PX_ALIGN(16, PxF32 x[4]) = { 1.0f, 0.0f, 0.0f, 0.0f };
1720 const __m128 x128 = _mm_load_ps(x);
1721 return x128;
1722}
1723
1724PX_FORCE_INLINE Vec4V V4UnitY()
1725{
1726 const PX_ALIGN(16, PxF32 y[4]) = { 0.0f, 1.0f, 0.0f, 0.0f };
1727 const __m128 y128 = _mm_load_ps(y);
1728 return y128;
1729}
1730
1731PX_FORCE_INLINE Vec4V V4UnitZ()
1732{
1733 const PX_ALIGN(16, PxF32 z[4]) = { 0.0f, 0.0f, 1.0f, 0.0f };
1734 const __m128 z128 = _mm_load_ps(z);
1735 return z128;
1736}
1737
1738PX_FORCE_INLINE FloatV V4GetW(const Vec4V f)
1739{
1740 return _mm_shuffle_ps(f, f, _MM_SHUFFLE(3, 3, 3, 3));
1741}
1742
1743PX_FORCE_INLINE FloatV V4GetX(const Vec4V f)
1744{
1745 return _mm_shuffle_ps(f, f, _MM_SHUFFLE(0, 0, 0, 0));
1746}
1747
1748PX_FORCE_INLINE FloatV V4GetY(const Vec4V f)
1749{
1750 return _mm_shuffle_ps(f, f, _MM_SHUFFLE(1, 1, 1, 1));
1751}
1752
1753PX_FORCE_INLINE FloatV V4GetZ(const Vec4V f)
1754{
1755 return _mm_shuffle_ps(f, f, _MM_SHUFFLE(2, 2, 2, 2));
1756}
1757
1758PX_FORCE_INLINE Vec4V V4SetW(const Vec4V v, const FloatV f)
1759{
1760 ASSERT_ISVALIDFLOATV(f);
1761 return V4Sel(BTTTF(), v, f);
1762}
1763
1764PX_FORCE_INLINE Vec4V V4ClearW(const Vec4V v)
1765{
1766 return _mm_and_ps(v, (VecI32V&)internalWindowsSimd::gMaskXYZ);
1767}
1768
1769PX_FORCE_INLINE Vec4V V4SetX(const Vec4V v, const FloatV f)
1770{
1771 ASSERT_ISVALIDFLOATV(f);
1772 return V4Sel(BFTTT(), v, f);
1773}
1774
1775PX_FORCE_INLINE Vec4V V4SetY(const Vec4V v, const FloatV f)
1776{
1777 ASSERT_ISVALIDFLOATV(f);
1778 return V4Sel(BTFTT(), v, f);
1779}
1780
1781PX_FORCE_INLINE Vec4V V4SetZ(const Vec4V v, const FloatV f)
1782{
1783 ASSERT_ISVALIDFLOATV(f);
1784 return V4Sel(BTTFT(), v, f);
1785}
1786
1787PX_FORCE_INLINE Vec4V V4Zero()
1788{
1789 return _mm_setzero_ps();
1790}
1791
1792PX_FORCE_INLINE Vec4V V4One()
1793{
1794 return V4Load(1.0f);
1795}
1796
1797PX_FORCE_INLINE Vec4V V4Eps()
1798{
1799 return V4Load(PX_EPS_REAL);
1800}
1801
1802PX_FORCE_INLINE Vec4V V4Neg(const Vec4V f)
1803{
1804 return _mm_sub_ps(_mm_setzero_ps(), f);
1805}
1806
1807PX_FORCE_INLINE Vec4V V4Add(const Vec4V a, const Vec4V b)
1808{
1809 return _mm_add_ps(a, b);
1810}
1811
1812PX_FORCE_INLINE Vec4V V4Sub(const Vec4V a, const Vec4V b)
1813{
1814 return _mm_sub_ps(a, b);
1815}
1816
1817PX_FORCE_INLINE Vec4V V4Scale(const Vec4V a, const FloatV b)
1818{
1819 return _mm_mul_ps(a, b);
1820}
1821
1822PX_FORCE_INLINE Vec4V V4Mul(const Vec4V a, const Vec4V b)
1823{
1824 return _mm_mul_ps(a, b);
1825}
1826
1827PX_FORCE_INLINE Vec4V V4ScaleInv(const Vec4V a, const FloatV b)
1828{
1829 ASSERT_ISVALIDFLOATV(b);
1830 return _mm_div_ps(a, b);
1831}
1832
1833PX_FORCE_INLINE Vec4V V4Div(const Vec4V a, const Vec4V b)
1834{
1835 return _mm_div_ps(a, b);
1836}
1837
1838PX_FORCE_INLINE Vec4V V4ScaleInvFast(const Vec4V a, const FloatV b)
1839{
1840 ASSERT_ISVALIDFLOATV(b);
1841 return _mm_mul_ps(a, _mm_rcp_ps(b));
1842}
1843
1844PX_FORCE_INLINE Vec4V V4DivFast(const Vec4V a, const Vec4V b)
1845{
1846 return _mm_mul_ps(a, _mm_rcp_ps(b));
1847}
1848
1849PX_FORCE_INLINE Vec4V V4Recip(const Vec4V a)
1850{
1851 return _mm_div_ps(V4One(), a);
1852}
1853
1854PX_FORCE_INLINE Vec4V V4RecipFast(const Vec4V a)
1855{
1856 return _mm_rcp_ps(a);
1857}
1858
1859PX_FORCE_INLINE Vec4V V4Rsqrt(const Vec4V a)
1860{
1861 return _mm_div_ps(V4One(), _mm_sqrt_ps(a));
1862}
1863
1864PX_FORCE_INLINE Vec4V V4RsqrtFast(const Vec4V a)
1865{
1866 return _mm_rsqrt_ps(a);
1867}
1868
1869PX_FORCE_INLINE Vec4V V4Sqrt(const Vec4V a)
1870{
1871 return _mm_sqrt_ps(a);
1872}
1873
1874PX_FORCE_INLINE Vec4V V4ScaleAdd(const Vec4V a, const FloatV b, const Vec4V c)
1875{
1876 ASSERT_ISVALIDFLOATV(b);
1877 return V4Add(V4Scale(a, b), c);
1878}
1879
1880PX_FORCE_INLINE Vec4V V4NegScaleSub(const Vec4V a, const FloatV b, const Vec4V c)
1881{
1882 ASSERT_ISVALIDFLOATV(b);
1883 return V4Sub(c, V4Scale(a, b));
1884}
1885
1886PX_FORCE_INLINE Vec4V V4MulAdd(const Vec4V a, const Vec4V b, const Vec4V c)
1887{
1888 return V4Add(V4Mul(a, b), c);
1889}
1890
1891PX_FORCE_INLINE Vec4V V4NegMulSub(const Vec4V a, const Vec4V b, const Vec4V c)
1892{
1893 return V4Sub(c, V4Mul(a, b));
1894}
1895
1896PX_FORCE_INLINE Vec4V V4Abs(const Vec4V a)
1897{
1898 return V4Max(a, V4Neg(a));
1899}
1900
1901PX_FORCE_INLINE FloatV V4SumElements(const Vec4V a)
1902{
1903 const Vec4V xy = V4UnpackXY(a, a); // x,x,y,y
1904 const Vec4V zw = V4UnpackZW(a, a); // z,z,w,w
1905 const Vec4V xz_yw = V4Add(xy, zw); // x+z,x+z,y+w,y+w
1906 const FloatV xz = V4GetX(xz_yw); // x+z
1907 const FloatV yw = V4GetZ(xz_yw); // y+w
1908 return FAdd(xz, yw); // sum
1909}
1910
1911PX_FORCE_INLINE FloatV V4Dot(const Vec4V a, const Vec4V b)
1912{
1913 //const __m128 dot1 = _mm_mul_ps(a, b); // x,y,z,w
1914 //const __m128 shuf1 = _mm_shuffle_ps(dot1, dot1, _MM_SHUFFLE(2, 1, 0, 3)); // w,x,y,z
1915 //const __m128 shuf2 = _mm_shuffle_ps(dot1, dot1, _MM_SHUFFLE(1, 0, 3, 2)); // z,w,x,y
1916 //const __m128 shuf3 = _mm_shuffle_ps(dot1, dot1, _MM_SHUFFLE(0, 3, 2, 1)); // y,z,w,x
1917 //return _mm_add_ps(_mm_add_ps(shuf2, shuf3), _mm_add_ps(dot1, shuf1));
1918
1919 // PT: this version has two less instructions but we should check its accuracy
1920 // aw*bw | az*bz | ay*by | ax*bx
1921 const __m128 t0 = _mm_mul_ps(a, b);
1922 // ay*by | ax*bx | aw*bw | az*bz
1923 const __m128 t1 = _mm_shuffle_ps(t0, t0, _MM_SHUFFLE(1,0,3,2));
1924 // ay*by + aw*bw | ax*bx + az*bz | aw*bw + ay*by | az*bz + ax*bx
1925 const __m128 t2 = _mm_add_ps(t0, t1);
1926 // ax*bx + az*bz | ay*by + aw*bw | az*bz + ax*bx | aw*bw + ay*by
1927 const __m128 t3 = _mm_shuffle_ps(t2, t2, _MM_SHUFFLE(2,3,0,1));
1928 // ax*bx + az*bz + ay*by + aw*bw
1929 return _mm_add_ps(t3, t2);
1930 // ay*by + aw*bw + ax*bx + az*bz
1931 // az*bz + ax*bx + aw*bw + ay*by
1932 // aw*bw + ay*by + az*bz + ax*bx
1933}
1934
1935PX_FORCE_INLINE FloatV V4Dot3(const Vec4V a, const Vec4V b)
1936{
1937 const __m128 dot1 = _mm_mul_ps(a, b); // aw*bw | az*bz | ay*by | ax*bx
1938 const __m128 shuf1 = _mm_shuffle_ps(dot1, dot1, _MM_SHUFFLE(0, 0, 0, 0)); // ax*bx | ax*bx | ax*bx | ax*bx
1939 const __m128 shuf2 = _mm_shuffle_ps(dot1, dot1, _MM_SHUFFLE(1, 1, 1, 1)); // ay*by | ay*by | ay*by | ay*by
1940 const __m128 shuf3 = _mm_shuffle_ps(dot1, dot1, _MM_SHUFFLE(2, 2, 2, 2)); // az*bz | az*bz | az*bz | az*bz
1941 return _mm_add_ps(_mm_add_ps(shuf1, shuf2), shuf3); // ax*bx + ay*by + az*bz in each component
1942}
1943
1944PX_FORCE_INLINE Vec4V V4Cross(const Vec4V a, const Vec4V b)
1945{
1946/* if(0)
1947 {
1948 const __m128 r1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 1, 0, 2)); // z,x,y,w
1949 const __m128 r2 = _mm_shuffle_ps(b, b, _MM_SHUFFLE(3, 0, 2, 1)); // y,z,x,w
1950 const __m128 l1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 0, 2, 1)); // y,z,x,w
1951 const __m128 l2 = _mm_shuffle_ps(b, b, _MM_SHUFFLE(3, 1, 0, 2)); // z,x,y,w
1952 return _mm_sub_ps(_mm_mul_ps(l1, l2), _mm_mul_ps(r1, r2));
1953 }
1954 else*/
1955 {
1956 const __m128 b0 = _mm_shuffle_ps(b, b, _MM_SHUFFLE(3,0,2,1));
1957 const __m128 a1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(3,0,2,1));
1958 __m128 v = _mm_mul_ps(a1, b);
1959 v = _mm_sub_ps(_mm_mul_ps(a, b0), v);
1960 return _mm_shuffle_ps(v, v, _MM_SHUFFLE(3,0,2,1));
1961 }
1962}
1963
1964PX_FORCE_INLINE FloatV V4Length(const Vec4V a)
1965{
1966 return _mm_sqrt_ps(V4Dot(a, a));
1967}
1968
1969PX_FORCE_INLINE FloatV V4LengthSq(const Vec4V a)
1970{
1971 return V4Dot(a, a);
1972}
1973
1974PX_FORCE_INLINE Vec4V V4Normalize(const Vec4V a)
1975{
1976 ASSERT_ISFINITELENGTH(a);
1977 return V4ScaleInv(a, _mm_sqrt_ps(V4Dot(a, a)));
1978}
1979
1980PX_FORCE_INLINE Vec4V V4NormalizeFast(const Vec4V a)
1981{
1982 ASSERT_ISFINITELENGTH(a);
1983 return V4ScaleInvFast(a, _mm_sqrt_ps(V4Dot(a, a)));
1984}
1985
1986PX_FORCE_INLINE Vec4V V4NormalizeSafe(const Vec4V a, const Vec4V unsafeReturnValue)
1987{
1988 const __m128 eps = V3Eps();
1989 const __m128 length = V4Length(a);
1990 const __m128 isGreaterThanZero = V4IsGrtr(length, eps);
1991 return V4Sel(isGreaterThanZero, V4ScaleInv(a, length), unsafeReturnValue);
1992}
1993
1994PX_FORCE_INLINE Vec4V V4Sel(const BoolV c, const Vec4V a, const Vec4V b)
1995{
1996 return _mm_or_ps(_mm_andnot_ps(c, b), _mm_and_ps(c, a));
1997}
1998
1999PX_FORCE_INLINE BoolV V4IsGrtr(const Vec4V a, const Vec4V b)
2000{
2001 return _mm_cmpgt_ps(a, b);
2002}
2003
2004PX_FORCE_INLINE BoolV V4IsGrtrOrEq(const Vec4V a, const Vec4V b)
2005{
2006 return _mm_cmpge_ps(a, b);
2007}
2008
2009PX_FORCE_INLINE BoolV V4IsEq(const Vec4V a, const Vec4V b)
2010{
2011 return _mm_cmpeq_ps(a, b);
2012}
2013
2014PX_FORCE_INLINE BoolV V4IsEqU32(const VecU32V a, const VecU32V b)
2015{
2016 return internalWindowsSimd::m128_I2F(
2017 _mm_cmpeq_epi32(internalWindowsSimd::m128_F2I(a), internalWindowsSimd::m128_F2I(b)));
2018}
2019
2020PX_FORCE_INLINE Vec4V V4Max(const Vec4V a, const Vec4V b)
2021{
2022 return _mm_max_ps(a, b);
2023}
2024
2025PX_FORCE_INLINE Vec4V V4Min(const Vec4V a, const Vec4V b)
2026{
2027 return _mm_min_ps(a, b);
2028}
2029
2030PX_FORCE_INLINE FloatV V4ExtractMax(const Vec4V a)
2031{
2032 const __m128 shuf1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 1, 0, 3));
2033 const __m128 shuf2 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 0, 3, 2));
2034 const __m128 shuf3 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 3, 2, 1));
2035
2036 return _mm_max_ps(_mm_max_ps(a, shuf1), _mm_max_ps(shuf2, shuf3));
2037}
2038
2039PX_FORCE_INLINE FloatV V4ExtractMin(const Vec4V a)
2040{
2041 const __m128 shuf1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 1, 0, 3));
2042 const __m128 shuf2 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 0, 3, 2));
2043 const __m128 shuf3 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 3, 2, 1));
2044
2045 return _mm_min_ps(_mm_min_ps(a, shuf1), _mm_min_ps(shuf2, shuf3));
2046}
2047
2048PX_FORCE_INLINE Vec4V V4Clamp(const Vec4V a, const Vec4V minV, const Vec4V maxV)
2049{
2050 return V4Max(V4Min(a, maxV), minV);
2051}
2052
2053PX_FORCE_INLINE PxU32 V4AllGrtr(const Vec4V a, const Vec4V b)
2054{
2055 return internalWindowsSimd::BAllTrue4_R(V4IsGrtr(a, b));
2056}
2057
2058PX_FORCE_INLINE PxU32 V4AllGrtrOrEq(const Vec4V a, const Vec4V b)
2059{
2060 return internalWindowsSimd::BAllTrue4_R(V4IsGrtrOrEq(a, b));
2061}
2062
2063PX_FORCE_INLINE PxU32 V4AllGrtrOrEq3(const Vec4V a, const Vec4V b)
2064{
2065 return internalWindowsSimd::BAllTrue3_R(V4IsGrtrOrEq(a, b));
2066}
2067
2068PX_FORCE_INLINE PxU32 V4AllEq(const Vec4V a, const Vec4V b)
2069{
2070 return internalWindowsSimd::BAllTrue4_R(V4IsEq(a, b));
2071}
2072
2073PX_FORCE_INLINE PxU32 V4AnyGrtr3(const Vec4V a, const Vec4V b)
2074{
2075 return internalWindowsSimd::BAnyTrue3_R(V4IsGrtr(a, b));
2076}
2077
2078PX_FORCE_INLINE Vec4V V4Round(const Vec4V a)
2079{
2080 // return _mm_round_ps(a, 0x0);
2081 const Vec4V half = V4Load(0.5f);
2082 const __m128 signBit = _mm_cvtepi32_ps(_mm_srli_epi32(_mm_cvtps_epi32(a), 31));
2083 const Vec4V aRound = V4Sub(V4Add(a, half), signBit);
2084 const __m128i tmp = _mm_cvttps_epi32(aRound);
2085 return _mm_cvtepi32_ps(tmp);
2086}
2087
2088PX_FORCE_INLINE Vec4V V4Sin(const Vec4V a)
2089{
2090 const Vec4V recipTwoPi = V4LoadA(g_PXReciprocalTwoPi.f);
2091 const Vec4V twoPi = V4LoadA(g_PXTwoPi.f);
2092 const Vec4V tmp = V4Mul(a, recipTwoPi);
2093 const Vec4V b = V4Round(tmp);
2094 const Vec4V V1 = V4NegMulSub(twoPi, b, a);
2095
2096 // sin(V) ~= V - V^3 / 3! + V^5 / 5! - V^7 / 7! + V^9 / 9! - V^11 / 11! + V^13 / 13! -
2097 // V^15 / 15! + V^17 / 17! - V^19 / 19! + V^21 / 21! - V^23 / 23! (for -PI <= V < PI)
2098 const Vec4V V2 = V4Mul(V1, V1);
2099 const Vec4V V3 = V4Mul(V2, V1);
2100 const Vec4V V5 = V4Mul(V3, V2);
2101 const Vec4V V7 = V4Mul(V5, V2);
2102 const Vec4V V9 = V4Mul(V7, V2);
2103 const Vec4V V11 = V4Mul(V9, V2);
2104 const Vec4V V13 = V4Mul(V11, V2);
2105 const Vec4V V15 = V4Mul(V13, V2);
2106 const Vec4V V17 = V4Mul(V15, V2);
2107 const Vec4V V19 = V4Mul(V17, V2);
2108 const Vec4V V21 = V4Mul(V19, V2);
2109 const Vec4V V23 = V4Mul(V21, V2);
2110
2111 const Vec4V sinCoefficients0 = V4LoadA(g_PXSinCoefficients0.f);
2112 const Vec4V sinCoefficients1 = V4LoadA(g_PXSinCoefficients1.f);
2113 const Vec4V sinCoefficients2 = V4LoadA(g_PXSinCoefficients2.f);
2114
2115 const FloatV S1 = V4GetY(sinCoefficients0);
2116 const FloatV S2 = V4GetZ(sinCoefficients0);
2117 const FloatV S3 = V4GetW(sinCoefficients0);
2118 const FloatV S4 = V4GetX(sinCoefficients1);
2119 const FloatV S5 = V4GetY(sinCoefficients1);
2120 const FloatV S6 = V4GetZ(sinCoefficients1);
2121 const FloatV S7 = V4GetW(sinCoefficients1);
2122 const FloatV S8 = V4GetX(sinCoefficients2);
2123 const FloatV S9 = V4GetY(sinCoefficients2);
2124 const FloatV S10 = V4GetZ(sinCoefficients2);
2125 const FloatV S11 = V4GetW(sinCoefficients2);
2126
2127 Vec4V Result;
2128 Result = V4MulAdd(S1, V3, V1);
2129 Result = V4MulAdd(S2, V5, Result);
2130 Result = V4MulAdd(S3, V7, Result);
2131 Result = V4MulAdd(S4, V9, Result);
2132 Result = V4MulAdd(S5, V11, Result);
2133 Result = V4MulAdd(S6, V13, Result);
2134 Result = V4MulAdd(S7, V15, Result);
2135 Result = V4MulAdd(S8, V17, Result);
2136 Result = V4MulAdd(S9, V19, Result);
2137 Result = V4MulAdd(S10, V21, Result);
2138 Result = V4MulAdd(S11, V23, Result);
2139
2140 return Result;
2141}
2142
2143PX_FORCE_INLINE Vec4V V4Cos(const Vec4V a)
2144{
2145 const Vec4V recipTwoPi = V4LoadA(g_PXReciprocalTwoPi.f);
2146 const FloatV twoPi = V4LoadA(g_PXTwoPi.f);
2147 const Vec4V tmp = V4Mul(a, recipTwoPi);
2148 const Vec4V b = V4Round(tmp);
2149 const Vec4V V1 = V4NegMulSub(twoPi, b, a);
2150
2151 // cos(V) ~= 1 - V^2 / 2! + V^4 / 4! - V^6 / 6! + V^8 / 8! - V^10 / 10! + V^12 / 12! -
2152 // V^14 / 14! + V^16 / 16! - V^18 / 18! + V^20 / 20! - V^22 / 22! (for -PI <= V < PI)
2153 const Vec4V V2 = V4Mul(V1, V1);
2154 const Vec4V V4 = V4Mul(V2, V2);
2155 const Vec4V V6 = V4Mul(V4, V2);
2156 const Vec4V V8 = V4Mul(V4, V4);
2157 const Vec4V V10 = V4Mul(V6, V4);
2158 const Vec4V V12 = V4Mul(V6, V6);
2159 const Vec4V V14 = V4Mul(V8, V6);
2160 const Vec4V V16 = V4Mul(V8, V8);
2161 const Vec4V V18 = V4Mul(V10, V8);
2162 const Vec4V V20 = V4Mul(V10, V10);
2163 const Vec4V V22 = V4Mul(V12, V10);
2164
2165 const Vec4V cosCoefficients0 = V4LoadA(g_PXCosCoefficients0.f);
2166 const Vec4V cosCoefficients1 = V4LoadA(g_PXCosCoefficients1.f);
2167 const Vec4V cosCoefficients2 = V4LoadA(g_PXCosCoefficients2.f);
2168
2169 const FloatV C1 = V4GetY(cosCoefficients0);
2170 const FloatV C2 = V4GetZ(cosCoefficients0);
2171 const FloatV C3 = V4GetW(cosCoefficients0);
2172 const FloatV C4 = V4GetX(cosCoefficients1);
2173 const FloatV C5 = V4GetY(cosCoefficients1);
2174 const FloatV C6 = V4GetZ(cosCoefficients1);
2175 const FloatV C7 = V4GetW(cosCoefficients1);
2176 const FloatV C8 = V4GetX(cosCoefficients2);
2177 const FloatV C9 = V4GetY(cosCoefficients2);
2178 const FloatV C10 = V4GetZ(cosCoefficients2);
2179 const FloatV C11 = V4GetW(cosCoefficients2);
2180
2181 Vec4V Result;
2182 Result = V4MulAdd(C1, V2, V4One());
2183 Result = V4MulAdd(C2, V4, Result);
2184 Result = V4MulAdd(C3, V6, Result);
2185 Result = V4MulAdd(C4, V8, Result);
2186 Result = V4MulAdd(C5, V10, Result);
2187 Result = V4MulAdd(C6, V12, Result);
2188 Result = V4MulAdd(C7, V14, Result);
2189 Result = V4MulAdd(C8, V16, Result);
2190 Result = V4MulAdd(C9, V18, Result);
2191 Result = V4MulAdd(C10, V20, Result);
2192 Result = V4MulAdd(C11, V22, Result);
2193
2194 return Result;
2195}
2196
2197PX_FORCE_INLINE void V4Transpose(Vec4V& col0, Vec4V& col1, Vec4V& col2, Vec4V& col3)
2198{
2199 Vec4V tmp0 = _mm_unpacklo_ps(col0, col1);
2200 Vec4V tmp2 = _mm_unpacklo_ps(col2, col3);
2201 Vec4V tmp1 = _mm_unpackhi_ps(col0, col1);
2202 Vec4V tmp3 = _mm_unpackhi_ps(col2, col3);
2203 col0 = _mm_movelh_ps(tmp0, tmp2);
2204 col1 = _mm_movehl_ps(tmp2, tmp0);
2205 col2 = _mm_movelh_ps(tmp1, tmp3);
2206 col3 = _mm_movehl_ps(tmp3, tmp1);
2207}
2208
2210// BoolV
2212
2213PX_FORCE_INLINE BoolV BFFFF()
2214{
2215 return _mm_setzero_ps();
2216}
2217
2218PX_FORCE_INLINE BoolV BFFFT()
2219{
2220 /*const PX_ALIGN(16, PxU32 f[4])={0,0,0,0xFFFFFFFF};
2221 const __m128 ffft=_mm_load_ps((float*)&f);
2222 return ffft;*/
2223 return internalWindowsSimd::m128_I2F(_mm_set_epi32(-1, 0, 0, 0));
2224}
2225
2226PX_FORCE_INLINE BoolV BFFTF()
2227{
2228 /*const PX_ALIGN(16, PxU32 f[4])={0,0,0xFFFFFFFF,0};
2229 const __m128 fftf=_mm_load_ps((float*)&f);
2230 return fftf;*/
2231 return internalWindowsSimd::m128_I2F(_mm_set_epi32(0, -1, 0, 0));
2232}
2233
2234PX_FORCE_INLINE BoolV BFFTT()
2235{
2236 /*const PX_ALIGN(16, PxU32 f[4])={0,0,0xFFFFFFFF,0xFFFFFFFF};
2237 const __m128 fftt=_mm_load_ps((float*)&f);
2238 return fftt;*/
2239 return internalWindowsSimd::m128_I2F(_mm_set_epi32(-1, -1, 0, 0));
2240}
2241
2242PX_FORCE_INLINE BoolV BFTFF()
2243{
2244 /*const PX_ALIGN(16, PxU32 f[4])={0,0xFFFFFFFF,0,0};
2245 const __m128 ftff=_mm_load_ps((float*)&f);
2246 return ftff;*/
2247 return internalWindowsSimd::m128_I2F(_mm_set_epi32(0, 0, -1, 0));
2248}
2249
2250PX_FORCE_INLINE BoolV BFTFT()
2251{
2252 /*const PX_ALIGN(16, PxU32 f[4])={0,0xFFFFFFFF,0,0xFFFFFFFF};
2253 const __m128 ftft=_mm_load_ps((float*)&f);
2254 return ftft;*/
2255 return internalWindowsSimd::m128_I2F(_mm_set_epi32(-1, 0, -1, 0));
2256}
2257
2258PX_FORCE_INLINE BoolV BFTTF()
2259{
2260 /*const PX_ALIGN(16, PxU32 f[4])={0,0xFFFFFFFF,0xFFFFFFFF,0};
2261 const __m128 fttf=_mm_load_ps((float*)&f);
2262 return fttf;*/
2263 return internalWindowsSimd::m128_I2F(_mm_set_epi32(0, -1, -1, 0));
2264}
2265
2266PX_FORCE_INLINE BoolV BFTTT()
2267{
2268 /*const PX_ALIGN(16, PxU32 f[4])={0,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
2269 const __m128 fttt=_mm_load_ps((float*)&f);
2270 return fttt;*/
2271 return internalWindowsSimd::m128_I2F(_mm_set_epi32(-1, -1, -1, 0));
2272}
2273
2274PX_FORCE_INLINE BoolV BTFFF()
2275{
2276 // const PX_ALIGN(16, PxU32 f[4])={0xFFFFFFFF,0,0,0};
2277 // const __m128 tfff=_mm_load_ps((float*)&f);
2278 // return tfff;
2279 return internalWindowsSimd::m128_I2F(_mm_set_epi32(0, 0, 0, -1));
2280}
2281
2282PX_FORCE_INLINE BoolV BTFFT()
2283{
2284 /*const PX_ALIGN(16, PxU32 f[4])={0xFFFFFFFF,0,0,0xFFFFFFFF};
2285 const __m128 tfft=_mm_load_ps((float*)&f);
2286 return tfft;*/
2287 return internalWindowsSimd::m128_I2F(_mm_set_epi32(-1, 0, 0, -1));
2288}
2289
2290PX_FORCE_INLINE BoolV BTFTF()
2291{
2292 /*const PX_ALIGN(16, PxU32 f[4])={0xFFFFFFFF,0,0xFFFFFFFF,0};
2293 const __m128 tftf=_mm_load_ps((float*)&f);
2294 return tftf;*/
2295 return internalWindowsSimd::m128_I2F(_mm_set_epi32(0, -1, 0, -1));
2296}
2297
2298PX_FORCE_INLINE BoolV BTFTT()
2299{
2300 /*const PX_ALIGN(16, PxU32 f[4])={0xFFFFFFFF,0,0xFFFFFFFF,0xFFFFFFFF};
2301 const __m128 tftt=_mm_load_ps((float*)&f);
2302 return tftt;*/
2303 return internalWindowsSimd::m128_I2F(_mm_set_epi32(-1, -1, 0, -1));
2304}
2305
2306PX_FORCE_INLINE BoolV BTTFF()
2307{
2308 /*const PX_ALIGN(16, PxU32 f[4])={0xFFFFFFFF,0xFFFFFFFF,0,0};
2309 const __m128 ttff=_mm_load_ps((float*)&f);
2310 return ttff;*/
2311 return internalWindowsSimd::m128_I2F(_mm_set_epi32(0, 0, -1, -1));
2312}
2313
2314PX_FORCE_INLINE BoolV BTTFT()
2315{
2316 /*const PX_ALIGN(16, PxU32 f[4])={0xFFFFFFFF,0xFFFFFFFF,0,0xFFFFFFFF};
2317 const __m128 ttft=_mm_load_ps((float*)&f);
2318 return ttft;*/
2319 return internalWindowsSimd::m128_I2F(_mm_set_epi32(-1, 0, -1, -1));
2320}
2321
2322PX_FORCE_INLINE BoolV BTTTF()
2323{
2324 /*const PX_ALIGN(16, PxU32 f[4])={0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0};
2325 const __m128 tttf=_mm_load_ps((float*)&f);
2326 return tttf;*/
2327 return internalWindowsSimd::m128_I2F(_mm_set_epi32(0, -1, -1, -1));
2328}
2329
2330PX_FORCE_INLINE BoolV BTTTT()
2331{
2332 /*const PX_ALIGN(16, PxU32 f[4])={0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
2333 const __m128 tttt=_mm_load_ps((float*)&f);
2334 return tttt;*/
2335 return internalWindowsSimd::m128_I2F(_mm_set_epi32(-1, -1, -1, -1));
2336}
2337
2338PX_FORCE_INLINE BoolV BXMask()
2339{
2340 /*const PX_ALIGN(16, PxU32 f[4])={0xFFFFFFFF,0,0,0};
2341 const __m128 tfff=_mm_load_ps((float*)&f);
2342 return tfff;*/
2343 return internalWindowsSimd::m128_I2F(_mm_set_epi32(0, 0, 0, -1));
2344}
2345
2346PX_FORCE_INLINE BoolV BYMask()
2347{
2348 /*const PX_ALIGN(16, PxU32 f[4])={0,0xFFFFFFFF,0,0};
2349 const __m128 ftff=_mm_load_ps((float*)&f);
2350 return ftff;*/
2351 return internalWindowsSimd::m128_I2F(_mm_set_epi32(0, 0, -1, 0));
2352}
2353
2354PX_FORCE_INLINE BoolV BZMask()
2355{
2356 /*const PX_ALIGN(16, PxU32 f[4])={0,0,0xFFFFFFFF,0};
2357 const __m128 fftf=_mm_load_ps((float*)&f);
2358 return fftf;*/
2359 return internalWindowsSimd::m128_I2F(_mm_set_epi32(0, -1, 0, 0));
2360}
2361
2362PX_FORCE_INLINE BoolV BWMask()
2363{
2364 /*const PX_ALIGN(16, PxU32 f[4])={0,0,0,0xFFFFFFFF};
2365 const __m128 ffft=_mm_load_ps((float*)&f);
2366 return ffft;*/
2367 return internalWindowsSimd::m128_I2F(_mm_set_epi32(-1, 0, 0, 0));
2368}
2369
2370PX_FORCE_INLINE BoolV BGetX(const BoolV f)
2371{
2372 return _mm_shuffle_ps(f, f, _MM_SHUFFLE(0, 0, 0, 0));
2373}
2374
2375PX_FORCE_INLINE BoolV BGetY(const BoolV f)
2376{
2377 return _mm_shuffle_ps(f, f, _MM_SHUFFLE(1, 1, 1, 1));
2378}
2379
2380PX_FORCE_INLINE BoolV BGetZ(const BoolV f)
2381{
2382 return _mm_shuffle_ps(f, f, _MM_SHUFFLE(2, 2, 2, 2));
2383}
2384
2385PX_FORCE_INLINE BoolV BGetW(const BoolV f)
2386{
2387 return _mm_shuffle_ps(f, f, _MM_SHUFFLE(3, 3, 3, 3));
2388}
2389
2390PX_FORCE_INLINE BoolV BSetX(const BoolV v, const BoolV f)
2391{
2392 return V4Sel(BFTTT(), v, f);
2393}
2394
2395PX_FORCE_INLINE BoolV BSetY(const BoolV v, const BoolV f)
2396{
2397 return V4Sel(BTFTT(), v, f);
2398}
2399
2400PX_FORCE_INLINE BoolV BSetZ(const BoolV v, const BoolV f)
2401{
2402 return V4Sel(BTTFT(), v, f);
2403}
2404
2405PX_FORCE_INLINE BoolV BSetW(const BoolV v, const BoolV f)
2406{
2407 return V4Sel(BTTTF(), v, f);
2408}
2409
2410template <int index>
2411BoolV BSplatElement(BoolV a)
2412{
2413 return internalWindowsSimd::m128_I2F(
2414 _mm_shuffle_epi32(internalWindowsSimd::m128_F2I(a), _MM_SHUFFLE(index, index, index, index)));
2415}
2416
2417PX_FORCE_INLINE BoolV BAnd(const BoolV a, const BoolV b)
2418{
2419 return _mm_and_ps(a, b);
2420}
2421
2422PX_FORCE_INLINE BoolV BNot(const BoolV a)
2423{
2424 const BoolV bAllTrue(BTTTT());
2425 return _mm_xor_ps(a, bAllTrue);
2426}
2427
2428PX_FORCE_INLINE BoolV BAndNot(const BoolV a, const BoolV b)
2429{
2430 return _mm_andnot_ps(b, a);
2431}
2432
2433PX_FORCE_INLINE BoolV BOr(const BoolV a, const BoolV b)
2434{
2435 return _mm_or_ps(a, b);
2436}
2437
2438PX_FORCE_INLINE BoolV BAllTrue4(const BoolV a)
2439{
2440 const BoolV bTmp =
2441 _mm_and_ps(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 1, 0, 1)), _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 3, 2, 3)));
2442 return _mm_and_ps(_mm_shuffle_ps(bTmp, bTmp, _MM_SHUFFLE(0, 0, 0, 0)),
2443 _mm_shuffle_ps(bTmp, bTmp, _MM_SHUFFLE(1, 1, 1, 1)));
2444}
2445
2446PX_FORCE_INLINE BoolV BAnyTrue4(const BoolV a)
2447{
2448 const BoolV bTmp =
2449 _mm_or_ps(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 1, 0, 1)), _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 3, 2, 3)));
2450 return _mm_or_ps(_mm_shuffle_ps(bTmp, bTmp, _MM_SHUFFLE(0, 0, 0, 0)),
2451 _mm_shuffle_ps(bTmp, bTmp, _MM_SHUFFLE(1, 1, 1, 1)));
2452}
2453
2454PX_FORCE_INLINE BoolV BAllTrue3(const BoolV a)
2455{
2456 const BoolV bTmp =
2457 _mm_and_ps(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 1, 0, 1)), _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2)));
2458 return _mm_and_ps(_mm_shuffle_ps(bTmp, bTmp, _MM_SHUFFLE(0, 0, 0, 0)),
2459 _mm_shuffle_ps(bTmp, bTmp, _MM_SHUFFLE(1, 1, 1, 1)));
2460}
2461
2462PX_FORCE_INLINE BoolV BAnyTrue3(const BoolV a)
2463{
2464 const BoolV bTmp =
2465 _mm_or_ps(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 1, 0, 1)), _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2)));
2466 return _mm_or_ps(_mm_shuffle_ps(bTmp, bTmp, _MM_SHUFFLE(0, 0, 0, 0)),
2467 _mm_shuffle_ps(bTmp, bTmp, _MM_SHUFFLE(1, 1, 1, 1)));
2468}
2469
2470PX_FORCE_INLINE PxU32 BAllEq(const BoolV a, const BoolV b)
2471{
2472 const BoolV bTest = internalWindowsSimd::m128_I2F(
2473 _mm_cmpeq_epi32(internalWindowsSimd::m128_F2I(a), internalWindowsSimd::m128_F2I(b)));
2474 return internalWindowsSimd::BAllTrue4_R(bTest);
2475}
2476
2477PX_FORCE_INLINE PxU32 BAllEqTTTT(const BoolV a)
2478{
2479 return PxU32(_mm_movemask_ps(a)==15);
2480}
2481
2482PX_FORCE_INLINE PxU32 BAllEqFFFF(const BoolV a)
2483{
2484 return PxU32(_mm_movemask_ps(a)==0);
2485}
2486
2487PX_FORCE_INLINE PxU32 BGetBitMask(const BoolV a)
2488{
2489 return PxU32(_mm_movemask_ps(a));
2490}
2491
2493// MAT33V
2495
2496PX_FORCE_INLINE Vec3V M33MulV3(const Mat33V& a, const Vec3V b)
2497{
2498 const FloatV x = V3GetX(b);
2499 const FloatV y = V3GetY(b);
2500 const FloatV z = V3GetZ(b);
2501 const Vec3V v0 = V3Scale(a.col0, x);
2502 const Vec3V v1 = V3Scale(a.col1, y);
2503 const Vec3V v2 = V3Scale(a.col2, z);
2504 const Vec3V v0PlusV1 = V3Add(v0, v1);
2505 return V3Add(v0PlusV1, v2);
2506}
2507
2508PX_FORCE_INLINE Vec3V M33TrnspsMulV3(const Mat33V& a, const Vec3V b)
2509{
2510 Vec3V v0 = V3Mul(a.col0, b);
2511 Vec3V v1 = V3Mul(a.col1, b);
2512 Vec3V v2 = V3Mul(a.col2, b);
2513 V3Transpose(v0, v1, v2);
2514 return V3Add(V3Add(v0, v1), v2);
2515}
2516
2517PX_FORCE_INLINE Vec3V M33MulV3AddV3(const Mat33V& A, const Vec3V b, const Vec3V c)
2518{
2519 const FloatV x = V3GetX(b);
2520 const FloatV y = V3GetY(b);
2521 const FloatV z = V3GetZ(b);
2522 Vec3V result = V3ScaleAdd(A.col0, x, c);
2523 result = V3ScaleAdd(A.col1, y, result);
2524 return V3ScaleAdd(A.col2, z, result);
2525}
2526
2527PX_FORCE_INLINE Mat33V M33MulM33(const Mat33V& a, const Mat33V& b)
2528{
2529 return Mat33V(M33MulV3(a, b.col0), M33MulV3(a, b.col1), M33MulV3(a, b.col2));
2530}
2531
2532PX_FORCE_INLINE Mat33V M33Add(const Mat33V& a, const Mat33V& b)
2533{
2534 return Mat33V(V3Add(a.col0, b.col0), V3Add(a.col1, b.col1), V3Add(a.col2, b.col2));
2535}
2536
2537PX_FORCE_INLINE Mat33V M33Scale(const Mat33V& a, const FloatV& b)
2538{
2539 return Mat33V(V3Scale(a.col0, b), V3Scale(a.col1, b), V3Scale(a.col2, b));
2540}
2541
2542PX_FORCE_INLINE Mat33V M33Sub(const Mat33V& a, const Mat33V& b)
2543{
2544 return Mat33V(V3Sub(a.col0, b.col0), V3Sub(a.col1, b.col1), V3Sub(a.col2, b.col2));
2545}
2546
2547PX_FORCE_INLINE Mat33V M33Neg(const Mat33V& a)
2548{
2549 return Mat33V(V3Neg(a.col0), V3Neg(a.col1), V3Neg(a.col2));
2550}
2551
2552PX_FORCE_INLINE Mat33V M33Abs(const Mat33V& a)
2553{
2554 return Mat33V(V3Abs(a.col0), V3Abs(a.col1), V3Abs(a.col2));
2555}
2556
2557PX_FORCE_INLINE Mat33V M33Inverse(const Mat33V& a)
2558{
2559 const BoolV tfft = BTFFT();
2560 const BoolV tttf = BTTTF();
2561 const FloatV zero = V3Zero();
2562 const Vec3V cross01 = V3Cross(a.col0, a.col1);
2563 const Vec3V cross12 = V3Cross(a.col1, a.col2);
2564 const Vec3V cross20 = V3Cross(a.col2, a.col0);
2565 const FloatV dot = V3Dot(cross01, a.col2);
2566 const FloatV invDet = _mm_rcp_ps(dot);
2567 const Vec3V mergeh = _mm_unpacklo_ps(cross12, cross01);
2568 const Vec3V mergel = _mm_unpackhi_ps(cross12, cross01);
2569 Vec3V colInv0 = _mm_unpacklo_ps(mergeh, cross20);
2570 colInv0 = _mm_or_ps(_mm_andnot_ps(tttf, zero), _mm_and_ps(tttf, colInv0));
2571 const Vec3V zppd = _mm_shuffle_ps(mergeh, cross20, _MM_SHUFFLE(3, 0, 0, 2));
2572 const Vec3V pbwp = _mm_shuffle_ps(cross20, mergeh, _MM_SHUFFLE(3, 3, 1, 0));
2573 const Vec3V colInv1 = _mm_or_ps(_mm_andnot_ps(BTFFT(), pbwp), _mm_and_ps(BTFFT(), zppd));
2574 const Vec3V xppd = _mm_shuffle_ps(mergel, cross20, _MM_SHUFFLE(3, 0, 0, 0));
2575 const Vec3V pcyp = _mm_shuffle_ps(cross20, mergel, _MM_SHUFFLE(3, 1, 2, 0));
2576 const Vec3V colInv2 = _mm_or_ps(_mm_andnot_ps(tfft, pcyp), _mm_and_ps(tfft, xppd));
2577
2578 return Mat33V(_mm_mul_ps(colInv0, invDet), _mm_mul_ps(colInv1, invDet), _mm_mul_ps(colInv2, invDet));
2579}
2580
2581PX_FORCE_INLINE Mat33V M33Trnsps(const Mat33V& a)
2582{
2583 Vec3V col0 = a.col0, col1 = a.col1, col2 = a.col2;
2584 V3Transpose(col0, col1, col2);
2585 return Mat33V(col0, col1, col2);
2586}
2587
2588PX_FORCE_INLINE Mat33V M33Identity()
2589{
2590 return Mat33V(V3UnitX(), V3UnitY(), V3UnitZ());
2591}
2592
2593PX_FORCE_INLINE Mat33V M33Diagonal(const Vec3VArg d)
2594{
2595 const FloatV x = V3Mul(V3UnitX(), d);
2596 const FloatV y = V3Mul(V3UnitY(), d);
2597 const FloatV z = V3Mul(V3UnitZ(), d);
2598 return Mat33V(x, y, z);
2599}
2600
2602// MAT34V
2604
2605PX_FORCE_INLINE Vec3V M34MulV3(const Mat34V& a, const Vec3V b)
2606{
2607 const FloatV x = V3GetX(b);
2608 const FloatV y = V3GetY(b);
2609 const FloatV z = V3GetZ(b);
2610 const Vec3V v0 = V3Scale(a.col0, x);
2611 const Vec3V v1 = V3Scale(a.col1, y);
2612 const Vec3V v2 = V3Scale(a.col2, z);
2613 const Vec3V v0PlusV1 = V3Add(v0, v1);
2614 const Vec3V v0PlusV1Plusv2 = V3Add(v0PlusV1, v2);
2615 return V3Add(v0PlusV1Plusv2, a.col3);
2616}
2617
2618PX_FORCE_INLINE Vec3V M34Mul33V3(const Mat34V& a, const Vec3V b)
2619{
2620 const FloatV x = V3GetX(b);
2621 const FloatV y = V3GetY(b);
2622 const FloatV z = V3GetZ(b);
2623 const Vec3V v0 = V3Scale(a.col0, x);
2624 const Vec3V v1 = V3Scale(a.col1, y);
2625 const Vec3V v2 = V3Scale(a.col2, z);
2626 const Vec3V v0PlusV1 = V3Add(v0, v1);
2627 return V3Add(v0PlusV1, v2);
2628}
2629
2630PX_FORCE_INLINE Vec3V M34TrnspsMul33V3(const Mat34V& a, const Vec3V b)
2631{
2632 Vec3V v0 = V3Mul(a.col0, b);
2633 Vec3V v1 = V3Mul(a.col1, b);
2634 Vec3V v2 = V3Mul(a.col2, b);
2635 V3Transpose(v0, v1, v2);
2636 return V3Add(V3Add(v0, v1), v2);
2637}
2638
2639PX_FORCE_INLINE Mat34V M34MulM34(const Mat34V& a, const Mat34V& b)
2640{
2641 return Mat34V(M34Mul33V3(a, b.col0), M34Mul33V3(a, b.col1), M34Mul33V3(a, b.col2), M34MulV3(a, b.col3));
2642}
2643
2644PX_FORCE_INLINE Mat33V M34MulM33(const Mat34V& a, const Mat33V& b)
2645{
2646 return Mat33V(M34Mul33V3(a, b.col0), M34Mul33V3(a, b.col1), M34Mul33V3(a, b.col2));
2647}
2648
2649PX_FORCE_INLINE Mat33V M34Mul33MM34(const Mat34V& a, const Mat34V& b)
2650{
2651 return Mat33V(M34Mul33V3(a, b.col0), M34Mul33V3(a, b.col1), M34Mul33V3(a, b.col2));
2652}
2653
2654PX_FORCE_INLINE Mat34V M34Add(const Mat34V& a, const Mat34V& b)
2655{
2656 return Mat34V(V3Add(a.col0, b.col0), V3Add(a.col1, b.col1), V3Add(a.col2, b.col2), V3Add(a.col3, b.col3));
2657}
2658
2659PX_FORCE_INLINE Mat34V M34Inverse(const Mat34V& a)
2660{
2661 Mat34V aInv;
2662 const BoolV tfft = BTFFT();
2663 const BoolV tttf = BTTTF();
2664 const FloatV zero = V3Zero();
2665 const Vec3V cross01 = V3Cross(a.col0, a.col1);
2666 const Vec3V cross12 = V3Cross(a.col1, a.col2);
2667 const Vec3V cross20 = V3Cross(a.col2, a.col0);
2668 const FloatV dot = V3Dot(cross01, a.col2);
2669 const FloatV invDet = _mm_rcp_ps(dot);
2670 const Vec3V mergeh = _mm_unpacklo_ps(cross12, cross01);
2671 const Vec3V mergel = _mm_unpackhi_ps(cross12, cross01);
2672 Vec3V colInv0 = _mm_unpacklo_ps(mergeh, cross20);
2673 colInv0 = _mm_or_ps(_mm_andnot_ps(tttf, zero), _mm_and_ps(tttf, colInv0));
2674 const Vec3V zppd = _mm_shuffle_ps(mergeh, cross20, _MM_SHUFFLE(3, 0, 0, 2));
2675 const Vec3V pbwp = _mm_shuffle_ps(cross20, mergeh, _MM_SHUFFLE(3, 3, 1, 0));
2676 const Vec3V colInv1 = _mm_or_ps(_mm_andnot_ps(BTFFT(), pbwp), _mm_and_ps(BTFFT(), zppd));
2677 const Vec3V xppd = _mm_shuffle_ps(mergel, cross20, _MM_SHUFFLE(3, 0, 0, 0));
2678 const Vec3V pcyp = _mm_shuffle_ps(cross20, mergel, _MM_SHUFFLE(3, 1, 2, 0));
2679 const Vec3V colInv2 = _mm_or_ps(_mm_andnot_ps(tfft, pcyp), _mm_and_ps(tfft, xppd));
2680 aInv.col0 = _mm_mul_ps(colInv0, invDet);
2681 aInv.col1 = _mm_mul_ps(colInv1, invDet);
2682 aInv.col2 = _mm_mul_ps(colInv2, invDet);
2683 aInv.col3 = M34Mul33V3(aInv, V3Neg(a.col3));
2684 return aInv;
2685}
2686
2687PX_FORCE_INLINE Mat33V M34Trnsps33(const Mat34V& a)
2688{
2689 Vec3V col0 = a.col0, col1 = a.col1, col2 = a.col2;
2690 V3Transpose(col0, col1, col2);
2691 return Mat33V(col0, col1, col2);
2692}
2693
2695// MAT44V
2697
2698PX_FORCE_INLINE Vec4V M44MulV4(const Mat44V& a, const Vec4V b)
2699{
2700 const FloatV x = V4GetX(b);
2701 const FloatV y = V4GetY(b);
2702 const FloatV z = V4GetZ(b);
2703 const FloatV w = V4GetW(b);
2704
2705 const Vec4V v0 = V4Scale(a.col0, x);
2706 const Vec4V v1 = V4Scale(a.col1, y);
2707 const Vec4V v2 = V4Scale(a.col2, z);
2708 const Vec4V v3 = V4Scale(a.col3, w);
2709 const Vec4V v0PlusV1 = V4Add(v0, v1);
2710 const Vec4V v0PlusV1Plusv2 = V4Add(v0PlusV1, v2);
2711 return V4Add(v0PlusV1Plusv2, v3);
2712}
2713
2714PX_FORCE_INLINE Vec4V M44TrnspsMulV4(const Mat44V& a, const Vec4V b)
2715{
2716 Vec4V v0 = V4Mul(a.col0, b);
2717 Vec4V v1 = V4Mul(a.col1, b);
2718 Vec4V v2 = V4Mul(a.col2, b);
2719 Vec4V v3 = V4Mul(a.col3, b);
2720 V4Transpose(v0, v1, v2, v3);
2721 return V4Add(V4Add(v0, v1), V4Add(v2, v3));
2722}
2723
2724PX_FORCE_INLINE Mat44V M44MulM44(const Mat44V& a, const Mat44V& b)
2725{
2726 return Mat44V(M44MulV4(a, b.col0), M44MulV4(a, b.col1), M44MulV4(a, b.col2), M44MulV4(a, b.col3));
2727}
2728
2729PX_FORCE_INLINE Mat44V M44Add(const Mat44V& a, const Mat44V& b)
2730{
2731 return Mat44V(V4Add(a.col0, b.col0), V4Add(a.col1, b.col1), V4Add(a.col2, b.col2), V4Add(a.col3, b.col3));
2732}
2733
2734PX_FORCE_INLINE Mat44V M44Trnsps(const Mat44V& a)
2735{
2736 Vec4V col0 = a.col0, col1 = a.col1, col2 = a.col2, col3 = a.col3;
2737 V4Transpose(col0, col1, col2, col3);
2738 return Mat44V(col0, col1, col2, col3);
2739}
2740
2741PX_FORCE_INLINE Mat44V M44Inverse(const Mat44V& a)
2742{
2743 __m128 minor0, minor1, minor2, minor3;
2744 __m128 row0, row1, row2, row3;
2745 __m128 det, tmp1;
2746
2747 tmp1 = V4Zero();
2748 row1 = V4Zero();
2749 row3 = V4Zero();
2750
2751 row0 = a.col0;
2752 row1 = _mm_shuffle_ps(a.col1, a.col1, _MM_SHUFFLE(1, 0, 3, 2));
2753 row2 = a.col2;
2754 row3 = _mm_shuffle_ps(a.col3, a.col3, _MM_SHUFFLE(1, 0, 3, 2));
2755
2756 tmp1 = _mm_mul_ps(row2, row3);
2757 tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0xB1);
2758 minor0 = _mm_mul_ps(row1, tmp1);
2759 minor1 = _mm_mul_ps(row0, tmp1);
2760 tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0x4E);
2761 minor0 = _mm_sub_ps(_mm_mul_ps(row1, tmp1), minor0);
2762 minor1 = _mm_sub_ps(_mm_mul_ps(row0, tmp1), minor1);
2763 minor1 = _mm_shuffle_ps(minor1, minor1, 0x4E);
2764
2765 tmp1 = _mm_mul_ps(row1, row2);
2766 tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0xB1);
2767 minor0 = _mm_add_ps(_mm_mul_ps(row3, tmp1), minor0);
2768 minor3 = _mm_mul_ps(row0, tmp1);
2769 tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0x4E);
2770 minor0 = _mm_sub_ps(minor0, _mm_mul_ps(row3, tmp1));
2771 minor3 = _mm_sub_ps(_mm_mul_ps(row0, tmp1), minor3);
2772 minor3 = _mm_shuffle_ps(minor3, minor3, 0x4E);
2773
2774 tmp1 = _mm_mul_ps(_mm_shuffle_ps(row1, row1, 0x4E), row3);
2775 tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0xB1);
2776 row2 = _mm_shuffle_ps(row2, row2, 0x4E);
2777 minor0 = _mm_add_ps(_mm_mul_ps(row2, tmp1), minor0);
2778 minor2 = _mm_mul_ps(row0, tmp1);
2779 tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0x4E);
2780 minor0 = _mm_sub_ps(minor0, _mm_mul_ps(row2, tmp1));
2781 minor2 = _mm_sub_ps(_mm_mul_ps(row0, tmp1), minor2);
2782 minor2 = _mm_shuffle_ps(minor2, minor2, 0x4E);
2783
2784 tmp1 = _mm_mul_ps(row0, row1);
2785 tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0xB1);
2786 minor2 = _mm_add_ps(_mm_mul_ps(row3, tmp1), minor2);
2787 minor3 = _mm_sub_ps(_mm_mul_ps(row2, tmp1), minor3);
2788 tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0x4E);
2789 minor2 = _mm_sub_ps(_mm_mul_ps(row3, tmp1), minor2);
2790 minor3 = _mm_sub_ps(minor3, _mm_mul_ps(row2, tmp1));
2791
2792 tmp1 = _mm_mul_ps(row0, row3);
2793 tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0xB1);
2794 minor1 = _mm_sub_ps(minor1, _mm_mul_ps(row2, tmp1));
2795 minor2 = _mm_add_ps(_mm_mul_ps(row1, tmp1), minor2);
2796 tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0x4E);
2797 minor1 = _mm_add_ps(_mm_mul_ps(row2, tmp1), minor1);
2798 minor2 = _mm_sub_ps(minor2, _mm_mul_ps(row1, tmp1));
2799
2800 tmp1 = _mm_mul_ps(row0, row2);
2801 tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0xB1);
2802 minor1 = _mm_add_ps(_mm_mul_ps(row3, tmp1), minor1);
2803 minor3 = _mm_sub_ps(minor3, _mm_mul_ps(row1, tmp1));
2804 tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0x4E);
2805 minor1 = _mm_sub_ps(minor1, _mm_mul_ps(row3, tmp1));
2806 minor3 = _mm_add_ps(_mm_mul_ps(row1, tmp1), minor3);
2807
2808 det = _mm_mul_ps(row0, minor0);
2809 det = _mm_add_ps(_mm_shuffle_ps(det, det, 0x4E), det);
2810 det = _mm_add_ss(_mm_shuffle_ps(det, det, 0xB1), det);
2811 tmp1 = _mm_rcp_ss(det);
2812#if 0
2813 det = _mm_sub_ss(_mm_add_ss(tmp1, tmp1), _mm_mul_ss(det, _mm_mul_ss(tmp1, tmp1)));
2814 det = _mm_shuffle_ps(det, det, 0x00);
2815#else
2816 det = _mm_shuffle_ps(tmp1, tmp1, _MM_SHUFFLE(0, 0, 0, 0));
2817#endif
2818
2819 minor0 = _mm_mul_ps(det, minor0);
2820 minor1 = _mm_mul_ps(det, minor1);
2821 minor2 = _mm_mul_ps(det, minor2);
2822 minor3 = _mm_mul_ps(det, minor3);
2823 Mat44V invTrans(minor0, minor1, minor2, minor3);
2824 return M44Trnsps(invTrans);
2825}
2826
2827PX_FORCE_INLINE Vec4V V4LoadXYZW(const PxF32& x, const PxF32& y, const PxF32& z, const PxF32& w)
2828{
2829 return _mm_set_ps(w, z, y, x);
2830}
2831
2832PX_FORCE_INLINE VecU32V V4U32Sel(const BoolV c, const VecU32V a, const VecU32V b)
2833{
2834 return internalWindowsSimd::m128_I2F(
2835 _mm_or_si128(_mm_andnot_si128(internalWindowsSimd::m128_F2I(c), internalWindowsSimd::m128_F2I(b)),
2836 _mm_and_si128(internalWindowsSimd::m128_F2I(c), internalWindowsSimd::m128_F2I(a))));
2837}
2838
2839PX_FORCE_INLINE VecU32V V4U32or(VecU32V a, VecU32V b)
2840{
2841 return internalWindowsSimd::m128_I2F(_mm_or_si128(internalWindowsSimd::m128_F2I(a), internalWindowsSimd::m128_F2I(b)));
2842}
2843
2844PX_FORCE_INLINE VecU32V V4U32xor(VecU32V a, VecU32V b)
2845{
2846 return internalWindowsSimd::m128_I2F(
2847 _mm_xor_si128(internalWindowsSimd::m128_F2I(a), internalWindowsSimd::m128_F2I(b)));
2848}
2849
2850PX_FORCE_INLINE VecU32V V4U32and(VecU32V a, VecU32V b)
2851{
2852 return internalWindowsSimd::m128_I2F(
2853 _mm_and_si128(internalWindowsSimd::m128_F2I(a), internalWindowsSimd::m128_F2I(b)));
2854}
2855
2856PX_FORCE_INLINE VecU32V V4U32Andc(VecU32V a, VecU32V b)
2857{
2858 return internalWindowsSimd::m128_I2F(
2859 _mm_andnot_si128(internalWindowsSimd::m128_F2I(b), internalWindowsSimd::m128_F2I(a)));
2860}
2861
2862PX_FORCE_INLINE VecI32V U4Load(const PxU32 i)
2863{
2864 return _mm_load1_ps((PxF32*)&i);
2865}
2866
2867PX_FORCE_INLINE VecU32V U4LoadU(const PxU32* i)
2868{
2869 return _mm_loadu_ps((PxF32*)i);
2870}
2871
2872PX_FORCE_INLINE VecU32V U4LoadA(const PxU32* i)
2873{
2874 ASSERT_ISALIGNED16(i);
2875 return _mm_load_ps((PxF32*)i);
2876}
2877
2878PX_FORCE_INLINE VecI32V I4LoadXYZW(const PxI32& x, const PxI32& y, const PxI32& z, const PxI32& w)
2879{
2880 return internalWindowsSimd::m128_I2F(_mm_set_epi32(w, z, y, x));
2881}
2882
2883PX_FORCE_INLINE VecI32V I4Load(const PxI32 i)
2884{
2885 return _mm_load1_ps((PxF32*)&i);
2886}
2887
2888PX_FORCE_INLINE VecI32V I4LoadU(const PxI32* i)
2889{
2890 return _mm_loadu_ps((PxF32*)i);
2891}
2892
2893PX_FORCE_INLINE VecI32V I4LoadA(const PxI32* i)
2894{
2895 ASSERT_ISALIGNED16(i);
2896 return _mm_load_ps((PxF32*)i);
2897}
2898
2899PX_FORCE_INLINE VecI32V VecI32V_Add(const VecI32VArg a, const VecI32VArg b)
2900{
2901 return internalWindowsSimd::m128_I2F(
2902 _mm_add_epi32(internalWindowsSimd::m128_F2I(a), internalWindowsSimd::m128_F2I(b)));
2903}
2904
2905PX_FORCE_INLINE VecI32V VecI32V_Sub(const VecI32VArg a, const VecI32VArg b)
2906{
2907 return internalWindowsSimd::m128_I2F(
2908 _mm_sub_epi32(internalWindowsSimd::m128_F2I(a), internalWindowsSimd::m128_F2I(b)));
2909}
2910
2911PX_FORCE_INLINE BoolV VecI32V_IsGrtr(const VecI32VArg a, const VecI32VArg b)
2912{
2913 return internalWindowsSimd::m128_I2F(
2914 _mm_cmpgt_epi32(internalWindowsSimd::m128_F2I(a), internalWindowsSimd::m128_F2I(b)));
2915}
2916
2917PX_FORCE_INLINE BoolV VecI32V_IsEq(const VecI32VArg a, const VecI32VArg b)
2918{
2919 return internalWindowsSimd::m128_I2F(
2920 _mm_cmpeq_epi32(internalWindowsSimd::m128_F2I(a), internalWindowsSimd::m128_F2I(b)));
2921}
2922
2923PX_FORCE_INLINE VecI32V V4I32Sel(const BoolV c, const VecI32V a, const VecI32V b)
2924{
2925 return V4U32Sel(c, a, b);
2926}
2927
2928PX_FORCE_INLINE VecI32V VecI32V_Zero()
2929{
2930 return V4Zero();
2931}
2932
2933PX_FORCE_INLINE VecI32V VecI32V_One()
2934{
2935 return I4Load(1);
2936}
2937
2938PX_FORCE_INLINE VecI32V VecI32V_Two()
2939{
2940 return I4Load(2);
2941}
2942
2943PX_FORCE_INLINE VecI32V VecI32V_MinusOne()
2944{
2945 return I4Load(-1);
2946}
2947
2948PX_FORCE_INLINE VecU32V U4Zero()
2949{
2950 return U4Load(0);
2951}
2952
2953PX_FORCE_INLINE VecU32V U4One()
2954{
2955 return U4Load(1);
2956}
2957
2958PX_FORCE_INLINE VecU32V U4Two()
2959{
2960 return U4Load(2);
2961}
2962
2963PX_FORCE_INLINE VecI32V VecI32V_Sel(const BoolV c, const VecI32VArg a, const VecI32VArg b)
2964{
2965 PX_ASSERT(vecMathTests::allElementsEqualBoolV(c, BTTTT()) ||
2966 vecMathTests::allElementsEqualBoolV(c, BFFFF()));
2967 return _mm_or_ps(_mm_andnot_ps(c, b), _mm_and_ps(c, a));
2968}
2969
2970PX_FORCE_INLINE VecShiftV VecI32V_PrepareShift(const VecI32VArg shift)
2971{
2972 VecShiftV preparedShift;
2973 preparedShift.shift = _mm_or_ps(_mm_andnot_ps(BTFFF(), VecI32V_Zero()), _mm_and_ps(BTFFF(), shift));
2974 return preparedShift;
2975}
2976
2977PX_FORCE_INLINE VecI32V VecI32V_LeftShift(const VecI32VArg a, const VecShiftVArg count)
2978{
2979 return internalWindowsSimd::m128_I2F(
2980 _mm_sll_epi32(internalWindowsSimd::m128_F2I(a), internalWindowsSimd::m128_F2I(count.shift)));
2981}
2982
2983PX_FORCE_INLINE VecI32V VecI32V_RightShift(const VecI32VArg a, const VecShiftVArg count)
2984{
2985 return internalWindowsSimd::m128_I2F(
2986 _mm_srl_epi32(internalWindowsSimd::m128_F2I(a), internalWindowsSimd::m128_F2I(count.shift)));
2987}
2988
2989PX_FORCE_INLINE VecI32V VecI32V_LeftShift(const VecI32VArg a, const PxU32 count)
2990{
2991 return internalWindowsSimd::m128_I2F(
2992 _mm_slli_epi32(internalWindowsSimd::m128_F2I(a), count));
2993}
2994
2995PX_FORCE_INLINE VecI32V VecI32V_RightShift(const VecI32VArg a, const PxU32 count)
2996{
2997 return internalWindowsSimd::m128_I2F(
2998 _mm_srai_epi32(internalWindowsSimd::m128_F2I(a), count));
2999}
3000
3001PX_FORCE_INLINE VecI32V VecI32V_And(const VecI32VArg a, const VecI32VArg b)
3002{
3003 return internalWindowsSimd::m128_I2F(
3004 _mm_and_si128(internalWindowsSimd::m128_F2I(a), internalWindowsSimd::m128_F2I(b)));
3005}
3006
3007PX_FORCE_INLINE VecI32V VecI32V_Or(const VecI32VArg a, const VecI32VArg b)
3008{
3009 return internalWindowsSimd::m128_I2F(
3010 _mm_or_si128(internalWindowsSimd::m128_F2I(a), internalWindowsSimd::m128_F2I(b)));
3011}
3012
3013PX_FORCE_INLINE VecI32V VecI32V_GetX(const VecI32VArg a)
3014{
3015 return _mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0));
3016}
3017
3018PX_FORCE_INLINE VecI32V VecI32V_GetY(const VecI32VArg a)
3019{
3020 return _mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 1, 1, 1));
3021}
3022
3023PX_FORCE_INLINE VecI32V VecI32V_GetZ(const VecI32VArg a)
3024{
3025 return _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2));
3026}
3027
3028PX_FORCE_INLINE VecI32V VecI32V_GetW(const VecI32VArg a)
3029{
3030 return _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 3, 3, 3));
3031}
3032
3033PX_FORCE_INLINE void PxI32_From_VecI32V(const VecI32VArg a, PxI32* i)
3034{
3035 _mm_store_ss((PxF32*)i, a);
3036}
3037
3038PX_FORCE_INLINE VecI32V VecI32V_From_BoolV(const BoolVArg a)
3039{
3040 return a;
3041}
3042
3043PX_FORCE_INLINE VecU32V VecU32V_From_BoolV(const BoolVArg a)
3044{
3045 return a;
3046}
3047
3048PX_FORCE_INLINE VecI32V VecI32V_Merge(const VecI32VArg a, const VecI32VArg b, const VecI32VArg c, const VecI32VArg d)
3049{
3050 const __m128 xw = _mm_move_ss(b, a); // y, y, y, x
3051 const __m128 yz = _mm_move_ss(c, d); // z, z, z, w
3052 return _mm_shuffle_ps(xw, yz, _MM_SHUFFLE(0, 2, 1, 0));
3053}
3054
3055PX_FORCE_INLINE void V4U32StoreAligned(VecU32V val, VecU32V* address)
3056{
3057 *address = val;
3058}
3059
3060PX_FORCE_INLINE Vec4V V4Andc(const Vec4V a, const VecU32V b)
3061{
3062 VecU32V result32(a);
3063 result32 = V4U32Andc(result32, b);
3064 return Vec4V(result32);
3065}
3066
3067PX_FORCE_INLINE VecU32V V4IsGrtrV32u(const Vec4V a, const Vec4V b)
3068{
3069 return V4IsGrtr(a, b);
3070}
3071
3072PX_FORCE_INLINE VecU16V V4U16LoadAligned(VecU16V* addr)
3073{
3074 return *addr;
3075}
3076
3077PX_FORCE_INLINE VecU16V V4U16LoadUnaligned(VecU16V* addr)
3078{
3079 return *addr;
3080}
3081
3082// unsigned compares are not supported on x86
3083PX_FORCE_INLINE VecU16V V4U16CompareGt(VecU16V a, VecU16V b)
3084{
3085 // _mm_cmpgt_epi16 doesn't work for unsigned values unfortunately
3086 // return m128_I2F(_mm_cmpgt_epi16(internalWindowsSimd::m128_F2I(a), internalWindowsSimd::m128_F2I(b)));
3087 VecU16V result;
3088 result.m128_u16[0] = PxU16((a).m128_u16[0] > (b).m128_u16[0]);
3089 result.m128_u16[1] = PxU16((a).m128_u16[1] > (b).m128_u16[1]);
3090 result.m128_u16[2] = PxU16((a).m128_u16[2] > (b).m128_u16[2]);
3091 result.m128_u16[3] = PxU16((a).m128_u16[3] > (b).m128_u16[3]);
3092 result.m128_u16[4] = PxU16((a).m128_u16[4] > (b).m128_u16[4]);
3093 result.m128_u16[5] = PxU16((a).m128_u16[5] > (b).m128_u16[5]);
3094 result.m128_u16[6] = PxU16((a).m128_u16[6] > (b).m128_u16[6]);
3095 result.m128_u16[7] = PxU16((a).m128_u16[7] > (b).m128_u16[7]);
3096 return result;
3097}
3098
3099PX_FORCE_INLINE VecU16V V4I16CompareGt(VecU16V a, VecU16V b)
3100{
3101 return internalWindowsSimd::m128_I2F(
3102 _mm_cmpgt_epi16(internalWindowsSimd::m128_F2I(a), internalWindowsSimd::m128_F2I(b)));
3103}
3104
3105PX_FORCE_INLINE Vec4V Vec4V_From_VecU32V(VecU32V a)
3106{
3107 Vec4V result = V4LoadXYZW(PxF32(a.m128_u32[0]), PxF32(a.m128_u32[1]), PxF32(a.m128_u32[2]), PxF32(a.m128_u32[3]));
3108 return result;
3109}
3110
3111PX_FORCE_INLINE Vec4V Vec4V_From_VecI32V(VecI32V a)
3112{
3113 return _mm_cvtepi32_ps(internalWindowsSimd::m128_F2I(a));
3114}
3115
3116PX_FORCE_INLINE VecI32V VecI32V_From_Vec4V(Vec4V a)
3117{
3118 return internalWindowsSimd::m128_I2F(_mm_cvttps_epi32(a));
3119}
3120
3121PX_FORCE_INLINE Vec4V Vec4V_ReinterpretFrom_VecU32V(VecU32V a)
3122{
3123 return Vec4V(a);
3124}
3125
3126PX_FORCE_INLINE Vec4V Vec4V_ReinterpretFrom_VecI32V(VecI32V a)
3127{
3128 return Vec4V(a);
3129}
3130
3131PX_FORCE_INLINE VecU32V VecU32V_ReinterpretFrom_Vec4V(Vec4V a)
3132{
3133 return VecU32V(a);
3134}
3135
3136PX_FORCE_INLINE VecI32V VecI32V_ReinterpretFrom_Vec4V(Vec4V a)
3137{
3138 return VecI32V(a);
3139}
3140
3141template <int index>
3142PX_FORCE_INLINE VecU32V V4U32SplatElement(VecU32V a)
3143{
3144 return internalWindowsSimd::m128_I2F(
3145 _mm_shuffle_epi32(internalWindowsSimd::m128_F2I(a), _MM_SHUFFLE(index, index, index, index)));
3146}
3147
3148template <int index>
3149PX_FORCE_INLINE Vec4V V4SplatElement(Vec4V a)
3150{
3151 return internalWindowsSimd::m128_I2F(
3152 _mm_shuffle_epi32(internalWindowsSimd::m128_F2I(a), _MM_SHUFFLE(index, index, index, index)));
3153}
3154
3155PX_FORCE_INLINE VecU32V U4LoadXYZW(PxU32 x, PxU32 y, PxU32 z, PxU32 w)
3156{
3157 VecU32V result;
3158 result.m128_u32[0] = x;
3159 result.m128_u32[1] = y;
3160 result.m128_u32[2] = z;
3161 result.m128_u32[3] = w;
3162 return result;
3163}
3164
3165PX_FORCE_INLINE Vec4V V4ConvertFromI32V(const VecI32V in)
3166{
3167 return _mm_cvtepi32_ps(internalWindowsSimd::m128_F2I(in));
3168}
3169
3170} // namespace aos
3171} // namespace physx
3172
3173#endif
3174
#define PX_RESTRICT
Definition PxPreprocessor.h:355
#define PX_FORCE_INLINE
Definition PxPreprocessor.h:335
#define PX_ALIGN(alignment, decl)
Definition PxPreprocessor.h:402
GLM_FUNC_DECL GLM_CONSTEXPR genType zero()
Definition constants.inl:6
Sorts an array of objects in ascending order, assuming that the predicate implements the < operator:
Definition PxBoxController.h:39
PX_CUDA_CALLABLE PX_FORCE_INLINE bool PxIsFinite(float f)
returns true if the passed number is a finite floating point number as opposed to INF,...
Definition PxMath.h:326