master
ブランチ master
VulkanExample / dep / include / glm / detail / type_vec_simd.inl
30 KB、1032行 生 Blame 履歴
1#pragma once
2
3#define CTORSL(L, CTOR)\
4CTOR(L, aligned_lowp)\
5CTOR(L, aligned_mediump)\
6CTOR(L, aligned_highp)\
7
8namespace glm {
9 namespace detail
10 {
11
12template<length_t L, typename T, qualifier Q, int IsInt, std::size_t Size>
13struct compute_vec_and<L, T, Q, IsInt, Size, true> : public compute_vec_and<L, T, Q, IsInt, Size, false>
14{};
15
16template<length_t L, typename T, qualifier Q, int IsInt, std::size_t Size>
17struct compute_vec_or<L, T, Q, IsInt, Size, true>: public compute_vec_or<L, T, Q, IsInt, Size, false>
18{};
19
20template<length_t L, typename T, qualifier Q, int IsInt, std::size_t Size>
21struct compute_vec_xor<L, T, Q, IsInt, Size, true> : public compute_vec_xor<L, T, Q, IsInt, Size, false>
22{};
23
24template<length_t L, typename T, qualifier Q, int IsInt, std::size_t Size>
25struct compute_vec_shift_left<L, T, Q, IsInt, Size, true> : public compute_vec_shift_left<L, T, Q, IsInt, Size, false>
26{};
27
28template<length_t L, typename T, qualifier Q, int IsInt, std::size_t Size>
29struct compute_vec_shift_right<L, T, Q, IsInt, Size, true> : public compute_vec_shift_right<L, T, Q, IsInt, Size, false>
30{};
31
32template<length_t L, typename T, qualifier Q, int IsInt, std::size_t Size>
33struct compute_vec_bitwise_not<L, T, Q, IsInt, Size, true>:public compute_vec_bitwise_not<L, T, Q, IsInt, Size, false>
34{};
35
36template<length_t L, typename T, qualifier Q, int IsInt, std::size_t Size>
37struct compute_vec_equal<L, T, Q, IsInt, Size, true> : public compute_vec_equal<L, T, Q, IsInt, Size, false>
38{};
39
40template<length_t L, typename T, qualifier Q, int IsInt, std::size_t Size>
41struct compute_vec_nequal<L, T, Q, IsInt, Size, true> : public compute_vec_nequal<L, T, Q, IsInt, Size, false>
42{};
43
44template<length_t L, typename T, qualifier Q>
45struct compute_vec_mod<L, T, Q, true> : public compute_vec_mod<L, T, Q, false>
46{};
47
48
49template<typename T, length_t L, qualifier Q>
50struct compute_vec_add<L, T, Q, true> : public compute_vec_add<L, T, Q, false>
51{};
52
53template< length_t L, typename T, qualifier Q>
54struct compute_vec_sub<L, T, Q, true> : public compute_vec_sub<L, T, Q, false>
55{};
56
57template< length_t L, typename T, qualifier Q>
58struct compute_vec_mul<L, T, Q, true> : public compute_vec_mul<L, T, Q, false>
59{};
60
61template< length_t L, typename T, qualifier Q>
62struct compute_vec_div<L, T, Q, true> : public compute_vec_div<L, T, Q, false>
63{};
64
65#if GLM_ARCH & GLM_ARCH_SSE2_BIT
66
67# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR
68 template<length_t L, qualifier Q, int E0, int E1, int E2, int E3>
69 struct _swizzle_base1<L, float, Q, E0,E1,E2,E3, true> : public _swizzle_base0<float, L>
70 {
71 GLM_FUNC_QUALIFIER vec<L, float, Q> operator ()() const
72 {
73 __m128 data = *reinterpret_cast<__m128 const*>(&this->_buffer);
74
75 vec<L, float, Q> Result;
76# if GLM_ARCH & GLM_ARCH_AVX_BIT
77 Result.data = _mm_permute_ps(data, _MM_SHUFFLE(E3, E2, E1, E0));
78# else
79 Result.data = _mm_shuffle_ps(data, data, _MM_SHUFFLE(E3, E2, E1, E0));
80# endif
81 return Result;
82 }
83 };
84
85 template<qualifier Q, int E0, int E1, int E2, int E3>
86 struct _swizzle_base1<2, float, Q, E0, E1, E2, E3, true> : public _swizzle_base1<2, float, Q, E0, E1, E2, E3, false> {};
87
88 template<qualifier Q, int E0, int E1, int E2, int E3>
89 struct _swizzle_base1<2, int, Q, E0, E1, E2, E3, true> : public _swizzle_base1<2, int, Q, E0, E1, E2, E3, false> {};
90
91 template<length_t L, qualifier Q, int E0, int E1, int E2, int E3>
92 struct _swizzle_base1<L, int, Q, E0,E1,E2,E3, true> : public _swizzle_base0<int, L>
93 {
94 GLM_FUNC_QUALIFIER vec<L, int, Q> operator ()() const
95 {
96 __m128i data = *reinterpret_cast<__m128i const*>(&this->_buffer);
97
98 vec<L, int, Q> Result;
99 Result.data = _mm_shuffle_epi32(data, _MM_SHUFFLE(E3, E2, E1, E0));
100 return Result;
101 }
102 };
103
104 template<length_t L, qualifier Q, int E0, int E1, int E2, int E3>
105 struct _swizzle_base1<L, uint, Q, E0,E1,E2,E3, true> : public _swizzle_base0<uint, L>
106 {
107 GLM_FUNC_QUALIFIER vec<L, uint, Q> operator ()() const
108 {
109 __m128i data = *reinterpret_cast<__m128i const*>(&this->_buffer);
110
111 vec<L, uint, Q> Result;
112 Result.data = _mm_shuffle_epi32(data, _MM_SHUFFLE(E3, E2, E1, E0));
113 return Result;
114 }
115 };
116# endif// GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR
117
118
119 template<length_t L, qualifier Q>
120 struct compute_vec_add<L, float, Q, true>
121 {
122 GLM_FUNC_QUALIFIER static vec<L, float, Q> call(vec<L, float, Q> const& a, vec<L, float, Q> const& b)
123 {
124 vec<L, float, Q> Result;
125 Result.data = _mm_add_ps(a.data, b.data);
126 return Result;
127 }
128 };
129
130 template<length_t L, qualifier Q>
131 struct compute_vec_add<L, int, Q, true>
132 {
133 GLM_FUNC_QUALIFIER static vec<L, int, Q> call(vec<L, int, Q> const& a, vec<L, int, Q> const& b)
134 {
135 vec<L, int, Q> Result;
136 Result.data = _mm_add_epi32(a.data, b.data);
137 return Result;
138 }
139 };
140
141 template<length_t L, qualifier Q>
142 struct compute_vec_add<L, double, Q, true>
143 {
144 GLM_FUNC_QUALIFIER static vec<L, double, Q> call(vec<L, double, Q> const& a, vec<L, double, Q> const& b)
145 {
146 vec<L, double, Q> Result;
147# if (GLM_ARCH & GLM_ARCH_AVX_BIT)
148 Result.data = _mm256_add_pd(a.data, b.data);
149#else
150 Result.data.setv(0, _mm_add_pd(a.data.getv(0), b.data.getv(0)));
151 Result.data.setv(1, _mm_add_pd(a.data.getv(1), b.data.getv(1)));
152#endif
153 return Result;
154 }
155 };
156
157 template<length_t L, qualifier Q>
158 struct compute_vec_sub<L, float, Q, true>
159 {
160 GLM_FUNC_QUALIFIER static vec<L, float, Q> call(vec<L, float, Q> const& a, vec<L, float, Q> const& b)
161 {
162 vec<L, float, Q> Result;
163 Result.data = _mm_sub_ps(a.data, b.data);
164 return Result;
165 }
166 };
167
168 template<length_t L, qualifier Q>
169 struct compute_vec_sub<L, int, Q, true>
170 {
171 GLM_FUNC_QUALIFIER static vec<L, int, Q> call(vec<L, int, Q> const& a, vec<L, int, Q> const& b)
172 {
173 vec<L, int, Q> Result;
174 Result.data = _mm_sub_epi32(a.data, b.data);
175 return Result;
176 }
177 };
178
179 template<length_t L, qualifier Q>
180 struct compute_vec_sub<L, double, Q, true>
181 {
182 GLM_FUNC_QUALIFIER static vec<L, double, Q> call(vec<L, double, Q> const& a, vec<L, double, Q> const& b)
183 {
184 vec<L, double, Q> Result;
185#if (GLM_ARCH & GLM_ARCH_AVX_BIT)
186 Result.data = _mm256_sub_pd(a.data, b.data);
187#else
188 Result.data.setv(0, _mm_sub_pd(a.data.getv(0), b.data.getv(0)));
189 Result.data.setv(1, _mm_sub_pd(a.data.getv(1), b.data.getv(1)));
190#endif
191 return Result;
192 }
193 };
194
195 template<length_t L, qualifier Q>
196 struct compute_vec_mul<L, float, Q, true>
197 {
198 GLM_FUNC_QUALIFIER static vec<L, float, Q> call(vec<L, float, Q> const& a, vec<L, float, Q> const& b)
199 {
200 vec<L, float, Q> Result;
201 Result.data = _mm_mul_ps(a.data, b.data);
202 return Result;
203 }
204 };
205
206
207 template<length_t L, qualifier Q>
208 struct compute_vec_mul<L, double, Q, true>
209 {
210 GLM_FUNC_QUALIFIER static vec<L, double, Q> call(vec<L, double, Q> const& a, vec<L, double, Q> const& b)
211 {
212 vec<L, double, Q> Result;
213#if (GLM_ARCH & GLM_ARCH_AVX_BIT)
214 Result.data = _mm256_mul_pd(a.data, b.data);
215#else
216 Result.data.setv(0, _mm_mul_pd(a.data.getv(0), b.data.getv(0)));
217 Result.data.setv(1, _mm_mul_pd(a.data.getv(1), b.data.getv(1)));
218#endif
219 return Result;
220 }
221 };
222
223 template<length_t L, qualifier Q>
224 struct compute_vec_mul<L, int, Q, true>
225 {
226 GLM_FUNC_QUALIFIER static vec<L, int, Q> call(vec<L, int, Q> const& a, vec<L, int, Q> const& b)
227 {
228 vec<L, int, Q> Result;
229 glm_i32vec4 ia = a.data;
230 glm_i32vec4 ib = b.data;
231#ifdef __SSE4_1__ // modern CPU - use SSE 4.1
232 Result.data = _mm_mullo_epi32(ia, ib);
233#else // old CPU - use SSE 2
234 __m128i tmp1 = _mm_mul_epu32(ia, ib); /* mul 2,0*/
235 __m128i tmp2 = _mm_mul_epu32(_mm_srli_si128(ia, 4), _mm_srli_si128(ib, 4)); /* mul 3,1 */
236 Result.data = _mm_unpacklo_epi32(_mm_shuffle_epi32(tmp1, _MM_SHUFFLE(0, 0, 2, 0)), _mm_shuffle_epi32(tmp2, _MM_SHUFFLE(0, 0, 2, 0))); /* shuffle results to [63..0] and pack */
237#endif
238 return Result;
239 }
240 };
241
242 template<length_t L, qualifier Q>
243 struct compute_vec_div<L, float, Q, true>
244 {
245 GLM_FUNC_QUALIFIER static vec<L, float, Q> call(vec<L, float, Q> const& a, vec<L, float, Q> const& b)
246 {
247 vec<L, float, Q> Result;
248 Result.data = _mm_div_ps(a.data, b.data);
249 return Result;
250 }
251 };
252
253 template<length_t L, qualifier Q>
254 struct compute_vec_div<L, int, Q, true>
255 {
256 GLM_FUNC_QUALIFIER static vec<L, int, Q> call(vec<L, int, Q> const& a, vec<L, int, Q> const& b)
257 {
258#if defined(_MSC_VER) && _MSC_VER >= 1920 //_mm_div_epi32 only defined with VS >= 2019
259 vec<L, int, Q> Result;
260 Result.data = _mm_div_epi32(a.data, b.data);
261 return Result;
262#else
263 return compute_vec_div<L, int, Q, false>::call(a, b);
264#endif
265 }
266 };
267
268
269 // note: div on uninitialized w can generate div by 0 exception
270 template<qualifier Q>
271 struct compute_vec_div<3, int, Q, true>
272 {
273
274 GLM_FUNC_QUALIFIER static vec<3, int, Q> call(vec<3, int, Q> const& a, vec<3, int, Q> const& b)
275 {
276#if defined(_MSC_VER) && _MSC_VER >= 1920 //_mm_div_epi32 only defined with VS >= 2019
277 vec<3, int, Q> Result;
278 glm_i32vec4 bv = b.data;
279 bv = _mm_shuffle_epi32(bv, _MM_SHUFFLE(0, 2, 1, 0));
280 Result.data = _mm_div_epi32(a.data, bv);
281 return Result;
282#else
283 return compute_vec_div<3, int, Q, false>::call(a, b);
284#endif
285 }
286 };
287
288
289 template<length_t L, qualifier Q>
290 struct compute_vec_div<L, double, Q, true>
291 {
292 GLM_FUNC_QUALIFIER static vec<L, double, Q> call(vec<L, double, Q> const& a, vec<L, double, Q> const& b)
293 {
294 vec<L, double, Q> Result;
295# if GLM_ARCH & GLM_ARCH_AVX_BIT
296 Result.data = _mm256_div_pd(a.data, b.data);
297# else
298 Result.data.setv(0, _mm_div_pd(a.data.getv(0), b.data.getv(0)));
299 Result.data.setv(1, _mm_div_pd(a.data.getv(1), b.data.getv(1)));
300# endif
301 return Result;
302 }
303 };
304
305 template<length_t L>
306 struct compute_vec_div<L, float, aligned_lowp, true>
307 {
308 GLM_FUNC_QUALIFIER static vec<L, float, aligned_lowp> call(vec<L, float, aligned_lowp> const& a, vec<L, float, aligned_lowp> const& b)
309 {
310 vec<L, float, aligned_lowp> Result;
311 Result.data = _mm_mul_ps(a.data, _mm_rcp_ps(b.data));
312 return Result;
313 }
314 };
315
316 template<length_t L, typename T, qualifier Q>
317 struct compute_vec_and<L, T, Q, -1, 32, true>
318 {
319 GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& a, vec<L, T, Q> const& b)
320 {
321 vec<L, T, Q> Result;
322 Result.data = _mm_and_si128(a.data, b.data);
323 return Result;
324 }
325 };
326
327
328 template<length_t L, typename T, qualifier Q>
329 struct compute_vec_and<L, T, Q, true, 64, true>
330 {
331 GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& a, vec<L, T, Q> const& b)
332 {
333 vec<L, T, Q> Result;
334# if GLM_ARCH & GLM_ARCH_AVX2_BIT
335 Result.data = _mm256_and_si256(a.data, b.data);
336# elif GLM_ARCH & GLM_ARCH_AVX_BIT
337 Result.data = _mm256_and_pd(_mm256_castpd256_pd128(a.data), _mm256_castpd256_pd128(b.data));
338# else
339 Result.data.setv(0, _mm_and_si128(a.data.getv(0), b.data.getv(0)));
340 Result.data.setv(1, _mm_and_si128(a.data.getv(1), b.data.getv(1)));
341# endif
342 return Result;
343 }
344 };
345
346
347
348 template<length_t L, typename T, qualifier Q>
349 struct compute_vec_or<L, T, Q, -1, 32, true>
350 {
351 GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& a, vec<L, T, Q> const& b)
352 {
353 vec<L, T, Q> Result;
354 Result.data = _mm_or_si128(a.data, b.data);
355 return Result;
356 }
357 };
358
359
360 template<length_t L, typename T, qualifier Q>
361 struct compute_vec_or<L, T, Q, true, 64, true>
362 {
363 GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& a, vec<L, T, Q> const& b)
364 {
365 vec<L, T, Q> Result;
366# if GLM_ARCH & GLM_ARCH_AVX2_BIT
367 Result.data = _mm256_or_si256(a.data, b.data);
368# else
369 Result.data.setv(0, _mm_or_si128(a.data.getv(0), b.data.getv(0)));
370 Result.data.setv(1, _mm_or_si128(a.data.getv(1), b.data.getv(1)));
371# endif
372 return Result;
373 }
374 };
375
376 template<length_t L, typename T, qualifier Q>
377 struct compute_vec_xor<L, T, Q, true, 32, true>
378 {
379 GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& a, vec<L, T, Q> const& b)
380 {
381 vec<L, T, Q> Result;
382 Result.data = _mm_xor_si128(a.data, b.data);
383 return Result;
384 }
385 };
386
387
388 template<length_t L, typename T, qualifier Q>
389 struct compute_vec_xor<L, T, Q, true, 64, true>
390 {
391 GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& a, vec<L, T, Q> const& b)
392 {
393 vec<L, T, Q> Result;
394# if GLM_ARCH & GLM_ARCH_AVX2_BIT
395 Result.data = _mm256_xor_si256(a.data, b.data);
396# else
397 Result.data.setv(0, _mm_xor_si128(a.data.getv(0), b.data.getv(0)));
398 Result.data.setv(1, _mm_xor_si128(a.data.getv(1), b.data.getv(1)));
399# endif
400 return Result;
401 }
402 };
403
404
405 //template<typename T, qualifier Q>
406 //struct compute_vec_shift_left<3, T, Q, -1, 32, true>
407 //{
408 // GLM_FUNC_QUALIFIER static vec<3, T, Q> call(vec<3, T, Q> const& a, vec<3, T, Q> const& b)
409 // {
410 // vec<3, T, Q> Result;
411 // __m128 v2 = _mm_castsi128_ps(b.data);
412 // v2 = _mm_shuffle_ps(v2, v2, _MM_SHUFFLE(0, 0, 0, 0)); // note: shift is done with xmm[3] that correspond vec w that doesn't exist on vect3
413 // _mm_set1_epi64x(_w, _z, _y, _x);
414 // __m128i vr = _mm_sll_epi32(a.data, _mm_castps_si128(v2));
415 // Result.data = vr;
416 // return Result;
417 // }
418 //};
419
420 //template<length_t L, typename T, qualifier Q>
421 //struct compute_vec_shift_left<L, T, Q, -1, 32, true>
422 //{
423 // GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& a, vec<L, T, Q> const& b)
424 // {
425 // vec<L, T, Q> Result;
426 // Result.data = _mm_sll_epi32(a.data, b.data);
427 // return Result;
428 // }
429 //};
430
431
432// template<length_t L, typename T, qualifier Q>
433// struct compute_vec_shift_left<L, T, Q, true, 64, true>
434// {
435// GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& a, vec<L, T, Q> const& b)
436// {
437// vec<L, T, Q> Result;
438//# if GLM_ARCH & GLM_ARCH_AVX2_BIT
439// Result.data = _mm256_sll_epi64(a.data, b.data);
440//# else
441// Result.data.setv(0, _mm_sll_epi64(a.data.getv(0), b.data.getv(0)));
442// Result.data.setv(1, _mm_sll_epi64(a.data.getv(1), b.data.getv(1)));
443//# endif
444// return Result;
445// }
446// };
447
448
449// template<length_t L, typename T, qualifier Q>
450// struct compute_vec_shift_right<L, T, Q, -1, 32, true>
451// {
452// GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& a, vec<L, T, Q> const& b)
453// {
454// vec<L, T, Q> Result;
455// Result.data = _mm_srl_epi32(a.data, b.data);
456// return Result;
457// }
458// };
459//
460// template<length_t L, typename T, qualifier Q>
461// struct compute_vec_shift_right<L, T, Q, true, 64, true>
462// {
463// GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& a, vec<L, T, Q> const& b)
464// {
465// vec<L, T, Q> Result;
466//# if GLM_ARCH & GLM_ARCH_AVX2_BIT
467// Result.data = _mm256_srl_epi64(a.data, b.data);
468//# else
469// Result.data.setv(0, _mm_srl_epi64(a.data.getv(0), b.data.getv(0)));
470// Result.data.setv(1, _mm_srl_epi64(a.data.getv(1), b.data.getv(1)));
471//# endif
472// return Result;
473// }
474// };
475
476 template<length_t L, typename T, qualifier Q>
477 struct compute_vec_bitwise_not<L, T, Q, true, 32, true>
478 {
479 GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& v)
480 {
481 vec<L, T, Q> Result;
482 Result.data = _mm_xor_si128(v.data, _mm_set1_epi32(-1));
483 return Result;
484 }
485 };
486
487
488 template<length_t L, typename T, qualifier Q>
489 struct compute_vec_bitwise_not<L, T, Q, true, 64, true>
490 {
491 GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& v)
492 {
493 vec<L, T, Q> Result;
494# if GLM_ARCH & GLM_ARCH_AVX2_BIT
495 Result.data = _mm256_xor_si256(v.data, _mm256_set1_epi32(-1));
496# else
497 Result.data.setv(0, _mm_xor_si128(v.data.getv(0), _mm_set1_epi32(-1)));
498 Result.data.setv(1, _mm_xor_si128(v.data.getv(1), _mm_set1_epi32(-1)));
499# endif
500 return Result;
501 }
502 };
503
504
505 template<length_t L, qualifier Q>
506 struct compute_vec_equal<L, float, Q, false, 32, true>
507 {
508 GLM_FUNC_QUALIFIER static bool call(vec<L, float, Q> const& v1, vec<L, float, Q> const& v2)
509 {
510 return _mm_movemask_ps(_mm_cmpneq_ps(v1.data, v2.data)) == 0;
511 }
512 };
513
514# if GLM_ARCH & GLM_ARCH_SSE41_BIT
515 template<length_t L, qualifier Q>
516 struct compute_vec_equal<L, int, Q, true, 32, true>
517 {
518 GLM_FUNC_QUALIFIER static bool call(vec<L, int, Q> const& v1, vec<L, int, Q> const& v2)
519 {
520 //return _mm_movemask_epi8(_mm_cmpeq_epi32(v1.data, v2.data)) != 0;
521 __m128i neq = _mm_xor_si128(v1.data, v2.data);
522 return _mm_test_all_zeros(neq, neq) == 0;
523 }
524 };
525# endif
526
527
528
529 template<length_t L, qualifier Q>
530 struct compute_vec_nequal<L, float, Q, false, 32, true>
531 {
532 GLM_FUNC_QUALIFIER static bool call(vec<L, float, Q> const& v1, vec<L, float, Q> const& v2)
533 {
534 return _mm_movemask_ps(_mm_cmpneq_ps(v1.data, v2.data)) != 0;
535 }
536 };
537
538# if GLM_ARCH & GLM_ARCH_SSE41_BIT
539 template<length_t L, qualifier Q>
540 struct compute_vec_nequal<L, int, Q, -1, 32, true>
541 {
542 GLM_FUNC_QUALIFIER static bool call(vec<L, int, Q> const& v1, vec<L, int, Q> const& v2)
543 {
544 //return _mm_movemask_epi8(_mm_cmpneq_epi32(v1.data, v2.data)) != 0;
545 __m128i neq = _mm_xor_si128(v1.data, v2.data);
546 int v = _mm_test_all_zeros(neq, neq);
547 return v != 1;
548 }
549 };
550 template<length_t L, qualifier Q>
551 struct compute_vec_nequal<L, unsigned int, Q, -1, 32, true>
552 {
553 GLM_FUNC_QUALIFIER static bool call(vec<L, unsigned int, Q> const& v1, vec<L, unsigned int, Q> const& v2)
554 {
555 //return _mm_movemask_epi8(_mm_cmpneq_epi32(v1.data, v2.data)) != 0;
556 __m128i neq = _mm_xor_si128(v1.data, v2.data);
557 return _mm_test_all_zeros(neq, neq) != 1;
558 }
559 };
560# else
561
562
563 template<length_t L, qualifier Q>
564 struct compute_vec_nequal<L, unsigned int, Q, -1, 32, true>
565 {
566 GLM_FUNC_QUALIFIER static bool call(vec<L, unsigned int, Q> const& v1, vec<L, unsigned int, Q> const& v2)
567 {
568 return compute_vec_nequal<L, unsigned int, Q, true, 32, false>::call(v1, v2);
569 }
570 };
571
572# endif
573
574
575
576
577}//namespace detail
578
579
580#define CTOR_FLOAT(L, Q)\
581 template<>\
582 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, float, Q>::vec(float _s) :\
583 data(_mm_set1_ps(_s))\
584 {}
585
586#if GLM_ARCH & GLM_ARCH_AVX_BIT
587# define CTOR_DOUBLE(L, Q)\
588 template<>\
589 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, double, Q>::vec(double _s) :\
590 data(_mm256_set1_pd(_s)){}
591
592#define CTOR_DOUBLE4(L, Q)\
593 template<>\
594 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, double, Q>::vec(double _x, double _y, double _z, double _w):\
595 data(_mm256_set_pd(_w, _z, _y, _x)) {}
596
597#define CTOR_DOUBLE3(L, Q)\
598 template<>\
599 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, double, Q>::vec(double _x, double _y, double _z):\
600 data(_mm256_set_pd(_z, _z, _y, _x)) {}
601
602# define CTOR_INT64(L, Q)\
603 template<>\
604 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, detail::int64, Q>::vec(detail::int64 _s) :\
605 data(_mm256_set1_epi64x(_s)){}
606
607#define CTOR_DOUBLE_COPY3(L, Q)\
608 template<>\
609 template<qualifier P>\
610 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, double, Q>::vec(vec<3, double, P> const& v) :\
611 data(_mm256_setr_pd(v.x, v.y, v.z, v.z)){}
612
613#else
614# define CTOR_DOUBLE(L, Q)\
615 template<>\
616 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, double, Q>::vec(double _v) \
617 {\
618 data.setv(0, _mm_set1_pd(_v)); \
619 data.setv(1, _mm_set1_pd(_v)); \
620 }
621
622#define CTOR_DOUBLE4(L, Q)\
623 template<>\
624 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, double, Q>::vec(double _x, double _y, double _z, double _w)\
625 {\
626 data.setv(0, _mm_setr_pd(_x, _y)); \
627 data.setv(1, _mm_setr_pd(_z, _w)); \
628 }
629
630#define CTOR_DOUBLE3(L, Q)\
631 template<>\
632 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, double, Q>::vec(double _x, double _y, double _z)\
633 {\
634 data.setv(0, _mm_setr_pd(_x, _y)); \
635 data.setv(1, _mm_setr_pd(_z, _z)); \
636 }
637
638# define CTOR_INT64(L, Q)\
639 template<>\
640 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, detail::int64, Q>::vec(detail::int64 _s) :\
641 data(_mm256_set1_epi64x(_s)){}
642
643#define CTOR_DOUBLE_COPY3(L, Q)\
644 template<>\
645 template<qualifier P>\
646 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, double, Q>::vec(vec<3, double, P> const& v)\
647 {\
648 data.setv(0, _mm_setr_pd(v.x, v.y));\
649 data.setv(1, _mm_setr_pd(v.z, 1.0));\
650 }
651
652#endif //GLM_ARCH & GLM_ARCH_AVX_BIT
653
654#define CTOR_INT(L, Q)\
655 template<>\
656 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, int, Q>::vec(int _s) :\
657 data(_mm_set1_epi32(_s))\
658 {}
659
660#define CTOR_FLOAT4(L, Q)\
661 template<>\
662 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, float, Q>::vec(float _x, float _y, float _z, float _w) :\
663 data(_mm_set_ps(_w, _z, _y, _x))\
664 {}
665
666#define CTOR_FLOAT3(L, Q)\
667 template<>\
668 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, float, Q>::vec(float _x, float _y, float _z) :\
669 data(_mm_set_ps(_z, _z, _y, _x)){}
670
671
672#define CTOR_INT4(L, Q)\
673 template<>\
674 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, int, Q>::vec(int _x, int _y, int _z, int _w) :\
675 data(_mm_set_epi32(_w, _z, _y, _x)){}
676
677#define CTOR_INT3(L, Q)\
678 template<>\
679 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, int, Q>::vec(int _x, int _y, int _z) :\
680 data(_mm_set_epi32(_z, _z, _y, _x)){}
681
682#define CTOR_VECF_INT4(L, Q)\
683 template<>\
684 template<>\
685 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, float, Q>::vec(int _x, int _y, int _z, int _w) :\
686 data(_mm_cvtepi32_ps(_mm_set_epi32(_w, _z, _y, _x)))\
687 {}
688
689#define CTOR_VECF_INT3(L, Q)\
690 template<>\
691 template<>\
692 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, float, Q>::vec(int _x, int _y, int _z) :\
693 data(_mm_cvtepi32_ps(_mm_set_epi32(_z, _z, _y, _x)))\
694 {}
695
696#define CTOR_DEFAULT(L, Q)\
697 template<>\
698 template<>\
699 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, float, Q>::vec() :\
700 data(_mm_setzero_ps())\
701 {}
702
703#define CTOR_FLOAT_COPY3(L, Q)\
704 template<>\
705 template<qualifier P>\
706 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, float, Q>::vec(vec<3, float, P> const& v)\
707 :data(_mm_set_ps(v.z, v.z, v.y, v.x))\
708 {}
709
710
711
712}//namespace glm
713
714#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT
715
716#if GLM_ARCH & GLM_ARCH_NEON_BIT
717
718#if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR
719// the functions below needs to be properly implemented, use unoptimized function fro now.
720
721template<length_t L, qualifier Q, int E0, int E1, int E2, int E3>
722struct _swizzle_base1<L, float, Q, E0, E1, E2, E3, true> : public _swizzle_base1<L, float, Q, E0, E1, E2, E3, false>{};
723
724template<length_t L, qualifier Q, int E0, int E1, int E2, int E3>
725struct _swizzle_base1<L, int, Q, E0, E1, E2, E3, true> : public _swizzle_base1<L, int, Q, E0, E1, E2, E3, false> {};
726
727template<length_t L, qualifier Q, int E0, int E1, int E2, int E3>
728struct _swizzle_base1<L, uint, Q, E0, E1, E2, E3, true> : public _swizzle_base1<L, uint, Q, E0, E1, E2, E3, false> {};
729
730# endif// GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR
731
732
733 template<length_t L, qualifier Q>
734 struct compute_vec_add<L, float, Q, true>
735 {
736 GLM_FUNC_QUALIFIER static
737 vec<L, float, Q>
738 call(vec<L, float, Q> const& a, vec<L, float, Q> const& b)
739 {
740 vec<L, float, Q> Result;
741 Result.data = vaddq_f32(a.data, b.data);
742 return Result;
743 }
744 };
745
746 template<length_t L, qualifier Q>
747 struct compute_vec_add<L, uint, Q, true>
748 {
749 GLM_FUNC_QUALIFIER static
750 vec<L, uint, Q>
751 call(vec<L, uint, Q> const& a, vec<L, uint, Q> const& b)
752 {
753 vec<L, uint, Q> Result;
754 Result.data = vaddq_u32(a.data, b.data);
755 return Result;
756 }
757 };
758
759 template<length_t L, qualifier Q>
760 struct compute_vec_add<L, int, Q, true>
761 {
762 static
763 vec<L, int, Q>
764 call(vec<L, int, Q> const& a, vec<L, int, Q> const& b)
765 {
766 vec<L, int, Q> Result;
767 Result.data = vaddq_s32(a.data, b.data);
768 return Result;
769 }
770 };
771
772 template<length_t L, qualifier Q>
773 struct compute_vec_sub<L, float, Q, true>
774 {
775 static vec<L, float, Q> call(vec<L, float, Q> const& a, vec<L, float, Q> const& b)
776 {
777 vec<L, float, Q> Result;
778 Result.data = vsubq_f32(a.data, b.data);
779 return Result;
780 }
781 };
782
783 template<length_t L, qualifier Q>
784 struct compute_vec_sub<L, uint, Q, true>
785 {
786 static vec<L, uint, Q> call(vec<L, uint, Q> const& a, vec<L, uint, Q> const& b)
787 {
788 vec<L, uint, Q> Result;
789 Result.data = vsubq_u32(a.data, b.data);
790 return Result;
791 }
792 };
793
794 template<length_t L, qualifier Q>
795 struct compute_vec_sub<L, int, Q, true>
796 {
797 static vec<L, int, Q> call(vec<L, int, Q> const& a, vec<L, int, Q> const& b)
798 {
799 vec<L, int, Q> Result;
800 Result.data = vsubq_s32(a.data, b.data);
801 return Result;
802 }
803 };
804
805 template<length_t L, qualifier Q>
806 struct compute_vec_mul<L, float, Q, true>
807 {
808 static vec<L, float, Q> call(vec<L, float, Q> const& a, vec<L, float, Q> const& b)
809 {
810 vec<L, float, Q> Result;
811 Result.data = vmulq_f32(a.data, b.data);
812 return Result;
813 }
814 };
815
816 template<length_t L, qualifier Q>
817 struct compute_vec_mul<L, uint, Q, true>
818 {
819 static vec<L, uint, Q> call(vec<L, uint, Q> const& a, vec<L, uint, Q> const& b)
820 {
821 vec<L, uint, Q> Result;
822 Result.data = vmulq_u32(a.data, b.data);
823 return Result;
824 }
825 };
826
827 template<length_t L, qualifier Q>
828 struct compute_vec_mul<L, int, Q, true>
829 {
830 static vec<L, int, Q> call(vec<L, int, Q> const& a, vec<L, int, Q> const& b)
831 {
832 vec<L, int, Q> Result;
833 Result.data = vmulq_s32(a.data, b.data);
834 return Result;
835 }
836 };
837
838 template<length_t L, qualifier Q>
839 struct compute_vec_div<L, float, Q, true>
840 {
841 static vec<L, float, Q> call(vec<L, float, Q> const& a, vec<L, float, Q> const& b)
842 {
843 vec<L, float, Q> Result;
844#if GLM_ARCH & GLM_ARCH_ARMV8_BIT
845 Result.data = vdivq_f32(a.data, b.data);
846#else
847 /* Arm assembler reference:
848 *
849 * The Newton-Raphson iteration: x[n+1] = x[n] * (2 - d * x[n])
850 * converges to (1/d) if x0 is the result of VRECPE applied to d.
851 *
852 * Note: The precision usually improves with two interactions, but more than two iterations are not helpful. */
853 float32x4_t x = vrecpeq_f32(b.data);
854 x = vmulq_f32(vrecpsq_f32(b.data, x), x);
855 x = vmulq_f32(vrecpsq_f32(b.data, x), x);
856 Result.data = vmulq_f32(a.data, x);
857#endif
858 return Result;
859 }
860 };
861
862 template<length_t L, qualifier Q>
863 struct compute_vec_equal<L, float, Q, false, 32, true>
864 {
865 static bool call(vec<L, float, Q> const& v1, vec<L, float, Q> const& v2)
866 {
867 uint32x4_t cmp = vceqq_f32(v1.data, v2.data);
868#if GLM_ARCH & GLM_ARCH_ARMV8_BIT
869 cmp = vpminq_u32(cmp, cmp);
870 cmp = vpminq_u32(cmp, cmp);
871 uint32_t r = cmp[0];
872#else
873 uint32x2_t cmpx2 = vpmin_u32(vget_low_u32(cmp), vget_high_u32(cmp));
874 cmpx2 = vpmin_u32(cmpx2, cmpx2);
875 uint32_t r = cmpx2[0];
876#endif
877 return r == ~0u;
878 }
879 };
880
881 template<length_t L, qualifier Q>
882 struct compute_vec_equal<L, uint, Q, false, 32, true>
883 {
884 static bool call(vec<L, uint, Q> const& v1, vec<L, uint, Q> const& v2)
885 {
886 uint32x4_t cmp = vceqq_u32(v1.data, v2.data);
887#if GLM_ARCH & GLM_ARCH_ARMV8_BIT
888 cmp = vpminq_u32(cmp, cmp);
889 cmp = vpminq_u32(cmp, cmp);
890 uint32_t r = cmp[0];
891#else
892 uint32x2_t cmpx2 = vpmin_u32(vget_low_u32(cmp), vget_high_u32(cmp));
893 cmpx2 = vpmin_u32(cmpx2, cmpx2);
894 uint32_t r = cmpx2[0];
895#endif
896 return r == ~0u;
897 }
898 };
899
900 template<length_t L, qualifier Q>
901 struct compute_vec_equal<L, int, Q, false, 32, true>
902 {
903 static bool call(vec<L, int, Q> const& v1, vec<L, int, Q> const& v2)
904 {
905 uint32x4_t cmp = vceqq_s32(v1.data, v2.data);
906#if GLM_ARCH & GLM_ARCH_ARMV8_BIT
907 cmp = vpminq_u32(cmp, cmp);
908 cmp = vpminq_u32(cmp, cmp);
909 uint32_t r = cmp[0];
910#else
911 uint32x2_t cmpx2 = vpmin_u32(vget_low_u32(cmp), vget_high_u32(cmp));
912 cmpx2 = vpmin_u32(cmpx2, cmpx2);
913 uint32_t r = cmpx2[0];
914#endif
915 return r == ~0u;
916 }
917 };
918
919 template<length_t L, qualifier Q>
920 struct compute_vec_nequal<L, float, Q, false, 32, true>
921 {
922 static bool call(vec<L, float, Q> const& v1, vec<L, float, Q> const& v2)
923 {
924 return !compute_vec_equal<L, float, Q, false, 32, true>::call(v1, v2);
925 }
926 };
927
928 template<length_t L, qualifier Q>
929 struct compute_vec_nequal<L, uint, Q, false, 32, true>
930 {
931 static bool call(vec<L, uint, Q> const& v1, vec<L, uint, Q> const& v2)
932 {
933 return !compute_vec_equal<L, uint, Q, false, 32, true>::call(v1, v2);
934 }
935 };
936
937 template<length_t L, qualifier Q>
938 struct compute_vec_nequal<L, int, Q, false, 32, true>
939 {
940 static bool call(vec<L, int, Q> const& v1, vec<L, int, Q> const& v2)
941 {
942 return !compute_vec_equal<L, int, Q, false, 32, true>::call(v1, v2);
943 }
944 };
945
946
947#if !GLM_CONFIG_XYZW_ONLY
948
949#define CTOR_FLOAT(L, Q)\
950 template<>\
951 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, float, Q>::vec(float _s) :\
952 data(vdupq_n_f32(_s))\
953 {}
954
955#define CTOR_INT(L, Q)\
956 template<>\
957 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, int, Q>::vec(int _s) :\
958 data(vdupq_n_s32(_s))\
959 {}
960
961#define CTOR_UINT(L, Q)\
962 template<>\
963 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, uint, Q>::vec(uint _s) :\
964 data(vdupq_n_u32(_s))\
965 {}
966
967#define CTOR_VECF_INT4(L, Q)\
968 template<>\
969 template<>\
970 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, float, Q>::vec(int _x, int _y, int _z, int _w) :\
971 data(vcvtq_f32_s32(vec<L, int, Q>(_x, _y, _z, _w).data))\
972 {}
973
974#define CTOR_VECF_UINT4(L, Q)\
975 template<>\
976 template<>\
977 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, float, Q>::vec(uint _x, uint _y, uint _z, uint _w) :\
978 data(vcvtq_f32_u32(vec<L, uint, Q>(_x, _y, _z, _w).data))\
979 {}
980
981#define CTOR_VECF_INT3(L, Q)\
982 template<>\
983 template<>\
984 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, float, Q>::vec(int _x, int _y, int _z) :\
985 data(vcvtq_f32_s32(vec<L, int, Q>(_x, _y, _z).data))\
986 {}
987
988#define CTOR_VECF_UINT4(L, Q)\
989 template<>\
990 template<>\
991 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, float, Q>::vec(uint _x, uint _y, uint _z, uint _w) :\
992 data(vcvtq_f32_u32(vec<L, uint, Q>(_x, _y, _z, _w).data))\
993 {}
994
995#define CTOR_VECF_UINT3(L, Q)\
996 template<>\
997 template<>\
998 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, float, Q>::vec(uint _x, uint _y, uint _z) :\
999 data(vcvtq_f32_u32(vec<L, uint, Q>(_x, _y, _z).data))\
1000 {}
1001
1002
1003#define CTOR_VECF_VECF(L, Q)\
1004 template<>\
1005 template<>\
1006 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, float, Q>::vec(const vec<L, float, Q>& rhs) :\
1007 data(rhs.data)\
1008 {}
1009
1010#define CTOR_VECF_VECI(L, Q)\
1011 template<>\
1012 template<>\
1013 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, float, Q>::vec(const vec<L, int, Q>& rhs) :\
1014 data(vcvtq_f32_s32(rhs.data))\
1015 {}
1016
1017#define CTOR_VECF_VECU(L, Q)\
1018 template<>\
1019 template<>\
1020 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, float, Q>::vec(const vec<L, uint, Q>& rhs) :\
1021 data(vcvtq_f32_u32(rhs.data))\
1022 {}
1023
1024
1025#endif
1026
1027
1028}//namespace detail
1029
1030}//namespace glm
1031
1032#endif