RavEngine
Loading...
Searching...
No Matches
soa_float.h
1//----------------------------------------------------------------------------//
2// //
3// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
4// and distributed under the MIT License (MIT). //
5// //
6// Copyright (c) Guillaume Blanc //
7// //
8// Permission is hereby granted, free of charge, to any person obtaining a //
9// copy of this software and associated documentation files (the "Software"), //
10// to deal in the Software without restriction, including without limitation //
11// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
12// and/or sell copies of the Software, and to permit persons to whom the //
13// Software is furnished to do so, subject to the following conditions: //
14// //
15// The above copyright notice and this permission notice shall be included in //
16// all copies or substantial portions of the Software. //
17// //
18// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
19// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
20// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
21// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
22// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
23// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
24// DEALINGS IN THE SOFTWARE. //
25// //
26//----------------------------------------------------------------------------//
27
28#ifndef OZZ_OZZ_BASE_MATHS_SOA_FLOAT_H_
29#define OZZ_OZZ_BASE_MATHS_SOA_FLOAT_H_
30
31#include <cassert>
32
33#include "ozz/base/maths/math_constant.h"
34#include "ozz/base/maths/simd_math.h"
35#include "ozz/base/platform.h"
36
37namespace ozz {
38namespace math {
39
40struct SoaFloat2 {
41 SimdFloat4 x, y;
42
43 static OZZ_INLINE SoaFloat2 Load(_SimdFloat4 _x, _SimdFloat4 _y) {
44 const SoaFloat2 r = {_x, _y};
45 return r;
46 }
47
48 static OZZ_INLINE SoaFloat2 zero() {
49 const SoaFloat2 r = {simd_float4::zero(), simd_float4::zero()};
50 return r;
51 }
52
53 static OZZ_INLINE SoaFloat2 one() {
54 const SoaFloat2 r = {simd_float4::one(), simd_float4::one()};
55 return r;
56 }
57
58 static OZZ_INLINE SoaFloat2 x_axis() {
59 const SoaFloat2 r = {simd_float4::one(), simd_float4::zero()};
60 return r;
61 }
62
63 static OZZ_INLINE SoaFloat2 y_axis() {
64 const SoaFloat2 r = {simd_float4::zero(), simd_float4::one()};
65 return r;
66 }
67};
68
69struct SoaFloat3 {
70 SimdFloat4 x, y, z;
71
72 static OZZ_INLINE SoaFloat3 Load(_SimdFloat4 _x, _SimdFloat4 _y,
73 _SimdFloat4 _z) {
74 const SoaFloat3 r = {_x, _y, _z};
75 return r;
76 }
77
78 static OZZ_INLINE SoaFloat3 Load(const SoaFloat2& _v, _SimdFloat4 _z) {
79 const SoaFloat3 r = {_v.x, _v.y, _z};
80 return r;
81 }
82
83 static OZZ_INLINE SoaFloat3 zero() {
84 const SoaFloat3 r = {simd_float4::zero(), simd_float4::zero(),
85 simd_float4::zero()};
86 return r;
87 }
88
89 static OZZ_INLINE SoaFloat3 one() {
90 const SoaFloat3 r = {simd_float4::one(), simd_float4::one(),
91 simd_float4::one()};
92 return r;
93 }
94
95 static OZZ_INLINE SoaFloat3 x_axis() {
96 const SoaFloat3 r = {simd_float4::one(), simd_float4::zero(),
97 simd_float4::zero()};
98 return r;
99 }
100
101 static OZZ_INLINE SoaFloat3 y_axis() {
102 const SoaFloat3 r = {simd_float4::zero(), simd_float4::one(),
103 simd_float4::zero()};
104 return r;
105 }
106
107 static OZZ_INLINE SoaFloat3 z_axis() {
108 const SoaFloat3 r = {simd_float4::zero(), simd_float4::zero(),
109 simd_float4::one()};
110 return r;
111 }
112};
113
114struct SoaFloat4 {
115 SimdFloat4 x, y, z, w;
116
117 static OZZ_INLINE SoaFloat4 Load(_SimdFloat4 _x, _SimdFloat4 _y,
118 _SimdFloat4 _z, const SimdFloat4& _w) {
119 const SoaFloat4 r = {_x, _y, _z, _w};
120 return r;
121 }
122
123 static OZZ_INLINE SoaFloat4 Load(const SoaFloat3& _v, _SimdFloat4 _w) {
124 const SoaFloat4 r = {_v.x, _v.y, _v.z, _w};
125 return r;
126 }
127
128 static OZZ_INLINE SoaFloat4 Load(const SoaFloat2& _v, _SimdFloat4 _z,
129 _SimdFloat4 _w) {
130 const SoaFloat4 r = {_v.x, _v.y, _z, _w};
131 return r;
132 }
133
134 static OZZ_INLINE SoaFloat4 zero() {
135 const SimdFloat4 zero = simd_float4::zero();
136 const SoaFloat4 r = {zero, zero, zero, zero};
137 return r;
138 }
139
140 static OZZ_INLINE SoaFloat4 one() {
141 const SimdFloat4 one = simd_float4::one();
142 const SoaFloat4 r = {one, one, one, one};
143 return r;
144 }
145
146 static OZZ_INLINE SoaFloat4 x_axis() {
147 const SimdFloat4 zero = simd_float4::zero();
148 const SoaFloat4 r = {simd_float4::one(), zero, zero, zero};
149 return r;
150 }
151
152 static OZZ_INLINE SoaFloat4 y_axis() {
153 const SimdFloat4 zero = simd_float4::zero();
154 const SoaFloat4 r = {zero, simd_float4::one(), zero, zero};
155 return r;
156 }
157
158 static OZZ_INLINE SoaFloat4 z_axis() {
159 const SimdFloat4 zero = simd_float4::zero();
160 const SoaFloat4 r = {zero, zero, simd_float4::one(), zero};
161 return r;
162 }
163
164 static OZZ_INLINE SoaFloat4 w_axis() {
165 const SimdFloat4 zero = simd_float4::zero();
166 const SoaFloat4 r = {zero, zero, zero, simd_float4::one()};
167 return r;
168 }
169};
170} // namespace math
171} // namespace ozz
172
173// Returns per element addition of _a and _b using operator +.
174OZZ_INLINE ozz::math::SoaFloat4 operator+(const ozz::math::SoaFloat4& _a,
175 const ozz::math::SoaFloat4& _b) {
176 const ozz::math::SoaFloat4 r = {_a.x + _b.x, _a.y + _b.y, _a.z + _b.z,
177 _a.w + _b.w};
178 return r;
179}
180OZZ_INLINE ozz::math::SoaFloat3 operator+(const ozz::math::SoaFloat3& _a,
181 const ozz::math::SoaFloat3& _b) {
182 const ozz::math::SoaFloat3 r = {_a.x + _b.x, _a.y + _b.y, _a.z + _b.z};
183 return r;
184}
185OZZ_INLINE ozz::math::SoaFloat2 operator+(const ozz::math::SoaFloat2& _a,
186 const ozz::math::SoaFloat2& _b) {
187 const ozz::math::SoaFloat2 r = {_a.x + _b.x, _a.y + _b.y};
188 return r;
189}
190
191// Returns per element subtraction of _a and _b using operator -.
192OZZ_INLINE ozz::math::SoaFloat4 operator-(const ozz::math::SoaFloat4& _a,
193 const ozz::math::SoaFloat4& _b) {
194 const ozz::math::SoaFloat4 r = {_a.x - _b.x, _a.y - _b.y, _a.z - _b.z,
195 _a.w - _b.w};
196 return r;
197}
198OZZ_INLINE ozz::math::SoaFloat3 operator-(const ozz::math::SoaFloat3& _a,
199 const ozz::math::SoaFloat3& _b) {
200 const ozz::math::SoaFloat3 r = {_a.x - _b.x, _a.y - _b.y, _a.z - _b.z};
201 return r;
202}
203OZZ_INLINE ozz::math::SoaFloat2 operator-(const ozz::math::SoaFloat2& _a,
204 const ozz::math::SoaFloat2& _b) {
205 const ozz::math::SoaFloat2 r = {_a.x - _b.x, _a.y - _b.y};
206 return r;
207}
208
209// Returns per element negative value of _v.
210OZZ_INLINE ozz::math::SoaFloat4 operator-(const ozz::math::SoaFloat4& _v) {
211 const ozz::math::SoaFloat4 r = {-_v.x, -_v.y, -_v.z, -_v.w};
212 return r;
213}
214OZZ_INLINE ozz::math::SoaFloat3 operator-(const ozz::math::SoaFloat3& _v) {
215 const ozz::math::SoaFloat3 r = {-_v.x, -_v.y, -_v.z};
216 return r;
217}
218OZZ_INLINE ozz::math::SoaFloat2 operator-(const ozz::math::SoaFloat2& _v) {
219 const ozz::math::SoaFloat2 r = {-_v.x, -_v.y};
220 return r;
221}
222
223// Returns per element multiplication of _a and _b using operator *.
224OZZ_INLINE ozz::math::SoaFloat4 operator*(const ozz::math::SoaFloat4& _a,
225 const ozz::math::SoaFloat4& _b) {
226 const ozz::math::SoaFloat4 r = {_a.x * _b.x, _a.y * _b.y, _a.z * _b.z,
227 _a.w * _b.w};
228 return r;
229}
230OZZ_INLINE ozz::math::SoaFloat3 operator*(const ozz::math::SoaFloat3& _a,
231 const ozz::math::SoaFloat3& _b) {
232 const ozz::math::SoaFloat3 r = {_a.x * _b.x, _a.y * _b.y, _a.z * _b.z};
233 return r;
234}
235OZZ_INLINE ozz::math::SoaFloat2 operator*(const ozz::math::SoaFloat2& _a,
236 const ozz::math::SoaFloat2& _b) {
237 const ozz::math::SoaFloat2 r = {_a.x * _b.x, _a.y * _b.y};
238 return r;
239}
240
241// Returns per element multiplication of _a and scalar value _f using
242// operator *.
243OZZ_INLINE ozz::math::SoaFloat4 operator*(const ozz::math::SoaFloat4& _a,
245 const ozz::math::SoaFloat4 r = {_a.x * _f, _a.y * _f, _a.z * _f, _a.w * _f};
246 return r;
247}
248OZZ_INLINE ozz::math::SoaFloat3 operator*(const ozz::math::SoaFloat3& _a,
250 const ozz::math::SoaFloat3 r = {_a.x * _f, _a.y * _f, _a.z * _f};
251 return r;
252}
253OZZ_INLINE ozz::math::SoaFloat2 operator*(const ozz::math::SoaFloat2& _a,
255 const ozz::math::SoaFloat2 r = {_a.x * _f, _a.y * _f};
256 return r;
257}
258
259// Multiplies _a and _b, then adds _addend.
260// v = (_a * _b) + _addend
261OZZ_INLINE ozz::math::SoaFloat2 MAdd(const ozz::math::SoaFloat2& _a,
262 const ozz::math::SoaFloat2& _b,
263 const ozz::math::SoaFloat2& _addend) {
264 const ozz::math::SoaFloat2 r = {ozz::math::MAdd(_a.x, _b.x, _addend.x),
265 ozz::math::MAdd(_a.y, _b.y, _addend.y)};
266 return r;
267}
268OZZ_INLINE ozz::math::SoaFloat3 MAdd(const ozz::math::SoaFloat3& _a,
269 const ozz::math::SoaFloat3& _b,
270 const ozz::math::SoaFloat3& _addend) {
271 const ozz::math::SoaFloat3 r = {ozz::math::MAdd(_a.x, _b.x, _addend.x),
272 ozz::math::MAdd(_a.y, _b.y, _addend.y),
273 ozz::math::MAdd(_a.z, _b.z, _addend.z)};
274 return r;
275}
276OZZ_INLINE ozz::math::SoaFloat4 MAdd(const ozz::math::SoaFloat4& _a,
277 const ozz::math::SoaFloat4& _b,
278 const ozz::math::SoaFloat4& _addend) {
279 const ozz::math::SoaFloat4 r = {ozz::math::MAdd(_a.x, _b.x, _addend.x),
280 ozz::math::MAdd(_a.y, _b.y, _addend.y),
281 ozz::math::MAdd(_a.z, _b.z, _addend.z),
282 ozz::math::MAdd(_a.w, _b.w, _addend.w)};
283 return r;
284}
285
286// Returns per element division of _a and _b using operator /.
287OZZ_INLINE ozz::math::SoaFloat4 operator/(const ozz::math::SoaFloat4& _a,
288 const ozz::math::SoaFloat4& _b) {
289 const ozz::math::SoaFloat4 r = {_a.x / _b.x, _a.y / _b.y, _a.z / _b.z,
290 _a.w / _b.w};
291 return r;
292}
293OZZ_INLINE ozz::math::SoaFloat3 operator/(const ozz::math::SoaFloat3& _a,
294 const ozz::math::SoaFloat3& _b) {
295 const ozz::math::SoaFloat3 r = {_a.x / _b.x, _a.y / _b.y, _a.z / _b.z};
296 return r;
297}
298OZZ_INLINE ozz::math::SoaFloat2 operator/(const ozz::math::SoaFloat2& _a,
299 const ozz::math::SoaFloat2& _b) {
300 const ozz::math::SoaFloat2 r = {_a.x / _b.x, _a.y / _b.y};
301 return r;
302}
303
304// Returns per element division of _a and scalar value _f using operator/.
305OZZ_INLINE ozz::math::SoaFloat4 operator/(const ozz::math::SoaFloat4& _a,
307 const ozz::math::SoaFloat4 r = {_a.x / _f, _a.y / _f, _a.z / _f, _a.w / _f};
308 return r;
309}
310OZZ_INLINE ozz::math::SoaFloat3 operator/(const ozz::math::SoaFloat3& _a,
312 const ozz::math::SoaFloat3 r = {_a.x / _f, _a.y / _f, _a.z / _f};
313 return r;
314}
315OZZ_INLINE ozz::math::SoaFloat2 operator/(const ozz::math::SoaFloat2& _a,
317 const ozz::math::SoaFloat2 r = {_a.x / _f, _a.y / _f};
318 return r;
319}
320
321// Returns true if each element of a is less than each element of _b.
322OZZ_INLINE ozz::math::SimdInt4 operator<(const ozz::math::SoaFloat4& _a,
323 const ozz::math::SoaFloat4& _b) {
324 const ozz::math::SimdInt4 x = ozz::math::CmpLt(_a.x, _b.x);
325 const ozz::math::SimdInt4 y = ozz::math::CmpLt(_a.y, _b.y);
326 const ozz::math::SimdInt4 z = ozz::math::CmpLt(_a.z, _b.z);
327 const ozz::math::SimdInt4 w = ozz::math::CmpLt(_a.w, _b.w);
328 return ozz::math::And(ozz::math::And(ozz::math::And(x, y), z), w);
329}
330OZZ_INLINE ozz::math::SimdInt4 operator<(const ozz::math::SoaFloat3& _a,
331 const ozz::math::SoaFloat3& _b) {
332 const ozz::math::SimdInt4 x = ozz::math::CmpLt(_a.x, _b.x);
333 const ozz::math::SimdInt4 y = ozz::math::CmpLt(_a.y, _b.y);
334 const ozz::math::SimdInt4 z = ozz::math::CmpLt(_a.z, _b.z);
335 return ozz::math::And(ozz::math::And(x, y), z);
336}
337OZZ_INLINE ozz::math::SimdInt4 operator<(const ozz::math::SoaFloat2& _a,
338 const ozz::math::SoaFloat2& _b) {
339 const ozz::math::SimdInt4 x = ozz::math::CmpLt(_a.x, _b.x);
340 const ozz::math::SimdInt4 y = ozz::math::CmpLt(_a.y, _b.y);
341 return ozz::math::And(x, y);
342}
343
344// Returns true if each element of a is less or equal to each element of _b.
345OZZ_INLINE ozz::math::SimdInt4 operator<=(const ozz::math::SoaFloat4& _a,
346 const ozz::math::SoaFloat4& _b) {
347 const ozz::math::SimdInt4 x = ozz::math::CmpLe(_a.x, _b.x);
348 const ozz::math::SimdInt4 y = ozz::math::CmpLe(_a.y, _b.y);
349 const ozz::math::SimdInt4 z = ozz::math::CmpLe(_a.z, _b.z);
350 const ozz::math::SimdInt4 w = ozz::math::CmpLe(_a.w, _b.w);
351 return ozz::math::And(ozz::math::And(ozz::math::And(x, y), z), w);
352}
353OZZ_INLINE ozz::math::SimdInt4 operator<=(const ozz::math::SoaFloat3& _a,
354 const ozz::math::SoaFloat3& _b) {
355 const ozz::math::SimdInt4 x = ozz::math::CmpLe(_a.x, _b.x);
356 const ozz::math::SimdInt4 y = ozz::math::CmpLe(_a.y, _b.y);
357 const ozz::math::SimdInt4 z = ozz::math::CmpLe(_a.z, _b.z);
358 return ozz::math::And(ozz::math::And(x, y), z);
359}
360OZZ_INLINE ozz::math::SimdInt4 operator<=(const ozz::math::SoaFloat2& _a,
361 const ozz::math::SoaFloat2& _b) {
362 const ozz::math::SimdInt4 x = ozz::math::CmpLe(_a.x, _b.x);
363 const ozz::math::SimdInt4 y = ozz::math::CmpLe(_a.y, _b.y);
364 return ozz::math::And(x, y);
365}
366
367// Returns true if each element of a is greater than each element of _b.
368OZZ_INLINE ozz::math::SimdInt4 operator>(const ozz::math::SoaFloat4& _a,
369 const ozz::math::SoaFloat4& _b) {
370 const ozz::math::SimdInt4 x = ozz::math::CmpGt(_a.x, _b.x);
371 const ozz::math::SimdInt4 y = ozz::math::CmpGt(_a.y, _b.y);
372 const ozz::math::SimdInt4 z = ozz::math::CmpGt(_a.z, _b.z);
373 const ozz::math::SimdInt4 w = ozz::math::CmpGt(_a.w, _b.w);
374 return ozz::math::And(ozz::math::And(ozz::math::And(x, y), z), w);
375}
376OZZ_INLINE ozz::math::SimdInt4 operator>(const ozz::math::SoaFloat3& _a,
377 const ozz::math::SoaFloat3& _b) {
378 const ozz::math::SimdInt4 x = ozz::math::CmpGt(_a.x, _b.x);
379 const ozz::math::SimdInt4 y = ozz::math::CmpGt(_a.y, _b.y);
380 const ozz::math::SimdInt4 z = ozz::math::CmpGt(_a.z, _b.z);
381 return ozz::math::And(ozz::math::And(x, y), z);
382}
383OZZ_INLINE ozz::math::SimdInt4 operator>(const ozz::math::SoaFloat2& _a,
384 const ozz::math::SoaFloat2& _b) {
385 const ozz::math::SimdInt4 x = ozz::math::CmpGt(_a.x, _b.x);
386 const ozz::math::SimdInt4 y = ozz::math::CmpGt(_a.y, _b.y);
387 return ozz::math::And(x, y);
388}
389
390// Returns true if each element of a is greater or equal to each element of _b.
391OZZ_INLINE ozz::math::SimdInt4 operator>=(const ozz::math::SoaFloat4& _a,
392 const ozz::math::SoaFloat4& _b) {
393 const ozz::math::SimdInt4 x = ozz::math::CmpGe(_a.x, _b.x);
394 const ozz::math::SimdInt4 y = ozz::math::CmpGe(_a.y, _b.y);
395 const ozz::math::SimdInt4 z = ozz::math::CmpGe(_a.z, _b.z);
396 const ozz::math::SimdInt4 w = ozz::math::CmpGe(_a.w, _b.w);
397 return ozz::math::And(ozz::math::And(ozz::math::And(x, y), z), w);
398}
399OZZ_INLINE ozz::math::SimdInt4 operator>=(const ozz::math::SoaFloat3& _a,
400 const ozz::math::SoaFloat3& _b) {
401 const ozz::math::SimdInt4 x = ozz::math::CmpGe(_a.x, _b.x);
402 const ozz::math::SimdInt4 y = ozz::math::CmpGe(_a.y, _b.y);
403 const ozz::math::SimdInt4 z = ozz::math::CmpGe(_a.z, _b.z);
404 return ozz::math::And(ozz::math::And(x, y), z);
405}
406OZZ_INLINE ozz::math::SimdInt4 operator>=(const ozz::math::SoaFloat2& _a,
407 const ozz::math::SoaFloat2& _b) {
408 const ozz::math::SimdInt4 x = ozz::math::CmpGe(_a.x, _b.x);
409 const ozz::math::SimdInt4 y = ozz::math::CmpGe(_a.y, _b.y);
410 return ozz::math::And(x, y);
411}
412
413// Returns true if each element of _a is equal to each element of _b.
414// Uses a bitwise comparison of _a and _b, no tolerance is applied.
415OZZ_INLINE ozz::math::SimdInt4 operator==(const ozz::math::SoaFloat4& _a,
416 const ozz::math::SoaFloat4& _b) {
417 const ozz::math::SimdInt4 x = ozz::math::CmpEq(_a.x, _b.x);
418 const ozz::math::SimdInt4 y = ozz::math::CmpEq(_a.y, _b.y);
419 const ozz::math::SimdInt4 z = ozz::math::CmpEq(_a.z, _b.z);
420 const ozz::math::SimdInt4 w = ozz::math::CmpEq(_a.w, _b.w);
421 return ozz::math::And(ozz::math::And(ozz::math::And(x, y), z), w);
422}
423OZZ_INLINE ozz::math::SimdInt4 operator==(const ozz::math::SoaFloat3& _a,
424 const ozz::math::SoaFloat3& _b) {
425 const ozz::math::SimdInt4 x = ozz::math::CmpEq(_a.x, _b.x);
426 const ozz::math::SimdInt4 y = ozz::math::CmpEq(_a.y, _b.y);
427 const ozz::math::SimdInt4 z = ozz::math::CmpEq(_a.z, _b.z);
428 return ozz::math::And(ozz::math::And(x, y), z);
429}
430OZZ_INLINE ozz::math::SimdInt4 operator==(const ozz::math::SoaFloat2& _a,
431 const ozz::math::SoaFloat2& _b) {
432 const ozz::math::SimdInt4 x = ozz::math::CmpEq(_a.x, _b.x);
433 const ozz::math::SimdInt4 y = ozz::math::CmpEq(_a.y, _b.y);
434 return ozz::math::And(x, y);
435}
436
437// Returns true if each element of a is different from each element of _b.
438// Uses a bitwise comparison of _a and _b, no tolerance is applied.
439OZZ_INLINE ozz::math::SimdInt4 operator!=(const ozz::math::SoaFloat4& _a,
440 const ozz::math::SoaFloat4& _b) {
441 const ozz::math::SimdInt4 x = ozz::math::CmpNe(_a.x, _b.x);
442 const ozz::math::SimdInt4 y = ozz::math::CmpNe(_a.y, _b.y);
443 const ozz::math::SimdInt4 z = ozz::math::CmpNe(_a.z, _b.z);
444 const ozz::math::SimdInt4 w = ozz::math::CmpNe(_a.w, _b.w);
445 return ozz::math::Or(ozz::math::Or(ozz::math::Or(x, y), z), w);
446}
447OZZ_INLINE ozz::math::SimdInt4 operator!=(const ozz::math::SoaFloat3& _a,
448 const ozz::math::SoaFloat3& _b) {
449 const ozz::math::SimdInt4 x = ozz::math::CmpNe(_a.x, _b.x);
450 const ozz::math::SimdInt4 y = ozz::math::CmpNe(_a.y, _b.y);
451 const ozz::math::SimdInt4 z = ozz::math::CmpNe(_a.z, _b.z);
452 return ozz::math::Or(ozz::math::Or(x, y), z);
453}
454OZZ_INLINE ozz::math::SimdInt4 operator!=(const ozz::math::SoaFloat2& _a,
455 const ozz::math::SoaFloat2& _b) {
456 const ozz::math::SimdInt4 x = ozz::math::CmpNe(_a.x, _b.x);
457 const ozz::math::SimdInt4 y = ozz::math::CmpNe(_a.y, _b.y);
458 return ozz::math::Or(x, y);
459}
460
461namespace ozz {
462namespace math {
463
464// Returns the (horizontal) addition of each element of _v.
465OZZ_INLINE SimdFloat4 HAdd(const SoaFloat4& _v) {
466 return _v.x + _v.y + _v.z + _v.w;
467}
468OZZ_INLINE SimdFloat4 HAdd(const SoaFloat3& _v) { return _v.x + _v.y + _v.z; }
469OZZ_INLINE SimdFloat4 HAdd(const SoaFloat2& _v) { return _v.x + _v.y; }
470
471// Returns the dot product of _a and _b.
472OZZ_INLINE SimdFloat4 Dot(const SoaFloat4& _a, const SoaFloat4& _b) {
473 return _a.x * _b.x + _a.y * _b.y + _a.z * _b.z + _a.w * _b.w;
474}
475OZZ_INLINE SimdFloat4 Dot(const SoaFloat3& _a, const SoaFloat3& _b) {
476 return _a.x * _b.x + _a.y * _b.y + _a.z * _b.z;
477}
478OZZ_INLINE SimdFloat4 Dot(const SoaFloat2& _a, const SoaFloat2& _b) {
479 return _a.x * _b.x + _a.y * _b.y;
480}
481
482// Returns the cross product of _a and _b.
483OZZ_INLINE SoaFloat3 Cross(const SoaFloat3& _a, const SoaFloat3& _b) {
484 const SoaFloat3 r = {_a.y * _b.z - _b.y * _a.z, _a.z * _b.x - _b.z * _a.x,
485 _a.x * _b.y - _b.x * _a.y};
486 return r;
487}
488
489// Returns the length |_v| of _v.
490OZZ_INLINE SimdFloat4 Length(const SoaFloat4& _v) {
491 const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z + _v.w * _v.w;
492 return Sqrt(len2);
493}
494OZZ_INLINE SimdFloat4 Length(const SoaFloat3& _v) {
495 const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z;
496 return Sqrt(len2);
497}
498OZZ_INLINE SimdFloat4 Length(const SoaFloat2& _v) {
499 const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y;
500 return Sqrt(len2);
501}
502
503// Returns the square length |_v|^2 of _v.
504OZZ_INLINE SimdFloat4 LengthSqr(const SoaFloat4& _v) {
505 return _v.x * _v.x + _v.y * _v.y + _v.z * _v.z + _v.w * _v.w;
506}
507OZZ_INLINE SimdFloat4 LengthSqr(const SoaFloat3& _v) {
508 return _v.x * _v.x + _v.y * _v.y + _v.z * _v.z;
509}
510OZZ_INLINE SimdFloat4 LengthSqr(const SoaFloat2& _v) {
511 return _v.x * _v.x + _v.y * _v.y;
512}
513
514// Returns the normalized vector _v.
515OZZ_INLINE SoaFloat4 Normalize(const SoaFloat4& _v) {
516 const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z + _v.w * _v.w;
517 assert(AreAllTrue(CmpNe(len2, simd_float4::zero())) &&
518 "_v is not normalizable");
519 const SimdFloat4 inv_len = math::simd_float4::one() / Sqrt(len2);
520 const SoaFloat4 r = {_v.x * inv_len, _v.y * inv_len, _v.z * inv_len,
521 _v.w * inv_len};
522 return r;
523}
524OZZ_INLINE SoaFloat3 Normalize(const SoaFloat3& _v) {
525 const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z;
526 assert(AreAllTrue(CmpNe(len2, simd_float4::zero())) &&
527 "_v is not normalizable");
528 const SimdFloat4 inv_len = math::simd_float4::one() / Sqrt(len2);
529 const SoaFloat3 r = {_v.x * inv_len, _v.y * inv_len, _v.z * inv_len};
530 return r;
531}
532OZZ_INLINE SoaFloat2 Normalize(const SoaFloat2& _v) {
533 const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y;
534 assert(AreAllTrue(CmpNe(len2, simd_float4::zero())) &&
535 "_v is not normalizable");
536 const SimdFloat4 inv_len = math::simd_float4::one() / Sqrt(len2);
537 const SoaFloat2 r = {_v.x * inv_len, _v.y * inv_len};
538 return r;
539}
540
541// Test if each vector _v is normalized.
542OZZ_INLINE math::SimdInt4 IsNormalized(const SoaFloat4& _v) {
543 const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z + _v.w * _v.w;
544 return CmpLt(Abs(len2 - math::simd_float4::one()),
545 simd_float4::Load1(kNormalizationToleranceSq));
546}
547OZZ_INLINE math::SimdInt4 IsNormalized(const SoaFloat3& _v) {
548 const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z;
549 return CmpLt(Abs(len2 - math::simd_float4::one()),
550 simd_float4::Load1(kNormalizationToleranceSq));
551}
552OZZ_INLINE math::SimdInt4 IsNormalized(const SoaFloat2& _v) {
553 const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y;
554 return CmpLt(Abs(len2 - math::simd_float4::one()),
555 simd_float4::Load1(kNormalizationToleranceSq));
556}
557
558// Test if each vector _v is normalized using estimated tolerance.
559OZZ_INLINE math::SimdInt4 IsNormalizedEst(const SoaFloat4& _v) {
560 const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z + _v.w * _v.w;
561 return CmpLt(Abs(len2 - math::simd_float4::one()),
562 simd_float4::Load1(kNormalizationToleranceEstSq));
563}
564OZZ_INLINE math::SimdInt4 IsNormalizedEst(const SoaFloat3& _v) {
565 const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z;
566 return CmpLt(Abs(len2 - math::simd_float4::one()),
567 simd_float4::Load1(kNormalizationToleranceEstSq));
568}
569OZZ_INLINE math::SimdInt4 IsNormalizedEst(const SoaFloat2& _v) {
570 const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y;
571 return CmpLt(Abs(len2 - math::simd_float4::one()),
572 simd_float4::Load1(kNormalizationToleranceEstSq));
573}
574
575// Returns the normalized vector _v if the norm of _v is not 0.
576// Otherwise returns _safer.
577OZZ_INLINE SoaFloat4 NormalizeSafe(const SoaFloat4& _v,
578 const SoaFloat4& _safer) {
579 assert(AreAllTrue(IsNormalizedEst(_safer)) && "_safer is not normalized");
580 const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z + _v.w * _v.w;
581 const math::SimdInt4 b = CmpNe(len2, math::simd_float4::zero());
582 const SimdFloat4 inv_len = math::simd_float4::one() / Sqrt(len2);
583 const SoaFloat4 r = {
584 Select(b, _v.x * inv_len, _safer.x), Select(b, _v.y * inv_len, _safer.y),
585 Select(b, _v.z * inv_len, _safer.z), Select(b, _v.w * inv_len, _safer.w)};
586 return r;
587}
588OZZ_INLINE SoaFloat3 NormalizeSafe(const SoaFloat3& _v,
589 const SoaFloat3& _safer) {
590 assert(AreAllTrue(IsNormalizedEst(_safer)) && "_safer is not normalized");
591 const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z;
592 const math::SimdInt4 b = CmpNe(len2, math::simd_float4::zero());
593 const SimdFloat4 inv_len = math::simd_float4::one() / Sqrt(len2);
594 const SoaFloat3 r = {Select(b, _v.x * inv_len, _safer.x),
595 Select(b, _v.y * inv_len, _safer.y),
596 Select(b, _v.z * inv_len, _safer.z)};
597 return r;
598}
599OZZ_INLINE SoaFloat2 NormalizeSafe(const SoaFloat2& _v,
600 const SoaFloat2& _safer) {
601 assert(AreAllTrue(IsNormalizedEst(_safer)) && "_safer is not normalized");
602 const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y;
603 const math::SimdInt4 b = CmpNe(len2, math::simd_float4::zero());
604 const SimdFloat4 inv_len = math::simd_float4::one() / Sqrt(len2);
605 const SoaFloat2 r = {Select(b, _v.x * inv_len, _safer.x),
606 Select(b, _v.y * inv_len, _safer.y)};
607 return r;
608}
609
610// Returns the linear interpolation of _a and _b with coefficient _f.
611// _f is not limited to range [0,1].
612OZZ_INLINE SoaFloat4 Lerp(const SoaFloat4& _a, const SoaFloat4& _b,
613 _SimdFloat4 _f) {
614 const SoaFloat4 r = {(_b.x - _a.x) * _f + _a.x, (_b.y - _a.y) * _f + _a.y,
615 (_b.z - _a.z) * _f + _a.z, (_b.w - _a.w) * _f + _a.w};
616 return r;
617}
618OZZ_INLINE SoaFloat3 Lerp(const SoaFloat3& _a, const SoaFloat3& _b,
619 _SimdFloat4 _f) {
620 const SoaFloat3 r = {(_b.x - _a.x) * _f + _a.x, (_b.y - _a.y) * _f + _a.y,
621 (_b.z - _a.z) * _f + _a.z};
622 return r;
623}
624OZZ_INLINE SoaFloat2 Lerp(const SoaFloat2& _a, const SoaFloat2& _b,
625 _SimdFloat4 _f) {
626 const SoaFloat2 r = {(_b.x - _a.x) * _f + _a.x, (_b.y - _a.y) * _f + _a.y};
627 return r;
628}
629
630// Returns the minimum of each element of _a and _b.
631OZZ_INLINE SoaFloat4 Min(const SoaFloat4& _a, const SoaFloat4& _b) {
632 const SoaFloat4 r = {Min(_a.x, _b.x), Min(_a.y, _b.y), Min(_a.z, _b.z),
633 Min(_a.w, _b.w)};
634 return r;
635}
636OZZ_INLINE SoaFloat3 Min(const SoaFloat3& _a, const SoaFloat3& _b) {
637 const SoaFloat3 r = {Min(_a.x, _b.x), Min(_a.y, _b.y), Min(_a.z, _b.z)};
638 return r;
639}
640OZZ_INLINE SoaFloat2 Min(const SoaFloat2& _a, const SoaFloat2& _b) {
641 const SoaFloat2 r = {Min(_a.x, _b.x), Min(_a.y, _b.y)};
642 return r;
643}
644
645// Returns the maximum of each element of _a and _b.
646OZZ_INLINE SoaFloat4 Max(const SoaFloat4& _a, const SoaFloat4& _b) {
647 const SoaFloat4 r = {Max(_a.x, _b.x), Max(_a.y, _b.y), Max(_a.z, _b.z),
648 Max(_a.w, _b.w)};
649 return r;
650}
651OZZ_INLINE SoaFloat3 Max(const SoaFloat3& _a, const SoaFloat3& _b) {
652 const SoaFloat3 r = {Max(_a.x, _b.x), Max(_a.y, _b.y), Max(_a.z, _b.z)};
653 return r;
654}
655OZZ_INLINE SoaFloat2 Max(const SoaFloat2& _a, const SoaFloat2& _b) {
656 const SoaFloat2 r = {Max(_a.x, _b.x), Max(_a.y, _b.y)};
657 return r;
658}
659
660// Clamps each element of _x between _a and _b.
661// _a must be less or equal to b;
662OZZ_INLINE SoaFloat4 Clamp(const SoaFloat4& _a, const SoaFloat4& _v,
663 const SoaFloat4& _b) {
664 return Max(_a, Min(_v, _b));
665}
666OZZ_INLINE SoaFloat3 Clamp(const SoaFloat3& _a, const SoaFloat3& _v,
667 const SoaFloat3& _b) {
668 return Max(_a, Min(_v, _b));
669}
670OZZ_INLINE SoaFloat2 Clamp(const SoaFloat2& _a, const SoaFloat2& _v,
671 const SoaFloat2& _b) {
672 return Max(_a, Min(_v, _b));
673}
674} // namespace math
675} // namespace ozz
676#endif // OZZ_OZZ_BASE_MATHS_SOA_FLOAT_H_
Definition simd_math_config.h:121
Definition simd_math_config.h:129
Definition soa_float.h:40
Definition soa_float.h:69
Definition soa_float.h:114