Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/embree/common/simd/vfloat8_avx.h
9912 views
1
// Copyright 2009-2021 Intel Corporation
2
// SPDX-License-Identifier: Apache-2.0
3
4
#pragma once
5
6
#define vboolf vboolf_impl
7
#define vboold vboold_impl
8
#define vint vint_impl
9
#define vuint vuint_impl
10
#define vllong vllong_impl
11
#define vfloat vfloat_impl
12
#define vdouble vdouble_impl
13
14
namespace embree
15
{
16
/* 8-wide AVX float type */
17
template<>
18
struct vfloat<8>
19
{
20
ALIGNED_STRUCT_(32);
21
22
typedef vboolf8 Bool;
23
typedef vint8 Int;
24
typedef vfloat8 Float;
25
26
enum { size = 8 }; // number of SIMD elements
27
union { __m256 v; float f[8]; int i[8]; }; // data
28
29
////////////////////////////////////////////////////////////////////////////////
30
/// Constructors, Assignment & Cast Operators
31
////////////////////////////////////////////////////////////////////////////////
32
33
__forceinline vfloat() {}
34
__forceinline vfloat(const vfloat8& other) { v = other.v; }
35
__forceinline vfloat8& operator =(const vfloat8& other) { v = other.v; return *this; }
36
37
__forceinline vfloat(__m256 a) : v(a) {}
38
__forceinline operator const __m256&() const { return v; }
39
__forceinline operator __m256&() { return v; }
40
41
__forceinline explicit vfloat(const vfloat4& a) : v(_mm256_insertf128_ps(_mm256_castps128_ps256(a),a,1)) {}
42
__forceinline vfloat(const vfloat4& a, const vfloat4& b) : v(_mm256_insertf128_ps(_mm256_castps128_ps256(a),b,1)) {}
43
44
__forceinline explicit vfloat(const char* a) : v(_mm256_loadu_ps((const float*)a)) {}
45
__forceinline vfloat(float a) : v(_mm256_set1_ps(a)) {}
46
__forceinline vfloat(float a, float b) : v(_mm256_set_ps(b, a, b, a, b, a, b, a)) {}
47
__forceinline vfloat(float a, float b, float c, float d) : v(_mm256_set_ps(d, c, b, a, d, c, b, a)) {}
48
__forceinline vfloat(float a, float b, float c, float d, float e, float f, float g, float h) : v(_mm256_set_ps(h, g, f, e, d, c, b, a)) {}
49
50
__forceinline explicit vfloat(__m256i a) : v(_mm256_cvtepi32_ps(a)) {}
51
52
////////////////////////////////////////////////////////////////////////////////
53
/// Constants
54
////////////////////////////////////////////////////////////////////////////////
55
56
__forceinline vfloat(ZeroTy) : v(_mm256_setzero_ps()) {}
57
__forceinline vfloat(OneTy) : v(_mm256_set1_ps(1.0f)) {}
58
__forceinline vfloat(PosInfTy) : v(_mm256_set1_ps(pos_inf)) {}
59
__forceinline vfloat(NegInfTy) : v(_mm256_set1_ps(neg_inf)) {}
60
__forceinline vfloat(StepTy) : v(_mm256_set_ps(7.0f, 6.0f, 5.0f, 4.0f, 3.0f, 2.0f, 1.0f, 0.0f)) {}
61
__forceinline vfloat(NaNTy) : v(_mm256_set1_ps(nan)) {}
62
__forceinline vfloat(UndefinedTy) : v(_mm256_undefined_ps()) {}
63
64
////////////////////////////////////////////////////////////////////////////////
65
/// Loads and Stores
66
////////////////////////////////////////////////////////////////////////////////
67
68
static __forceinline vfloat8 broadcast(const void* a) {
69
return _mm256_broadcast_ss((float*)a);
70
}
71
72
static __forceinline vfloat8 load(const char* ptr) {
73
#if defined(__AVX2__)
74
return _mm256_cvtepi32_ps(_mm256_cvtepi8_epi32(_mm_loadu_si128((__m128i*)ptr)));
75
#else
76
return vfloat8(vfloat4::load(ptr),vfloat4::load(ptr+4));
77
#endif
78
}
79
80
static __forceinline vfloat8 load(const unsigned char* ptr) {
81
#if defined(__AVX2__)
82
return _mm256_cvtepi32_ps(_mm256_cvtepu8_epi32(_mm_loadu_si128((__m128i*)ptr)));
83
#else
84
return vfloat8(vfloat4::load(ptr),vfloat4::load(ptr+4));
85
#endif
86
}
87
88
static __forceinline vfloat8 load(const short* ptr) {
89
#if defined(__AVX2__)
90
return _mm256_cvtepi32_ps(_mm256_cvtepi16_epi32(_mm_loadu_si128((__m128i*)ptr)));
91
#else
92
return vfloat8(vfloat4::load(ptr),vfloat4::load(ptr+4));
93
#endif
94
}
95
96
static __forceinline vfloat8 load (const void* ptr) { return _mm256_load_ps((float*)ptr); }
97
static __forceinline vfloat8 loadu(const void* ptr) { return _mm256_loadu_ps((float*)ptr); }
98
99
static __forceinline void store (void* ptr, const vfloat8& v) { return _mm256_store_ps((float*)ptr,v); }
100
static __forceinline void storeu(void* ptr, const vfloat8& v) { return _mm256_storeu_ps((float*)ptr,v); }
101
102
#if defined(__AVX512VL__)
103
104
static __forceinline vfloat8 load (const vboolf8& mask, const void* ptr) { return _mm256_mask_load_ps (_mm256_setzero_ps(),mask,(float*)ptr); }
105
static __forceinline vfloat8 loadu(const vboolf8& mask, const void* ptr) { return _mm256_mask_loadu_ps(_mm256_setzero_ps(),mask,(float*)ptr); }
106
107
static __forceinline void store (const vboolf8& mask, void* ptr, const vfloat8& v) { _mm256_mask_store_ps ((float*)ptr,mask,v); }
108
static __forceinline void storeu(const vboolf8& mask, void* ptr, const vfloat8& v) { _mm256_mask_storeu_ps((float*)ptr,mask,v); }
109
#else
110
static __forceinline vfloat8 load (const vboolf8& mask, const void* ptr) { return _mm256_maskload_ps((float*)ptr,_mm256_castps_si256(mask.v)); }
111
static __forceinline vfloat8 loadu(const vboolf8& mask, const void* ptr) { return _mm256_maskload_ps((float*)ptr,_mm256_castps_si256(mask.v)); }
112
113
static __forceinline void store (const vboolf8& mask, void* ptr, const vfloat8& v) { _mm256_maskstore_ps((float*)ptr,_mm256_castps_si256(mask.v),v); }
114
static __forceinline void storeu(const vboolf8& mask, void* ptr, const vfloat8& v) { _mm256_maskstore_ps((float*)ptr,_mm256_castps_si256(mask.v),v); }
115
#endif
116
117
#if defined(__AVX2__)
118
static __forceinline vfloat8 load_nt(void* ptr) {
119
return _mm256_castsi256_ps(_mm256_stream_load_si256((__m256i*)ptr));
120
}
121
#endif
122
123
static __forceinline void store_nt(void* ptr, const vfloat8& v) {
124
_mm256_stream_ps((float*)ptr,v);
125
}
126
127
template<int scale = 4>
128
static __forceinline vfloat8 gather(const float* ptr, const vint8& index) {
129
#if defined(__AVX2__) && !defined(__aarch64__)
130
return _mm256_i32gather_ps(ptr, index ,scale);
131
#else
132
return vfloat8(
133
*(float*)(((char*)ptr)+scale*index[0]),
134
*(float*)(((char*)ptr)+scale*index[1]),
135
*(float*)(((char*)ptr)+scale*index[2]),
136
*(float*)(((char*)ptr)+scale*index[3]),
137
*(float*)(((char*)ptr)+scale*index[4]),
138
*(float*)(((char*)ptr)+scale*index[5]),
139
*(float*)(((char*)ptr)+scale*index[6]),
140
*(float*)(((char*)ptr)+scale*index[7]));
141
#endif
142
}
143
144
template<int scale = 4>
145
static __forceinline vfloat8 gather(const vboolf8& mask, const float* ptr, const vint8& index) {
146
vfloat8 r = zero;
147
#if defined(__AVX512VL__)
148
return _mm256_mmask_i32gather_ps(r, mask, index, ptr, scale);
149
#elif defined(__AVX2__) && !defined(__aarch64__)
150
return _mm256_mask_i32gather_ps(r, ptr, index, mask, scale);
151
#else
152
if (likely(mask[0])) r[0] = *(float*)(((char*)ptr)+scale*index[0]);
153
if (likely(mask[1])) r[1] = *(float*)(((char*)ptr)+scale*index[1]);
154
if (likely(mask[2])) r[2] = *(float*)(((char*)ptr)+scale*index[2]);
155
if (likely(mask[3])) r[3] = *(float*)(((char*)ptr)+scale*index[3]);
156
if (likely(mask[4])) r[4] = *(float*)(((char*)ptr)+scale*index[4]);
157
if (likely(mask[5])) r[5] = *(float*)(((char*)ptr)+scale*index[5]);
158
if (likely(mask[6])) r[6] = *(float*)(((char*)ptr)+scale*index[6]);
159
if (likely(mask[7])) r[7] = *(float*)(((char*)ptr)+scale*index[7]);
160
return r;
161
#endif
162
}
163
164
template<int scale = 4>
165
static __forceinline void scatter(void* ptr, const vint8& ofs, const vfloat8& v)
166
{
167
#if defined(__AVX512VL__)
168
_mm256_i32scatter_ps((float*)ptr, ofs, v, scale);
169
#else
170
*(float*)(((char*)ptr)+scale*ofs[0]) = v[0];
171
*(float*)(((char*)ptr)+scale*ofs[1]) = v[1];
172
*(float*)(((char*)ptr)+scale*ofs[2]) = v[2];
173
*(float*)(((char*)ptr)+scale*ofs[3]) = v[3];
174
*(float*)(((char*)ptr)+scale*ofs[4]) = v[4];
175
*(float*)(((char*)ptr)+scale*ofs[5]) = v[5];
176
*(float*)(((char*)ptr)+scale*ofs[6]) = v[6];
177
*(float*)(((char*)ptr)+scale*ofs[7]) = v[7];
178
#endif
179
}
180
181
template<int scale = 4>
182
static __forceinline void scatter(const vboolf8& mask, void* ptr, const vint8& ofs, const vfloat8& v)
183
{
184
#if defined(__AVX512VL__)
185
_mm256_mask_i32scatter_ps((float*)ptr, mask, ofs, v, scale);
186
#else
187
if (likely(mask[0])) *(float*)(((char*)ptr)+scale*ofs[0]) = v[0];
188
if (likely(mask[1])) *(float*)(((char*)ptr)+scale*ofs[1]) = v[1];
189
if (likely(mask[2])) *(float*)(((char*)ptr)+scale*ofs[2]) = v[2];
190
if (likely(mask[3])) *(float*)(((char*)ptr)+scale*ofs[3]) = v[3];
191
if (likely(mask[4])) *(float*)(((char*)ptr)+scale*ofs[4]) = v[4];
192
if (likely(mask[5])) *(float*)(((char*)ptr)+scale*ofs[5]) = v[5];
193
if (likely(mask[6])) *(float*)(((char*)ptr)+scale*ofs[6]) = v[6];
194
if (likely(mask[7])) *(float*)(((char*)ptr)+scale*ofs[7]) = v[7];
195
#endif
196
}
197
198
////////////////////////////////////////////////////////////////////////////////
199
/// Array Access
200
////////////////////////////////////////////////////////////////////////////////
201
202
__forceinline const float& operator [](size_t index) const { assert(index < 8); return f[index]; }
203
__forceinline float& operator [](size_t index) { assert(index < 8); return f[index]; }
204
};
205
206
207
////////////////////////////////////////////////////////////////////////////////
208
/// Unary Operators
209
////////////////////////////////////////////////////////////////////////////////
210
211
__forceinline vfloat8 asFloat(const vint8& a) { return _mm256_castsi256_ps(a); }
212
__forceinline vint8 asInt (const vfloat8& a) { return _mm256_castps_si256(a); }
213
214
__forceinline vint8 toInt (const vfloat8& a) { return vint8(a); }
215
__forceinline vfloat8 toFloat(const vint8& a) { return vfloat8(a); }
216
217
__forceinline vfloat8 operator +(const vfloat8& a) { return a; }
218
#if !defined(__aarch64__)
219
__forceinline vfloat8 operator -(const vfloat8& a) {
220
const __m256 mask = _mm256_castsi256_ps(_mm256_set1_epi32(0x80000000));
221
return _mm256_xor_ps(a, mask);
222
}
223
#else
224
__forceinline vfloat8 operator -(const vfloat8& a) {
225
__m256 res;
226
res.lo = vnegq_f32(a.v.lo);
227
res.hi = vnegq_f32(a.v.hi);
228
return res;
229
}
230
#endif
231
232
#if !defined(__aarch64__)
233
__forceinline vfloat8 abs(const vfloat8& a) {
234
const __m256 mask = _mm256_castsi256_ps(_mm256_set1_epi32(0x7fffffff));
235
return _mm256_and_ps(a, mask);
236
}
237
#else
238
__forceinline vfloat8 abs(const vfloat8& a) {
239
__m256 res;
240
res.lo = vabsq_f32(a.v.lo);
241
res.hi = vabsq_f32(a.v.hi);
242
return res;
243
}
244
#endif
245
246
#if !defined(__aarch64__)
247
__forceinline vfloat8 sign (const vfloat8& a) { return _mm256_blendv_ps(vfloat8(one), -vfloat8(one), _mm256_cmp_ps(a, vfloat8(zero), _CMP_NGE_UQ)); }
248
#else
249
__forceinline vfloat8 sign (const vfloat8& a) { return _mm256_blendv_ps(vfloat8(one), -vfloat8(one), _mm256_cmplt_ps(a, vfloat8(zero))); }
250
#endif
251
__forceinline vfloat8 signmsk(const vfloat8& a) { return _mm256_and_ps(a,_mm256_castsi256_ps(_mm256_set1_epi32(0x80000000))); }
252
253
254
static __forceinline vfloat8 rcp(const vfloat8& a)
255
{
256
#if defined(__aarch64__)
257
vfloat8 ret;
258
const float32x4_t one = vdupq_n_f32(1.0f);
259
ret.v.lo = vdivq_f32(one, a.v.lo);
260
ret.v.hi = vdivq_f32(one, a.v.hi);
261
return ret;
262
#endif
263
264
#if defined(__AVX512VL__)
265
const vfloat8 r = _mm256_rcp14_ps(a);
266
#else
267
const vfloat8 r = _mm256_rcp_ps(a);
268
#endif
269
270
#if defined(__AVX2__)
271
// First, compute 1 - a * r (which will be very close to 0)
272
const vfloat8 h_n = _mm256_fnmadd_ps(a, r, vfloat8(1.0f));
273
// Then compute r + r * h_n
274
return _mm256_fmadd_ps(r, h_n, r);
275
#else
276
return _mm256_add_ps(r,_mm256_mul_ps(r, _mm256_sub_ps(vfloat8(1.0f), _mm256_mul_ps(a, r)))); // computes r + r * (1 - a * r)
277
#endif
278
}
279
__forceinline vfloat8 sqr (const vfloat8& a) { return _mm256_mul_ps(a,a); }
280
__forceinline vfloat8 sqrt(const vfloat8& a) { return _mm256_sqrt_ps(a); }
281
282
static __forceinline vfloat8 rsqrt(const vfloat8& a)
283
{
284
#if defined(__AVX512VL__)
285
const vfloat8 r = _mm256_rsqrt14_ps(a);
286
#else
287
const vfloat8 r = _mm256_rsqrt_ps(a);
288
#endif
289
290
#if defined(__AVX2__)
291
return _mm256_fmadd_ps(_mm256_set1_ps(1.5f), r,
292
_mm256_mul_ps(_mm256_mul_ps(_mm256_mul_ps(a, _mm256_set1_ps(-0.5f)), r), _mm256_mul_ps(r, r)));
293
#else
294
return _mm256_add_ps(_mm256_mul_ps(_mm256_set1_ps(1.5f), r),
295
_mm256_mul_ps(_mm256_mul_ps(_mm256_mul_ps(a, _mm256_set1_ps(-0.5f)), r), _mm256_mul_ps(r, r)));
296
#endif
297
}
298
299
////////////////////////////////////////////////////////////////////////////////
300
/// Binary Operators
301
////////////////////////////////////////////////////////////////////////////////
302
303
__forceinline vfloat8 operator +(const vfloat8& a, const vfloat8& b) { return _mm256_add_ps(a, b); }
304
__forceinline vfloat8 operator +(const vfloat8& a, float b) { return a + vfloat8(b); }
305
__forceinline vfloat8 operator +(float a, const vfloat8& b) { return vfloat8(a) + b; }
306
307
__forceinline vfloat8 operator -(const vfloat8& a, const vfloat8& b) { return _mm256_sub_ps(a, b); }
308
__forceinline vfloat8 operator -(const vfloat8& a, float b) { return a - vfloat8(b); }
309
__forceinline vfloat8 operator -(float a, const vfloat8& b) { return vfloat8(a) - b; }
310
311
__forceinline vfloat8 operator *(const vfloat8& a, const vfloat8& b) { return _mm256_mul_ps(a, b); }
312
__forceinline vfloat8 operator *(const vfloat8& a, float b) { return a * vfloat8(b); }
313
__forceinline vfloat8 operator *(float a, const vfloat8& b) { return vfloat8(a) * b; }
314
315
__forceinline vfloat8 operator /(const vfloat8& a, const vfloat8& b) { return _mm256_div_ps(a, b); }
316
__forceinline vfloat8 operator /(const vfloat8& a, float b) { return a / vfloat8(b); }
317
__forceinline vfloat8 operator /(float a, const vfloat8& b) { return vfloat8(a) / b; }
318
319
__forceinline vfloat8 operator &(const vfloat8& a, const vfloat8& b) { return _mm256_and_ps(a,b); }
320
__forceinline vfloat8 operator |(const vfloat8& a, const vfloat8& b) { return _mm256_or_ps(a,b); }
321
__forceinline vfloat8 operator ^(const vfloat8& a, const vfloat8& b) { return _mm256_xor_ps(a,b); }
322
__forceinline vfloat8 operator ^(const vfloat8& a, const vint8& b) { return _mm256_xor_ps(a,_mm256_castsi256_ps(b)); }
323
324
__forceinline vfloat8 min(const vfloat8& a, const vfloat8& b) { return _mm256_min_ps(a, b); }
325
__forceinline vfloat8 min(const vfloat8& a, float b) { return _mm256_min_ps(a, vfloat8(b)); }
326
__forceinline vfloat8 min(float a, const vfloat8& b) { return _mm256_min_ps(vfloat8(a), b); }
327
328
__forceinline vfloat8 max(const vfloat8& a, const vfloat8& b) { return _mm256_max_ps(a, b); }
329
__forceinline vfloat8 max(const vfloat8& a, float b) { return _mm256_max_ps(a, vfloat8(b)); }
330
__forceinline vfloat8 max(float a, const vfloat8& b) { return _mm256_max_ps(vfloat8(a), b); }
331
332
/* need "static __forceinline for MSVC, otherwise we'll link the wrong version in debug mode */
333
#if defined(__AVX2__)
334
335
static __forceinline vfloat8 mini(const vfloat8& a, const vfloat8& b) {
336
const vint8 ai = _mm256_castps_si256(a);
337
const vint8 bi = _mm256_castps_si256(b);
338
const vint8 ci = _mm256_min_epi32(ai,bi);
339
return _mm256_castsi256_ps(ci);
340
}
341
342
static __forceinline vfloat8 maxi(const vfloat8& a, const vfloat8& b) {
343
const vint8 ai = _mm256_castps_si256(a);
344
const vint8 bi = _mm256_castps_si256(b);
345
const vint8 ci = _mm256_max_epi32(ai,bi);
346
return _mm256_castsi256_ps(ci);
347
}
348
349
static __forceinline vfloat8 minui(const vfloat8& a, const vfloat8& b) {
350
const vint8 ai = _mm256_castps_si256(a);
351
const vint8 bi = _mm256_castps_si256(b);
352
const vint8 ci = _mm256_min_epu32(ai,bi);
353
return _mm256_castsi256_ps(ci);
354
}
355
356
static __forceinline vfloat8 maxui(const vfloat8& a, const vfloat8& b) {
357
const vint8 ai = _mm256_castps_si256(a);
358
const vint8 bi = _mm256_castps_si256(b);
359
const vint8 ci = _mm256_max_epu32(ai,bi);
360
return _mm256_castsi256_ps(ci);
361
}
362
363
#else
364
365
static __forceinline vfloat8 mini(const vfloat8& a, const vfloat8& b) {
366
return asFloat(min(asInt(a),asInt(b)));
367
}
368
369
static __forceinline vfloat8 maxi(const vfloat8& a, const vfloat8& b) {
370
return asFloat(max(asInt(a),asInt(b)));
371
}
372
373
#endif
374
375
////////////////////////////////////////////////////////////////////////////////
376
/// Ternary Operators
377
////////////////////////////////////////////////////////////////////////////////
378
379
#if defined(__AVX2__)
380
static __forceinline vfloat8 madd (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return _mm256_fmadd_ps(a,b,c); }
381
static __forceinline vfloat8 msub (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return _mm256_fmsub_ps(a,b,c); }
382
static __forceinline vfloat8 nmadd (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return _mm256_fnmadd_ps(a,b,c); }
383
static __forceinline vfloat8 nmsub (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return _mm256_fnmsub_ps(a,b,c); }
384
#else
385
static __forceinline vfloat8 madd (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return a*b+c; }
386
static __forceinline vfloat8 msub (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return a*b-c; }
387
static __forceinline vfloat8 nmadd (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return -a*b+c;}
388
static __forceinline vfloat8 nmsub (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return -a*b-c; }
389
#endif
390
391
////////////////////////////////////////////////////////////////////////////////
392
/// Assignment Operators
393
////////////////////////////////////////////////////////////////////////////////
394
395
__forceinline vfloat8& operator +=(vfloat8& a, const vfloat8& b) { return a = a + b; }
396
__forceinline vfloat8& operator +=(vfloat8& a, float b) { return a = a + b; }
397
398
__forceinline vfloat8& operator -=(vfloat8& a, const vfloat8& b) { return a = a - b; }
399
__forceinline vfloat8& operator -=(vfloat8& a, float b) { return a = a - b; }
400
401
__forceinline vfloat8& operator *=(vfloat8& a, const vfloat8& b) { return a = a * b; }
402
__forceinline vfloat8& operator *=(vfloat8& a, float b) { return a = a * b; }
403
404
__forceinline vfloat8& operator /=(vfloat8& a, const vfloat8& b) { return a = a / b; }
405
__forceinline vfloat8& operator /=(vfloat8& a, float b) { return a = a / b; }
406
407
////////////////////////////////////////////////////////////////////////////////
408
/// Comparison Operators + Select
409
////////////////////////////////////////////////////////////////////////////////
410
411
#if defined(__AVX512VL__)
412
static __forceinline vboolf8 operator ==(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps_mask(a, b, _MM_CMPINT_EQ); }
413
static __forceinline vboolf8 operator !=(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps_mask(a, b, _MM_CMPINT_NE); }
414
static __forceinline vboolf8 operator < (const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps_mask(a, b, _MM_CMPINT_LT); }
415
static __forceinline vboolf8 operator >=(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps_mask(a, b, _MM_CMPINT_GE); }
416
static __forceinline vboolf8 operator > (const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps_mask(a, b, _MM_CMPINT_GT); }
417
static __forceinline vboolf8 operator <=(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps_mask(a, b, _MM_CMPINT_LE); }
418
419
static __forceinline vfloat8 select(const vboolf8& m, const vfloat8& t, const vfloat8& f) {
420
return _mm256_mask_blend_ps(m, f, t);
421
}
422
#elif !defined(__aarch64__)
423
static __forceinline vboolf8 operator ==(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps(a, b, _CMP_EQ_OQ); }
424
static __forceinline vboolf8 operator !=(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps(a, b, _CMP_NEQ_UQ); }
425
static __forceinline vboolf8 operator < (const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps(a, b, _CMP_LT_OS); }
426
static __forceinline vboolf8 operator >=(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps(a, b, _CMP_NLT_US); }
427
static __forceinline vboolf8 operator > (const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps(a, b, _CMP_NLE_US); }
428
static __forceinline vboolf8 operator <=(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps(a, b, _CMP_LE_OS); }
429
430
static __forceinline vfloat8 select(const vboolf8& m, const vfloat8& t, const vfloat8& f) {
431
return _mm256_blendv_ps(f, t, m);
432
}
433
#else
434
static __forceinline vboolf8 operator ==(const vfloat8& a, const vfloat8& b) { return _mm256_cmpeq_ps(a, b); }
435
static __forceinline vboolf8 operator !=(const vfloat8& a, const vfloat8& b) { return _mm256_cmpneq_ps(a, b); }
436
static __forceinline vboolf8 operator < (const vfloat8& a, const vfloat8& b) { return _mm256_cmplt_ps(a, b); }
437
static __forceinline vboolf8 operator >=(const vfloat8& a, const vfloat8& b) { return _mm256_cmpge_ps(a, b); }
438
static __forceinline vboolf8 operator > (const vfloat8& a, const vfloat8& b) { return _mm256_cmpgt_ps(a, b); }
439
static __forceinline vboolf8 operator <=(const vfloat8& a, const vfloat8& b) { return _mm256_cmple_ps(a, b); }
440
441
static __forceinline vfloat8 select(const vboolf8& m, const vfloat8& t, const vfloat8& f) {
442
return _mm256_blendv_ps(f, t, m);
443
}
444
445
#endif
446
447
template<int mask>
448
__forceinline vfloat8 select(const vfloat8& t, const vfloat8& f) {
449
return _mm256_blend_ps(f, t, mask);
450
}
451
452
__forceinline vboolf8 operator ==(const vfloat8& a, const float& b) { return a == vfloat8(b); }
453
__forceinline vboolf8 operator ==(const float& a, const vfloat8& b) { return vfloat8(a) == b; }
454
455
__forceinline vboolf8 operator !=(const vfloat8& a, const float& b) { return a != vfloat8(b); }
456
__forceinline vboolf8 operator !=(const float& a, const vfloat8& b) { return vfloat8(a) != b; }
457
458
__forceinline vboolf8 operator < (const vfloat8& a, const float& b) { return a < vfloat8(b); }
459
__forceinline vboolf8 operator < (const float& a, const vfloat8& b) { return vfloat8(a) < b; }
460
461
__forceinline vboolf8 operator >=(const vfloat8& a, const float& b) { return a >= vfloat8(b); }
462
__forceinline vboolf8 operator >=(const float& a, const vfloat8& b) { return vfloat8(a) >= b; }
463
464
__forceinline vboolf8 operator > (const vfloat8& a, const float& b) { return a > vfloat8(b); }
465
__forceinline vboolf8 operator > (const float& a, const vfloat8& b) { return vfloat8(a) > b; }
466
467
__forceinline vboolf8 operator <=(const vfloat8& a, const float& b) { return a <= vfloat8(b); }
468
__forceinline vboolf8 operator <=(const float& a, const vfloat8& b) { return vfloat8(a) <= b; }
469
470
__forceinline vboolf8 eq(const vfloat8& a, const vfloat8& b) { return a == b; }
471
__forceinline vboolf8 ne(const vfloat8& a, const vfloat8& b) { return a != b; }
472
__forceinline vboolf8 lt(const vfloat8& a, const vfloat8& b) { return a < b; }
473
__forceinline vboolf8 ge(const vfloat8& a, const vfloat8& b) { return a >= b; }
474
__forceinline vboolf8 gt(const vfloat8& a, const vfloat8& b) { return a > b; }
475
__forceinline vboolf8 le(const vfloat8& a, const vfloat8& b) { return a <= b; }
476
477
#if defined(__AVX512VL__)
478
static __forceinline vboolf8 eq(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return _mm256_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_EQ); }
479
static __forceinline vboolf8 ne(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return _mm256_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_NE); }
480
static __forceinline vboolf8 lt(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return _mm256_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_LT); }
481
static __forceinline vboolf8 ge(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return _mm256_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_GE); }
482
static __forceinline vboolf8 gt(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return _mm256_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_GT); }
483
static __forceinline vboolf8 le(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return _mm256_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_LE); }
484
#else
485
static __forceinline vboolf8 eq(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return mask & (a == b); }
486
static __forceinline vboolf8 ne(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return mask & (a != b); }
487
static __forceinline vboolf8 lt(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return mask & (a < b); }
488
static __forceinline vboolf8 ge(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return mask & (a >= b); }
489
static __forceinline vboolf8 gt(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return mask & (a > b); }
490
static __forceinline vboolf8 le(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return mask & (a <= b); }
491
#endif
492
493
__forceinline vfloat8 lerp(const vfloat8& a, const vfloat8& b, const vfloat8& t) {
494
return madd(t,b-a,a);
495
}
496
497
__forceinline bool isvalid (const vfloat8& v) {
498
return all((v > vfloat8(-FLT_LARGE)) & (v < vfloat8(+FLT_LARGE)));
499
}
500
501
__forceinline bool is_finite (const vfloat8& a) {
502
return all((a >= vfloat8(-FLT_MAX)) & (a <= vfloat8(+FLT_MAX)));
503
}
504
505
__forceinline bool is_finite (const vboolf8& valid, const vfloat8& a) {
506
return all(valid, (a >= vfloat8(-FLT_MAX)) & (a <= vfloat8(+FLT_MAX)));
507
}
508
509
////////////////////////////////////////////////////////////////////////////////
510
/// Rounding Functions
511
////////////////////////////////////////////////////////////////////////////////
512
513
#if !defined(__aarch64__)
514
__forceinline vfloat8 floor(const vfloat8& a) { return _mm256_round_ps(a, _MM_FROUND_TO_NEG_INF ); }
515
__forceinline vfloat8 ceil (const vfloat8& a) { return _mm256_round_ps(a, _MM_FROUND_TO_POS_INF ); }
516
__forceinline vfloat8 trunc(const vfloat8& a) { return _mm256_round_ps(a, _MM_FROUND_TO_ZERO ); }
517
__forceinline vfloat8 round(const vfloat8& a) { return _mm256_round_ps(a, _MM_FROUND_TO_NEAREST_INT); }
518
#else
519
__forceinline vfloat8 floor(const vfloat8& a) { return _mm256_floor_ps(a); }
520
__forceinline vfloat8 ceil (const vfloat8& a) { return _mm256_ceil_ps(a); }
521
#endif
522
523
524
__forceinline vfloat8 frac (const vfloat8& a) { return a-floor(a); }
525
526
////////////////////////////////////////////////////////////////////////////////
527
/// Movement/Shifting/Shuffling Functions
528
////////////////////////////////////////////////////////////////////////////////
529
530
__forceinline vfloat8 unpacklo(const vfloat8& a, const vfloat8& b) { return _mm256_unpacklo_ps(a, b); }
531
__forceinline vfloat8 unpackhi(const vfloat8& a, const vfloat8& b) { return _mm256_unpackhi_ps(a, b); }
532
533
template<int i>
534
__forceinline vfloat8 shuffle(const vfloat8& v) {
535
return _mm256_permute_ps(v, _MM_SHUFFLE(i, i, i, i));
536
}
537
538
template<int i0, int i1>
539
__forceinline vfloat8 shuffle4(const vfloat8& v) {
540
return _mm256_permute2f128_ps(v, v, (i1 << 4) | (i0 << 0));
541
}
542
543
template<int i0, int i1>
544
__forceinline vfloat8 shuffle4(const vfloat8& a, const vfloat8& b) {
545
return _mm256_permute2f128_ps(a, b, (i1 << 4) | (i0 << 0));
546
}
547
548
template<int i0, int i1, int i2, int i3>
549
__forceinline vfloat8 shuffle(const vfloat8& v) {
550
return _mm256_permute_ps(v, _MM_SHUFFLE(i3, i2, i1, i0));
551
}
552
553
template<int i0, int i1, int i2, int i3>
554
__forceinline vfloat8 shuffle(const vfloat8& a, const vfloat8& b) {
555
return _mm256_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
556
}
557
558
#if !defined(__aarch64__)
559
template<> __forceinline vfloat8 shuffle<0, 0, 2, 2>(const vfloat8& v) { return _mm256_moveldup_ps(v); }
560
template<> __forceinline vfloat8 shuffle<1, 1, 3, 3>(const vfloat8& v) { return _mm256_movehdup_ps(v); }
561
template<> __forceinline vfloat8 shuffle<0, 1, 0, 1>(const vfloat8& v) { return _mm256_castpd_ps(_mm256_movedup_pd(_mm256_castps_pd(v))); }
562
#endif
563
564
__forceinline vfloat8 broadcast(const float* ptr) { return _mm256_broadcast_ss(ptr); }
565
template<size_t i> __forceinline vfloat8 insert4(const vfloat8& a, const vfloat4& b) { return _mm256_insertf128_ps(a, b, i); }
566
template<size_t i> __forceinline vfloat4 extract4 (const vfloat8& a) { return _mm256_extractf128_ps(a, i); }
567
template<> __forceinline vfloat4 extract4<0>(const vfloat8& a) { return _mm256_castps256_ps128(a); }
568
569
__forceinline float toScalar(const vfloat8& v) { return _mm_cvtss_f32(_mm256_castps256_ps128(v)); }
570
571
#if defined (__AVX2__) && !defined(__aarch64__)
572
static __forceinline vfloat8 permute(const vfloat8& a, const __m256i& index) {
573
return _mm256_permutevar8x32_ps(a, index);
574
}
575
#endif
576
577
#if defined(__AVX512VL__)
578
template<int i>
579
static __forceinline vfloat8 align_shift_right(const vfloat8& a, const vfloat8& b) {
580
return _mm256_castsi256_ps(_mm256_alignr_epi32(_mm256_castps_si256(a), _mm256_castps_si256(b), i));
581
}
582
#endif
583
584
#if defined (__AVX_I__)
585
template<const int mode>
586
static __forceinline vint4 convert_to_hf16(const vfloat8& a) {
587
return _mm256_cvtps_ph(a, mode);
588
}
589
590
static __forceinline vfloat8 convert_from_hf16(const vint4& a) {
591
return _mm256_cvtph_ps(a);
592
}
593
#endif
594
595
#if defined(__AVX512VL__)
596
static __forceinline vfloat8 shift_right_1(const vfloat8& x) {
597
return align_shift_right<1>(zero,x);
598
}
599
#else
600
static __forceinline vfloat8 shift_right_1(const vfloat8& x) {
601
const vfloat8 t0 = shuffle<1,2,3,0>(x);
602
const vfloat8 t1 = shuffle4<1,0>(t0);
603
return _mm256_blend_ps(t0,t1,0x88);
604
}
605
#endif
606
607
__forceinline vint8 floori(const vfloat8& a) {
608
return vint8(floor(a));
609
}
610
611
////////////////////////////////////////////////////////////////////////////////
612
/// Transpose
613
////////////////////////////////////////////////////////////////////////////////
614
615
__forceinline void transpose(const vfloat8& r0, const vfloat8& r1, const vfloat8& r2, const vfloat8& r3, vfloat8& c0, vfloat8& c1, vfloat8& c2, vfloat8& c3)
616
{
617
vfloat8 l02 = unpacklo(r0,r2);
618
vfloat8 h02 = unpackhi(r0,r2);
619
vfloat8 l13 = unpacklo(r1,r3);
620
vfloat8 h13 = unpackhi(r1,r3);
621
c0 = unpacklo(l02,l13);
622
c1 = unpackhi(l02,l13);
623
c2 = unpacklo(h02,h13);
624
c3 = unpackhi(h02,h13);
625
}
626
627
__forceinline void transpose(const vfloat8& r0, const vfloat8& r1, const vfloat8& r2, const vfloat8& r3, vfloat8& c0, vfloat8& c1, vfloat8& c2)
628
{
629
vfloat8 l02 = unpacklo(r0,r2);
630
vfloat8 h02 = unpackhi(r0,r2);
631
vfloat8 l13 = unpacklo(r1,r3);
632
vfloat8 h13 = unpackhi(r1,r3);
633
c0 = unpacklo(l02,l13);
634
c1 = unpackhi(l02,l13);
635
c2 = unpacklo(h02,h13);
636
}
637
638
__forceinline void transpose(const vfloat8& r0, const vfloat8& r1, const vfloat8& r2, const vfloat8& r3, const vfloat8& r4, const vfloat8& r5, const vfloat8& r6, const vfloat8& r7,
639
vfloat8& c0, vfloat8& c1, vfloat8& c2, vfloat8& c3, vfloat8& c4, vfloat8& c5, vfloat8& c6, vfloat8& c7)
640
{
641
vfloat8 h0,h1,h2,h3; transpose(r0,r1,r2,r3,h0,h1,h2,h3);
642
vfloat8 h4,h5,h6,h7; transpose(r4,r5,r6,r7,h4,h5,h6,h7);
643
c0 = shuffle4<0,2>(h0,h4);
644
c1 = shuffle4<0,2>(h1,h5);
645
c2 = shuffle4<0,2>(h2,h6);
646
c3 = shuffle4<0,2>(h3,h7);
647
c4 = shuffle4<1,3>(h0,h4);
648
c5 = shuffle4<1,3>(h1,h5);
649
c6 = shuffle4<1,3>(h2,h6);
650
c7 = shuffle4<1,3>(h3,h7);
651
}
652
653
__forceinline void transpose(const vfloat4& r0, const vfloat4& r1, const vfloat4& r2, const vfloat4& r3, const vfloat4& r4, const vfloat4& r5, const vfloat4& r6, const vfloat4& r7,
654
vfloat8& c0, vfloat8& c1, vfloat8& c2, vfloat8& c3)
655
{
656
transpose(vfloat8(r0,r4), vfloat8(r1,r5), vfloat8(r2,r6), vfloat8(r3,r7), c0, c1, c2, c3);
657
}
658
659
__forceinline void transpose(const vfloat4& r0, const vfloat4& r1, const vfloat4& r2, const vfloat4& r3, const vfloat4& r4, const vfloat4& r5, const vfloat4& r6, const vfloat4& r7,
660
vfloat8& c0, vfloat8& c1, vfloat8& c2)
661
{
662
transpose(vfloat8(r0,r4), vfloat8(r1,r5), vfloat8(r2,r6), vfloat8(r3,r7), c0, c1, c2);
663
}
664
665
////////////////////////////////////////////////////////////////////////////////
666
/// Reductions
667
////////////////////////////////////////////////////////////////////////////////
668
#if !defined(__aarch64__)
669
__forceinline vfloat8 vreduce_min2(const vfloat8& v) { return min(v,shuffle<1,0,3,2>(v)); }
670
__forceinline vfloat8 vreduce_min4(const vfloat8& v) { vfloat8 v1 = vreduce_min2(v); return min(v1,shuffle<2,3,0,1>(v1)); }
671
__forceinline vfloat8 vreduce_min (const vfloat8& v) { vfloat8 v1 = vreduce_min4(v); return min(v1,shuffle4<1,0>(v1)); }
672
673
__forceinline vfloat8 vreduce_max2(const vfloat8& v) { return max(v,shuffle<1,0,3,2>(v)); }
674
__forceinline vfloat8 vreduce_max4(const vfloat8& v) { vfloat8 v1 = vreduce_max2(v); return max(v1,shuffle<2,3,0,1>(v1)); }
675
__forceinline vfloat8 vreduce_max (const vfloat8& v) { vfloat8 v1 = vreduce_max4(v); return max(v1,shuffle4<1,0>(v1)); }
676
677
__forceinline vfloat8 vreduce_add2(const vfloat8& v) { return v + shuffle<1,0,3,2>(v); }
678
__forceinline vfloat8 vreduce_add4(const vfloat8& v) { vfloat8 v1 = vreduce_add2(v); return v1 + shuffle<2,3,0,1>(v1); }
679
__forceinline vfloat8 vreduce_add (const vfloat8& v) { vfloat8 v1 = vreduce_add4(v); return v1 + shuffle4<1,0>(v1); }
680
681
__forceinline float reduce_min(const vfloat8& v) { return toScalar(vreduce_min(v)); }
682
__forceinline float reduce_max(const vfloat8& v) { return toScalar(vreduce_max(v)); }
683
__forceinline float reduce_add(const vfloat8& v) { return toScalar(vreduce_add(v)); }
684
#else
685
__forceinline float reduce_min(const vfloat8& v) { return vminvq_f32(_mm_min_ps(v.v.lo,v.v.hi)); }
686
__forceinline float reduce_max(const vfloat8& v) { return vmaxvq_f32(_mm_max_ps(v.v.lo,v.v.hi)); }
687
__forceinline vfloat8 vreduce_min(const vfloat8& v) { return vfloat8(reduce_min(v)); }
688
__forceinline vfloat8 vreduce_max(const vfloat8& v) { return vfloat8(reduce_max(v)); }
689
__forceinline float reduce_add(const vfloat8& v) { return vaddvq_f32(_mm_add_ps(v.v.lo,v.v.hi)); }
690
691
#endif
692
__forceinline size_t select_min(const vboolf8& valid, const vfloat8& v)
693
{
694
const vfloat8 a = select(valid,v,vfloat8(pos_inf));
695
const vbool8 valid_min = valid & (a == vreduce_min(a));
696
return bsf(movemask(any(valid_min) ? valid_min : valid));
697
}
698
699
__forceinline size_t select_max(const vboolf8& valid, const vfloat8& v)
700
{
701
const vfloat8 a = select(valid,v,vfloat8(neg_inf));
702
const vbool8 valid_max = valid & (a == vreduce_max(a));
703
return bsf(movemask(any(valid_max) ? valid_max : valid));
704
}
705
706
707
////////////////////////////////////////////////////////////////////////////////
708
/// Euclidean Space Operators (pairs of Vec3fa's)
709
////////////////////////////////////////////////////////////////////////////////
710
711
//__forceinline vfloat8 dot(const vfloat8& a, const vfloat8& b) {
712
// return vreduce_add4(a*b);
713
//}
714
715
__forceinline vfloat8 dot(const vfloat8& a, const vfloat8& b) {
716
return _mm256_dp_ps(a,b,0x7F);
717
}
718
719
__forceinline vfloat8 cross(const vfloat8& a, const vfloat8& b)
720
{
721
const vfloat8 a0 = a;
722
const vfloat8 b0 = shuffle<1,2,0,3>(b);
723
const vfloat8 a1 = shuffle<1,2,0,3>(a);
724
const vfloat8 b1 = b;
725
return shuffle<1,2,0,3>(msub(a0,b0,a1*b1));
726
}
727
728
//__forceinline float sqr_length (const vfloat<8>& a) { return dot(a,a); }
729
//__forceinline float rcp_length (const vfloat<8>& a) { return rsqrt(dot(a,a)); }
730
//__forceinline float rcp_length2(const vfloat<8>& a) { return rcp(dot(a,a)); }
731
//__forceinline float length (const vfloat<8>& a) { return sqrt(dot(a,a)); }
732
__forceinline vfloat<8> normalize(const vfloat<8>& a) { return a*rsqrt(dot(a,a)); }
733
//__forceinline float distance(const vfloat<8>& a, const vfloat<8>& b) { return length(a-b); }
734
//__forceinline float halfArea(const vfloat<8>& d) { return madd(d.x,(d.y+d.z),d.y*d.z); }
735
//__forceinline float area (const vfloat<8>& d) { return 2.0f*halfArea(d); }
736
//__forceinline vfloat<8> reflect(const vfloat<8>& V, const vfloat<8>& N) { return 2.0f*dot(V,N)*N-V; }
737
738
//__forceinline vfloat<8> normalize_safe(const vfloat<8>& a) {
739
// const float d = dot(a,a); if (unlikely(d == 0.0f)) return a; else return a*rsqrt(d);
740
//}
741
742
////////////////////////////////////////////////////////////////////////////////
743
/// In Register Sorting
744
////////////////////////////////////////////////////////////////////////////////
745
746
__forceinline vfloat8 sort_ascending(const vfloat8& v)
747
{
748
const vfloat8 a0 = v;
749
const vfloat8 b0 = shuffle<1,0,3,2>(a0);
750
const vfloat8 c0 = min(a0,b0);
751
const vfloat8 d0 = max(a0,b0);
752
const vfloat8 a1 = select<0x99 /* 0b10011001 */>(c0,d0);
753
const vfloat8 b1 = shuffle<2,3,0,1>(a1);
754
const vfloat8 c1 = min(a1,b1);
755
const vfloat8 d1 = max(a1,b1);
756
const vfloat8 a2 = select<0xc3 /* 0b11000011 */>(c1,d1);
757
const vfloat8 b2 = shuffle<1,0,3,2>(a2);
758
const vfloat8 c2 = min(a2,b2);
759
const vfloat8 d2 = max(a2,b2);
760
const vfloat8 a3 = select<0xa5 /* 0b10100101 */>(c2,d2);
761
const vfloat8 b3 = shuffle4<1,0>(a3);
762
const vfloat8 c3 = min(a3,b3);
763
const vfloat8 d3 = max(a3,b3);
764
const vfloat8 a4 = select<0xf /* 0b00001111 */>(c3,d3);
765
const vfloat8 b4 = shuffle<2,3,0,1>(a4);
766
const vfloat8 c4 = min(a4,b4);
767
const vfloat8 d4 = max(a4,b4);
768
const vfloat8 a5 = select<0x33 /* 0b00110011 */>(c4,d4);
769
const vfloat8 b5 = shuffle<1,0,3,2>(a5);
770
const vfloat8 c5 = min(a5,b5);
771
const vfloat8 d5 = max(a5,b5);
772
const vfloat8 a6 = select<0x55 /* 0b01010101 */>(c5,d5);
773
return a6;
774
}
775
776
__forceinline vfloat8 sort_descending(const vfloat8& v)
777
{
778
const vfloat8 a0 = v;
779
const vfloat8 b0 = shuffle<1,0,3,2>(a0);
780
const vfloat8 c0 = max(a0,b0);
781
const vfloat8 d0 = min(a0,b0);
782
const vfloat8 a1 = select<0x99 /* 0b10011001 */>(c0,d0);
783
const vfloat8 b1 = shuffle<2,3,0,1>(a1);
784
const vfloat8 c1 = max(a1,b1);
785
const vfloat8 d1 = min(a1,b1);
786
const vfloat8 a2 = select<0xc3 /* 0b11000011 */>(c1,d1);
787
const vfloat8 b2 = shuffle<1,0,3,2>(a2);
788
const vfloat8 c2 = max(a2,b2);
789
const vfloat8 d2 = min(a2,b2);
790
const vfloat8 a3 = select<0xa5 /* 0b10100101 */>(c2,d2);
791
const vfloat8 b3 = shuffle4<1,0>(a3);
792
const vfloat8 c3 = max(a3,b3);
793
const vfloat8 d3 = min(a3,b3);
794
const vfloat8 a4 = select<0xf /* 0b00001111 */>(c3,d3);
795
const vfloat8 b4 = shuffle<2,3,0,1>(a4);
796
const vfloat8 c4 = max(a4,b4);
797
const vfloat8 d4 = min(a4,b4);
798
const vfloat8 a5 = select<0x33 /* 0b00110011 */>(c4,d4);
799
const vfloat8 b5 = shuffle<1,0,3,2>(a5);
800
const vfloat8 c5 = max(a5,b5);
801
const vfloat8 d5 = min(a5,b5);
802
const vfloat8 a6 = select<0x55 /* 0b01010101 */>(c5,d5);
803
return a6;
804
}
805
806
////////////////////////////////////////////////////////////////////////////////
807
/// Output Operators
808
////////////////////////////////////////////////////////////////////////////////
809
810
__forceinline embree_ostream operator <<(embree_ostream cout, const vfloat8& a) {
811
return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", " << a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">";
812
}
813
}
814
815
#undef vboolf
816
#undef vboold
817
#undef vint
818
#undef vuint
819
#undef vllong
820
#undef vfloat
821
#undef vdouble
822
823