#pragma once
#define vboolf …
#define vboold …
#define vint …
#define vuint …
#define vllong …
#define vfloat …
#define vdouble …
namespace embree
{
template<>
struct vfloat<4>
{ … };
template<> struct mem<vfloat4>
{ … };
__forceinline vfloat4 asFloat(const vint4& a) { … }
__forceinline vint4 asInt (const vfloat4& a) { … }
__forceinline vuint4 asUInt (const vfloat4& a) { … }
__forceinline vint4 toInt (const vfloat4& a) { … }
__forceinline vfloat4 toFloat(const vint4& a) { … }
__forceinline vfloat4 operator +(const vfloat4& a) { … }
#if defined(__aarch64__)
__forceinline vfloat4 operator -(const vfloat4& a) {
return vnegq_f32(a);
}
#else
__forceinline vfloat4 operator -(const vfloat4& a) { … }
#endif
#if defined(__aarch64__)
__forceinline vfloat4 abs(const vfloat4& a) { return _mm_abs_ps(a); }
#else
__forceinline vfloat4 abs(const vfloat4& a) { … }
#endif
#if defined(__AVX512VL__)
__forceinline vfloat4 sign(const vfloat4& a) { return _mm_mask_blend_ps(_mm_cmp_ps_mask(a, vfloat4(zero), _CMP_LT_OQ), vfloat4(one), -vfloat4(one)); }
#else
__forceinline vfloat4 sign(const vfloat4& a) { … }
#endif
__forceinline vfloat4 signmsk(const vfloat4& a) { … }
__forceinline vfloat4 rcp(const vfloat4& a)
{ … }
__forceinline vfloat4 sqr (const vfloat4& a) { … }
__forceinline vfloat4 sqrt(const vfloat4& a) { … }
__forceinline vfloat4 rsqrt(const vfloat4& a)
{ … }
__forceinline vboolf4 isnan(const vfloat4& a) { … }
__forceinline vfloat4 operator +(const vfloat4& a, const vfloat4& b) { … }
__forceinline vfloat4 operator +(const vfloat4& a, float b) { … }
__forceinline vfloat4 operator +(float a, const vfloat4& b) { … }
__forceinline vfloat4 operator -(const vfloat4& a, const vfloat4& b) { … }
__forceinline vfloat4 operator -(const vfloat4& a, float b) { … }
__forceinline vfloat4 operator -(float a, const vfloat4& b) { … }
__forceinline vfloat4 operator *(const vfloat4& a, const vfloat4& b) { … }
__forceinline vfloat4 operator *(const vfloat4& a, float b) { … }
__forceinline vfloat4 operator *(float a, const vfloat4& b) { … }
__forceinline vfloat4 operator /(const vfloat4& a, const vfloat4& b) { … }
__forceinline vfloat4 operator /(const vfloat4& a, float b) { … }
__forceinline vfloat4 operator /(float a, const vfloat4& b) { … }
__forceinline vfloat4 operator &(const vfloat4& a, const vfloat4& b) { … }
__forceinline vfloat4 operator |(const vfloat4& a, const vfloat4& b) { … }
__forceinline vfloat4 operator ^(const vfloat4& a, const vfloat4& b) { … }
__forceinline vfloat4 operator ^(const vfloat4& a, const vint4& b) { … }
__forceinline vfloat4 min(const vfloat4& a, const vfloat4& b) { … }
__forceinline vfloat4 min(const vfloat4& a, float b) { … }
__forceinline vfloat4 min(float a, const vfloat4& b) { … }
__forceinline vfloat4 max(const vfloat4& a, const vfloat4& b) { … }
__forceinline vfloat4 max(const vfloat4& a, float b) { … }
__forceinline vfloat4 max(float a, const vfloat4& b) { … }
#if defined(__SSE4_1__) || defined(__aarch64__)
__forceinline vfloat4 mini(const vfloat4& a, const vfloat4& b) {
const vint4 ai = _mm_castps_si128(a);
const vint4 bi = _mm_castps_si128(b);
const vint4 ci = _mm_min_epi32(ai,bi);
return _mm_castsi128_ps(ci);
}
__forceinline vfloat4 maxi(const vfloat4& a, const vfloat4& b) {
const vint4 ai = _mm_castps_si128(a);
const vint4 bi = _mm_castps_si128(b);
const vint4 ci = _mm_max_epi32(ai,bi);
return _mm_castsi128_ps(ci);
}
__forceinline vfloat4 minui(const vfloat4& a, const vfloat4& b) {
const vint4 ai = _mm_castps_si128(a);
const vint4 bi = _mm_castps_si128(b);
const vint4 ci = _mm_min_epu32(ai,bi);
return _mm_castsi128_ps(ci);
}
__forceinline vfloat4 maxui(const vfloat4& a, const vfloat4& b) {
const vint4 ai = _mm_castps_si128(a);
const vint4 bi = _mm_castps_si128(b);
const vint4 ci = _mm_max_epu32(ai,bi);
return _mm_castsi128_ps(ci);
}
#else
__forceinline vfloat4 mini(const vfloat4& a, const vfloat4& b) { … }
__forceinline vfloat4 maxi(const vfloat4& a, const vfloat4& b) { … }
#endif
#if defined(__AVX2__) || defined(__ARM_NEON)
__forceinline vfloat4 madd (const vfloat4& a, const vfloat4& b, const vfloat4& c) { return _mm_fmadd_ps(a,b,c); }
__forceinline vfloat4 msub (const vfloat4& a, const vfloat4& b, const vfloat4& c) { return _mm_fmsub_ps(a,b,c); }
__forceinline vfloat4 nmadd(const vfloat4& a, const vfloat4& b, const vfloat4& c) { return _mm_fnmadd_ps(a,b,c); }
__forceinline vfloat4 nmsub(const vfloat4& a, const vfloat4& b, const vfloat4& c) { return _mm_fnmsub_ps(a,b,c); }
#else
__forceinline vfloat4 madd (const vfloat4& a, const vfloat4& b, const vfloat4& c) { … }
__forceinline vfloat4 nmadd(const vfloat4& a, const vfloat4& b, const vfloat4& c) { … }
__forceinline vfloat4 nmsub(const vfloat4& a, const vfloat4& b, const vfloat4& c) { … }
__forceinline vfloat4 msub (const vfloat4& a, const vfloat4& b, const vfloat4& c) { … }
#endif
__forceinline vfloat4& operator +=(vfloat4& a, const vfloat4& b) { … }
__forceinline vfloat4& operator +=(vfloat4& a, float b) { … }
__forceinline vfloat4& operator -=(vfloat4& a, const vfloat4& b) { … }
__forceinline vfloat4& operator -=(vfloat4& a, float b) { … }
__forceinline vfloat4& operator *=(vfloat4& a, const vfloat4& b) { … }
__forceinline vfloat4& operator *=(vfloat4& a, float b) { … }
__forceinline vfloat4& operator /=(vfloat4& a, const vfloat4& b) { … }
__forceinline vfloat4& operator /=(vfloat4& a, float b) { … }
#if defined(__AVX512VL__)
__forceinline vboolf4 operator ==(const vfloat4& a, const vfloat4& b) { return _mm_cmp_ps_mask(a, b, _MM_CMPINT_EQ); }
__forceinline vboolf4 operator !=(const vfloat4& a, const vfloat4& b) { return _mm_cmp_ps_mask(a, b, _MM_CMPINT_NE); }
__forceinline vboolf4 operator < (const vfloat4& a, const vfloat4& b) { return _mm_cmp_ps_mask(a, b, _MM_CMPINT_LT); }
__forceinline vboolf4 operator >=(const vfloat4& a, const vfloat4& b) { return _mm_cmp_ps_mask(a, b, _MM_CMPINT_GE); }
__forceinline vboolf4 operator > (const vfloat4& a, const vfloat4& b) { return _mm_cmp_ps_mask(a, b, _MM_CMPINT_GT); }
__forceinline vboolf4 operator <=(const vfloat4& a, const vfloat4& b) { return _mm_cmp_ps_mask(a, b, _MM_CMPINT_LE); }
#else
__forceinline vboolf4 operator ==(const vfloat4& a, const vfloat4& b) { … }
__forceinline vboolf4 operator !=(const vfloat4& a, const vfloat4& b) { … }
__forceinline vboolf4 operator < (const vfloat4& a, const vfloat4& b) { … }
#if defined(__aarch64__)
__forceinline vboolf4 operator >=(const vfloat4& a, const vfloat4& b) { return _mm_cmpge_ps (a, b); }
__forceinline vboolf4 operator > (const vfloat4& a, const vfloat4& b) { return _mm_cmpgt_ps (a, b); }
#else
__forceinline vboolf4 operator >=(const vfloat4& a, const vfloat4& b) { … }
__forceinline vboolf4 operator > (const vfloat4& a, const vfloat4& b) { … }
#endif
__forceinline vboolf4 operator <=(const vfloat4& a, const vfloat4& b) { … }
#endif
__forceinline vboolf4 operator ==(const vfloat4& a, float b) { … }
__forceinline vboolf4 operator ==(float a, const vfloat4& b) { … }
__forceinline vboolf4 operator !=(const vfloat4& a, float b) { … }
__forceinline vboolf4 operator !=(float a, const vfloat4& b) { … }
__forceinline vboolf4 operator < (const vfloat4& a, float b) { … }
__forceinline vboolf4 operator < (float a, const vfloat4& b) { … }
__forceinline vboolf4 operator >=(const vfloat4& a, float b) { … }
__forceinline vboolf4 operator >=(float a, const vfloat4& b) { … }
__forceinline vboolf4 operator > (const vfloat4& a, float b) { … }
__forceinline vboolf4 operator > (float a, const vfloat4& b) { … }
__forceinline vboolf4 operator <=(const vfloat4& a, float b) { … }
__forceinline vboolf4 operator <=(float a, const vfloat4& b) { … }
__forceinline vboolf4 eq(const vfloat4& a, const vfloat4& b) { … }
__forceinline vboolf4 ne(const vfloat4& a, const vfloat4& b) { … }
__forceinline vboolf4 lt(const vfloat4& a, const vfloat4& b) { … }
__forceinline vboolf4 ge(const vfloat4& a, const vfloat4& b) { … }
__forceinline vboolf4 gt(const vfloat4& a, const vfloat4& b) { … }
__forceinline vboolf4 le(const vfloat4& a, const vfloat4& b) { … }
#if defined(__AVX512VL__)
__forceinline vboolf4 eq(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { return _mm_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_EQ); }
__forceinline vboolf4 ne(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { return _mm_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_NE); }
__forceinline vboolf4 lt(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { return _mm_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_LT); }
__forceinline vboolf4 ge(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { return _mm_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_GE); }
__forceinline vboolf4 gt(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { return _mm_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_GT); }
__forceinline vboolf4 le(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { return _mm_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_LE); }
#else
__forceinline vboolf4 eq(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { … }
__forceinline vboolf4 ne(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { … }
__forceinline vboolf4 lt(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { … }
__forceinline vboolf4 ge(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { … }
__forceinline vboolf4 gt(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { … }
__forceinline vboolf4 le(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { … }
#endif
template<int mask>
__forceinline vfloat4 select(const vfloat4& t, const vfloat4& f)
{ … }
__forceinline vfloat4 lerp(const vfloat4& a, const vfloat4& b, const vfloat4& t) { … }
__forceinline bool isvalid(const vfloat4& v) { … }
__forceinline bool is_finite(const vfloat4& a) { … }
__forceinline bool is_finite(const vboolf4& valid, const vfloat4& a) { … }
#if defined(__aarch64__)
__forceinline vfloat4 floor(const vfloat4& a) { return vrndmq_f32(a.v); }
__forceinline vfloat4 ceil (const vfloat4& a) { return vrndpq_f32(a.v); }
__forceinline vfloat4 trunc(const vfloat4& a) { return vrndq_f32(a.v); }
__forceinline vfloat4 round(const vfloat4& a) { return vrndnq_f32(a.v); }
#elif defined (__SSE4_1__)
__forceinline vfloat4 floor(const vfloat4& a) { return _mm_round_ps(a, _MM_FROUND_TO_NEG_INF ); }
__forceinline vfloat4 ceil (const vfloat4& a) { return _mm_round_ps(a, _MM_FROUND_TO_POS_INF ); }
__forceinline vfloat4 trunc(const vfloat4& a) { return _mm_round_ps(a, _MM_FROUND_TO_ZERO ); }
__forceinline vfloat4 round(const vfloat4& a) { return _mm_round_ps(a, _MM_FROUND_TO_NEAREST_INT); }
#else
__forceinline vfloat4 floor(const vfloat4& a) { … }
__forceinline vfloat4 ceil (const vfloat4& a) { … }
__forceinline vfloat4 trunc(const vfloat4& a) { … }
__forceinline vfloat4 round(const vfloat4& a) { … }
#endif
__forceinline vfloat4 frac(const vfloat4& a) { … }
__forceinline vint4 floori(const vfloat4& a) { … }
__forceinline vfloat4 unpacklo(const vfloat4& a, const vfloat4& b) { … }
__forceinline vfloat4 unpackhi(const vfloat4& a, const vfloat4& b) { … }
#if defined(__aarch64__)
template<int i0, int i1, int i2, int i3>
__forceinline vfloat4 shuffle(const vfloat4& v) {
return vreinterpretq_f32_u8(vqtbl1q_u8( (uint8x16_t)v.v, _MN_SHUFFLE(i0, i1, i2, i3)));
}
template<int i0, int i1, int i2, int i3>
__forceinline vfloat4 shuffle(const vfloat4& a, const vfloat4& b) {
return vreinterpretq_f32_u8(vqtbl2q_u8( (uint8x16x2_t){(uint8x16_t)a.v, (uint8x16_t)b.v}, _MF_SHUFFLE(i0, i1, i2, i3)));
}
#else
template<int i0, int i1, int i2, int i3>
__forceinline vfloat4 shuffle(const vfloat4& v) { … }
template<int i0, int i1, int i2, int i3>
__forceinline vfloat4 shuffle(const vfloat4& a, const vfloat4& b) { … }
#endif
#if defined(__SSE3__) && !defined(__aarch64__)
template<> __forceinline vfloat4 shuffle<0, 0, 2, 2>(const vfloat4& v) { return _mm_moveldup_ps(v); }
template<> __forceinline vfloat4 shuffle<1, 1, 3, 3>(const vfloat4& v) { return _mm_movehdup_ps(v); }
template<> __forceinline vfloat4 shuffle<0, 1, 0, 1>(const vfloat4& v) { return _mm_castpd_ps(_mm_movedup_pd(_mm_castps_pd(v))); }
#endif
template<int i>
__forceinline vfloat4 shuffle(const vfloat4& v) { … }
#if defined(__aarch64__)
template<int i> __forceinline float extract(const vfloat4& a) { return a[i]; }
#else
template<int i> __forceinline float extract (const vfloat4& a) { … }
template<> __forceinline float extract<0>(const vfloat4& a) { … }
#endif
#if defined (__SSE4_1__) && !defined(__aarch64__)
template<int dst, int src, int clr> __forceinline vfloat4 insert(const vfloat4& a, const vfloat4& b) { return _mm_insert_ps(a, b, (dst << 4) | (src << 6) | clr); }
template<int dst, int src> __forceinline vfloat4 insert(const vfloat4& a, const vfloat4& b) { return insert<dst, src, 0>(a, b); }
template<int dst> __forceinline vfloat4 insert(const vfloat4& a, const float b) { return insert<dst, 0>(a, _mm_set_ss(b)); }
#else
template<int dst, int src> __forceinline vfloat4 insert(const vfloat4& a, const vfloat4& b) { … }
template<int dst> __forceinline vfloat4 insert(const vfloat4& a, float b) { … }
#endif
__forceinline float toScalar(const vfloat4& v) { … }
__forceinline vfloat4 shift_right_1(const vfloat4& x) { … }
#if defined (__AVX2__)
__forceinline vfloat4 permute(const vfloat4 &a, const __m128i &index) {
return _mm_permutevar_ps(a,index);
}
__forceinline vfloat4 broadcast1f(const void* a) { return _mm_broadcast_ss((float*)a); }
#endif
#if defined(__AVX512VL__)
template<int i>
__forceinline vfloat4 align_shift_right(const vfloat4& a, const vfloat4& b) {
return _mm_castsi128_ps(_mm_alignr_epi32(_mm_castps_si128(a), _mm_castps_si128(b), i));
}
#endif
__forceinline vfloat4 sort_ascending(const vfloat4& v)
{ … }
__forceinline vfloat4 sort_descending(const vfloat4& v)
{ … }
__forceinline void transpose(const vfloat4& r0, const vfloat4& r1, const vfloat4& r2, const vfloat4& r3, vfloat4& c0, vfloat4& c1, vfloat4& c2, vfloat4& c3)
{ … }
__forceinline void transpose(const vfloat4& r0, const vfloat4& r1, const vfloat4& r2, const vfloat4& r3, vfloat4& c0, vfloat4& c1, vfloat4& c2)
{ … }
#if defined(__aarch64__)
__forceinline vfloat4 vreduce_min(const vfloat4& v) { float h = vminvq_f32(v); return vdupq_n_f32(h); }
__forceinline vfloat4 vreduce_max(const vfloat4& v) { float h = vmaxvq_f32(v); return vdupq_n_f32(h); }
__forceinline vfloat4 vreduce_add(const vfloat4& v) { float h = vaddvq_f32(v); return vdupq_n_f32(h); }
#else
__forceinline vfloat4 vreduce_min(const vfloat4& v) { … }
__forceinline vfloat4 vreduce_max(const vfloat4& v) { … }
__forceinline vfloat4 vreduce_add(const vfloat4& v) { … }
#endif
#if defined(__aarch64__)
__forceinline float reduce_min(const vfloat4& v) { return vminvq_f32(v); }
__forceinline float reduce_max(const vfloat4& v) { return vmaxvq_f32(v); }
__forceinline float reduce_add(const vfloat4& v) { return vaddvq_f32(v); }
#else
__forceinline float reduce_min(const vfloat4& v) { … }
__forceinline float reduce_max(const vfloat4& v) { … }
__forceinline float reduce_add(const vfloat4& v) { … }
#endif
__forceinline size_t select_min(const vboolf4& valid, const vfloat4& v)
{ … }
__forceinline size_t select_max(const vboolf4& valid, const vfloat4& v)
{ … }
__forceinline float dot(const vfloat4& a, const vfloat4& b) { … }
__forceinline vfloat4 cross(const vfloat4& a, const vfloat4& b)
{ … }
__forceinline embree_ostream operator <<(embree_ostream cout, const vfloat4& a) { … }
}
#undef vboolf
#undef vboold
#undef vint
#undef vuint
#undef vllong
#undef vfloat
#undef vdouble