mirror of
https://github.com/bkaradzic/bx.git
synced 2026-09-07 02:48:33 +00:00
Added BX_CONFIG_FMA, SIMD madd/msub/nmsub, f32 rounding and integer div/mod. (#421)
This commit is contained in:
committed by
GitHub
parent
080f466590
commit
2b9ef62e7a
@@ -20,4 +20,20 @@
|
||||
)
|
||||
#endif // BX_CONFIG_SUPPORTS_THREADING
|
||||
|
||||
/// Use fused multiply-add instructions for bx::mad and simd_f32_madd/msub/nmsub.
|
||||
#ifndef BX_CONFIG_FMA
|
||||
# if BX_CPU_X86 \
|
||||
&& (defined(__FMA__) || (BX_COMPILER_MSVC && defined(__AVX2__) ) )
|
||||
# define BX_CONFIG_FMA 1
|
||||
# elif BX_CPU_ARM \
|
||||
&& defined(__ARM_FEATURE_FMA) \
|
||||
&& (defined(__ARM_NEON) || defined(__ARM_NEON__) )
|
||||
# define BX_CONFIG_FMA 1
|
||||
# elif BX_CPU_ARM && BX_ARCH_64BIT && BX_COMPILER_MSVC
|
||||
# define BX_CONFIG_FMA 1
|
||||
# else
|
||||
# define BX_CONFIG_FMA 0
|
||||
# endif
|
||||
#endif // BX_CONFIG_FMA
|
||||
|
||||
#endif // BX_CONFIG_H_HEADER_GUARD
|
||||
|
||||
@@ -109,27 +109,159 @@ namespace bx
|
||||
return tmp == kDoubleExponentMask;
|
||||
}
|
||||
|
||||
inline BX_CONSTEXPR_FUNC float floor(float _a)
|
||||
inline BX_CONSTEXPR_FUNC float truncRef(float _a)
|
||||
{
|
||||
if (_a < 0.0f)
|
||||
{
|
||||
const float fr = fract(-_a);
|
||||
const float tr = trunc(-_a);
|
||||
const uint32_t bits = floatToBits(_a);
|
||||
const uint32_t sign = bits & kFloatSignMask;
|
||||
const uint32_t magnitude = bits & ~kFloatSignMask;
|
||||
|
||||
return -tr - float(0.0f != fr);
|
||||
if (0x4b000000u <= magnitude)
|
||||
{
|
||||
return _a;
|
||||
}
|
||||
|
||||
return _a - fract(_a);
|
||||
const float tr = float(int(_a) );
|
||||
const uint32_t trBits = floatToBits(tr) | sign;
|
||||
const float result = bitsToFloat(trBits);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline BX_CONSTEXPR_FUNC float floorRef(float _a)
|
||||
{
|
||||
const uint32_t bits = floatToBits(_a);
|
||||
const uint32_t sign = bits & kFloatSignMask;
|
||||
const uint32_t magnitude = bits & ~kFloatSignMask;
|
||||
|
||||
if (0x4b000000u <= magnitude)
|
||||
{
|
||||
return _a;
|
||||
}
|
||||
|
||||
const float tr = float(int(_a) );
|
||||
const float fl = tr > _a ? tr - 1.0f : tr;
|
||||
const uint32_t flBits = floatToBits(fl) | sign;
|
||||
const float result = bitsToFloat(flBits);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline BX_CONSTEXPR_FUNC float ceilRef(float _a)
|
||||
{
|
||||
const float na = -_a;
|
||||
const float fl = floorRef(na);
|
||||
const float result = -fl;
|
||||
return result;
|
||||
}
|
||||
|
||||
#if BX_SIMD_SUPPORTED
|
||||
inline BX_CONST_FUNC float truncSimd(float _a)
|
||||
{
|
||||
const simd128_t aa = simd_splat<simd128_t>(_a);
|
||||
const simd128_t result = simd_f32_trunc<simd128_t>(aa);
|
||||
|
||||
float out = 0.0f;
|
||||
simd_x32_st1<simd128_t>(&out, result);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
inline BX_CONST_FUNC float floorSimd(float _a)
|
||||
{
|
||||
const simd128_t aa = simd_splat<simd128_t>(_a);
|
||||
const simd128_t result = simd_f32_floor<simd128_t>(aa);
|
||||
|
||||
float out = 0.0f;
|
||||
simd_x32_st1<simd128_t>(&out, result);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
inline BX_CONST_FUNC float ceilSimd(float _a)
|
||||
{
|
||||
const simd128_t aa = simd_splat<simd128_t>(_a);
|
||||
const simd128_t result = simd_f32_ceil<simd128_t>(aa);
|
||||
|
||||
float out = 0.0f;
|
||||
simd_x32_st1<simd128_t>(&out, result);
|
||||
|
||||
return out;
|
||||
}
|
||||
#endif // BX_SIMD_SUPPORTED
|
||||
|
||||
inline BX_CONSTEXPR_FUNC float floor(float _a)
|
||||
{
|
||||
#if BX_SIMD_SUPPORTED
|
||||
if (isConstantEvaluated() )
|
||||
{
|
||||
return floorRef(_a);
|
||||
}
|
||||
|
||||
return floorSimd(_a);
|
||||
#else
|
||||
return floorRef(_a);
|
||||
#endif // BX_SIMD_SUPPORTED
|
||||
}
|
||||
|
||||
inline BX_CONSTEXPR_FUNC float ceil(float _a)
|
||||
{
|
||||
return -floor(-_a);
|
||||
#if BX_SIMD_SUPPORTED
|
||||
if (isConstantEvaluated() )
|
||||
{
|
||||
return ceilRef(_a);
|
||||
}
|
||||
|
||||
return ceilSimd(_a);
|
||||
#else
|
||||
return ceilRef(_a);
|
||||
#endif // BX_SIMD_SUPPORTED
|
||||
}
|
||||
|
||||
inline BX_CONSTEXPR_FUNC float roundRef(float _a)
|
||||
{
|
||||
const uint32_t bits = floatToBits(_a);
|
||||
const uint32_t sign = bits & kFloatSignMask;
|
||||
const uint32_t magnitude = bits & ~kFloatSignMask;
|
||||
|
||||
if (0x4b000000u <= magnitude)
|
||||
{
|
||||
return _a;
|
||||
}
|
||||
|
||||
const float fl = floorRef(_a);
|
||||
const float fr = _a - fl;
|
||||
const bool odd = 0 != (int32_t(fl) & 1);
|
||||
const bool up = fr > 0.5f || (fr == 0.5f && odd);
|
||||
const float rd = up ? fl + 1.0f : fl;
|
||||
const uint32_t rdBits = floatToBits(rd) | sign;
|
||||
const float result = bitsToFloat(rdBits);
|
||||
return result;
|
||||
}
|
||||
|
||||
#if BX_SIMD_SUPPORTED
|
||||
inline BX_CONST_FUNC float roundSimd(float _a)
|
||||
{
|
||||
const simd128_t aa = simd_splat<simd128_t>(_a);
|
||||
const simd128_t result = simd_f32_round<simd128_t>(aa);
|
||||
|
||||
float out = 0.0f;
|
||||
simd_x32_st1<simd128_t>(&out, result);
|
||||
|
||||
return out;
|
||||
}
|
||||
#endif // BX_SIMD_SUPPORTED
|
||||
|
||||
inline BX_CONSTEXPR_FUNC float round(float _a)
|
||||
{
|
||||
return floor(_a + 0.5f);
|
||||
#if BX_SIMD_SUPPORTED
|
||||
if (isConstantEvaluated() )
|
||||
{
|
||||
return roundRef(_a);
|
||||
}
|
||||
|
||||
return roundSimd(_a);
|
||||
#else
|
||||
return roundRef(_a);
|
||||
#endif // BX_SIMD_SUPPORTED
|
||||
}
|
||||
|
||||
inline BX_CONSTEXPR_FUNC float lerp(float _a, float _b, float _t)
|
||||
@@ -153,13 +285,18 @@ namespace bx
|
||||
|
||||
inline BX_CONSTEXPR_FUNC bool signBit(float _a)
|
||||
{
|
||||
return -0.0f == _a ? 0.0f != _a : 0.0f > _a;
|
||||
const uint32_t bits = floatToBits(_a);
|
||||
return 0 != (bits & kFloatSignMask);
|
||||
}
|
||||
|
||||
inline BX_CONSTEXPR_FUNC float copySign(float _value, float _sign)
|
||||
{
|
||||
#if BX_COMPILER_MSVC
|
||||
return signBit(_value) != signBit(_sign) ? -_value : _value;
|
||||
const uint32_t magnitude = floatToBits(_value) & ~kFloatSignMask;
|
||||
const uint32_t sign = floatToBits(_sign) & kFloatSignMask;
|
||||
const uint32_t bits = magnitude | sign;
|
||||
const float result = bitsToFloat(bits);
|
||||
return result;
|
||||
#else
|
||||
return __builtin_copysign(_value, _sign);
|
||||
#endif // BX_COMPILER_MSVC
|
||||
@@ -177,7 +314,16 @@ namespace bx
|
||||
|
||||
inline BX_CONSTEXPR_FUNC float trunc(float _a)
|
||||
{
|
||||
return float(int(_a) );
|
||||
#if BX_SIMD_SUPPORTED
|
||||
if (isConstantEvaluated() )
|
||||
{
|
||||
return truncRef(_a);
|
||||
}
|
||||
|
||||
return truncSimd(_a);
|
||||
#else
|
||||
return truncRef(_a);
|
||||
#endif // BX_SIMD_SUPPORTED
|
||||
}
|
||||
|
||||
inline BX_CONSTEXPR_FUNC float fract(float _a)
|
||||
@@ -187,7 +333,10 @@ namespace bx
|
||||
|
||||
inline BX_CONSTEXPR_FUNC float nms(float _a, float _b, float _c)
|
||||
{
|
||||
return _c - _a * _b;
|
||||
const float na = -_a;
|
||||
const float result = mad(na, _b, _c);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline BX_CONSTEXPR_FUNC float add(float _a, float _b)
|
||||
@@ -252,7 +401,12 @@ namespace bx
|
||||
|
||||
inline BX_CONSTEXPR_FUNC float mad(float _a, float _b, float _c)
|
||||
{
|
||||
return add(mul(_a, _b), _c);
|
||||
const simd32_t aa = simd32_ld(_a);
|
||||
const simd32_t bb = simd32_ld(_b);
|
||||
const simd32_t cc = simd32_ld(_c);
|
||||
const simd32_t result = simd32_f32_madd(aa, bb, cc);
|
||||
|
||||
return bitCast<float>(result);
|
||||
}
|
||||
|
||||
inline BX_CONSTEXPR_FUNC float rcp(float _a)
|
||||
@@ -275,14 +429,19 @@ namespace bx
|
||||
return mul(_a, rcpSafe(_b) );
|
||||
}
|
||||
|
||||
BX_FP_PRECISE_BEGIN()
|
||||
|
||||
inline BX_CONSTEXPR_FUNC float mod(float _a, float _b)
|
||||
{
|
||||
return _a - _b * floor(div(_a, _b) );
|
||||
const float quotient = _a / _b;
|
||||
const float whole = floor(quotient);
|
||||
const float result = nms(_b, whole, _a);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline BX_CONSTEXPR_FUNC float cos(float _a)
|
||||
{
|
||||
const float scaled = _a * 2.0f*kInvPi;
|
||||
const float scaled = _a * (2.0f*kInvPi);
|
||||
const float real = floor(scaled);
|
||||
const float xx = _a - real * kPiHalf;
|
||||
const int32_t bits = int32_t(real) & 3;
|
||||
@@ -412,9 +571,11 @@ namespace bx
|
||||
const float maxaxy = max(ax, ay);
|
||||
const float minaxy = min(ax, ay);
|
||||
|
||||
const uint32_t ysign = floatToBits(_y) & kFloatSignMask;
|
||||
|
||||
if (maxaxy == 0.0f)
|
||||
{
|
||||
return _y < 0.0f ? -0.0f : 0.0f;
|
||||
return bitsToFloat(ysign);
|
||||
}
|
||||
|
||||
constexpr float kAtan2C0 = -0.013480470f;
|
||||
@@ -424,17 +585,19 @@ namespace bx
|
||||
constexpr float kAtan2C4 = -0.332994597f;
|
||||
constexpr float kAtan2C5 = 0.999995630f;
|
||||
|
||||
const float mxy = minaxy / maxaxy;
|
||||
const float mxysq = square(mxy);
|
||||
const float tmp0 = mad(kAtan2C0, mxysq, kAtan2C1);
|
||||
const float tmp1 = mad(tmp0, mxysq, kAtan2C2);
|
||||
const float tmp2 = mad(tmp1, mxysq, kAtan2C3);
|
||||
const float tmp3 = mad(tmp2, mxysq, kAtan2C4);
|
||||
const float tmp4 = mad(tmp3, mxysq, kAtan2C5);
|
||||
const float tmp5 = tmp4 * mxy;
|
||||
const float tmp6 = ay > ax ? kPiHalf - tmp5 : tmp5;
|
||||
const float tmp7 = _x < 0.0f ? kPi - tmp6 : tmp6;
|
||||
const float result = _y < 0.0f ? -tmp7 : tmp7;
|
||||
const float mxy = minaxy / maxaxy;
|
||||
const float mxysq = square(mxy);
|
||||
const float tmp0 = mad(kAtan2C0, mxysq, kAtan2C1);
|
||||
const float tmp1 = mad(tmp0, mxysq, kAtan2C2);
|
||||
const float tmp2 = mad(tmp1, mxysq, kAtan2C3);
|
||||
const float tmp3 = mad(tmp2, mxysq, kAtan2C4);
|
||||
const float tmp4 = mad(tmp3, mxysq, kAtan2C5);
|
||||
const float tmp5 = tmp4 * mxy;
|
||||
const float tmp6 = ay > ax ? kPiHalf - tmp5 : tmp5;
|
||||
const float tmp7 = _x < 0.0f ? kPi - tmp6 : tmp6;
|
||||
|
||||
const uint32_t bits = floatToBits(tmp7) | ysign;
|
||||
const float result = bitsToFloat(bits);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -588,6 +751,8 @@ namespace bx
|
||||
return log(_a) * kInvLogNat2;
|
||||
}
|
||||
|
||||
BX_FP_PRECISE_END()
|
||||
|
||||
template<>
|
||||
inline BX_CONSTEXPR_FUNC uint8_t countBits(uint32_t _val)
|
||||
{
|
||||
@@ -1199,17 +1364,29 @@ namespace bx
|
||||
|
||||
inline BX_CONSTEXPR_FUNC Vec3 nms(const Vec3& _a, const Vec3& _b, const Vec3& _c)
|
||||
{
|
||||
return sub(_c, mul(_a, _b) );
|
||||
const float xx = nms(_a.x, _b.x, _c.x);
|
||||
const float yy = nms(_a.y, _b.y, _c.y);
|
||||
const float zz = nms(_a.z, _b.z, _c.z);
|
||||
|
||||
return Vec3(xx, yy, zz);
|
||||
}
|
||||
|
||||
inline BX_CONSTEXPR_FUNC Vec3 mad(const Vec3& _a, const float _b, const Vec3& _c)
|
||||
{
|
||||
return add(mul(_a, _b), _c);
|
||||
const float xx = mad(_a.x, _b, _c.x);
|
||||
const float yy = mad(_a.y, _b, _c.y);
|
||||
const float zz = mad(_a.z, _b, _c.z);
|
||||
|
||||
return Vec3(xx, yy, zz);
|
||||
}
|
||||
|
||||
inline BX_CONSTEXPR_FUNC Vec3 mad(const Vec3& _a, const Vec3& _b, const Vec3& _c)
|
||||
{
|
||||
return add(mul(_a, _b), _c);
|
||||
const float xx = mad(_a.x, _b.x, _c.x);
|
||||
const float yy = mad(_a.y, _b.y, _c.y);
|
||||
const float zz = mad(_a.z, _b.z, _c.z);
|
||||
|
||||
return Vec3(xx, yy, zz);
|
||||
}
|
||||
|
||||
inline BX_CONSTEXPR_FUNC float dot(const Vec3& _a, const Vec3& _b)
|
||||
|
||||
@@ -334,7 +334,7 @@ namespace bx
|
||||
return vrndnq_f32(_a);
|
||||
#else
|
||||
return simd_f32_round_ni(_a);
|
||||
#endif
|
||||
#endif // BX_ARCH_64BIT
|
||||
}
|
||||
|
||||
template<>
|
||||
@@ -344,7 +344,7 @@ namespace bx
|
||||
return vrndpq_f32(_a);
|
||||
#else
|
||||
return simd_f32_ceil_ni(_a);
|
||||
#endif
|
||||
#endif // BX_ARCH_64BIT
|
||||
}
|
||||
|
||||
template<>
|
||||
@@ -354,7 +354,17 @@ namespace bx
|
||||
return vrndmq_f32(_a);
|
||||
#else
|
||||
return simd_f32_floor_ni(_a);
|
||||
#endif
|
||||
#endif // BX_ARCH_64BIT
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_neon_t simd128_f32_trunc(simd128_neon_t _a)
|
||||
{
|
||||
#if BX_ARCH_64BIT
|
||||
return vrndq_f32(_a);
|
||||
#else
|
||||
return simd_f32_trunc_ni(_a);
|
||||
#endif // BX_ARCH_64BIT
|
||||
}
|
||||
|
||||
template<>
|
||||
@@ -382,7 +392,7 @@ namespace bx
|
||||
return vdivq_f32(_a, _b);
|
||||
#else
|
||||
return simd_f32_div_nr_ni(_a, _b);
|
||||
#endif
|
||||
#endif // BX_ARCH_64BIT
|
||||
}
|
||||
|
||||
template<>
|
||||
@@ -621,6 +631,30 @@ namespace bx
|
||||
return vreinterpretq_f32_u32(result);
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_neon_t simd128_i32_div(simd128_neon_t _a, simd128_neon_t _b)
|
||||
{
|
||||
return simd_i32_div_ni(_a, _b);
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_neon_t simd128_i32_mod(simd128_neon_t _a, simd128_neon_t _b)
|
||||
{
|
||||
return simd_i32_mod_ni(_a, _b);
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_neon_t simd128_u32_div(simd128_neon_t _a, simd128_neon_t _b)
|
||||
{
|
||||
return simd_u32_div_ni(_a, _b);
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_neon_t simd128_u32_mod(simd128_neon_t _a, simd128_neon_t _b)
|
||||
{
|
||||
return simd_u32_mod_ni(_a, _b);
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_neon_t simd128_u32_cmpgt(simd128_neon_t _a, simd128_neon_t _b)
|
||||
{
|
||||
@@ -912,27 +946,33 @@ namespace bx
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_neon_t simd128_f32_madd(simd128_neon_t _a, simd128_neon_t _b, simd128_neon_t _c)
|
||||
{
|
||||
#if BX_ARCH_64BIT
|
||||
#if BX_CONFIG_FMA
|
||||
return vfmaq_f32(_c, _a, _b);
|
||||
#else
|
||||
return simd_f32_madd_ni(_a, _b, _c);
|
||||
#endif
|
||||
#endif // BX_CONFIG_FMA
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_neon_t simd128_f32_msub(simd128_neon_t _a, simd128_neon_t _b, simd128_neon_t _c)
|
||||
{
|
||||
#if BX_CONFIG_FMA
|
||||
const simd128_neon_t nmsub = vfmsq_f32(_c, _a, _b);
|
||||
const simd128_neon_t result = vnegq_f32(nmsub);
|
||||
return result;
|
||||
#else
|
||||
return simd_f32_msub_ni(_a, _b, _c);
|
||||
#endif // BX_CONFIG_FMA
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_neon_t simd128_f32_nmsub(simd128_neon_t _a, simd128_neon_t _b, simd128_neon_t _c)
|
||||
{
|
||||
#if BX_ARCH_64BIT
|
||||
#if BX_CONFIG_FMA
|
||||
return vfmsq_f32(_c, _a, _b);
|
||||
#else
|
||||
return simd_f32_nmsub_ni(_a, _b, _c);
|
||||
#endif
|
||||
#endif // BX_CONFIG_FMA
|
||||
}
|
||||
|
||||
template<>
|
||||
|
||||
@@ -557,6 +557,12 @@ namespace bx
|
||||
return simd_f32_floor_ni(_a);
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_ref_t simd128_f32_trunc(simd128_ref_t _a)
|
||||
{
|
||||
return simd_f32_trunc_ni(_a);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline BX_CONSTEXPR_FUNC simd128_ref_t simd128_f32_cmpeq(simd128_ref_t _a, simd128_ref_t _b)
|
||||
{
|
||||
@@ -913,6 +919,30 @@ namespace bx
|
||||
#endif // BX_SIMD_LANGEXT
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_ref_t simd128_i32_div(simd128_ref_t _a, simd128_ref_t _b)
|
||||
{
|
||||
return simd_i32_div_ni(_a, _b);
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_ref_t simd128_i32_mod(simd128_ref_t _a, simd128_ref_t _b)
|
||||
{
|
||||
return simd_i32_mod_ni(_a, _b);
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_ref_t simd128_u32_div(simd128_ref_t _a, simd128_ref_t _b)
|
||||
{
|
||||
return simd_u32_div_ni(_a, _b);
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_ref_t simd128_u32_mod(simd128_ref_t _a, simd128_ref_t _b)
|
||||
{
|
||||
return simd_u32_mod_ni(_a, _b);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline BX_CONSTEXPR_FUNC simd128_ref_t simd128_u32_cmplt(simd128_ref_t _a, simd128_ref_t _b)
|
||||
{
|
||||
@@ -1350,19 +1380,42 @@ namespace bx
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_ref_t simd128_f32_madd(simd128_ref_t _a, simd128_ref_t _b, simd128_ref_t _c)
|
||||
{
|
||||
return simd_f32_madd_ni(_a, _b, _c);
|
||||
const simd128_f32_ref_t a = bitCast<simd128_f32_ref_t>(_a);
|
||||
const simd128_f32_ref_t b = bitCast<simd128_f32_ref_t>(_b);
|
||||
const simd128_f32_ref_t c = bitCast<simd128_f32_ref_t>(_c);
|
||||
|
||||
simd128_f32_ref_t result = {};
|
||||
|
||||
for (uint32_t ii = 0; ii < 4; ++ii)
|
||||
{
|
||||
const simd32_t aa = simd32_ld(a.f32[ii]);
|
||||
const simd32_t bb = simd32_ld(b.f32[ii]);
|
||||
const simd32_t cc = simd32_ld(c.f32[ii]);
|
||||
const simd32_t rr = simd32_f32_madd(aa, bb, cc);
|
||||
result.f32[ii] = bitCast<float>(rr);
|
||||
}
|
||||
|
||||
return bitCast<simd128_ref_t>(result);
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_ref_t simd128_f32_msub(simd128_ref_t _a, simd128_ref_t _b, simd128_ref_t _c)
|
||||
{
|
||||
return simd_f32_msub_ni(_a, _b, _c);
|
||||
const simd128_f32_ref_t c = bitCast<simd128_f32_ref_t>(_c);
|
||||
const simd128_f32_ref_t nc = { { -c.f32[0], -c.f32[1], -c.f32[2], -c.f32[3] } };
|
||||
const simd128_ref_t ncc = bitCast<simd128_ref_t>(nc);
|
||||
const simd128_ref_t result = simd128_f32_madd(_a, _b, ncc);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_ref_t simd128_f32_nmsub(simd128_ref_t _a, simd128_ref_t _b, simd128_ref_t _c)
|
||||
{
|
||||
return simd_f32_nmsub_ni(_a, _b, _c);
|
||||
const simd128_f32_ref_t a = bitCast<simd128_f32_ref_t>(_a);
|
||||
const simd128_f32_ref_t na = { { -a.f32[0], -a.f32[1], -a.f32[2], -a.f32[3] } };
|
||||
const simd128_ref_t naa = bitCast<simd128_ref_t>(na);
|
||||
const simd128_ref_t result = simd128_f32_madd(naa, _b, _c);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
||||
@@ -308,6 +308,12 @@ namespace bx
|
||||
return _mm_floor_ps(_a);
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_sse_t simd128_f32_trunc(simd128_sse_t _a)
|
||||
{
|
||||
return _mm_round_ps(_a, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC);
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_sse_t simd128_f32_add(simd128_sse_t _a, simd128_sse_t _b)
|
||||
{
|
||||
@@ -556,6 +562,114 @@ namespace bx
|
||||
return simd_u32_cmplt_ni(_a, _b);
|
||||
}
|
||||
|
||||
BX_SIMD_FORCE_INLINE __m128i simd128_sse_i32_quot(__m128i _a, __m128i _b)
|
||||
{
|
||||
const __m128i ahi = _mm_unpackhi_epi64(_a, _a);
|
||||
const __m128i bhi = _mm_unpackhi_epi64(_b, _b);
|
||||
const __m128d alo_d = _mm_cvtepi32_pd(_a);
|
||||
const __m128d ahi_d = _mm_cvtepi32_pd(ahi);
|
||||
const __m128d blo_d = _mm_cvtepi32_pd(_b);
|
||||
const __m128d bhi_d = _mm_cvtepi32_pd(bhi);
|
||||
const __m128d qlo = _mm_div_pd(alo_d, blo_d);
|
||||
const __m128d qhi = _mm_div_pd(ahi_d, bhi_d);
|
||||
const __m128i ilo = _mm_cvttpd_epi32(qlo);
|
||||
const __m128i ihi = _mm_cvttpd_epi32(qhi);
|
||||
const __m128i result = _mm_unpacklo_epi64(ilo, ihi);
|
||||
return result;
|
||||
}
|
||||
|
||||
BX_SIMD_FORCE_INLINE __m128i simd128_sse_u32_quot(__m128i _a, __m128i _b)
|
||||
{
|
||||
// The signed convert, plus 2^32 where the top bit was set.
|
||||
const __m128d two32 = _mm_set1_pd(4294967296.0);
|
||||
const __m128i aneg = _mm_srai_epi32(_a, 31);
|
||||
const __m128i bneg = _mm_srai_epi32(_b, 31);
|
||||
const __m128i ahi = _mm_unpackhi_epi64(_a, _a);
|
||||
const __m128i bhi = _mm_unpackhi_epi64(_b, _b);
|
||||
const __m128i anhi = _mm_unpackhi_epi64(aneg, aneg);
|
||||
const __m128i bnhi = _mm_unpackhi_epi64(bneg, bneg);
|
||||
const __m128d alo_s = _mm_cvtepi32_pd(_a);
|
||||
const __m128d ahi_s = _mm_cvtepi32_pd(ahi);
|
||||
const __m128d blo_s = _mm_cvtepi32_pd(_b);
|
||||
const __m128d bhi_s = _mm_cvtepi32_pd(bhi);
|
||||
const __m128d anlo_d = _mm_cvtepi32_pd(aneg);
|
||||
const __m128d anhi_d = _mm_cvtepi32_pd(anhi);
|
||||
const __m128d bnlo_d = _mm_cvtepi32_pd(bneg);
|
||||
const __m128d bnhi_d = _mm_cvtepi32_pd(bnhi);
|
||||
const __m128d alo_f = _mm_mul_pd(anlo_d, two32);
|
||||
const __m128d ahi_f = _mm_mul_pd(anhi_d, two32);
|
||||
const __m128d blo_f = _mm_mul_pd(bnlo_d, two32);
|
||||
const __m128d bhi_f = _mm_mul_pd(bnhi_d, two32);
|
||||
const __m128d alo_d = _mm_sub_pd(alo_s, alo_f);
|
||||
const __m128d ahi_d = _mm_sub_pd(ahi_s, ahi_f);
|
||||
const __m128d blo_d = _mm_sub_pd(blo_s, blo_f);
|
||||
const __m128d bhi_d = _mm_sub_pd(bhi_s, bhi_f);
|
||||
const __m128d qlo = _mm_div_pd(alo_d, blo_d);
|
||||
const __m128d qhi = _mm_div_pd(ahi_d, bhi_d);
|
||||
const __m128i ilo = _mm_cvttpd_epi32(qlo);
|
||||
const __m128i ihi = _mm_cvttpd_epi32(qhi);
|
||||
const __m128i result = _mm_unpacklo_epi64(ilo, ihi);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_sse_t simd128_i32_div(simd128_sse_t _a, simd128_sse_t _b)
|
||||
{
|
||||
const __m128i a = _mm_castps_si128(_a);
|
||||
const __m128i b = _mm_castps_si128(_b);
|
||||
const __m128i zero = _mm_setzero_si128();
|
||||
const __m128i quot = simd128_sse_i32_quot(a, b);
|
||||
const __m128i bzero = _mm_cmpeq_epi32(b, zero);
|
||||
const __m128i result = _mm_blendv_epi8(quot, a, bzero);
|
||||
return _mm_castsi128_ps(result);
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_sse_t simd128_i32_mod(simd128_sse_t _a, simd128_sse_t _b)
|
||||
{
|
||||
const __m128i a = _mm_castps_si128(_a);
|
||||
const __m128i b = _mm_castps_si128(_b);
|
||||
const __m128i zero = _mm_setzero_si128();
|
||||
const __m128i quot = simd128_sse_i32_quot(a, b);
|
||||
const __m128i prod = _mm_mullo_epi32(quot, b);
|
||||
const __m128i rem = _mm_sub_epi32(a, prod);
|
||||
const __m128i bzero = _mm_cmpeq_epi32(b, zero);
|
||||
const __m128i result = _mm_andnot_si128(bzero, rem);
|
||||
return _mm_castsi128_ps(result);
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_sse_t simd128_u32_div(simd128_sse_t _a, simd128_sse_t _b)
|
||||
{
|
||||
const __m128i a = _mm_castps_si128(_a);
|
||||
const __m128i b = _mm_castps_si128(_b);
|
||||
const __m128i zero = _mm_setzero_si128();
|
||||
const __m128i one = _mm_set1_epi32(1);
|
||||
const __m128i quot = simd128_sse_u32_quot(a, b);
|
||||
const __m128i bzero = _mm_cmpeq_epi32(b, zero);
|
||||
const __m128i bone = _mm_cmpeq_epi32(b, one);
|
||||
const __m128i keep = _mm_or_si128(bzero, bone);
|
||||
const __m128i result = _mm_blendv_epi8(quot, a, keep);
|
||||
return _mm_castsi128_ps(result);
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_sse_t simd128_u32_mod(simd128_sse_t _a, simd128_sse_t _b)
|
||||
{
|
||||
const __m128i a = _mm_castps_si128(_a);
|
||||
const __m128i b = _mm_castps_si128(_b);
|
||||
const __m128i zero = _mm_setzero_si128();
|
||||
const __m128i one = _mm_set1_epi32(1);
|
||||
const __m128i quot0 = simd128_sse_u32_quot(a, b);
|
||||
const __m128i bone = _mm_cmpeq_epi32(b, one);
|
||||
const __m128i quot = _mm_blendv_epi8(quot0, a, bone);
|
||||
const __m128i prod = _mm_mullo_epi32(quot, b);
|
||||
const __m128i rem = _mm_sub_epi32(a, prod);
|
||||
const __m128i bzero = _mm_cmpeq_epi32(b, zero);
|
||||
const __m128i result = _mm_andnot_si128(bzero, rem);
|
||||
return _mm_castsi128_ps(result);
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_sse_t simd128_u32_cmpgt(simd128_sse_t _a, simd128_sse_t _b)
|
||||
{
|
||||
@@ -821,23 +935,49 @@ namespace bx
|
||||
return simd128_orx_ni(_a);
|
||||
}
|
||||
|
||||
#if BX_CONFIG_FMA
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_sse_t simd128_f32_madd(simd128_sse_t _a, simd128_sse_t _b, simd128_sse_t _c)
|
||||
{
|
||||
return simd_f32_madd_ni(_a, _b, _c);
|
||||
return _mm_fmadd_ps(_a, _b, _c);
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_sse_t simd128_f32_msub(simd128_sse_t _a, simd128_sse_t _b, simd128_sse_t _c)
|
||||
{
|
||||
return simd_f32_msub_ni(_a, _b, _c);
|
||||
return _mm_fmsub_ps(_a, _b, _c);
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_sse_t simd128_f32_nmsub(simd128_sse_t _a, simd128_sse_t _b, simd128_sse_t _c)
|
||||
{
|
||||
return simd_f32_nmsub_ni(_a, _b, _c);
|
||||
return _mm_fnmadd_ps(_a, _b, _c);
|
||||
}
|
||||
#else
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_sse_t simd128_f32_madd(simd128_sse_t _a, simd128_sse_t _b, simd128_sse_t _c)
|
||||
{
|
||||
const simd128_sse_t prod = _mm_mul_ps(_a, _b);
|
||||
const simd128_sse_t result = _mm_add_ps(prod, _c);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_sse_t simd128_f32_msub(simd128_sse_t _a, simd128_sse_t _b, simd128_sse_t _c)
|
||||
{
|
||||
const simd128_sse_t prod = _mm_mul_ps(_a, _b);
|
||||
const simd128_sse_t result = _mm_sub_ps(prod, _c);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_sse_t simd128_f32_nmsub(simd128_sse_t _a, simd128_sse_t _b, simd128_sse_t _c)
|
||||
{
|
||||
const simd128_sse_t prod = _mm_mul_ps(_a, _b);
|
||||
const simd128_sse_t result = _mm_sub_ps(_c, prod);
|
||||
return result;
|
||||
}
|
||||
#endif // BX_CONFIG_FMA
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE int simd128_x32_signbitsmask(simd128_sse_t _a)
|
||||
|
||||
@@ -299,6 +299,12 @@ namespace bx
|
||||
return wasm_f32x4_floor(_a);
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_wasm_t simd128_f32_trunc(simd128_wasm_t _a)
|
||||
{
|
||||
return wasm_f32x4_trunc(_a);
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_wasm_t simd128_f32_add(simd128_wasm_t _a, simd128_wasm_t _b)
|
||||
{
|
||||
@@ -512,6 +518,30 @@ namespace bx
|
||||
return wasm_u32x4_lt(_a, _b);
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_wasm_t simd128_i32_div(simd128_wasm_t _a, simd128_wasm_t _b)
|
||||
{
|
||||
return simd_i32_div_ni(_a, _b);
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_wasm_t simd128_i32_mod(simd128_wasm_t _a, simd128_wasm_t _b)
|
||||
{
|
||||
return simd_i32_mod_ni(_a, _b);
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_wasm_t simd128_u32_div(simd128_wasm_t _a, simd128_wasm_t _b)
|
||||
{
|
||||
return simd_u32_div_ni(_a, _b);
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_wasm_t simd128_u32_mod(simd128_wasm_t _a, simd128_wasm_t _b)
|
||||
{
|
||||
return simd_u32_mod_ni(_a, _b);
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_wasm_t simd128_u32_cmpgt(simd128_wasm_t _a, simd128_wasm_t _b)
|
||||
{
|
||||
|
||||
@@ -178,23 +178,49 @@ namespace bx
|
||||
return _mm256_rsqrt_ps(_a);
|
||||
}
|
||||
|
||||
#if BX_CONFIG_FMA
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_avx_t simd256_f32_madd(simd256_avx_t _a, simd256_avx_t _b, simd256_avx_t _c)
|
||||
{
|
||||
return simd_f32_madd_ni(_a, _b, _c);
|
||||
return _mm256_fmadd_ps(_a, _b, _c);
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_avx_t simd256_f32_msub(simd256_avx_t _a, simd256_avx_t _b, simd256_avx_t _c)
|
||||
{
|
||||
return simd_f32_msub_ni(_a, _b, _c);
|
||||
return _mm256_fmsub_ps(_a, _b, _c);
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_avx_t simd256_f32_nmsub(simd256_avx_t _a, simd256_avx_t _b, simd256_avx_t _c)
|
||||
{
|
||||
return simd_f32_nmsub_ni(_a, _b, _c);
|
||||
return _mm256_fnmadd_ps(_a, _b, _c);
|
||||
}
|
||||
#else
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_avx_t simd256_f32_madd(simd256_avx_t _a, simd256_avx_t _b, simd256_avx_t _c)
|
||||
{
|
||||
const simd256_avx_t prod = _mm256_mul_ps(_a, _b);
|
||||
const simd256_avx_t result = _mm256_add_ps(prod, _c);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_avx_t simd256_f32_msub(simd256_avx_t _a, simd256_avx_t _b, simd256_avx_t _c)
|
||||
{
|
||||
const simd256_avx_t prod = _mm256_mul_ps(_a, _b);
|
||||
const simd256_avx_t result = _mm256_sub_ps(prod, _c);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_avx_t simd256_f32_nmsub(simd256_avx_t _a, simd256_avx_t _b, simd256_avx_t _c)
|
||||
{
|
||||
const simd256_avx_t prod = _mm256_mul_ps(_a, _b);
|
||||
const simd256_avx_t result = _mm256_sub_ps(_c, prod);
|
||||
return result;
|
||||
}
|
||||
#endif // BX_CONFIG_FMA
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_avx_t simd256_f32_neg(simd256_avx_t _a)
|
||||
@@ -268,6 +294,12 @@ namespace bx
|
||||
return _mm256_floor_ps(_a);
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_avx_t simd256_f32_trunc(simd256_avx_t _a)
|
||||
{
|
||||
return _mm256_round_ps(_a, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC);
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_avx_t simd256_f32_cmpeq(simd256_avx_t _a, simd256_avx_t _b)
|
||||
{
|
||||
@@ -520,6 +552,62 @@ namespace bx
|
||||
return simd_u32_cmplt_ni(_a, _b);
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_avx_t simd256_i32_div(simd256_avx_t _a, simd256_avx_t _b)
|
||||
{
|
||||
const simd128_sse_t alo = _mm256_castps256_ps128(_a);
|
||||
const simd128_sse_t blo = _mm256_castps256_ps128(_b);
|
||||
const simd128_sse_t ahi = _mm256_extractf128_ps(_a, 1);
|
||||
const simd128_sse_t bhi = _mm256_extractf128_ps(_b, 1);
|
||||
const simd128_sse_t lo = simd128_i32_div(alo, blo);
|
||||
const simd128_sse_t hi = simd128_i32_div(ahi, bhi);
|
||||
const simd256_avx_t lo256 = _mm256_castps128_ps256(lo);
|
||||
const simd256_avx_t result = _mm256_insertf128_ps(lo256, hi, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_avx_t simd256_i32_mod(simd256_avx_t _a, simd256_avx_t _b)
|
||||
{
|
||||
const simd128_sse_t alo = _mm256_castps256_ps128(_a);
|
||||
const simd128_sse_t blo = _mm256_castps256_ps128(_b);
|
||||
const simd128_sse_t ahi = _mm256_extractf128_ps(_a, 1);
|
||||
const simd128_sse_t bhi = _mm256_extractf128_ps(_b, 1);
|
||||
const simd128_sse_t lo = simd128_i32_mod(alo, blo);
|
||||
const simd128_sse_t hi = simd128_i32_mod(ahi, bhi);
|
||||
const simd256_avx_t lo256 = _mm256_castps128_ps256(lo);
|
||||
const simd256_avx_t result = _mm256_insertf128_ps(lo256, hi, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_avx_t simd256_u32_div(simd256_avx_t _a, simd256_avx_t _b)
|
||||
{
|
||||
const simd128_sse_t alo = _mm256_castps256_ps128(_a);
|
||||
const simd128_sse_t blo = _mm256_castps256_ps128(_b);
|
||||
const simd128_sse_t ahi = _mm256_extractf128_ps(_a, 1);
|
||||
const simd128_sse_t bhi = _mm256_extractf128_ps(_b, 1);
|
||||
const simd128_sse_t lo = simd128_u32_div(alo, blo);
|
||||
const simd128_sse_t hi = simd128_u32_div(ahi, bhi);
|
||||
const simd256_avx_t lo256 = _mm256_castps128_ps256(lo);
|
||||
const simd256_avx_t result = _mm256_insertf128_ps(lo256, hi, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_avx_t simd256_u32_mod(simd256_avx_t _a, simd256_avx_t _b)
|
||||
{
|
||||
const simd128_sse_t alo = _mm256_castps256_ps128(_a);
|
||||
const simd128_sse_t blo = _mm256_castps256_ps128(_b);
|
||||
const simd128_sse_t ahi = _mm256_extractf128_ps(_a, 1);
|
||||
const simd128_sse_t bhi = _mm256_extractf128_ps(_b, 1);
|
||||
const simd128_sse_t lo = simd128_u32_mod(alo, blo);
|
||||
const simd128_sse_t hi = simd128_u32_mod(ahi, bhi);
|
||||
const simd256_avx_t lo256 = _mm256_castps128_ps256(lo);
|
||||
const simd256_avx_t result = _mm256_insertf128_ps(lo256, hi, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_avx_t simd256_u32_cmpgt(simd256_avx_t _a, simd256_avx_t _b)
|
||||
{
|
||||
@@ -1025,6 +1113,62 @@ namespace bx
|
||||
return simd_u32_cmplt_ni(_a, _b);
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_avx_t simd256_i32_div(simd256_avx_t _a, simd256_avx_t _b)
|
||||
{
|
||||
const simd128_sse_t alo = _mm256_castps256_ps128(_a);
|
||||
const simd128_sse_t blo = _mm256_castps256_ps128(_b);
|
||||
const simd128_sse_t ahi = _mm256_extractf128_ps(_a, 1);
|
||||
const simd128_sse_t bhi = _mm256_extractf128_ps(_b, 1);
|
||||
const simd128_sse_t lo = simd128_i32_div(alo, blo);
|
||||
const simd128_sse_t hi = simd128_i32_div(ahi, bhi);
|
||||
const simd256_avx_t lo256 = _mm256_castps128_ps256(lo);
|
||||
const simd256_avx_t result = _mm256_insertf128_ps(lo256, hi, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_avx_t simd256_i32_mod(simd256_avx_t _a, simd256_avx_t _b)
|
||||
{
|
||||
const simd128_sse_t alo = _mm256_castps256_ps128(_a);
|
||||
const simd128_sse_t blo = _mm256_castps256_ps128(_b);
|
||||
const simd128_sse_t ahi = _mm256_extractf128_ps(_a, 1);
|
||||
const simd128_sse_t bhi = _mm256_extractf128_ps(_b, 1);
|
||||
const simd128_sse_t lo = simd128_i32_mod(alo, blo);
|
||||
const simd128_sse_t hi = simd128_i32_mod(ahi, bhi);
|
||||
const simd256_avx_t lo256 = _mm256_castps128_ps256(lo);
|
||||
const simd256_avx_t result = _mm256_insertf128_ps(lo256, hi, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_avx_t simd256_u32_div(simd256_avx_t _a, simd256_avx_t _b)
|
||||
{
|
||||
const simd128_sse_t alo = _mm256_castps256_ps128(_a);
|
||||
const simd128_sse_t blo = _mm256_castps256_ps128(_b);
|
||||
const simd128_sse_t ahi = _mm256_extractf128_ps(_a, 1);
|
||||
const simd128_sse_t bhi = _mm256_extractf128_ps(_b, 1);
|
||||
const simd128_sse_t lo = simd128_u32_div(alo, blo);
|
||||
const simd128_sse_t hi = simd128_u32_div(ahi, bhi);
|
||||
const simd256_avx_t lo256 = _mm256_castps128_ps256(lo);
|
||||
const simd256_avx_t result = _mm256_insertf128_ps(lo256, hi, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_avx_t simd256_u32_mod(simd256_avx_t _a, simd256_avx_t _b)
|
||||
{
|
||||
const simd128_sse_t alo = _mm256_castps256_ps128(_a);
|
||||
const simd128_sse_t blo = _mm256_castps256_ps128(_b);
|
||||
const simd128_sse_t ahi = _mm256_extractf128_ps(_a, 1);
|
||||
const simd128_sse_t bhi = _mm256_extractf128_ps(_b, 1);
|
||||
const simd128_sse_t lo = simd128_u32_mod(alo, blo);
|
||||
const simd128_sse_t hi = simd128_u32_mod(ahi, bhi);
|
||||
const simd256_avx_t lo256 = _mm256_castps128_ps256(lo);
|
||||
const simd256_avx_t result = _mm256_insertf128_ps(lo256, hi, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_avx_t simd256_u32_cmpgt(simd256_avx_t _a, simd256_avx_t _b)
|
||||
{
|
||||
|
||||
@@ -260,49 +260,28 @@ namespace bx
|
||||
template<>
|
||||
inline BX_CONST_FUNC simd256_ref_t simd256_f32_madd(simd256_ref_t _a, simd256_ref_t _b, simd256_ref_t _c)
|
||||
{
|
||||
#if BX_SIMD_LANGEXT
|
||||
const simd256_f32_langext_t a = bitCast<simd256_f32_langext_t>(_a);
|
||||
const simd256_f32_langext_t b = bitCast<simd256_f32_langext_t>(_b);
|
||||
const simd256_f32_langext_t c = bitCast<simd256_f32_langext_t>(_c);
|
||||
const simd256_f32_langext_t prod = a * b;
|
||||
const simd256_f32_langext_t sum = prod + c;
|
||||
const simd256_ref_t result = bitCast<simd256_ref_t>(sum);
|
||||
simd256_ref_t result;
|
||||
result.lo = simd128_f32_madd(_a.lo, _b.lo, _c.lo);
|
||||
result.hi = simd128_f32_madd(_a.hi, _b.hi, _c.hi);
|
||||
return result;
|
||||
#else
|
||||
return simd_f32_madd_ni(_a, _b, _c);
|
||||
#endif // BX_SIMD_LANGEXT
|
||||
}
|
||||
|
||||
template<>
|
||||
inline BX_CONST_FUNC simd256_ref_t simd256_f32_msub(simd256_ref_t _a, simd256_ref_t _b, simd256_ref_t _c)
|
||||
{
|
||||
#if BX_SIMD_LANGEXT
|
||||
const simd256_f32_langext_t a = bitCast<simd256_f32_langext_t>(_a);
|
||||
const simd256_f32_langext_t b = bitCast<simd256_f32_langext_t>(_b);
|
||||
const simd256_f32_langext_t c = bitCast<simd256_f32_langext_t>(_c);
|
||||
const simd256_f32_langext_t prod = a * b;
|
||||
const simd256_f32_langext_t diff = prod - c;
|
||||
const simd256_ref_t result = bitCast<simd256_ref_t>(diff);
|
||||
simd256_ref_t result;
|
||||
result.lo = simd128_f32_msub(_a.lo, _b.lo, _c.lo);
|
||||
result.hi = simd128_f32_msub(_a.hi, _b.hi, _c.hi);
|
||||
return result;
|
||||
#else
|
||||
return simd_f32_msub_ni(_a, _b, _c);
|
||||
#endif // BX_SIMD_LANGEXT
|
||||
}
|
||||
|
||||
template<>
|
||||
inline BX_CONST_FUNC simd256_ref_t simd256_f32_nmsub(simd256_ref_t _a, simd256_ref_t _b, simd256_ref_t _c)
|
||||
{
|
||||
#if BX_SIMD_LANGEXT
|
||||
const simd256_f32_langext_t a = bitCast<simd256_f32_langext_t>(_a);
|
||||
const simd256_f32_langext_t b = bitCast<simd256_f32_langext_t>(_b);
|
||||
const simd256_f32_langext_t c = bitCast<simd256_f32_langext_t>(_c);
|
||||
const simd256_f32_langext_t prod = a * b;
|
||||
const simd256_f32_langext_t diff = c - prod;
|
||||
const simd256_ref_t result = bitCast<simd256_ref_t>(diff);
|
||||
simd256_ref_t result;
|
||||
result.lo = simd128_f32_nmsub(_a.lo, _b.lo, _c.lo);
|
||||
result.hi = simd128_f32_nmsub(_a.hi, _b.hi, _c.hi);
|
||||
return result;
|
||||
#else
|
||||
return simd_f32_nmsub_ni(_a, _b, _c);
|
||||
#endif // BX_SIMD_LANGEXT
|
||||
}
|
||||
|
||||
template<>
|
||||
@@ -377,10 +356,10 @@ namespace bx
|
||||
inline BX_CONSTEXPR_FUNC simd256_ref_t simd256_f32_rcp_est(simd256_ref_t _a)
|
||||
{
|
||||
#if BX_SIMD_LANGEXT
|
||||
const simd256_f32_langext_t one = {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f};
|
||||
const simd256_f32_langext_t one = {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f};
|
||||
const simd256_f32_langext_t a = bitCast<simd256_f32_langext_t>(_a);
|
||||
const simd256_f32_langext_t quot = one / a;
|
||||
const simd256_ref_t result = bitCast<simd256_ref_t>(quot);
|
||||
const simd256_ref_t result = bitCast<simd256_ref_t>(quot);
|
||||
return result;
|
||||
#else
|
||||
simd256_ref_t result;
|
||||
@@ -432,6 +411,12 @@ namespace bx
|
||||
return simd_f32_floor_ni(_a);
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_ref_t simd256_f32_trunc(simd256_ref_t _a)
|
||||
{
|
||||
return simd_f32_trunc_ni(_a);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline BX_CONSTEXPR_FUNC simd256_ref_t simd256_f32_cmpeq(simd256_ref_t _a, simd256_ref_t _b)
|
||||
{
|
||||
@@ -497,6 +482,40 @@ namespace bx
|
||||
#endif // BX_SIMD_LANGEXT
|
||||
}
|
||||
|
||||
template<>
|
||||
inline BX_CONSTEXPR_FUNC simd256_ref_t simd256_f32_cmple(simd256_ref_t _a, simd256_ref_t _b)
|
||||
{
|
||||
#if BX_SIMD_LANGEXT
|
||||
const simd256_f32_langext_t a = bitCast<simd256_f32_langext_t>(_a);
|
||||
const simd256_f32_langext_t b = bitCast<simd256_f32_langext_t>(_b);
|
||||
const simd256_f32_langext_t cmp = a <= b;
|
||||
const simd256_ref_t result = bitCast<simd256_ref_t>(cmp);
|
||||
return result;
|
||||
#else
|
||||
simd256_ref_t result;
|
||||
result.lo = simd128_f32_cmple(_a.lo, _b.lo);
|
||||
result.hi = simd128_f32_cmple(_a.hi, _b.hi);
|
||||
return result;
|
||||
#endif // BX_SIMD_LANGEXT
|
||||
}
|
||||
|
||||
template<>
|
||||
inline BX_CONSTEXPR_FUNC simd256_ref_t simd256_f32_cmpge(simd256_ref_t _a, simd256_ref_t _b)
|
||||
{
|
||||
#if BX_SIMD_LANGEXT
|
||||
const simd256_f32_langext_t a = bitCast<simd256_f32_langext_t>(_a);
|
||||
const simd256_f32_langext_t b = bitCast<simd256_f32_langext_t>(_b);
|
||||
const simd256_f32_langext_t cmp = a >= b;
|
||||
const simd256_ref_t result = bitCast<simd256_ref_t>(cmp);
|
||||
return result;
|
||||
#else
|
||||
simd256_ref_t result;
|
||||
result.lo = simd128_f32_cmpge(_a.lo, _b.lo);
|
||||
result.hi = simd128_f32_cmpge(_a.hi, _b.hi);
|
||||
return result;
|
||||
#endif // BX_SIMD_LANGEXT
|
||||
}
|
||||
|
||||
template<>
|
||||
inline BX_CONSTEXPR_FUNC simd256_ref_t simd256_i32_add(simd256_ref_t _a, simd256_ref_t _b)
|
||||
{
|
||||
@@ -721,6 +740,42 @@ namespace bx
|
||||
#endif // BX_SIMD_LANGEXT
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_ref_t simd256_i32_div(simd256_ref_t _a, simd256_ref_t _b)
|
||||
{
|
||||
simd256_ref_t result;
|
||||
result.lo = simd128_i32_div(_a.lo, _b.lo);
|
||||
result.hi = simd128_i32_div(_a.hi, _b.hi);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_ref_t simd256_i32_mod(simd256_ref_t _a, simd256_ref_t _b)
|
||||
{
|
||||
simd256_ref_t result;
|
||||
result.lo = simd128_i32_mod(_a.lo, _b.lo);
|
||||
result.hi = simd128_i32_mod(_a.hi, _b.hi);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_ref_t simd256_u32_div(simd256_ref_t _a, simd256_ref_t _b)
|
||||
{
|
||||
simd256_ref_t result;
|
||||
result.lo = simd128_u32_div(_a.lo, _b.lo);
|
||||
result.hi = simd128_u32_div(_a.hi, _b.hi);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_ref_t simd256_u32_mod(simd256_ref_t _a, simd256_ref_t _b)
|
||||
{
|
||||
simd256_ref_t result;
|
||||
result.lo = simd128_u32_mod(_a.lo, _b.lo);
|
||||
result.hi = simd128_u32_mod(_a.hi, _b.hi);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline BX_CONSTEXPR_FUNC simd256_ref_t simd256_u32_cmplt(simd256_ref_t _a, simd256_ref_t _b)
|
||||
{
|
||||
|
||||
@@ -121,31 +121,82 @@ namespace bx
|
||||
return bitCast<simd32_t>(result);
|
||||
}
|
||||
|
||||
BX_FP_PRECISE_BEGIN()
|
||||
|
||||
inline BX_CONSTEXPR_FUNC simd32_t simd32_f32_madd_ref(simd32_t _a, simd32_t _b, simd32_t _c)
|
||||
{
|
||||
const double aa = double(bitCast<simd32_f32_ref_t>(_a).f32);
|
||||
const double bb = double(bitCast<simd32_f32_ref_t>(_b).f32);
|
||||
const double cc = double(bitCast<simd32_f32_ref_t>(_c).f32);
|
||||
const double prod = aa * bb;
|
||||
const double sum = prod + cc;
|
||||
|
||||
const uint64_t sumBits = bitCast<uint64_t>(sum);
|
||||
|
||||
// A non-finite sum is exact; the two-sum below would evaluate Inf - Inf.
|
||||
if (kDoubleExponentMask == (sumBits & kDoubleExponentMask) )
|
||||
{
|
||||
return simd32_ld(float(sum) );
|
||||
}
|
||||
|
||||
const double hi = sum - prod;
|
||||
const double tmp0 = sum - hi;
|
||||
const double tmp1 = prod - tmp0;
|
||||
const double tmp2 = cc - hi;
|
||||
const double err = tmp1 + tmp2;
|
||||
|
||||
const uint64_t bits = bitCast<uint64_t>(sum);
|
||||
const uint64_t exponent = bits & kDoubleExponentMask;
|
||||
const bool inexact = 0.0 != err;
|
||||
const bool even = 0 == (bits & 1);
|
||||
const bool finite = kDoubleExponentMask != exponent;
|
||||
const bool up = (0.0 < err) == (0.0 < sum);
|
||||
const uint64_t nudged = up ? bits + 1 : bits - 1;
|
||||
const uint64_t odd = (inexact && even && finite) ? nudged : bits;
|
||||
const double result = bitCast<double>(odd);
|
||||
|
||||
return simd32_ld(float(result) );
|
||||
}
|
||||
|
||||
BX_FP_PRECISE_END()
|
||||
|
||||
inline BX_CONSTEXPR_FUNC simd32_t simd32_f32_madd(simd32_t _a, simd32_t _b, simd32_t _c)
|
||||
{
|
||||
const simd32_f32_ref_t a = bitCast<simd32_f32_ref_t>(_a);
|
||||
const simd32_f32_ref_t b = bitCast<simd32_f32_ref_t>(_b);
|
||||
const simd32_f32_ref_t c = bitCast<simd32_f32_ref_t>(_c);
|
||||
const simd32_f32_ref_t result = { .f32 = a.f32 * b.f32 + c.f32 };
|
||||
return bitCast<simd32_t>(result);
|
||||
|
||||
if (isConstantEvaluated() )
|
||||
{
|
||||
return simd32_f32_madd_ref(_a, _b, _c);
|
||||
}
|
||||
|
||||
#if BX_CONFIG_FMA
|
||||
# if BX_COMPILER_MSVC
|
||||
const float result = fmaf(a.f32, b.f32, c.f32);
|
||||
# else
|
||||
const float result = __builtin_fmaf(a.f32, b.f32, c.f32);
|
||||
# endif // BX_COMPILER_MSVC
|
||||
return simd32_ld(result);
|
||||
#else
|
||||
const float prod = a.f32 * b.f32;
|
||||
const float result = prod + c.f32;
|
||||
return simd32_ld(result);
|
||||
#endif // BX_CONFIG_FMA
|
||||
}
|
||||
|
||||
inline BX_CONSTEXPR_FUNC simd32_t simd32_f32_msub(simd32_t _a, simd32_t _b, simd32_t _c)
|
||||
{
|
||||
const simd32_f32_ref_t a = bitCast<simd32_f32_ref_t>(_a);
|
||||
const simd32_f32_ref_t b = bitCast<simd32_f32_ref_t>(_b);
|
||||
const simd32_f32_ref_t c = bitCast<simd32_f32_ref_t>(_c);
|
||||
const simd32_f32_ref_t result = { .f32 = a.f32 * b.f32 - c.f32 };
|
||||
return bitCast<simd32_t>(result);
|
||||
const simd32_t nc = simd32_f32_neg(_c);
|
||||
const simd32_t result = simd32_f32_madd(_a, _b, nc);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline BX_CONSTEXPR_FUNC simd32_t simd32_f32_nmsub(simd32_t _a, simd32_t _b, simd32_t _c)
|
||||
{
|
||||
const simd32_f32_ref_t a = bitCast<simd32_f32_ref_t>(_a);
|
||||
const simd32_f32_ref_t b = bitCast<simd32_f32_ref_t>(_b);
|
||||
const simd32_f32_ref_t c = bitCast<simd32_f32_ref_t>(_c);
|
||||
const simd32_f32_ref_t result = { .f32 = c.f32 - a.f32 * b.f32 };
|
||||
return bitCast<simd32_t>(result);
|
||||
const simd32_t na = simd32_f32_neg(_a);
|
||||
const simd32_t result = simd32_f32_madd(na, _b, _c);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline BX_CONSTEXPR_FUNC int simd32_x32_signbitsmask(simd32_t _a)
|
||||
@@ -278,6 +329,13 @@ namespace bx
|
||||
return bitCast<simd32_t>(result);
|
||||
}
|
||||
|
||||
inline BX_CONSTEXPR_FUNC simd32_t simd32_f32_trunc(simd32_t _a)
|
||||
{
|
||||
const simd32_f32_ref_t a = bitCast<simd32_f32_ref_t>(_a);
|
||||
const simd32_f32_ref_t result = { .f32 = trunc(a.f32) };
|
||||
return bitCast<simd32_t>(result);
|
||||
}
|
||||
|
||||
inline BX_CONSTEXPR_FUNC simd32_t simd32_f32_cmpeq(simd32_t _a, simd32_t _b)
|
||||
{
|
||||
const simd32_f32_ref_t a = bitCast<simd32_f32_ref_t>(_a);
|
||||
|
||||
@@ -419,41 +419,36 @@ namespace bx
|
||||
|
||||
inline BX_CONSTEXPR_FUNC simd64_t simd64_f32_madd(simd64_t _a, simd64_t _b, simd64_t _c)
|
||||
{
|
||||
#if BX_SIMD_LANGEXT
|
||||
return bitCast<simd64_t>(bitCast<simd64_f32_langext_t>(_a) * bitCast<simd64_f32_langext_t>(_b) + bitCast<simd64_f32_langext_t>(_c));
|
||||
#else
|
||||
const simd64_f32_ref_t a = bitCast<simd64_f32_ref_t>(_a);
|
||||
const simd64_f32_ref_t b = bitCast<simd64_f32_ref_t>(_b);
|
||||
const simd64_f32_ref_t c = bitCast<simd64_f32_ref_t>(_c);
|
||||
const simd64_f32_ref_t result = { { a.f32[0] * b.f32[0] + c.f32[0], a.f32[1] * b.f32[1] + c.f32[1] } };
|
||||
|
||||
simd64_f32_ref_t result = {};
|
||||
|
||||
for (uint32_t ii = 0; ii < 2; ++ii)
|
||||
{
|
||||
const simd32_t aa = simd32_ld(a.f32[ii]);
|
||||
const simd32_t bb = simd32_ld(b.f32[ii]);
|
||||
const simd32_t cc = simd32_ld(c.f32[ii]);
|
||||
const simd32_t rr = simd32_f32_madd(aa, bb, cc);
|
||||
result.f32[ii] = bitCast<float>(rr);
|
||||
}
|
||||
|
||||
return bitCast<simd64_t>(result);
|
||||
#endif // BX_SIMD_LANGEXT
|
||||
}
|
||||
|
||||
inline BX_CONSTEXPR_FUNC simd64_t simd64_f32_msub(simd64_t _a, simd64_t _b, simd64_t _c)
|
||||
{
|
||||
#if BX_SIMD_LANGEXT
|
||||
return bitCast<simd64_t>(bitCast<simd64_f32_langext_t>(_a) * bitCast<simd64_f32_langext_t>(_b) - bitCast<simd64_f32_langext_t>(_c));
|
||||
#else
|
||||
const simd64_f32_ref_t a = bitCast<simd64_f32_ref_t>(_a);
|
||||
const simd64_f32_ref_t b = bitCast<simd64_f32_ref_t>(_b);
|
||||
const simd64_f32_ref_t c = bitCast<simd64_f32_ref_t>(_c);
|
||||
const simd64_f32_ref_t result = { { a.f32[0] * b.f32[0] - c.f32[0], a.f32[1] * b.f32[1] - c.f32[1] } };
|
||||
return bitCast<simd64_t>(result);
|
||||
#endif // BX_SIMD_LANGEXT
|
||||
const simd64_t nc = simd64_f32_neg(_c);
|
||||
const simd64_t result = simd64_f32_madd(_a, _b, nc);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline BX_CONSTEXPR_FUNC simd64_t simd64_f32_nmsub(simd64_t _a, simd64_t _b, simd64_t _c)
|
||||
{
|
||||
#if BX_SIMD_LANGEXT
|
||||
return bitCast<simd64_t>(bitCast<simd64_f32_langext_t>(_c) - bitCast<simd64_f32_langext_t>(_a) * bitCast<simd64_f32_langext_t>(_b));
|
||||
#else
|
||||
const simd64_f32_ref_t a = bitCast<simd64_f32_ref_t>(_a);
|
||||
const simd64_f32_ref_t b = bitCast<simd64_f32_ref_t>(_b);
|
||||
const simd64_f32_ref_t c = bitCast<simd64_f32_ref_t>(_c);
|
||||
const simd64_f32_ref_t result = { { c.f32[0] - a.f32[0] * b.f32[0], c.f32[1] - a.f32[1] * b.f32[1] } };
|
||||
return bitCast<simd64_t>(result);
|
||||
#endif // BX_SIMD_LANGEXT
|
||||
const simd64_t na = simd64_f32_neg(_a);
|
||||
const simd64_t result = simd64_f32_madd(na, _b, _c);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline BX_CONSTEXPR_FUNC int simd64_x32_signbitsmask(simd64_t _a)
|
||||
@@ -587,6 +582,13 @@ namespace bx
|
||||
return bitCast<simd64_t>(result);
|
||||
}
|
||||
|
||||
inline BX_CONSTEXPR_FUNC simd64_t simd64_f32_trunc(simd64_t _a)
|
||||
{
|
||||
const simd64_f32_ref_t a = bitCast<simd64_f32_ref_t>(_a);
|
||||
const simd64_f32_ref_t result = { { trunc(a.f32[0]), trunc(a.f32[1]) } };
|
||||
return bitCast<simd64_t>(result);
|
||||
}
|
||||
|
||||
inline BX_CONSTEXPR_FUNC simd64_t simd64_f32_cmpeq(simd64_t _a, simd64_t _b)
|
||||
{
|
||||
#if BX_SIMD_LANGEXT
|
||||
|
||||
@@ -48,6 +48,7 @@ namespace bx
|
||||
BX_CONSTEXPR_FUNC simd32_t simd32_f32_round(simd32_t _a);
|
||||
BX_CONSTEXPR_FUNC simd32_t simd32_f32_ceil(simd32_t _a);
|
||||
BX_CONSTEXPR_FUNC simd32_t simd32_f32_floor(simd32_t _a);
|
||||
BX_CONSTEXPR_FUNC simd32_t simd32_f32_trunc(simd32_t _a);
|
||||
|
||||
BX_CONSTEXPR_FUNC simd32_t simd32_f32_cmpeq(simd32_t _a, simd32_t _b);
|
||||
BX_CONSTEXPR_FUNC simd32_t simd32_f32_cmpneq(simd32_t _a, simd32_t _b);
|
||||
@@ -182,6 +183,7 @@ namespace bx
|
||||
BX_CONSTEXPR_FUNC simd64_t simd64_f32_round(simd64_t _a);
|
||||
BX_CONSTEXPR_FUNC simd64_t simd64_f32_ceil(simd64_t _a);
|
||||
BX_CONSTEXPR_FUNC simd64_t simd64_f32_floor(simd64_t _a);
|
||||
BX_CONSTEXPR_FUNC simd64_t simd64_f32_trunc(simd64_t _a);
|
||||
BX_CONSTEXPR_FUNC simd64_t simd64_f32_cmpeq(simd64_t _a, simd64_t _b);
|
||||
BX_CONSTEXPR_FUNC simd64_t simd64_f32_cmpneq(simd64_t _a, simd64_t _b);
|
||||
BX_CONSTEXPR_FUNC simd64_t simd64_f32_cmplt(simd64_t _a, simd64_t _b);
|
||||
@@ -483,6 +485,11 @@ namespace bx
|
||||
template<typename Ty>
|
||||
Ty simd128_f32_floor(Ty _a);
|
||||
|
||||
/// 4xf32 truncate toward zero.
|
||||
///
|
||||
template<typename Ty>
|
||||
Ty simd128_f32_trunc(Ty _a);
|
||||
|
||||
/// 4xf32 compare equal (returns mask).
|
||||
///
|
||||
template<typename Ty>
|
||||
@@ -618,6 +625,26 @@ namespace bx
|
||||
template<typename Ty>
|
||||
Ty simd128_u32_clamp(Ty _a, Ty _min, Ty _max);
|
||||
|
||||
/// 4xi32 division, x / 0 == x and INT32_MIN / -1 == INT32_MIN.
|
||||
///
|
||||
template<typename Ty>
|
||||
Ty simd128_i32_div(Ty _a, Ty _b);
|
||||
|
||||
/// 4xi32 remainder, x % 0 == 0 and INT32_MIN % -1 == 0.
|
||||
///
|
||||
template<typename Ty>
|
||||
Ty simd128_i32_mod(Ty _a, Ty _b);
|
||||
|
||||
/// 4xu32 division, x / 0 == x.
|
||||
///
|
||||
template<typename Ty>
|
||||
Ty simd128_u32_div(Ty _a, Ty _b);
|
||||
|
||||
/// 4xu32 remainder, x % 0 == 0.
|
||||
///
|
||||
template<typename Ty>
|
||||
Ty simd128_u32_mod(Ty _a, Ty _b);
|
||||
|
||||
/// 4xu32 compare equal.
|
||||
///
|
||||
template<typename Ty>
|
||||
@@ -996,6 +1023,7 @@ namespace bx
|
||||
template<typename Ty> Ty simd256_f32_round(Ty _a);
|
||||
template<typename Ty> Ty simd256_f32_ceil(Ty _a);
|
||||
template<typename Ty> Ty simd256_f32_floor(Ty _a);
|
||||
template<typename Ty> Ty simd256_f32_trunc(Ty _a);
|
||||
template<typename Ty> Ty simd256_f32_cmpeq(Ty _a, Ty _b);
|
||||
template<typename Ty> Ty simd256_f32_cmpneq(Ty _a, Ty _b);
|
||||
template<typename Ty> Ty simd256_f32_cmplt(Ty _a, Ty _b);
|
||||
@@ -1017,6 +1045,10 @@ namespace bx
|
||||
template<typename Ty> Ty simd256_u32_min(Ty _a, Ty _b);
|
||||
template<typename Ty> Ty simd256_u32_max(Ty _a, Ty _b);
|
||||
template<typename Ty> Ty simd256_u32_clamp(Ty _a, Ty _min, Ty _max);
|
||||
template<typename Ty> Ty simd256_i32_div(Ty _a, Ty _b);
|
||||
template<typename Ty> Ty simd256_i32_mod(Ty _a, Ty _b);
|
||||
template<typename Ty> Ty simd256_u32_div(Ty _a, Ty _b);
|
||||
template<typename Ty> Ty simd256_u32_mod(Ty _a, Ty _b);
|
||||
template<typename Ty> Ty simd256_u32_cmpeq(Ty _a, Ty _b);
|
||||
template<typename Ty> Ty simd256_u32_cmplt(Ty _a, Ty _b);
|
||||
template<typename Ty> Ty simd256_u32_cmpgt(Ty _a, Ty _b);
|
||||
@@ -1220,6 +1252,48 @@ namespace bx
|
||||
template<typename Ty>
|
||||
Ty simd_f32_exp_ni(Ty _a);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_f32_trunc_ni(Ty _a);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_f32_fract_ni(Ty _a);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_f32_sign_ni(Ty _a);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_f32_step_ni(Ty _edge, Ty _a);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_f32_smoothstep_ni(Ty _a);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_f32_mod_ni(Ty _a, Ty _b);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_f32_tan_ni(Ty _a);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_f32_acos_ni(Ty _a);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_f32_asin_ni(Ty _a);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_f32_atan2_ni(Ty _y, Ty _x);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_f32_atan_ni(Ty _a);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_f32_sinh_ni(Ty _a);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_f32_cosh_ni(Ty _a);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_f32_tanh_ni(Ty _a);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_f32_cmpneq_ni(Ty _a, Ty _b);
|
||||
|
||||
@@ -1271,6 +1345,63 @@ namespace bx
|
||||
template<typename Ty>
|
||||
Ty simd_u32_cntlz_ni(Ty _a);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_u32_cntbits_ni(Ty _a);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_u32_cnttz_ni(Ty _a);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_u32_reversebits_ni(Ty _a);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_i32_cmpneq_ni(Ty _a, Ty _b);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_i32_cmple_ni(Ty _a, Ty _b);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_i32_cmpge_ni(Ty _a, Ty _b);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_u32_cmpneq_ni(Ty _a, Ty _b);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_u32_cmple_ni(Ty _a, Ty _b);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_u32_cmpge_ni(Ty _a, Ty _b);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_u32_min_ni(Ty _a, Ty _b);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_u32_max_ni(Ty _a, Ty _b);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_u32_clamp_ni(Ty _a, Ty _min, Ty _max);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_i32_div_ni(Ty _a, Ty _b);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_i32_mod_ni(Ty _a, Ty _b);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_u32_div_ni(Ty _a, Ty _b);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_u32_mod_ni(Ty _a, Ty _b);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_f32_ftoi_sat_ni(Ty _a);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_f32_ftou_sat_ni(Ty _a);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_u32_utof_ni(Ty _a);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_x32_srl_ni(Ty _a, Ty _count);
|
||||
|
||||
@@ -1294,14 +1425,14 @@ namespace bx
|
||||
|
||||
} // namespace bx
|
||||
|
||||
#if BX_SIMD_AVX
|
||||
# include "simd256_avx.inl"
|
||||
#endif // BX_SIMD_AVX
|
||||
|
||||
#if BX_SIMD_SSE
|
||||
# include "simd128_sse.inl"
|
||||
#endif // BX_SIMD_SSE
|
||||
|
||||
#if BX_SIMD_AVX
|
||||
# include "simd256_avx.inl" // After SSE: 256-bit fallbacks use the 128-bit ops.
|
||||
#endif // BX_SIMD_AVX
|
||||
|
||||
#if BX_SIMD_NEON
|
||||
# include "simd128_neon.inl"
|
||||
#endif // BX_SIMD_NEON
|
||||
@@ -1315,6 +1446,7 @@ namespace bx
|
||||
BX_CONSTEXPR_FUNC float floor(float _f);
|
||||
BX_CONSTEXPR_FUNC float ceil(float _f);
|
||||
BX_CONSTEXPR_FUNC float round(float _f);
|
||||
BX_CONSTEXPR_FUNC float trunc(float _f);
|
||||
BX_CONSTEXPR_FUNC float sqrt(float _a);
|
||||
} // namespace bx
|
||||
|
||||
@@ -1490,10 +1622,10 @@ namespace bx
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_f32_cmpneq(simd128_t _a, simd128_t _b) { return simd128_f32_cmpneq(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_f32_cmple(simd128_t _a, simd128_t _b) { return simd128_f32_cmpgt(_b, _a); }
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_f32_cmple(simd128_t _a, simd128_t _b) { return simd128_f32_cmple(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_f32_cmpge(simd128_t _a, simd128_t _b) { return simd128_f32_cmplt(_b, _a); }
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_f32_cmpge(simd128_t _a, simd128_t _b) { return simd128_f32_cmpge(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_f32_clamp(simd128_t _a, simd128_t _min, simd128_t _max) { return simd128_f32_clamp(_a, _min, _max); }
|
||||
@@ -1528,6 +1660,48 @@ namespace bx
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_f32_ldexp(simd128_t _a, simd128_t _b) { return simd_f32_ldexp_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_f32_trunc(simd128_t _a) { return simd128_f32_trunc(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_f32_fract(simd128_t _a) { return simd_f32_fract_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_f32_sign(simd128_t _a) { return simd_f32_sign_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_f32_step(simd128_t _edge, simd128_t _a) { return simd_f32_step_ni(_edge, _a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_f32_smoothstep(simd128_t _a) { return simd_f32_smoothstep_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_f32_mod(simd128_t _a, simd128_t _b) { return simd_f32_mod_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_f32_tan(simd128_t _a) { return simd_f32_tan_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_f32_acos(simd128_t _a) { return simd_f32_acos_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_f32_asin(simd128_t _a) { return simd_f32_asin_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_f32_atan2(simd128_t _y, simd128_t _x) { return simd_f32_atan2_ni(_y, _x); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_f32_atan(simd128_t _a) { return simd_f32_atan_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_f32_sinh(simd128_t _a) { return simd_f32_sinh_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_f32_cosh(simd128_t _a) { return simd_f32_cosh_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_f32_tanh(simd128_t _a) { return simd_f32_tanh_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_f32_log2(simd128_t _a) { return simd_f32_log2_ni(_a); }
|
||||
|
||||
@@ -1648,6 +1822,72 @@ namespace bx
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_u32_cmpgt(simd128_t _a, simd128_t _b) { return simd128_u32_cmpgt(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_i32_cmpneq(simd128_t _a, simd128_t _b) { return simd_i32_cmpneq_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_i32_cmple(simd128_t _a, simd128_t _b) { return simd_i32_cmple_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_i32_cmpge(simd128_t _a, simd128_t _b) { return simd_i32_cmpge_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_u32_cmpneq(simd128_t _a, simd128_t _b) { return simd_u32_cmpneq_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_u32_cmple(simd128_t _a, simd128_t _b) { return simd_u32_cmple_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_u32_cmpge(simd128_t _a, simd128_t _b) { return simd_u32_cmpge_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_u32_min(simd128_t _a, simd128_t _b) { return simd128_u32_min(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_u32_max(simd128_t _a, simd128_t _b) { return simd128_u32_max(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_u32_clamp(simd128_t _a, simd128_t _min, simd128_t _max) { return simd128_u32_clamp(_a, _min, _max); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_i32_div(simd128_t _a, simd128_t _b) { return simd128_i32_div(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_i32_mod(simd128_t _a, simd128_t _b) { return simd128_i32_mod(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_u32_div(simd128_t _a, simd128_t _b) { return simd128_u32_div(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_u32_mod(simd128_t _a, simd128_t _b) { return simd128_u32_mod(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_f32_ftoi_sat(simd128_t _a) { return simd_f32_ftoi_sat_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_f32_ftou_sat(simd128_t _a) { return simd_f32_ftou_sat_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_u32_utof(simd128_t _a) { return simd_u32_utof_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_u32_cntlz(simd128_t _a) { return simd_u32_cntlz_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_u32_cnttz(simd128_t _a) { return simd_u32_cnttz_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_u32_cntbits(simd128_t _a) { return simd_u32_cntbits_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_u32_reversebits(simd128_t _a) { return simd_u32_reversebits_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_f16_fromf32(simd128_t _a) { return simd_f16_fromf32_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_f16_tof32(simd128_t _a) { return simd_f16_tof32_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_t simd_orc(simd128_t _a, simd128_t _b) { return simd128_orc(_a, _b); }
|
||||
|
||||
@@ -1663,6 +1903,20 @@ namespace bx
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE void simd_stu(void* _ptr, simd128_t _a) { simd128_stu(_ptr, _a); }
|
||||
|
||||
#if BX_SIMD_SSE || BX_SIMD_NEON || BX_SIMD_WASM
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_ref_t simd_ld<simd128_ref_t>(const void* _ptr) { return simd128_ld<simd128_ref_t>(_ptr); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd128_ref_t simd_ldu<simd128_ref_t>(const void* _ptr) { return simd128_ldu<simd128_ref_t>(_ptr); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE void simd_st(void* _ptr, simd128_ref_t _a) { simd128_st(_ptr, _a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE void simd_stu(void* _ptr, simd128_ref_t _a) { simd128_stu(_ptr, _a); }
|
||||
#endif // BX_SIMD_SSE || BX_SIMD_NEON || BX_SIMD_WASM
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE void simd_x32_st1(void* _ptr, simd128_t _a) { simd128_x32_st1(_ptr, _a); }
|
||||
|
||||
@@ -1781,10 +2035,10 @@ namespace bx
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_f32_cmpneq(simd256_t _a, simd256_t _b) { return simd256_f32_cmpneq(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_f32_cmple(simd256_t _a, simd256_t _b) { return simd256_f32_cmpgt(_b, _a); }
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_f32_cmple(simd256_t _a, simd256_t _b) { return simd256_f32_cmple(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_f32_cmpge(simd256_t _a, simd256_t _b) { return simd256_f32_cmplt(_b, _a); }
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_f32_cmpge(simd256_t _a, simd256_t _b) { return simd256_f32_cmpge(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_f32_clamp(simd256_t _a, simd256_t _min, simd256_t _max) { return simd256_f32_clamp(_a, _min, _max); }
|
||||
@@ -1819,6 +2073,48 @@ namespace bx
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_f32_ldexp(simd256_t _a, simd256_t _b) { return simd_f32_ldexp_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_f32_trunc(simd256_t _a) { return simd256_f32_trunc(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_f32_fract(simd256_t _a) { return simd_f32_fract_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_f32_sign(simd256_t _a) { return simd_f32_sign_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_f32_step(simd256_t _edge, simd256_t _a) { return simd_f32_step_ni(_edge, _a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_f32_smoothstep(simd256_t _a) { return simd_f32_smoothstep_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_f32_mod(simd256_t _a, simd256_t _b) { return simd_f32_mod_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_f32_tan(simd256_t _a) { return simd_f32_tan_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_f32_acos(simd256_t _a) { return simd_f32_acos_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_f32_asin(simd256_t _a) { return simd_f32_asin_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_f32_atan2(simd256_t _y, simd256_t _x) { return simd_f32_atan2_ni(_y, _x); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_f32_atan(simd256_t _a) { return simd_f32_atan_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_f32_sinh(simd256_t _a) { return simd_f32_sinh_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_f32_cosh(simd256_t _a) { return simd_f32_cosh_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_f32_tanh(simd256_t _a) { return simd_f32_tanh_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_f32_log2(simd256_t _a) { return simd_f32_log2_ni(_a); }
|
||||
|
||||
@@ -1936,6 +2232,72 @@ namespace bx
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_u32_cmplt(simd256_t _a, simd256_t _b) { return simd256_u32_cmplt(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_i32_cmpneq(simd256_t _a, simd256_t _b) { return simd_i32_cmpneq_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_i32_cmple(simd256_t _a, simd256_t _b) { return simd_i32_cmple_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_i32_cmpge(simd256_t _a, simd256_t _b) { return simd_i32_cmpge_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_u32_cmpneq(simd256_t _a, simd256_t _b) { return simd_u32_cmpneq_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_u32_cmple(simd256_t _a, simd256_t _b) { return simd_u32_cmple_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_u32_cmpge(simd256_t _a, simd256_t _b) { return simd_u32_cmpge_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_u32_min(simd256_t _a, simd256_t _b) { return simd256_u32_min(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_u32_max(simd256_t _a, simd256_t _b) { return simd256_u32_max(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_u32_clamp(simd256_t _a, simd256_t _min, simd256_t _max) { return simd256_u32_clamp(_a, _min, _max); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_i32_div(simd256_t _a, simd256_t _b) { return simd256_i32_div(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_i32_mod(simd256_t _a, simd256_t _b) { return simd256_i32_mod(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_u32_div(simd256_t _a, simd256_t _b) { return simd256_u32_div(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_u32_mod(simd256_t _a, simd256_t _b) { return simd256_u32_mod(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_f32_ftoi_sat(simd256_t _a) { return simd_f32_ftoi_sat_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_f32_ftou_sat(simd256_t _a) { return simd_f32_ftou_sat_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_u32_utof(simd256_t _a) { return simd_u32_utof_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_u32_cntlz(simd256_t _a) { return simd_u32_cntlz_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_u32_cnttz(simd256_t _a) { return simd_u32_cnttz_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_u32_cntbits(simd256_t _a) { return simd_u32_cntbits_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_u32_reversebits(simd256_t _a) { return simd_u32_reversebits_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_f16_fromf32(simd256_t _a) { return simd_f16_fromf32_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_f16_tof32(simd256_t _a) { return simd_f16_tof32_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_t simd_u32_cmpgt(simd256_t _a, simd256_t _b) { return simd256_u32_cmpgt(_a, _b); }
|
||||
|
||||
@@ -1954,6 +2316,20 @@ namespace bx
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE void simd_stu(void* _ptr, simd256_t _a) { simd256_stu(_ptr, _a); }
|
||||
|
||||
#if BX_SIMD_AVX
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_ref_t simd_ld<simd256_ref_t>(const void* _ptr) { return simd256_ld<simd256_ref_t>(_ptr); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd256_ref_t simd_ldu<simd256_ref_t>(const void* _ptr) { return simd256_ldu<simd256_ref_t>(_ptr); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE void simd_st(void* _ptr, simd256_ref_t _a) { simd256_st(_ptr, _a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE void simd_stu(void* _ptr, simd256_ref_t _a) { simd256_stu(_ptr, _a); }
|
||||
#endif // BX_SIMD_AVX
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE void simd_x32_st1(void* _ptr, simd256_t _a) { simd256_x32_st1(_ptr, _a); }
|
||||
|
||||
@@ -2091,6 +2467,72 @@ namespace bx
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_u32_cmplt(simd32_t _a, simd32_t _b) { return simd32_u32_cmplt(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_i32_cmpneq(simd32_t _a, simd32_t _b) { return simd_i32_cmpneq_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_i32_cmple(simd32_t _a, simd32_t _b) { return simd_i32_cmple_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_i32_cmpge(simd32_t _a, simd32_t _b) { return simd_i32_cmpge_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_u32_cmpneq(simd32_t _a, simd32_t _b) { return simd_u32_cmpneq_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_u32_cmple(simd32_t _a, simd32_t _b) { return simd_u32_cmple_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_u32_cmpge(simd32_t _a, simd32_t _b) { return simd_u32_cmpge_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_u32_min(simd32_t _a, simd32_t _b) { return simd_u32_min_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_u32_max(simd32_t _a, simd32_t _b) { return simd_u32_max_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_u32_clamp(simd32_t _a, simd32_t _min, simd32_t _max) { return simd_u32_clamp_ni(_a, _min, _max); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_i32_div(simd32_t _a, simd32_t _b) { return simd_i32_div_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_i32_mod(simd32_t _a, simd32_t _b) { return simd_i32_mod_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_u32_div(simd32_t _a, simd32_t _b) { return simd_u32_div_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_u32_mod(simd32_t _a, simd32_t _b) { return simd_u32_mod_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_f32_ftoi_sat(simd32_t _a) { return simd_f32_ftoi_sat_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_f32_ftou_sat(simd32_t _a) { return simd_f32_ftou_sat_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_u32_utof(simd32_t _a) { return simd_u32_utof_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_u32_cntlz(simd32_t _a) { return simd_u32_cntlz_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_u32_cnttz(simd32_t _a) { return simd_u32_cnttz_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_u32_cntbits(simd32_t _a) { return simd_u32_cntbits_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_u32_reversebits(simd32_t _a) { return simd_u32_reversebits_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_f16_fromf32(simd32_t _a) { return simd_f16_fromf32_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_f16_tof32(simd32_t _a) { return simd_f16_tof32_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_u32_cmpgt(simd32_t _a, simd32_t _b) { return simd32_u32_cmpgt(_a, _b); }
|
||||
|
||||
@@ -2226,6 +2668,48 @@ namespace bx
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_f32_ldexp(simd32_t _a, simd32_t _b) { return simd_f32_ldexp_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_f32_trunc(simd32_t _a) { return simd32_f32_trunc(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_f32_fract(simd32_t _a) { return simd_f32_fract_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_f32_sign(simd32_t _a) { return simd_f32_sign_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_f32_step(simd32_t _edge, simd32_t _a) { return simd_f32_step_ni(_edge, _a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_f32_smoothstep(simd32_t _a) { return simd_f32_smoothstep_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_f32_mod(simd32_t _a, simd32_t _b) { return simd_f32_mod_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_f32_tan(simd32_t _a) { return simd_f32_tan_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_f32_acos(simd32_t _a) { return simd_f32_acos_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_f32_asin(simd32_t _a) { return simd_f32_asin_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_f32_atan2(simd32_t _y, simd32_t _x) { return simd_f32_atan2_ni(_y, _x); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_f32_atan(simd32_t _a) { return simd_f32_atan_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_f32_sinh(simd32_t _a) { return simd_f32_sinh_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_f32_cosh(simd32_t _a) { return simd_f32_cosh_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_f32_tanh(simd32_t _a) { return simd_f32_tanh_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd32_t simd_f32_ftoi_trunc(simd32_t _a) { return simd32_f32_ftoi_trunc(_a); }
|
||||
|
||||
@@ -2363,6 +2847,72 @@ namespace bx
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_u32_cmplt(simd64_t _a, simd64_t _b) { return simd64_u32_cmplt(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_i32_cmpneq(simd64_t _a, simd64_t _b) { return simd_i32_cmpneq_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_i32_cmple(simd64_t _a, simd64_t _b) { return simd_i32_cmple_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_i32_cmpge(simd64_t _a, simd64_t _b) { return simd_i32_cmpge_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_u32_cmpneq(simd64_t _a, simd64_t _b) { return simd_u32_cmpneq_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_u32_cmple(simd64_t _a, simd64_t _b) { return simd_u32_cmple_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_u32_cmpge(simd64_t _a, simd64_t _b) { return simd_u32_cmpge_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_u32_min(simd64_t _a, simd64_t _b) { return simd_u32_min_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_u32_max(simd64_t _a, simd64_t _b) { return simd_u32_max_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_u32_clamp(simd64_t _a, simd64_t _min, simd64_t _max) { return simd_u32_clamp_ni(_a, _min, _max); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_i32_div(simd64_t _a, simd64_t _b) { return simd_i32_div_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_i32_mod(simd64_t _a, simd64_t _b) { return simd_i32_mod_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_u32_div(simd64_t _a, simd64_t _b) { return simd_u32_div_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_u32_mod(simd64_t _a, simd64_t _b) { return simd_u32_mod_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_f32_ftoi_sat(simd64_t _a) { return simd_f32_ftoi_sat_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_f32_ftou_sat(simd64_t _a) { return simd_f32_ftou_sat_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_u32_utof(simd64_t _a) { return simd_u32_utof_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_u32_cntlz(simd64_t _a) { return simd_u32_cntlz_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_u32_cnttz(simd64_t _a) { return simd_u32_cnttz_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_u32_cntbits(simd64_t _a) { return simd_u32_cntbits_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_u32_reversebits(simd64_t _a) { return simd_u32_reversebits_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_f16_fromf32(simd64_t _a) { return simd_f16_fromf32_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_f16_tof32(simd64_t _a) { return simd_f16_tof32_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_u32_cmpgt(simd64_t _a, simd64_t _b) { return simd64_u32_cmpgt(_a, _b); }
|
||||
|
||||
@@ -2498,6 +3048,48 @@ namespace bx
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_f32_ldexp(simd64_t _a, simd64_t _b) { return simd_f32_ldexp_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_f32_trunc(simd64_t _a) { return simd64_f32_trunc(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_f32_fract(simd64_t _a) { return simd_f32_fract_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_f32_sign(simd64_t _a) { return simd_f32_sign_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_f32_step(simd64_t _edge, simd64_t _a) { return simd_f32_step_ni(_edge, _a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_f32_smoothstep(simd64_t _a) { return simd_f32_smoothstep_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_f32_mod(simd64_t _a, simd64_t _b) { return simd_f32_mod_ni(_a, _b); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_f32_tan(simd64_t _a) { return simd_f32_tan_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_f32_acos(simd64_t _a) { return simd_f32_acos_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_f32_asin(simd64_t _a) { return simd_f32_asin_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_f32_atan2(simd64_t _y, simd64_t _x) { return simd_f32_atan2_ni(_y, _x); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_f32_atan(simd64_t _a) { return simd_f32_atan_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_f32_sinh(simd64_t _a) { return simd_f32_sinh_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_f32_cosh(simd64_t _a) { return simd_f32_cosh_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_f32_tanh(simd64_t _a) { return simd_f32_tanh_ni(_a); }
|
||||
|
||||
template<>
|
||||
BX_SIMD_FORCE_INLINE simd64_t simd_f32_ftoi_trunc(simd64_t _a) { return simd64_f32_ftoi_trunc(_a); }
|
||||
|
||||
|
||||
@@ -29,28 +29,29 @@ namespace bx
|
||||
return result;
|
||||
}
|
||||
|
||||
// Without an fma instruction these round twice: the fastest fallback.
|
||||
// simd32_f32_madd_ref is the exact software fma when that is what is needed.
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_f32_madd_ni(Ty _a, Ty _b, Ty _c)
|
||||
{
|
||||
const Ty mul = simd_f32_mul(_a, _b);
|
||||
const Ty result = simd_f32_add(mul, _c);
|
||||
const Ty prod = simd_f32_mul(_a, _b);
|
||||
const Ty result = simd_f32_add(prod, _c);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_f32_nmsub_ni(Ty _a, Ty _b, Ty _c)
|
||||
{
|
||||
const Ty mul = simd_f32_mul(_a, _b);
|
||||
const Ty result = simd_f32_sub(_c, mul);
|
||||
const Ty prod = simd_f32_mul(_a, _b);
|
||||
const Ty result = simd_f32_sub(_c, prod);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_f32_msub_ni(Ty _a, Ty _b, Ty _c)
|
||||
{
|
||||
const Ty mul = simd_f32_mul(_a, _b);
|
||||
const Ty result = simd_f32_sub(mul, _c);
|
||||
|
||||
const Ty prod = simd_f32_mul(_a, _b);
|
||||
const Ty result = simd_f32_sub(prod, _c);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -451,33 +452,64 @@ namespace bx
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_f32_ceil_ni(Ty _a)
|
||||
{
|
||||
const Ty tmp = simd_f32_ftoi_trunc(_a);
|
||||
const Ty tmp0 = simd_i32_itof(tmp);
|
||||
const Ty mask = simd_f32_cmplt(tmp0, _a);
|
||||
const Ty one = simd_splat<Ty>(1.0f);
|
||||
const Ty tmp1 = simd_and(one, mask);
|
||||
const Ty result = simd_f32_add(tmp0, tmp1);
|
||||
const Ty tmp = simd_f32_ftoi_trunc(_a);
|
||||
const Ty tmp0 = simd_i32_itof(tmp);
|
||||
const Ty mask = simd_f32_cmplt(tmp0, _a);
|
||||
const Ty one = simd_splat<Ty>(1.0f);
|
||||
const Ty tmp1 = simd_and(one, mask);
|
||||
const Ty up = simd_f32_add(tmp0, tmp1);
|
||||
const Ty absmask = simd_splat<Ty>(uint32_t(~kFloatSignMask) );
|
||||
const Ty bigLimit = simd_splat<Ty>(uint32_t(0x4affffff) );
|
||||
const Ty magnitude = simd_and(_a, absmask);
|
||||
const Ty bigMask = simd_u32_cmpgt(magnitude, bigLimit);
|
||||
const Ty rounded = simd_selb(bigMask, _a, up);
|
||||
// float->int->float drops the sign of zero; ceil(-0.5) is -0.0.
|
||||
const Ty signmask = simd_splat<Ty>(kFloatSignMask);
|
||||
const Ty sign = simd_and(_a, signmask);
|
||||
const Ty result = simd_or(rounded, sign);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_f32_floor_ni(Ty _a)
|
||||
{
|
||||
const Ty tmp = simd_f32_ftoi_trunc(_a);
|
||||
const Ty tmp0 = simd_i32_itof(tmp);
|
||||
const Ty mask = simd_f32_cmpgt(tmp0, _a);
|
||||
const Ty one = simd_splat<Ty>(1.0f);
|
||||
const Ty tmp1 = simd_and(one, mask);
|
||||
const Ty result = simd_f32_sub(tmp0, tmp1);
|
||||
const Ty tmp = simd_f32_ftoi_trunc(_a);
|
||||
const Ty tmp0 = simd_i32_itof(tmp);
|
||||
const Ty mask = simd_f32_cmpgt(tmp0, _a);
|
||||
const Ty one = simd_splat<Ty>(1.0f);
|
||||
const Ty tmp1 = simd_and(one, mask);
|
||||
const Ty down = simd_f32_sub(tmp0, tmp1);
|
||||
const Ty absmask = simd_splat<Ty>(uint32_t(~kFloatSignMask) );
|
||||
const Ty bigLimit = simd_splat<Ty>(uint32_t(0x4affffff) );
|
||||
const Ty magnitude = simd_and(_a, absmask);
|
||||
const Ty bigMask = simd_u32_cmpgt(magnitude, bigLimit);
|
||||
const Ty rounded = simd_selb(bigMask, _a, down);
|
||||
const Ty signmask = simd_splat<Ty>(kFloatSignMask);
|
||||
const Ty sign = simd_and(_a, signmask);
|
||||
const Ty result = simd_or(rounded, sign);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_f32_round_ni(Ty _a)
|
||||
{
|
||||
const Ty half = simd_splat<Ty>(0.5f);
|
||||
const Ty tmp0 = simd_f32_add(_a, half);
|
||||
const Ty result = simd_f32_floor(tmp0);
|
||||
const Ty half = simd_splat<Ty>(0.5f);
|
||||
const Ty one = simd_splat<Ty>(1.0f);
|
||||
const Ty ione = simd_splat<Ty>(uint32_t(1) );
|
||||
const Ty signmask = simd_splat<Ty>(kFloatSignMask);
|
||||
const Ty fl = simd_f32_floor(_a);
|
||||
const Ty fr = simd_f32_sub(_a, fl);
|
||||
const Ty gtMask = simd_f32_cmpgt(fr, half);
|
||||
const Ty eqMask = simd_f32_cmpeq(fr, half);
|
||||
const Ty ifl = simd_f32_ftoi_trunc(fl);
|
||||
const Ty lsb = simd_and(ifl, ione);
|
||||
const Ty oddMask = simd_i32_cmpeq(lsb, ione);
|
||||
const Ty tieUp = simd_and(eqMask, oddMask);
|
||||
const Ty upMask = simd_or(gtMask, tieUp);
|
||||
const Ty up = simd_and(upMask, one);
|
||||
const Ty rd = simd_f32_add(fl, up);
|
||||
const Ty asign = simd_and(_a, signmask);
|
||||
const Ty result = simd_or(rd, asign); // rd is 0 or has _a's sign
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -496,6 +528,8 @@ namespace bx
|
||||
return result;
|
||||
}
|
||||
|
||||
BX_FP_PRECISE_BEGIN()
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_f32_cos_ni(Ty _a)
|
||||
{
|
||||
@@ -554,6 +588,197 @@ namespace bx
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_f32_trunc_ni(Ty _a)
|
||||
{
|
||||
const Ty zero = simd_zero<Ty>();
|
||||
const Ty negMask = simd_f32_cmplt(_a, zero);
|
||||
const Ty up = simd_f32_ceil(_a);
|
||||
const Ty down = simd_f32_floor(_a);
|
||||
const Ty result = simd_selb(negMask, up, down);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_f32_fract_ni(Ty _a)
|
||||
{
|
||||
const Ty whole = simd_f32_trunc(_a);
|
||||
const Ty result = simd_f32_sub(_a, whole);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_f32_sign_ni(Ty _a)
|
||||
{
|
||||
const Ty zero = simd_zero<Ty>();
|
||||
const Ty one = simd_splat<Ty>(1.0f);
|
||||
const Ty posMask = simd_f32_cmpgt(_a, zero);
|
||||
const Ty negMask = simd_f32_cmplt(_a, zero);
|
||||
const Ty pos = simd_and(posMask, one);
|
||||
const Ty neg = simd_and(negMask, one);
|
||||
const Ty result = simd_f32_sub(pos, neg);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_f32_step_ni(Ty _edge, Ty _a)
|
||||
{
|
||||
const Ty one = simd_splat<Ty>(1.0f);
|
||||
const Ty ltMask = simd_f32_cmplt(_a, _edge);
|
||||
const Ty result = simd_andc(one, ltMask);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_f32_smoothstep_ni(Ty _a)
|
||||
{
|
||||
const Ty two = simd_splat<Ty>(2.0f);
|
||||
const Ty three = simd_splat<Ty>(3.0f);
|
||||
const Ty sq = simd_f32_mul(_a, _a);
|
||||
const Ty twoA = simd_f32_mul(two, _a);
|
||||
const Ty tmp0 = simd_f32_sub(three, twoA);
|
||||
const Ty result = simd_f32_mul(sq, tmp0);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_f32_mod_ni(Ty _a, Ty _b)
|
||||
{
|
||||
const Ty quotient = simd_f32_div(_a, _b);
|
||||
const Ty whole = simd_f32_floor(quotient);
|
||||
const Ty result = simd_f32_nmsub(_b, whole, _a);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_f32_tan_ni(Ty _a)
|
||||
{
|
||||
const Ty sine = simd_f32_sin(_a);
|
||||
const Ty cosine = simd_f32_cos(_a);
|
||||
const Ty result = simd_f32_div(sine, cosine);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_f32_acos_ni(Ty _a)
|
||||
{
|
||||
const Ty acosC0 = simd_splat<Ty>( 1.5707288f);
|
||||
const Ty acosC1 = simd_splat<Ty>(-0.2121144f);
|
||||
const Ty acosC2 = simd_splat<Ty>( 0.0742610f);
|
||||
const Ty acosC3 = simd_splat<Ty>(-0.0187293f);
|
||||
const Ty zero = simd_zero<Ty>();
|
||||
const Ty one = simd_splat<Ty>(1.0f);
|
||||
const Ty two = simd_splat<Ty>(2.0f);
|
||||
const Ty pi = simd_splat<Ty>(kPi);
|
||||
const Ty absa = simd_f32_abs(_a);
|
||||
const Ty tmp0 = simd_f32_madd(acosC3, absa, acosC2);
|
||||
const Ty tmp1 = simd_f32_madd(tmp0, absa, acosC1);
|
||||
const Ty tmp2 = simd_f32_madd(tmp1, absa, acosC0);
|
||||
const Ty rest = simd_f32_sub(one, absa);
|
||||
const Ty root = simd_f32_sqrt(rest);
|
||||
const Ty tmp3 = simd_f32_mul(tmp2, root);
|
||||
const Ty negMask = simd_f32_cmplt(_a, zero);
|
||||
const Ty negate = simd_and(negMask, one);
|
||||
const Ty twoNeg = simd_f32_mul(two, negate);
|
||||
const Ty tmp3n = simd_f32_mul(twoNeg, tmp3);
|
||||
const Ty tmp4 = simd_f32_sub(tmp3, tmp3n);
|
||||
const Ty negPi = simd_f32_mul(negate, pi);
|
||||
const Ty result = simd_f32_add(negPi, tmp4);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_f32_asin_ni(Ty _a)
|
||||
{
|
||||
const Ty pi_half = simd_splat<Ty>(kPiHalf);
|
||||
const Ty ac = simd_f32_acos(_a);
|
||||
const Ty result = simd_f32_sub(pi_half, ac);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_f32_atan2_ni(Ty _y, Ty _x)
|
||||
{
|
||||
const Ty atan2C0 = simd_splat<Ty>(-0.013480470f);
|
||||
const Ty atan2C1 = simd_splat<Ty>( 0.057477314f);
|
||||
const Ty atan2C2 = simd_splat<Ty>(-0.121239071f);
|
||||
const Ty atan2C3 = simd_splat<Ty>( 0.195635925f);
|
||||
const Ty atan2C4 = simd_splat<Ty>(-0.332994597f);
|
||||
const Ty atan2C5 = simd_splat<Ty>( 0.999995630f);
|
||||
const Ty zero = simd_zero<Ty>();
|
||||
const Ty signmask = simd_splat<Ty>(kFloatSignMask);
|
||||
const Ty pi = simd_splat<Ty>(kPi);
|
||||
const Ty pi_half = simd_splat<Ty>(kPiHalf);
|
||||
const Ty ax = simd_f32_abs(_x);
|
||||
const Ty ay = simd_f32_abs(_y);
|
||||
const Ty maxaxy = simd_f32_max(ax, ay);
|
||||
const Ty minaxy = simd_f32_min(ax, ay);
|
||||
const Ty zeroMask = simd_f32_cmpeq(maxaxy, zero);
|
||||
const Ty ysign = simd_and(_y, signmask);
|
||||
const Ty mxy = simd_f32_div(minaxy, maxaxy);
|
||||
const Ty mxysq = simd_f32_mul(mxy, mxy);
|
||||
const Ty tmp0 = simd_f32_madd(atan2C0, mxysq, atan2C1);
|
||||
const Ty tmp1 = simd_f32_madd(tmp0, mxysq, atan2C2);
|
||||
const Ty tmp2 = simd_f32_madd(tmp1, mxysq, atan2C3);
|
||||
const Ty tmp3 = simd_f32_madd(tmp2, mxysq, atan2C4);
|
||||
const Ty tmp4 = simd_f32_madd(tmp3, mxysq, atan2C5);
|
||||
const Ty tmp5 = simd_f32_mul(tmp4, mxy);
|
||||
const Ty gtMask = simd_f32_cmpgt(ay, ax);
|
||||
const Ty fromHalf = simd_f32_sub(pi_half, tmp5);
|
||||
const Ty tmp6 = simd_selb(gtMask, fromHalf, tmp5);
|
||||
const Ty xNegMask = simd_f32_cmplt(_x, zero);
|
||||
const Ty fromPi = simd_f32_sub(pi, tmp6);
|
||||
const Ty tmp7 = simd_selb(xNegMask, fromPi, tmp6);
|
||||
const Ty signed_ = simd_or(tmp7, ysign);
|
||||
const Ty result = simd_selb(zeroMask, ysign, signed_);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_f32_atan_ni(Ty _a)
|
||||
{
|
||||
const Ty one = simd_splat<Ty>(1.0f);
|
||||
const Ty result = simd_f32_atan2(_a, one);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_f32_sinh_ni(Ty _a)
|
||||
{
|
||||
const Ty half = simd_splat<Ty>(0.5f);
|
||||
const Ty na = simd_f32_neg(_a);
|
||||
const Ty ea = simd_f32_exp(_a);
|
||||
const Ty ena = simd_f32_exp(na);
|
||||
const Ty diff = simd_f32_sub(ea, ena);
|
||||
const Ty result = simd_f32_mul(half, diff);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_f32_cosh_ni(Ty _a)
|
||||
{
|
||||
const Ty half = simd_splat<Ty>(0.5f);
|
||||
const Ty na = simd_f32_neg(_a);
|
||||
const Ty ea = simd_f32_exp(_a);
|
||||
const Ty ena = simd_f32_exp(na);
|
||||
const Ty sum = simd_f32_add(ea, ena);
|
||||
const Ty result = simd_f32_mul(half, sum);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_f32_tanh_ni(Ty _a)
|
||||
{
|
||||
const Ty one = simd_splat<Ty>(1.0f);
|
||||
const Ty two = simd_splat<Ty>(2.0f);
|
||||
const Ty twoA = simd_f32_mul(two, _a);
|
||||
const Ty tmp0 = simd_f32_exp(twoA);
|
||||
const Ty tmp1 = simd_f32_sub(tmp0, one);
|
||||
const Ty tmp2 = simd_f32_add(tmp0, one);
|
||||
const Ty result = simd_f32_div(tmp1, tmp2);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_f32_log_ni(Ty _a)
|
||||
{
|
||||
@@ -703,12 +928,14 @@ namespace bx
|
||||
const Ty result0 = simd_or(pwabs, asign);
|
||||
const Ty bmask = simd_f32_cmplt(absb, smallest);
|
||||
const Ty amask = simd_f32_cmplt(absa, smallest);
|
||||
const Ty result1 = simd_selb(bmask, one, result0);
|
||||
const Ty result = simd_selb(amask, zero, result1);
|
||||
const Ty result1 = simd_selb(amask, zero, result0);
|
||||
const Ty result = simd_selb(bmask, one, result1);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
BX_FP_PRECISE_END()
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE bool simd128_test_any_ni(Ty _a)
|
||||
{
|
||||
@@ -801,6 +1028,287 @@ namespace bx
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_u32_cntbits_ni(Ty _a)
|
||||
{
|
||||
const Ty c55 = simd_splat<Ty>(uint32_t(0x55555555) );
|
||||
const Ty c33 = simd_splat<Ty>(uint32_t(0x33333333) );
|
||||
const Ty c0f = simd_splat<Ty>(uint32_t(0x0f0f0f0f) );
|
||||
const Ty c3f = simd_splat<Ty>(uint32_t(0x3f) );
|
||||
|
||||
const Ty p1s = simd_x32_srl(_a, 1);
|
||||
const Ty p1m = simd_and(p1s, c55);
|
||||
const Ty p1 = simd_u32_sub(_a, p1m);
|
||||
|
||||
const Ty p2a = simd_and(p1, c33);
|
||||
const Ty p2s = simd_x32_srl(p1, 2);
|
||||
const Ty p2m = simd_and(p2s, c33);
|
||||
const Ty p2 = simd_u32_add(p2a, p2m);
|
||||
|
||||
const Ty p4s = simd_x32_srl(p2, 4);
|
||||
const Ty p4a = simd_u32_add(p2, p4s);
|
||||
const Ty p4 = simd_and(p4a, c0f);
|
||||
|
||||
const Ty p8s = simd_x32_srl(p4, 8);
|
||||
const Ty p8 = simd_u32_add(p4, p8s);
|
||||
|
||||
const Ty p16s = simd_x32_srl(p8, 16);
|
||||
const Ty p16 = simd_u32_add(p8, p16s);
|
||||
|
||||
const Ty result = simd_and(p16, c3f);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_u32_cnttz_ni(Ty _a)
|
||||
{
|
||||
const Ty one = simd_splat<Ty>(uint32_t(1) );
|
||||
const Ty na = simd_i32_neg(_a);
|
||||
const Ty lowest = simd_and(_a, na);
|
||||
const Ty below = simd_u32_sub(lowest, one);
|
||||
const Ty result = simd_u32_cntbits_ni(below);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_u32_reversebits_ni(Ty _a)
|
||||
{
|
||||
const Ty c55 = simd_splat<Ty>(uint32_t(0x55555555) );
|
||||
const Ty c33 = simd_splat<Ty>(uint32_t(0x33333333) );
|
||||
const Ty c0f = simd_splat<Ty>(uint32_t(0x0f0f0f0f) );
|
||||
const Ty cff = simd_splat<Ty>(uint32_t(0x00ff00ff) );
|
||||
|
||||
const Ty r1a = simd_x32_srl(_a, 1);
|
||||
const Ty r1b = simd_and(r1a, c55);
|
||||
const Ty r1c = simd_and(_a, c55);
|
||||
const Ty r1d = simd_x32_sll(r1c, 1);
|
||||
const Ty r1 = simd_or(r1b, r1d);
|
||||
|
||||
const Ty r2a = simd_x32_srl(r1, 2);
|
||||
const Ty r2b = simd_and(r2a, c33);
|
||||
const Ty r2c = simd_and(r1, c33);
|
||||
const Ty r2d = simd_x32_sll(r2c, 2);
|
||||
const Ty r2 = simd_or(r2b, r2d);
|
||||
|
||||
const Ty r4a = simd_x32_srl(r2, 4);
|
||||
const Ty r4b = simd_and(r4a, c0f);
|
||||
const Ty r4c = simd_and(r2, c0f);
|
||||
const Ty r4d = simd_x32_sll(r4c, 4);
|
||||
const Ty r4 = simd_or(r4b, r4d);
|
||||
|
||||
const Ty r8a = simd_x32_srl(r4, 8);
|
||||
const Ty r8b = simd_and(r8a, cff);
|
||||
const Ty r8c = simd_and(r4, cff);
|
||||
const Ty r8d = simd_x32_sll(r8c, 8);
|
||||
const Ty r8 = simd_or(r8b, r8d);
|
||||
|
||||
const Ty r16a = simd_x32_srl(r8, 16);
|
||||
const Ty r16b = simd_x32_sll(r8, 16);
|
||||
const Ty result = simd_or(r16a, r16b);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_i32_cmpneq_ni(Ty _a, Ty _b)
|
||||
{
|
||||
const Ty eq = simd_i32_cmpeq(_a, _b);
|
||||
const Ty result = simd_not(eq);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_i32_cmple_ni(Ty _a, Ty _b)
|
||||
{
|
||||
const Ty gt = simd_i32_cmpgt(_a, _b);
|
||||
const Ty result = simd_not(gt);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_i32_cmpge_ni(Ty _a, Ty _b)
|
||||
{
|
||||
const Ty lt = simd_i32_cmplt(_a, _b);
|
||||
const Ty result = simd_not(lt);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_u32_cmpneq_ni(Ty _a, Ty _b)
|
||||
{
|
||||
const Ty eq = simd_i32_cmpeq(_a, _b);
|
||||
const Ty result = simd_not(eq);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_u32_cmple_ni(Ty _a, Ty _b)
|
||||
{
|
||||
const Ty gt = simd_u32_cmpgt(_a, _b);
|
||||
const Ty result = simd_not(gt);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_u32_cmpge_ni(Ty _a, Ty _b)
|
||||
{
|
||||
const Ty lt = simd_u32_cmplt(_a, _b);
|
||||
const Ty result = simd_not(lt);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_u32_min_ni(Ty _a, Ty _b)
|
||||
{
|
||||
const Ty ltMask = simd_u32_cmplt(_a, _b);
|
||||
const Ty result = simd_selb(ltMask, _a, _b);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_u32_max_ni(Ty _a, Ty _b)
|
||||
{
|
||||
const Ty gtMask = simd_u32_cmpgt(_a, _b);
|
||||
const Ty result = simd_selb(gtMask, _a, _b);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_u32_clamp_ni(Ty _a, Ty _min, Ty _max)
|
||||
{
|
||||
const Ty lo = simd_u32_max(_a, _min);
|
||||
const Ty result = simd_u32_min(lo, _max);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_i32_div_ni(Ty _a, Ty _b)
|
||||
{
|
||||
constexpr uint32_t kNumLanes = sizeof(Ty)/sizeof(int32_t);
|
||||
|
||||
alignas(sizeof(Ty) ) int32_t a[kNumLanes];
|
||||
alignas(sizeof(Ty) ) int32_t b[kNumLanes];
|
||||
simd_st(a, _a);
|
||||
simd_st(b, _b);
|
||||
|
||||
for (uint32_t ii = 0; ii < kNumLanes; ++ii)
|
||||
{
|
||||
const int32_t aa = a[ii];
|
||||
const int32_t bb = b[ii];
|
||||
a[ii] = 0 == bb ? aa : (INT32_MIN == aa && -1 == bb) ? aa : aa / bb;
|
||||
}
|
||||
|
||||
return simd_ld<Ty>(a);
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_i32_mod_ni(Ty _a, Ty _b)
|
||||
{
|
||||
constexpr uint32_t kNumLanes = sizeof(Ty)/sizeof(int32_t);
|
||||
|
||||
alignas(sizeof(Ty) ) int32_t a[kNumLanes];
|
||||
alignas(sizeof(Ty) ) int32_t b[kNumLanes];
|
||||
simd_st(a, _a);
|
||||
simd_st(b, _b);
|
||||
|
||||
for (uint32_t ii = 0; ii < kNumLanes; ++ii)
|
||||
{
|
||||
const int32_t aa = a[ii];
|
||||
const int32_t bb = b[ii];
|
||||
a[ii] = 0 == bb ? 0 : (INT32_MIN == aa && -1 == bb) ? 0 : aa % bb;
|
||||
}
|
||||
|
||||
return simd_ld<Ty>(a);
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_u32_div_ni(Ty _a, Ty _b)
|
||||
{
|
||||
constexpr uint32_t kNumLanes = sizeof(Ty)/sizeof(uint32_t);
|
||||
|
||||
alignas(sizeof(Ty) ) uint32_t a[kNumLanes];
|
||||
alignas(sizeof(Ty) ) uint32_t b[kNumLanes];
|
||||
simd_st(a, _a);
|
||||
simd_st(b, _b);
|
||||
|
||||
for (uint32_t ii = 0; ii < kNumLanes; ++ii)
|
||||
{
|
||||
const uint32_t aa = a[ii];
|
||||
const uint32_t bb = b[ii];
|
||||
a[ii] = 0 == bb ? aa : aa / bb;
|
||||
}
|
||||
|
||||
return simd_ld<Ty>(a);
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_u32_mod_ni(Ty _a, Ty _b)
|
||||
{
|
||||
constexpr uint32_t kNumLanes = sizeof(Ty)/sizeof(uint32_t);
|
||||
|
||||
alignas(sizeof(Ty) ) uint32_t a[kNumLanes];
|
||||
alignas(sizeof(Ty) ) uint32_t b[kNumLanes];
|
||||
simd_st(a, _a);
|
||||
simd_st(b, _b);
|
||||
|
||||
for (uint32_t ii = 0; ii < kNumLanes; ++ii)
|
||||
{
|
||||
const uint32_t aa = a[ii];
|
||||
const uint32_t bb = b[ii];
|
||||
a[ii] = 0 == bb ? 0u : aa % bb;
|
||||
}
|
||||
|
||||
return simd_ld<Ty>(a);
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_f32_ftoi_sat_ni(Ty _a)
|
||||
{
|
||||
const Ty two31 = simd_splat<Ty>(2147483648.0f);
|
||||
const Ty intMax = simd_splat<Ty>(uint32_t(0x7fffffff) );
|
||||
const Ty absmask = simd_splat<Ty>(uint32_t(~kFloatSignMask) );
|
||||
const Ty inf = simd_splat<Ty>(kFloatExponentMask);
|
||||
const Ty magnitude = simd_and(_a, absmask);
|
||||
const Ty nanMask = simd_u32_cmpgt(magnitude, inf);
|
||||
const Ty big = simd_f32_cmpge(_a, two31);
|
||||
const Ty trunc = simd_f32_ftoi_trunc(_a);
|
||||
const Ty clamped = simd_selb(big, intMax, trunc);
|
||||
const Ty result = simd_andc(clamped, nanMask);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_f32_ftou_sat_ni(Ty _a)
|
||||
{
|
||||
const Ty zero = simd_zero<Ty>();
|
||||
const Ty two31 = simd_splat<Ty>(2147483648.0f);
|
||||
const Ty two32 = simd_splat<Ty>(4294967296.0f);
|
||||
const Ty topBit = simd_splat<Ty>(uint32_t(0x80000000) );
|
||||
const Ty x = simd_f32_max(_a, zero);
|
||||
const Ty big = simd_f32_cmpge(x, two32);
|
||||
const Ty high = simd_f32_cmpge(x, two31);
|
||||
const Ty shifted = simd_f32_sub(x, two31);
|
||||
const Ty y = simd_selb(high, shifted, x);
|
||||
const Ty trunc = simd_f32_ftoi_trunc(y);
|
||||
const Ty bit = simd_and(high, topBit);
|
||||
const Ty low = simd_or(trunc, bit);
|
||||
const Ty result = simd_or(low, big);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_u32_utof_ni(Ty _a)
|
||||
{
|
||||
const Ty lowMask = simd_splat<Ty>(uint32_t(0xffff) );
|
||||
const Ty two16 = simd_splat<Ty>(65536.0f);
|
||||
const Ty hiBits = simd_x32_srl(_a, 16);
|
||||
const Ty loBits = simd_and(_a, lowMask);
|
||||
const Ty hi = simd_i32_itof(hiBits);
|
||||
const Ty lo = simd_i32_itof(loBits);
|
||||
const Ty hiScaled = simd_f32_mul(hi, two16);
|
||||
const Ty result = simd_f32_add(hiScaled, lo);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<int32_t BitT, typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_x32_bit_mask_ni(Ty _count)
|
||||
{
|
||||
@@ -896,8 +1404,7 @@ namespace bx
|
||||
alignas(32) uint8_t oBuf[sizeof(Ty)];
|
||||
simd_st<Ty>(aBuf, _a);
|
||||
simd_st<Ty>(iBuf, _indices);
|
||||
// Per-16-byte-lane shuffle: matches PSHUFB / vqtbl1q semantics.
|
||||
// For widths < 16 bytes, the lane is the full register.
|
||||
|
||||
constexpr int kLaneBytes = sizeof(Ty) >= 16 ? 16 : int(sizeof(Ty));
|
||||
constexpr int kLaneMask = kLaneBytes - 1;
|
||||
for (int lane = 0; lane < int(sizeof(Ty)); lane += kLaneBytes)
|
||||
@@ -921,11 +1428,9 @@ namespace bx
|
||||
simd_st<Ty>(aBuf, _a);
|
||||
simd_st<Ty>(bBuf, _b);
|
||||
simd_st<Ty>(iBuf, _indices);
|
||||
// Two-source per-16-byte-lane shuffle: indices select from concatenated
|
||||
// [a|b] within the matching 16-byte lane (or full register for < 16 bytes).
|
||||
// Bit 7 of an index byte zeroes the output byte; bits 0..(log2(2*lane)-1)
|
||||
// select within the 2*lane concatenation; remaining bits must be 0.
|
||||
|
||||
constexpr int kLaneBytes = sizeof(Ty) >= 16 ? 16 : int(sizeof(Ty));
|
||||
|
||||
constexpr int kPairMask = (kLaneBytes * 2) - 1;
|
||||
for (int lane = 0; lane < int(sizeof(Ty)); lane += kLaneBytes)
|
||||
{
|
||||
@@ -943,6 +1448,7 @@ namespace bx
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return simd_ld<Ty>(oBuf);
|
||||
}
|
||||
|
||||
|
||||
@@ -178,6 +178,29 @@ extern "C" void* __cdecl _alloca(size_t _size);
|
||||
# define BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC(_x)
|
||||
#endif // BX_COMPILER_
|
||||
|
||||
///
|
||||
#if BX_COMPILER_MSVC
|
||||
# define BX_FP_CONTRACT_OFF_BEGIN()
|
||||
# define BX_FP_CONTRACT_OFF_END()
|
||||
# define BX_FP_PRECISE_BEGIN() __pragma(float_control(push) ) __pragma(float_control(precise, on) ) __pragma(fp_contract(off) )
|
||||
# define BX_FP_PRECISE_END() __pragma(float_control(pop) )
|
||||
#elif BX_COMPILER_CLANG
|
||||
# define BX_FP_CONTRACT_OFF_BEGIN() _Pragma("float_control(push)") _Pragma("clang fp contract(off)")
|
||||
# define BX_FP_CONTRACT_OFF_END() _Pragma("float_control(pop)")
|
||||
# define BX_FP_PRECISE_BEGIN() _Pragma("float_control(push)") _Pragma("float_control(precise, on)") _Pragma("clang fp contract(off)")
|
||||
# define BX_FP_PRECISE_END() _Pragma("float_control(pop)")
|
||||
#elif BX_COMPILER_GCC
|
||||
# define BX_FP_CONTRACT_OFF_BEGIN()
|
||||
# define BX_FP_CONTRACT_OFF_END()
|
||||
# define BX_FP_PRECISE_BEGIN() _Pragma("GCC push_options") _Pragma("GCC optimize(\"no-fast-math\",\"fp-contract=off\")")
|
||||
# define BX_FP_PRECISE_END() _Pragma("GCC pop_options")
|
||||
#else
|
||||
# define BX_FP_CONTRACT_OFF_BEGIN()
|
||||
# define BX_FP_CONTRACT_OFF_END()
|
||||
# define BX_FP_PRECISE_BEGIN()
|
||||
# define BX_FP_PRECISE_END()
|
||||
#endif // BX_COMPILER_
|
||||
|
||||
/// No default constructor.
|
||||
#define BX_CLASS_NO_DEFAULT_CTOR(_class) \
|
||||
_class() = delete
|
||||
|
||||
@@ -566,7 +566,8 @@ namespace bx
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float fract(float _a);
|
||||
|
||||
/// Returns result of negated multiply-sub operation -(_a * _b - _c) -> _c - _a * _b.
|
||||
/// Returns result of negated multiply-sub operation -(_a * _b - _c) -> _c - _a * _b,
|
||||
/// rounded like mad.
|
||||
///
|
||||
/// @param[in] _a First factor.
|
||||
/// @param[in] _b Second factor.
|
||||
|
||||
@@ -72,6 +72,19 @@
|
||||
# define BX_SIMD_AVX 1
|
||||
#endif //
|
||||
|
||||
#if BX_CONFIG_FMA
|
||||
# if BX_CPU_X86
|
||||
# include <immintrin.h> // FMA3
|
||||
# endif // BX_CPU_X86
|
||||
# if BX_COMPILER_MSVC
|
||||
// With /arch:AVX2 MSVC compiles fmaf to a single vfmadd213ss (no CRT call and,
|
||||
// unlike _mm_fmadd_ss, no zeroing of the upper lanes); the CRT's own
|
||||
// declaration is compatible with this one. On ARM64 it compiles to fmadd.
|
||||
extern "C" float fmaf(float, float, float);
|
||||
# pragma intrinsic(fmaf)
|
||||
# endif // BX_COMPILER_MSVC
|
||||
#endif // BX_CONFIG_FMA
|
||||
|
||||
#if BX_CPU_X86 && (defined(__SSE2__) || (BX_COMPILER_MSVC && (BX_ARCH_64BIT || _M_IX86_FP >= 2) ) )
|
||||
# include <emmintrin.h>
|
||||
# include <smmintrin.h> // SSE4.1 minspec is SSE4.2 so always available
|
||||
@@ -733,6 +746,17 @@ namespace bx
|
||||
template<typename Ty>
|
||||
Ty simd_f32_floor(Ty _a);
|
||||
|
||||
/// Per-lane f32 truncation toward zero.
|
||||
///
|
||||
/// @param[in] _a Input register.
|
||||
///
|
||||
/// @returns Per-lane integral value not greater in magnitude than `_a`.
|
||||
///
|
||||
/// @remark Widths: simd32, simd64, simd128, simd256.
|
||||
///
|
||||
template<typename Ty>
|
||||
Ty simd_f32_trunc(Ty _a);
|
||||
|
||||
/// Per-lane f32 base-2 logarithm: `log2(_a)`.
|
||||
///
|
||||
/// @param[in] _a Input register.
|
||||
@@ -823,6 +847,97 @@ namespace bx
|
||||
template<typename Ty>
|
||||
Ty simd_f32_ldexp(Ty _a, Ty _b);
|
||||
|
||||
/// Per-lane f32 fractional part: `_a - trunc(_a)`, as bx::fract.
|
||||
///
|
||||
/// @remark Widths: simd32, simd64, simd128, simd256.
|
||||
///
|
||||
template<typename Ty>
|
||||
Ty simd_f32_fract(Ty _a);
|
||||
|
||||
/// Per-lane f32 sign: -1, 0 or 1, as bx::sign.
|
||||
///
|
||||
/// @remark Widths: simd32, simd64, simd128, simd256.
|
||||
///
|
||||
template<typename Ty>
|
||||
Ty simd_f32_sign(Ty _a);
|
||||
|
||||
/// Per-lane f32 step: 0 where `_a < _edge`, 1 elsewhere, as bx::step.
|
||||
///
|
||||
/// @remark Widths: simd32, simd64, simd128, simd256.
|
||||
///
|
||||
template<typename Ty>
|
||||
Ty simd_f32_step(Ty _edge, Ty _a);
|
||||
|
||||
/// Per-lane f32 Hermite smoothstep: `_a^2 * (3 - 2 * _a)`, as bx::smoothStep.
|
||||
///
|
||||
/// @remark Widths: simd32, simd64, simd128, simd256.
|
||||
///
|
||||
template<typename Ty>
|
||||
Ty simd_f32_smoothstep(Ty _a);
|
||||
|
||||
/// Per-lane f32 remainder: `_a - _b * floor(_a / _b)`, as bx::mod.
|
||||
///
|
||||
/// @remark Widths: simd32, simd64, simd128, simd256.
|
||||
///
|
||||
template<typename Ty>
|
||||
Ty simd_f32_mod(Ty _a, Ty _b);
|
||||
|
||||
/// Per-lane f32 tangent, as bx::tan.
|
||||
///
|
||||
/// @remark Widths: simd32, simd64, simd128, simd256.
|
||||
///
|
||||
template<typename Ty>
|
||||
Ty simd_f32_tan(Ty _a);
|
||||
|
||||
/// Per-lane f32 arc cosine, as bx::acos.
|
||||
///
|
||||
/// @remark Widths: simd32, simd64, simd128, simd256.
|
||||
///
|
||||
template<typename Ty>
|
||||
Ty simd_f32_acos(Ty _a);
|
||||
|
||||
/// Per-lane f32 arc sine, as bx::asin.
|
||||
///
|
||||
/// @remark Widths: simd32, simd64, simd128, simd256.
|
||||
///
|
||||
template<typename Ty>
|
||||
Ty simd_f32_asin(Ty _a);
|
||||
|
||||
/// Per-lane f32 two-argument arc tangent of `_y / _x`, as bx::atan2.
|
||||
///
|
||||
/// @remark Widths: simd32, simd64, simd128, simd256.
|
||||
///
|
||||
template<typename Ty>
|
||||
Ty simd_f32_atan2(Ty _y, Ty _x);
|
||||
|
||||
/// Per-lane f32 arc tangent, as bx::atan.
|
||||
///
|
||||
/// @remark Widths: simd32, simd64, simd128, simd256.
|
||||
///
|
||||
template<typename Ty>
|
||||
Ty simd_f32_atan(Ty _a);
|
||||
|
||||
/// Per-lane f32 hyperbolic sine, as bx::sinh.
|
||||
///
|
||||
/// @remark Widths: simd32, simd64, simd128, simd256.
|
||||
///
|
||||
template<typename Ty>
|
||||
Ty simd_f32_sinh(Ty _a);
|
||||
|
||||
/// Per-lane f32 hyperbolic cosine, as bx::cosh.
|
||||
///
|
||||
/// @remark Widths: simd32, simd64, simd128, simd256.
|
||||
///
|
||||
template<typename Ty>
|
||||
Ty simd_f32_cosh(Ty _a);
|
||||
|
||||
/// Per-lane f32 hyperbolic tangent, as bx::tanh.
|
||||
///
|
||||
/// @remark Widths: simd32, simd64, simd128, simd256.
|
||||
///
|
||||
template<typename Ty>
|
||||
Ty simd_f32_tanh(Ty _a);
|
||||
|
||||
/// Per-lane f32 to i32 conversion with truncation toward zero.
|
||||
///
|
||||
/// @param[in] _a Input f32 register.
|
||||
@@ -1261,6 +1376,109 @@ namespace bx
|
||||
template<typename Ty>
|
||||
Ty simd_u32_cmpgt(Ty _a, Ty _b);
|
||||
|
||||
/// Per-lane i32 compare not-equal, less-or-equal, greater-or-equal (masks).
|
||||
///
|
||||
/// @remark Widths: simd32, simd64, simd128, simd256.
|
||||
///
|
||||
template<typename Ty>
|
||||
Ty simd_i32_cmpneq(Ty _a, Ty _b);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_i32_cmple(Ty _a, Ty _b);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_i32_cmpge(Ty _a, Ty _b);
|
||||
|
||||
/// Per-lane u32 compare not-equal, less-or-equal, greater-or-equal (masks).
|
||||
///
|
||||
/// @remark Widths: simd32, simd64, simd128, simd256.
|
||||
///
|
||||
template<typename Ty>
|
||||
Ty simd_u32_cmpneq(Ty _a, Ty _b);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_u32_cmple(Ty _a, Ty _b);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_u32_cmpge(Ty _a, Ty _b);
|
||||
|
||||
/// Per-lane u32 minimum, maximum and clamp.
|
||||
///
|
||||
/// @remark Widths: simd32, simd64, simd128, simd256.
|
||||
///
|
||||
template<typename Ty>
|
||||
Ty simd_u32_min(Ty _a, Ty _b);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_u32_max(Ty _a, Ty _b);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_u32_clamp(Ty _a, Ty _min, Ty _max);
|
||||
|
||||
/// Per-lane integer division and remainder with the shading-language
|
||||
/// rules: `x / 0 == x`, `x % 0 == 0`, `INT32_MIN / -1 == INT32_MIN` and
|
||||
/// `INT32_MIN % -1 == 0`. Never traps.
|
||||
///
|
||||
/// @remark Widths: simd32, simd64, simd128, simd256.
|
||||
///
|
||||
template<typename Ty>
|
||||
Ty simd_i32_div(Ty _a, Ty _b);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_i32_mod(Ty _a, Ty _b);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_u32_div(Ty _a, Ty _b);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_u32_mod(Ty _a, Ty _b);
|
||||
|
||||
/// Per-lane f32 to i32/u32 conversion, saturating: out of range clamps to
|
||||
/// the type's limits, NaN is 0.
|
||||
///
|
||||
/// @remark Widths: simd32, simd64, simd128, simd256.
|
||||
///
|
||||
template<typename Ty>
|
||||
Ty simd_f32_ftoi_sat(Ty _a);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_f32_ftou_sat(Ty _a);
|
||||
|
||||
/// Per-lane u32 to f32 conversion, correctly rounded.
|
||||
///
|
||||
/// @remark Widths: simd32, simd64, simd128, simd256.
|
||||
///
|
||||
template<typename Ty>
|
||||
Ty simd_u32_utof(Ty _a);
|
||||
|
||||
/// Per-lane bit counts: leading zeros, trailing zeros (32 for a zero lane)
|
||||
/// and set bits; and the bit-reversed lane.
|
||||
///
|
||||
/// @remark Widths: simd32, simd64, simd128, simd256.
|
||||
///
|
||||
template<typename Ty>
|
||||
Ty simd_u32_cntlz(Ty _a);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_u32_cnttz(Ty _a);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_u32_cntbits(Ty _a);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_u32_reversebits(Ty _a);
|
||||
|
||||
/// Per-lane f32 to half (in the low 16 bits of the lane) and back, the same
|
||||
/// bits as bx::halfFromFloat / bx::halfToFloat.
|
||||
///
|
||||
/// @remark Widths: simd32, simd64, simd128, simd256.
|
||||
///
|
||||
template<typename Ty>
|
||||
Ty simd_f16_fromf32(Ty _a);
|
||||
|
||||
template<typename Ty>
|
||||
Ty simd_f16_tof32(Ty _a);
|
||||
|
||||
/// Broadcast float value to all lanes.
|
||||
///
|
||||
/// @param[in] _a Value to broadcast.
|
||||
|
||||
Reference in New Issue
Block a user