nlib
SimdVector4.h
Go to the documentation of this file.
1 
2 /*--------------------------------------------------------------------------------*
3  Project: CrossRoad
4  Copyright (C)Nintendo All rights reserved.
5 
6  These coded instructions, statements, and computer programs contain proprietary
7  information of Nintendo and/or its licensed developers and are protected by
8  national and international copyright laws. They may not be disclosed to third
9  parties or copied or duplicated in any form, in whole or in part, without the
10  prior written consent of Nintendo.
11 
12  The content herein is highly confidential and should be handled accordingly.
13  *--------------------------------------------------------------------------------*/
14 
15 #pragma once
16 #ifndef INCLUDE_NN_NLIB_SIMD_SIMDVECTOR4_H_
17 #define INCLUDE_NN_NLIB_SIMD_SIMDVECTOR4_H_
18 
19 #include "nn/nlib/simd/SimdFloat.h"
20 
21 NLIB_NAMESPACE_BEGIN
22 namespace simd {
23 
25  public:
26  template<typename MyVector4>
27  static SimdVector __vectorcall LoadFloat4(const MyVector4* p) NLIB_NOEXCEPT;
28  template<typename MyVector4>
29  static void __vectorcall StoreFloat4(MyVector4* p, SimdVectorArg vec) NLIB_NOEXCEPT;
30  static bool __vectorcall CmpEq(SimdVectorArg vec1, SimdVectorArg vec2) NLIB_NOEXCEPT {
31  return F128::IsAllMaskTrue(F128::CmpEq(vec1, vec2));
32  }
33  static bool __vectorcall CmpLt(SimdVectorArg vec1, SimdVectorArg vec2) NLIB_NOEXCEPT {
34  return F128::IsAllMaskTrue(F128::CmpLt(vec1, vec2));
35  }
36  static bool __vectorcall CmpLe(SimdVectorArg vec1, SimdVectorArg vec2) NLIB_NOEXCEPT {
37  return F128::IsAllMaskTrue(F128::CmpLe(vec1, vec2));
38  }
39  static bool __vectorcall CmpGt(SimdVectorArg vec1, SimdVectorArg vec2) NLIB_NOEXCEPT {
40  return F128::IsAllMaskTrue(F128::CmpGt(vec1, vec2));
41  }
42  static bool __vectorcall CmpGe(SimdVectorArg vec1, SimdVectorArg vec2) NLIB_NOEXCEPT {
43  return F128::IsAllMaskTrue(F128::CmpGe(vec1, vec2));
44  }
45  static bool __vectorcall CmpNe(SimdVectorArg vec1, SimdVectorArg vec2) NLIB_NOEXCEPT {
46  return F128::IsAllMaskTrue(F128::CmpNe(vec1, vec2));
47  }
48  static bool __vectorcall
49  CmpNearEq(SimdVectorArg vec1, SimdVectorArg vec2, SimdVectorArg eps) NLIB_NOEXCEPT {
50  return F128::IsAllMaskTrue(F128::CmpNearEq(vec1, vec2, eps));
51  }
52  static bool __vectorcall IsNaN(SimdVectorArg vec) NLIB_NOEXCEPT {
53  return !F128::IsAllMaskFalse(F128::IsNaN(vec));
54  }
55  static bool __vectorcall IsInfinite(SimdVectorArg vec) NLIB_NOEXCEPT {
56  return !F128::IsAllMaskFalse(F128::IsInfinite(vec));
57  }
58  static bool __vectorcall InBound(SimdVectorArg vec, SimdVectorArg bounds) NLIB_NOEXCEPT {
59  return F128::IsAllMaskTrue(F128::InBound(vec, bounds));
60  }
61 
62  static f128 __vectorcall Dot(SimdVectorArg vec1, SimdVectorArg vec2) NLIB_NOEXCEPT;
63  template <bool SetLane0, bool SetLane1, bool SetLane2, bool SetLane3>
64  static f128 __vectorcall DotEx(SimdVectorArg vec1, SimdVectorArg vec2) NLIB_NOEXCEPT;
65  static f128 __vectorcall
67  static f128 __vectorcall
69  static f128 __vectorcall Dot4(SimdVectorArg a, SimdVectorArg b0, SimdVectorArg b1,
71  static SimdVector __vectorcall Normalize(SimdVectorArg vec) NLIB_NOEXCEPT;
72  static SimdVector __vectorcall NormalizeEst(SimdVectorArg vec) NLIB_NOEXCEPT;
73  static f128 __vectorcall LengthSq(SimdVectorArg vec) NLIB_NOEXCEPT;
74  static f128 __vectorcall Length(SimdVectorArg vec) NLIB_NOEXCEPT;
75  static f128 __vectorcall LengthEst(SimdVectorArg vec) NLIB_NOEXCEPT;
76  static f128 __vectorcall RecpLength(SimdVectorArg vec) NLIB_NOEXCEPT;
77  static f128 __vectorcall RecpLengthEst(SimdVectorArg vec) NLIB_NOEXCEPT;
78  static f128 __vectorcall GetAngle(SimdVectorArg vec1_normalized,
79  SimdVectorArg vec2_normalized) NLIB_NOEXCEPT;
80  static SimdVector __vectorcall Reflect(SimdVectorArg vec, SimdVectorArg normal) NLIB_NOEXCEPT;
81  // static SimdVector __vectorcall Transform(SimdMatrixArg m, SimdVectorArg vec) NLIB_NOEXCEPT;
82  static SimdVector __vectorcall Transform(SimdVectorArg vec, SimdMatrixArg m) NLIB_NOEXCEPT;
83 
84  // TransformSequence(....)
85  // Refract, Ortho
86 
87  private:
88  Vector4(); // forbidden
89 };
90 
91 #ifndef NLIB_DOXYGEN
92 
93 #define NLIB_M(tp) inline tp __vectorcall
94 #define NLIB_MH(tp) inline tp __vectorcall
95 
96 template<typename MyVector4>
97 // MyVector is a structure like 'struct MyVector4 { float x, y, z, w; };'
98 // nlib_ns::simd::Float4, DirectX::XMFLOAT3, DirectX::XMFLOAT3A for example
99 NLIB_MH(SimdVector) Vector4::LoadFloat4(const MyVector4* p) NLIB_NOEXCEPT {
100  NLIB_STATIC_ASSERT(sizeof(p->x) == 4);
101  NLIB_STATIC_ASSERT(sizeof(p->y) == 4);
102  NLIB_STATIC_ASSERT(sizeof(p->z) == 4);
103  NLIB_STATIC_ASSERT(sizeof(p->w) == 4);
104  return F128::LoadA4(reinterpret_cast<const float*>(&p->x));
105 }
106 
107 template<typename MyVector4>
108 // MyVector is a structure like 'struct MyVector4 { float x, y, z, w; };'
109 // nlib_ns::simd::Float4, DirectX::XMFLOAT3, DirectX::XMFLOAT3A for example
110 NLIB_MH(void) Vector4::StoreFloat4(MyVector4* p, SimdVectorArg vec) NLIB_NOEXCEPT { // NOLINT
111  NLIB_STATIC_ASSERT(sizeof(p->x) == 4);
112  NLIB_STATIC_ASSERT(sizeof(p->y) == 4);
113  NLIB_STATIC_ASSERT(sizeof(p->z) == 4);
114  NLIB_STATIC_ASSERT(sizeof(p->w) == 4);
115  F128::StoreA4(reinterpret_cast<float*>(&p->x), vec);
116 }
117 
118 // r = { dot, dot, dot, dot }
119 NLIB_M(f128) Vector4::Dot(SimdVectorArg vec1, SimdVectorArg vec2) NLIB_NOEXCEPT {
120 #ifdef NLIB_F128_SIMD_NOUSE
121  f128 ret;
122  ret.vec.v[0] = ret.vec.v[1] = ret.vec.v[2] = ret.vec.v[3] =
123  vec1.vec.v[0] * vec2.vec.v[0] + vec1.vec.v[1] * vec2.vec.v[1] +
124  vec1.vec.v[2] * vec2.vec.v[2] + vec1.vec.v[3] * vec2.vec.v[3];
125  return ret;
126 #elif defined(NLIB_SSE41)
127  return _mm_dp_ps(vec1, vec2, 0xFF);
128 #elif defined(NLIB_NEON)
129 # ifdef __aarch64__
130  float32x4_t tmp = vmulq_f32(vec1, vec2);
131  tmp = vpaddq_f32(tmp, tmp);
132  tmp = vpaddq_f32(tmp, tmp);
133  return tmp;
134 # else
135  float32x4_t tmp = vmulq_f32(vec1, vec2);
136  float32x2_t v1 = vget_low_f32(tmp);
137  float32x2_t v2 = vget_high_f32(tmp);
138  v1 = vpadd_f32(v1, v1);
139  v2 = vpadd_f32(v2, v2);
140  v1 = vadd_f32(v1, v2);
141  return vcombine_f32(v1, v1);
142 # endif
143 #elif defined(CAFE)
144  f128 tmp = F128::Mult(vec1, vec2);
145  f32x2 val = __PS_ADD(tmp.vec.ps[0], tmp.vec.ps[1]);
146  val = __PS_SUM0(val, val, val);
147  f128 ret;
148  ret.vec.ps[0] = ret.vec.ps[1] = __PS_FDUP(val[0]);
149  return ret;
150 #endif
151 }
152 
153 template <bool SetLane0, bool SetLane1, bool SetLane2, bool SetLane3>
154 // r[i] = SetLane[i] ? dot : 0.f
155 NLIB_MH(f128) Vector4::DotEx(SimdVectorArg vec1, SimdVectorArg vec2) NLIB_NOEXCEPT {
156 #if !defined(NLIB_F128_SIMD_NOUSE) && defined(NLIB_SSE41)
157  return _mm_dp_ps(vec1, vec2, (0xF0 | (SetLane0 ? 1 : 0) | (SetLane1 ? 2 : 0) |
158  (SetLane2 ? 4 : 0) | (SetLane3 ? 8 : 0)));
159 #else
160  return F128::Splat<SetLane0, SetLane1, SetLane2, SetLane3>(F128::SetZero(), Dot(vec1, vec2));
161 #endif
162 }
163 
164 // r = { dot(a, b0), dot(a, b1), 0.f, 0.f }
165 NLIB_M(f128) Vector4::Dot2(SimdVectorArg a, SimdVectorArg b0, SimdVectorArg b1) NLIB_NOEXCEPT {
166 #if !defined(NLIB_F128_SIMD_NOUSE) && defined(NLIB_NEON)
167 #ifdef __aarch64__
168  float32x4_t zero = vdupq_n_f32(0);
169  float32x4_t tmp0 = vmulq_f32(a, b0);
170  float32x4_t tmp1 = vmulq_f32(a, b1);
171  tmp0 = vpaddq_f32(tmp0, tmp1);
172  tmp0 = vpaddq_f32(tmp0, zero);
173  return tmp0;
174 #else
175  float32x4x2_t trn = vtrnq_f32(b0, b1);
176  float32x2_t lo = vget_low_f32(a);
177  float32x2_t hi = vget_high_f32(a);
178  float32x4_t xxzz = vcombine_f32(vdup_lane_f32(lo, 0), vdup_lane_f32(hi, 0));
179  float32x4_t yyww = vcombine_f32(vdup_lane_f32(lo, 1), vdup_lane_f32(hi, 1));
180  float32x4_t tmp = vmulq_f32(trn.val[0], xxzz);
181  tmp = vmlaq_f32(tmp, yyww, trn.val[1]);
182  float32x2_t result = vadd_f32(vget_low_f32(tmp), vget_high_f32(tmp));
183  return vcombine_f32(result, vdup_n_f32(0.f));
184 #endif
185 #else
186  f128 t0 = Vector4::DotEx<true, false, false, false>(a, b0);
187  f128 t1 = Vector4::DotEx<false, true, false, false>(a, b1);
188  return F128::Or(t0, t1);
189 #endif
190 }
191 
192 // r = { dot(a, b0), dot(a, b1), dot(a, b2), 0.f }
193 NLIB_M(f128) Vector4::Dot3(SimdVectorArg a, SimdVectorArg b0, SimdVectorArg b1,
195 #if !defined(NLIB_F128_SIMD_NOUSE) && defined(NLIB_NEON)
196 #ifdef __aarch64__
197  float32x4_t zero = vdupq_n_f32(0);
198  float32x4_t tmp0 = vmulq_f32(a, b0);
199  float32x4_t tmp1 = vmulq_f32(a, b1);
200  float32x4_t tmp2 = vmulq_f32(a, b2);
201  tmp0 = vpaddq_f32(tmp0, tmp1);
202  tmp2 = vpaddq_f32(tmp2, zero);
203  tmp0 = vpaddq_f32(tmp0, tmp2);
204  return tmp0;
205 #else
206  f128 row0, row1, row2, row3;
207  float32x4x2_t trn_f0_ = vtrnq_f32(b0, b1);
208  float32x4x2_t trn_f1_ = vtrnq_f32(b2, vdupq_n_f32(0.f));
209  row0 = vcombine_f32(vget_low_f32(trn_f0_.val[0]), vget_low_f32(trn_f1_.val[0]));
210  row1 = vcombine_f32(vget_low_f32(trn_f0_.val[1]), vget_low_f32(trn_f1_.val[1]));
211  row2 = vcombine_f32(vget_high_f32(trn_f0_.val[0]), vget_high_f32(trn_f1_.val[0]));
212  row3 = vcombine_f32(vget_high_f32(trn_f0_.val[1]), vget_high_f32(trn_f1_.val[1]));
213  f128 ret = F128::Mult<0>(a, row0, each_select32);
214  ret = F128::MultAdd<1>(a, row1, ret, each_select32);
215  ret = F128::MultAdd<2>(a, row2, ret, each_select32);
216  return F128::MultAdd<3>(a, row3, ret, each_select32);
217 #endif
218 #else
219  f128 t0 = Vector4::DotEx<true, false, false, false>(a, b0);
220  f128 t1 = Vector4::DotEx<false, true, false, false>(a, b1);
221  f128 t2 = Vector4::DotEx<false, false, true, false>(a, b2);
222  return F128::Or(F128::Or(t0, t1), t2);
223 #endif
224 }
225 
226 // r = { dot(a, b0), dot(a, b1), dot(a, b2), dot(a, b3) }
227 NLIB_M(f128) Vector4::Dot4(SimdVectorArg a, SimdVectorArg b0, SimdVectorArg b1, SimdVectorArg b2,
229 #if !defined(NLIB_F128_SIMD_NOUSE) && defined(NLIB_NEON)
230 #ifdef __aarch64__
231  float32x4_t tmp0 = vmulq_f32(a, b0);
232  float32x4_t tmp1 = vmulq_f32(a, b1);
233  float32x4_t tmp2 = vmulq_f32(a, b2);
234  float32x4_t tmp3 = vmulq_f32(a, b3);
235  tmp0 = vpaddq_f32(tmp0, tmp1);
236  tmp2 = vpaddq_f32(tmp2, tmp3);
237  tmp0 = vpaddq_f32(tmp0, tmp2);
238  return tmp0;
239 #else
240  f128 row0, row1, row2, row3;
241  float32x4x2_t trn_f0_ = vtrnq_f32(b0, b1);
242  float32x4x2_t trn_f1_ = vtrnq_f32(b2, b3);
243  row0 = vcombine_f32(vget_low_f32(trn_f0_.val[0]), vget_low_f32(trn_f1_.val[0]));
244  row1 = vcombine_f32(vget_low_f32(trn_f0_.val[1]), vget_low_f32(trn_f1_.val[1]));
245  row2 = vcombine_f32(vget_high_f32(trn_f0_.val[0]), vget_high_f32(trn_f1_.val[0]));
246  row3 = vcombine_f32(vget_high_f32(trn_f0_.val[1]), vget_high_f32(trn_f1_.val[1]));
247  f128 ret = F128::Mult<0>(a, row0, each_select32);
248  ret = F128::MultAdd<1>(a, row1, ret, each_select32);
249  ret = F128::MultAdd<2>(a, row2, ret, each_select32);
250  return F128::MultAdd<3>(a, row3, ret, each_select32);
251 #endif
252 #else
253  f128 t0 = Vector4::DotEx<true, false, false, false>(a, b0);
254  f128 t1 = Vector4::DotEx<false, true, false, false>(a, b1);
255  f128 t2 = Vector4::DotEx<false, false, true, false>(a, b2);
256  f128 t3 = Vector4::DotEx<false, false, false, true>(a, b3);
257  return F128::Or(F128::Or(t0, t1), F128::Or(t2, t3));
258 #endif
259 }
260 
261 // nan if |vec| is too big, 0 if |vec| = 0
262 NLIB_M(SimdVector) Vector4::Normalize(SimdVectorArg vec) NLIB_NOEXCEPT {
263  f128 dot = Vector4::Dot(vec, vec);
264 #if defined(NLIB_NEON) && !defined(NLIB_F128_SIMD_NOUSE)
265  float32x4_t x;
266  x = vrsqrteq_f32(dot);
267  x = vmulq_f32(x, vrsqrtsq_f32(dot, vmulq_f32(x, x)));
268  f128 rsqrt = vmulq_f32(x, vrsqrtsq_f32(dot, vmulq_f32(x, x)));
269 #else
270  f128 rsqrt = F128::RecpSqrt(dot);
271 #endif
272  f128 inf = F128::SetInfinity();
273  f128 eqzero = F128::CmpEqZero(dot);
274  f128 eqinf = F128::CmpEq(dot, inf);
275  SimdVector ret = F128::Mult(vec, rsqrt);
276  f128 nan = F128::SetNaN();
277  ret = F128::AndNot(eqzero, ret);
278  ret = F128::Select(eqinf, nan, ret);
279  return ret;
280 }
281 
282 // r = { lensq, lensq, lensq, lensq }
283 NLIB_M(f128) Vector4::LengthSq(SimdVectorArg vec) NLIB_NOEXCEPT { return Dot(vec, vec); }
284 
285 // r = { len, len, len, len }
286 NLIB_M(f128) Vector4::Length(SimdVectorArg vec) NLIB_NOEXCEPT {
287  return F128::Sqrt(Dot(vec, vec));
288 }
289 
290 // r = { len, len, len, len }
291 NLIB_M(f128) Vector4::LengthEst(SimdVectorArg vec) NLIB_NOEXCEPT {
292  return F128::SqrtEst(Dot(vec, vec));
293 }
294 
295 // r = { recpLen, recpLen, recpLen, recpLen }
296 NLIB_M(f128) Vector4::RecpLength(SimdVectorArg vec) NLIB_NOEXCEPT {
297  return F128::RecpSqrt(Dot(vec, vec));
298 }
299 
300 // r = { recpLen, recpLen, recpLen, recpLen }
301 NLIB_M(f128) Vector4::RecpLengthEst(SimdVectorArg vec) NLIB_NOEXCEPT {
302  return F128::RecpSqrtEst(Dot(vec, vec));
303 }
304 
305 NLIB_M(SimdVector) Vector4::NormalizeEst(SimdVectorArg vec) NLIB_NOEXCEPT {
306  return F128::Mult(vec, RecpLengthEst(vec));
307 }
308 
309 // { radian, radian, radian, radian }
310 NLIB_M(f128) Vector4::GetAngle(SimdVectorArg vec1_normalized,
311  SimdVectorArg vec2_normalized) NLIB_NOEXCEPT {
312  f128 ret = Dot(vec1_normalized, vec2_normalized);
313  ret = F128::Clamp(ret, F128::SetNegativeOne(), F128::SetOne());
314  return F128::ArcCos(ret);
315 }
316 
317 NLIB_M(SimdVector) Vector4::Reflect(SimdVectorArg vec, SimdVectorArg normal) NLIB_NOEXCEPT {
318  f128 s = Dot(vec, normal);
319  s = F128::Add(s, s);
320  return F128::MultSub(s, normal, vec);
321 }
322 
323 /*
324 // r = m * vec
325 NLIB_M(SimdVector) Vector4::Transform(SimdMatrixArg m, SimdVectorArg vec) NLIB_NOEXCEPT {
326 #ifdef NLIB_F128_SIMD_NOUSE
327  f128 ret;
328  ret.vec.v[0] = m.r[0].vec.v[0] * vec.vec.v[0] + m.r[0].vec.v[1] * vec.vec.v[1] +
329  m.r[0].vec.v[2] * vec.vec.v[2] + m.r[0].vec.v[3] * vec.vec.v[3];
330  ret.vec.v[1] = m.r[1].vec.v[0] * vec.vec.v[0] + m.r[1].vec.v[1] * vec.vec.v[1] +
331  m.r[1].vec.v[2] * vec.vec.v[2] + m.r[1].vec.v[3] * vec.vec.v[3];
332  ret.vec.v[2] = m.r[2].vec.v[0] * vec.vec.v[0] + m.r[2].vec.v[1] * vec.vec.v[1] +
333  m.r[2].vec.v[2] * vec.vec.v[2] + m.r[2].vec.v[3] * vec.vec.v[3];
334  ret.vec.v[3] = m.r[3].vec.v[0] * vec.vec.v[0] + m.r[3].vec.v[1] * vec.vec.v[1] +
335  m.r[3].vec.v[2] * vec.vec.v[2] + m.r[3].vec.v[3] * vec.vec.v[3];
336  return ret;
337 #elif defined(NLIB_SSE41)
338  f128 tmp, ret;
339  ret = _mm_dp_ps(m.r[0], vec, 0xF1);
340  tmp = _mm_dp_ps(m.r[1], vec, 0xF2);
341  ret = _mm_or_ps(ret, tmp);
342  tmp = _mm_dp_ps(m.r[2], vec, 0xF4);
343  ret = _mm_or_ps(ret, tmp);
344  tmp = _mm_dp_ps(m.r[3], vec, 0xF8);
345  ret = _mm_or_ps(ret, tmp);
346  return ret;
347 #elif defined(NLIB_NEON)
348  float32x4_t r0, r1;
349  float32x2_t lo, hi, tmp;
350 
351  r0 = vmulq_f32(m.r[0], vec);
352  r1 = vmulq_f32(m.r[1], vec);
353  lo = vpadd_f32(vget_low_f32(r0), vget_high_f32(r0));
354  tmp = vpadd_f32(vget_low_f32(r1), vget_high_f32(r1));
355  lo = vpadd_f32(lo, tmp);
356 
357  r0 = vmulq_f32(m.r[2], vec);
358  r1 = vmulq_f32(m.r[3], vec);
359  hi = vpadd_f32(vget_low_f32(r0), vget_high_f32(r0));
360  tmp = vpadd_f32(vget_low_f32(r1), vget_high_f32(r1));
361  hi = vpadd_f32(hi, tmp);
362 
363  return vcombine_f32(lo, hi);
364 #endif
365 }
366 */
367 
368 // r = vec * m
369 NLIB_M(SimdVector) Vector4::Transform(SimdVectorArg vec, SimdMatrixArg m) NLIB_NOEXCEPT {
370  f128 ret = F128::Mult<0>(vec, m.r[0], each_select32);
371  ret = F128::MultAdd<1>(vec, m.r[1], ret, each_select32);
372  ret = F128::MultAdd<2>(vec, m.r[2], ret, each_select32);
373  return F128::MultAdd<3>(vec, m.r[3], ret, each_select32);
374 }
375 
376 #undef NLIB_M
377 #undef NLIB_MH
378 
379 #endif // NLIB_DOXYGEN
380 
381 } // namespace simd
382 NLIB_NAMESPACE_END
383 
384 #endif // INCLUDE_NN_NLIB_SIMD_SIMDVECTOR4_H_
static bool InBound(SimdVectorArg vec, SimdVectorArg bounds) noexcept
Evaluates whether the elements of vec are inside the bounds of bounds.
Definition: SimdVector4.h:58
static bool CmpNearEq(SimdVectorArg vec1, SimdVectorArg vec2, SimdVectorArg eps) noexcept
Compares vec1 and vec2 to see whether they are nearly equal.
Definition: SimdVector4.h:49
f128arg SimdVectorArg
f128arg is defined using typedef.
Definition: SimdFloat.h:4148
static bool IsNaN(SimdVectorArg vec) noexcept
Evaluates whether any of the elements of vec are NaN.
Definition: SimdVector4.h:52
#define NLIB_VIS_HIDDEN
Symbols for functions and classes are not made available outside of the library.
Definition: Platform_unix.h:88
static bool CmpGe(SimdVectorArg vec1, SimdVectorArg vec2) noexcept
Checks to see whether all of the elements of vec1 are equal or greater than the corresponding element...
Definition: SimdVector4.h:42
static bool CmpGt(SimdVectorArg vec1, SimdVectorArg vec2) noexcept
Checks to see whether all of the elements of vec1 are larger than the corresponding elements of vec2...
Definition: SimdVector4.h:39
f128 r[4]
Keeps each row of a 4x4 matrix.
Definition: SimdFloat.h:4175
The structure for keeping a 4x4 matrix.
Definition: SimdFloat.h:4159
static bool CmpNe(SimdVectorArg vec1, SimdVectorArg vec2) noexcept
Compares vec1 and vec2 to see whether they are unequal.
Definition: SimdVector4.h:45
#define NLIB_NOEXCEPT
Defines noexcept geared to the environment, or the equivalent.
Definition: Config.h:99
The class with the collection of functions that perform calculations on four-dimensional vectors...
Definition: SimdVector4.h:24
Defines the class and functions for SIMD computations on single-precision floating-point numbers...
constexpr const each_select32_tag each_select32
The tag for representing the selection of a 32-bit lane with an each_select32_tag-type constant objec...
Definition: SimdInt.h:63
static bool CmpEq(SimdVectorArg vec1, SimdVectorArg vec2) noexcept
Compares two four-dimensional vectors to see if they are equal.
Definition: SimdVector4.h:30
nlib_f128_t f128
nlib_f128_t is defined using typedef.
Definition: SimdFloat.h:71
static bool CmpLt(SimdVectorArg vec1, SimdVectorArg vec2) noexcept
Checks to see whether all of the elements of vec1 are smaller than the corresponding elements of vec2...
Definition: SimdVector4.h:33
#define NLIB_STATIC_ASSERT(exp)
Defines a static assertion. Uses static_assert if it is available for use.
Definition: Config.h:154
static bool IsInfinite(SimdVectorArg vec) noexcept
Evaluates whether any of the elements of vec are positive infinity or negative infinity.
Definition: SimdVector4.h:55
static bool CmpLe(SimdVectorArg vec1, SimdVectorArg vec2) noexcept
Checks to see whether all of the elements of vec1 are equal or less than the corresponding elements o...
Definition: SimdVector4.h:36
f128 SimdVector
f128 is defined using typedef. Used when handling three-dimensional or four-dimensional vectors...
Definition: SimdFloat.h:4147