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