diff --git a/include/bx/inline/float4x4_t.inl b/include/bx/inline/float4x4_t.inl index 1e7a3cbf..1c4e7e6c 100644 --- a/include/bx/inline/float4x4_t.inl +++ b/include/bx/inline/float4x4_t.inl @@ -40,99 +40,106 @@ namespace bx BX_SIMD_INLINE void float4x4_mul(float4x4_t* _result, const float4x4_t* _a, const float4x4_t* _b) { -#if BX_SIMD_SUPPORTED - _result->col[0] = simd128_mul(_a->col[0], _b); - _result->col[1] = simd128_mul(_a->col[1], _b); - _result->col[2] = simd128_mul(_a->col[2], _b); - _result->col[3] = simd128_mul(_a->col[3], _b); -#else - const float* aa = (const float*)_a; - const float* bb = (const float*)_b; - float *rr = (float*)_result; + if constexpr (kSimdSupported) + { + _result->col[0] = simd128_mul(_a->col[0], _b); + _result->col[1] = simd128_mul(_a->col[1], _b); + _result->col[2] = simd128_mul(_a->col[2], _b); + _result->col[3] = simd128_mul(_a->col[3], _b); + } + else + { + const float* aa = (const float*)_a; + const float* bb = (const float*)_b; + float *rr = (float*)_result; - rr[ 0] = aa[ 0]*bb[ 0] + aa[ 1]*bb[ 4] + aa[ 2]*bb[ 8] + aa[ 3]*bb[12]; - rr[ 1] = aa[ 0]*bb[ 1] + aa[ 1]*bb[ 5] + aa[ 2]*bb[ 9] + aa[ 3]*bb[13]; - rr[ 2] = aa[ 0]*bb[ 2] + aa[ 1]*bb[ 6] + aa[ 2]*bb[10] + aa[ 3]*bb[14]; - rr[ 3] = aa[ 0]*bb[ 3] + aa[ 1]*bb[ 7] + aa[ 2]*bb[11] + aa[ 3]*bb[15]; + rr[ 0] = aa[ 0]*bb[ 0] + aa[ 1]*bb[ 4] + aa[ 2]*bb[ 8] + aa[ 3]*bb[12]; + rr[ 1] = aa[ 0]*bb[ 1] + aa[ 1]*bb[ 5] + aa[ 2]*bb[ 9] + aa[ 3]*bb[13]; + rr[ 2] = aa[ 0]*bb[ 2] + aa[ 1]*bb[ 6] + aa[ 2]*bb[10] + aa[ 3]*bb[14]; + rr[ 3] = aa[ 0]*bb[ 3] + aa[ 1]*bb[ 7] + aa[ 2]*bb[11] + aa[ 3]*bb[15]; - rr[ 4] = aa[ 4]*bb[ 0] + aa[ 5]*bb[ 4] + aa[ 6]*bb[ 8] + aa[ 7]*bb[12]; - rr[ 5] = aa[ 4]*bb[ 1] + aa[ 5]*bb[ 5] + aa[ 6]*bb[ 9] + aa[ 7]*bb[13]; - rr[ 6] = aa[ 4]*bb[ 2] + aa[ 5]*bb[ 6] + aa[ 6]*bb[10] + aa[ 7]*bb[14]; - rr[ 7] = aa[ 4]*bb[ 3] + aa[ 5]*bb[ 7] + aa[ 6]*bb[11] + aa[ 7]*bb[15]; + rr[ 4] = aa[ 4]*bb[ 0] + aa[ 5]*bb[ 4] + aa[ 6]*bb[ 8] + aa[ 7]*bb[12]; + rr[ 5] = aa[ 4]*bb[ 1] + aa[ 5]*bb[ 5] + aa[ 6]*bb[ 9] + aa[ 7]*bb[13]; + rr[ 6] = aa[ 4]*bb[ 2] + aa[ 5]*bb[ 6] + aa[ 6]*bb[10] + aa[ 7]*bb[14]; + rr[ 7] = aa[ 4]*bb[ 3] + aa[ 5]*bb[ 7] + aa[ 6]*bb[11] + aa[ 7]*bb[15]; - rr[ 8] = aa[ 8]*bb[ 0] + aa[ 9]*bb[ 4] + aa[10]*bb[ 8] + aa[11]*bb[12]; - rr[ 9] = aa[ 8]*bb[ 1] + aa[ 9]*bb[ 5] + aa[10]*bb[ 9] + aa[11]*bb[13]; - rr[10] = aa[ 8]*bb[ 2] + aa[ 9]*bb[ 6] + aa[10]*bb[10] + aa[11]*bb[14]; - rr[11] = aa[ 8]*bb[ 3] + aa[ 9]*bb[ 7] + aa[10]*bb[11] + aa[11]*bb[15]; + rr[ 8] = aa[ 8]*bb[ 0] + aa[ 9]*bb[ 4] + aa[10]*bb[ 8] + aa[11]*bb[12]; + rr[ 9] = aa[ 8]*bb[ 1] + aa[ 9]*bb[ 5] + aa[10]*bb[ 9] + aa[11]*bb[13]; + rr[10] = aa[ 8]*bb[ 2] + aa[ 9]*bb[ 6] + aa[10]*bb[10] + aa[11]*bb[14]; + rr[11] = aa[ 8]*bb[ 3] + aa[ 9]*bb[ 7] + aa[10]*bb[11] + aa[11]*bb[15]; - rr[12] = aa[12]*bb[ 0] + aa[13]*bb[ 4] + aa[14]*bb[ 8] + aa[15]*bb[12]; - rr[13] = aa[12]*bb[ 1] + aa[13]*bb[ 5] + aa[14]*bb[ 9] + aa[15]*bb[13]; - rr[14] = aa[12]*bb[ 2] + aa[13]*bb[ 6] + aa[14]*bb[10] + aa[15]*bb[14]; - rr[15] = aa[12]*bb[ 3] + aa[13]*bb[ 7] + aa[14]*bb[11] + aa[15]*bb[15]; -#endif // BX_SIMD_SUPPORTED + rr[12] = aa[12]*bb[ 0] + aa[13]*bb[ 4] + aa[14]*bb[ 8] + aa[15]*bb[12]; + rr[13] = aa[12]*bb[ 1] + aa[13]*bb[ 5] + aa[14]*bb[ 9] + aa[15]*bb[13]; + rr[14] = aa[12]*bb[ 2] + aa[13]*bb[ 6] + aa[14]*bb[10] + aa[15]*bb[14]; + rr[15] = aa[12]*bb[ 3] + aa[13]*bb[ 7] + aa[14]*bb[11] + aa[15]*bb[15]; + } } BX_SIMD_INLINE void model4x4_mul(float4x4_t* _result, const float4x4_t* _a, const float4x4_t* _b) { -#if BX_SIMD_SUPPORTED - // With SIMD faster to do the general 4x4 form: - float4x4_mul(_result, _a, _b); -#else - const float* aa = (const float*)_a; // aa[ 3] == aa[ 7] == aa[11] == 0.0f, aa[15] = 1.0f - const float* bb = (const float*)_b; // bb[ 3] == bb[ 7] == bb[11] == 0.0f, bb[15] = 1.0f - float *rr = (float*)_result; + if constexpr (kSimdSupported) + { + float4x4_mul(_result, _a, _b); + } + else + { + const float* aa = (const float*)_a; // aa[ 3] == aa[ 7] == aa[11] == 0.0f, aa[15] = 1.0f + const float* bb = (const float*)_b; // bb[ 3] == bb[ 7] == bb[11] == 0.0f, bb[15] = 1.0f + float *rr = (float*)_result; - rr[ 0] = aa[ 0]*bb[ 0] + aa[ 1]*bb[ 4] + aa[ 2]*bb[ 8]; - rr[ 1] = aa[ 0]*bb[ 1] + aa[ 1]*bb[ 5] + aa[ 2]*bb[ 9]; - rr[ 2] = aa[ 0]*bb[ 2] + aa[ 1]*bb[ 6] + aa[ 2]*bb[10]; - rr[ 3] = 0.0f; + rr[ 0] = aa[ 0]*bb[ 0] + aa[ 1]*bb[ 4] + aa[ 2]*bb[ 8]; + rr[ 1] = aa[ 0]*bb[ 1] + aa[ 1]*bb[ 5] + aa[ 2]*bb[ 9]; + rr[ 2] = aa[ 0]*bb[ 2] + aa[ 1]*bb[ 6] + aa[ 2]*bb[10]; + rr[ 3] = 0.0f; - rr[ 4] = aa[ 4]*bb[ 0] + aa[ 5]*bb[ 4] + aa[ 6]*bb[ 8]; - rr[ 5] = aa[ 4]*bb[ 1] + aa[ 5]*bb[ 5] + aa[ 6]*bb[ 9]; - rr[ 6] = aa[ 4]*bb[ 2] + aa[ 5]*bb[ 6] + aa[ 6]*bb[10]; - rr[ 7] = 0.0f; + rr[ 4] = aa[ 4]*bb[ 0] + aa[ 5]*bb[ 4] + aa[ 6]*bb[ 8]; + rr[ 5] = aa[ 4]*bb[ 1] + aa[ 5]*bb[ 5] + aa[ 6]*bb[ 9]; + rr[ 6] = aa[ 4]*bb[ 2] + aa[ 5]*bb[ 6] + aa[ 6]*bb[10]; + rr[ 7] = 0.0f; - rr[ 8] = aa[ 8]*bb[ 0] + aa[ 9]*bb[ 4] + aa[10]*bb[ 8]; - rr[ 9] = aa[ 8]*bb[ 1] + aa[ 9]*bb[ 5] + aa[10]*bb[ 9]; - rr[10] = aa[ 8]*bb[ 2] + aa[ 9]*bb[ 6] + aa[10]*bb[10]; - rr[11] = 0.0f; + rr[ 8] = aa[ 8]*bb[ 0] + aa[ 9]*bb[ 4] + aa[10]*bb[ 8]; + rr[ 9] = aa[ 8]*bb[ 1] + aa[ 9]*bb[ 5] + aa[10]*bb[ 9]; + rr[10] = aa[ 8]*bb[ 2] + aa[ 9]*bb[ 6] + aa[10]*bb[10]; + rr[11] = 0.0f; - rr[12] = aa[12]*bb[ 0] + aa[13]*bb[ 4] + aa[14]*bb[ 8] + bb[12]; - rr[13] = aa[12]*bb[ 1] + aa[13]*bb[ 5] + aa[14]*bb[ 9] + bb[13]; - rr[14] = aa[12]*bb[ 2] + aa[13]*bb[ 6] + aa[14]*bb[10] + bb[14]; - rr[15] = 1.0f; -#endif // BX_SIMD_SUPPORTED + rr[12] = aa[12]*bb[ 0] + aa[13]*bb[ 4] + aa[14]*bb[ 8] + bb[12]; + rr[13] = aa[12]*bb[ 1] + aa[13]*bb[ 5] + aa[14]*bb[ 9] + bb[13]; + rr[14] = aa[12]*bb[ 2] + aa[13]*bb[ 6] + aa[14]*bb[10] + bb[14]; + rr[15] = 1.0f; + } } BX_SIMD_INLINE void model4x4_mul_viewproj4x4(float4x4_t* _result, const float4x4_t* _model, const float4x4_t* _viewProj) { -#if BX_SIMD_SUPPORTED - // With SIMD faster to do the general 4x4 form: - float4x4_mul(_result, _model, _viewProj); -#else - const float* aa = (const float*)_model; // aa[ 3] == aa[ 7] == aa[11] == 0.0f, aa[15] == 1.0f - const float* bb = (const float*)_viewProj; - float *rr = (float*)_result; - rr[ 0] = aa[ 0]*bb[ 0] + aa[ 1]*bb[ 4] + aa[ 2]*bb[ 8]; - rr[ 1] = aa[ 0]*bb[ 1] + aa[ 1]*bb[ 5] + aa[ 2]*bb[ 9]; - rr[ 2] = aa[ 0]*bb[ 2] + aa[ 1]*bb[ 6] + aa[ 2]*bb[10]; - rr[ 3] = aa[ 0]*bb[ 3] + aa[ 1]*bb[ 7] + aa[ 2]*bb[11]; + if constexpr (kSimdSupported) + { + float4x4_mul(_result, _model, _viewProj); + } + else + { + const float* aa = (const float*)_model; // aa[ 3] == aa[ 7] == aa[11] == 0.0f, aa[15] == 1.0f + const float* bb = (const float*)_viewProj; + float *rr = (float*)_result; + rr[ 0] = aa[ 0]*bb[ 0] + aa[ 1]*bb[ 4] + aa[ 2]*bb[ 8]; + rr[ 1] = aa[ 0]*bb[ 1] + aa[ 1]*bb[ 5] + aa[ 2]*bb[ 9]; + rr[ 2] = aa[ 0]*bb[ 2] + aa[ 1]*bb[ 6] + aa[ 2]*bb[10]; + rr[ 3] = aa[ 0]*bb[ 3] + aa[ 1]*bb[ 7] + aa[ 2]*bb[11]; - rr[ 4] = aa[ 4]*bb[ 0] + aa[ 5]*bb[ 4] + aa[ 6]*bb[ 8]; - rr[ 5] = aa[ 4]*bb[ 1] + aa[ 5]*bb[ 5] + aa[ 6]*bb[ 9]; - rr[ 6] = aa[ 4]*bb[ 2] + aa[ 5]*bb[ 6] + aa[ 6]*bb[10]; - rr[ 7] = aa[ 4]*bb[ 3] + aa[ 5]*bb[ 7] + aa[ 6]*bb[11]; + rr[ 4] = aa[ 4]*bb[ 0] + aa[ 5]*bb[ 4] + aa[ 6]*bb[ 8]; + rr[ 5] = aa[ 4]*bb[ 1] + aa[ 5]*bb[ 5] + aa[ 6]*bb[ 9]; + rr[ 6] = aa[ 4]*bb[ 2] + aa[ 5]*bb[ 6] + aa[ 6]*bb[10]; + rr[ 7] = aa[ 4]*bb[ 3] + aa[ 5]*bb[ 7] + aa[ 6]*bb[11]; - rr[ 8] = aa[ 8]*bb[ 0] + aa[ 9]*bb[ 4] + aa[10]*bb[ 8]; - rr[ 9] = aa[ 8]*bb[ 1] + aa[ 9]*bb[ 5] + aa[10]*bb[ 9]; - rr[10] = aa[ 8]*bb[ 2] + aa[ 9]*bb[ 6] + aa[10]*bb[10]; - rr[11] = aa[ 8]*bb[ 3] + aa[ 9]*bb[ 7] + aa[10]*bb[11]; + rr[ 8] = aa[ 8]*bb[ 0] + aa[ 9]*bb[ 4] + aa[10]*bb[ 8]; + rr[ 9] = aa[ 8]*bb[ 1] + aa[ 9]*bb[ 5] + aa[10]*bb[ 9]; + rr[10] = aa[ 8]*bb[ 2] + aa[ 9]*bb[ 6] + aa[10]*bb[10]; + rr[11] = aa[ 8]*bb[ 3] + aa[ 9]*bb[ 7] + aa[10]*bb[11]; - rr[12] = aa[12]*bb[ 0] + aa[13]*bb[ 4] + aa[14]*bb[ 8] + bb[12]; - rr[13] = aa[12]*bb[ 1] + aa[13]*bb[ 5] + aa[14]*bb[ 9] + bb[13]; - rr[14] = aa[12]*bb[ 2] + aa[13]*bb[ 6] + aa[14]*bb[10] + bb[14]; - rr[15] = aa[12]*bb[ 3] + aa[13]*bb[ 7] + aa[14]*bb[11] + bb[15]; -#endif // BX_SIMD_SUPPORTED + rr[12] = aa[12]*bb[ 0] + aa[13]*bb[ 4] + aa[14]*bb[ 8] + bb[12]; + rr[13] = aa[12]*bb[ 1] + aa[13]*bb[ 5] + aa[14]*bb[ 9] + bb[13]; + rr[14] = aa[12]*bb[ 2] + aa[13]*bb[ 6] + aa[14]*bb[10] + bb[14]; + rr[15] = aa[12]*bb[ 3] + aa[13]*bb[ 7] + aa[14]*bb[11] + bb[15]; + } } BX_SIMD_FORCE_INLINE void float4x4_transpose(float4x4_t* _result, const float4x4_t* _mtx) diff --git a/include/bx/inline/math.inl b/include/bx/inline/math.inl index b3975d1a..f62238cd 100644 --- a/include/bx/inline/math.inl +++ b/include/bx/inline/math.inl @@ -24,6 +24,9 @@ extern "C" unsigned char _BitScanReverse64(unsigned long* _Index, unsigned __int extern "C" unsigned char _BitScanForward64(unsigned long* _Index, unsigned __int64 _Mask); # pragma intrinsic(_BitScanForward64) + +extern "C" unsigned __int64 __umulh(unsigned __int64 _a, unsigned __int64 _b); +# pragma intrinsic(__umulh) # endif // BX_ARCH_64BIT #endif // BX_COMPILER_MSVC @@ -232,7 +235,6 @@ namespace bx return ceilT(_a); } -#if BX_SIMD_SUPPORTED inline BX_CONST_FUNC float truncSimd(float _a) { const simd128_t aa = simd_splat(_a); @@ -287,7 +289,6 @@ namespace bx return out[0]; } -#endif // BX_SIMD_SUPPORTED inline BX_CONSTEXPR_FUNC float roundRef(float _a) { @@ -299,7 +300,6 @@ namespace bx return roundT(_a); } -#if BX_SIMD_SUPPORTED inline BX_CONST_FUNC float roundSimd(float _a) { const simd128_t aa = simd_splat(_a); @@ -321,7 +321,6 @@ namespace bx return out[0]; } -#endif // BX_SIMD_SUPPORTED inline BX_CONSTEXPR_FUNC float lerp(float _a, float _b, float _t) { @@ -1084,16 +1083,15 @@ BX_FP_PRECISE_BEGIN() inline BX_CONSTEXPR_FUNC float trunc(float _a) { -#if BX_SIMD_SUPPORTED - if (isConstantEvaluated() ) + if constexpr (kSimdSupported) { - return truncRef(_a); + if (!isConstantEvaluated() ) + { + return truncSimd(_a); + } } - return truncSimd(_a); -#else return truncRef(_a); -#endif // BX_SIMD_SUPPORTED } inline BX_CONSTEXPR_FUNC double trunc(double _a) @@ -1103,86 +1101,80 @@ BX_FP_PRECISE_BEGIN() inline BX_CONSTEXPR_FUNC float floor(float _a) { -#if BX_SIMD_SUPPORTED - if (isConstantEvaluated() ) + if constexpr (kSimdSupported) { - return floorRef(_a); + if (!isConstantEvaluated() ) + { + return floorSimd(_a); + } } - return floorSimd(_a); -#else return floorRef(_a); -#endif // BX_SIMD_SUPPORTED } inline BX_CONSTEXPR_FUNC double floor(double _a) { -#if BX_SIMD_SUPPORTED - if (isConstantEvaluated() ) + if constexpr (kSimdSupported) { - return floorRef(_a); + if (!isConstantEvaluated() ) + { + return floorSimd(_a); + } } - return floorSimd(_a); -#else return floorRef(_a); -#endif // BX_SIMD_SUPPORTED } inline BX_CONSTEXPR_FUNC float ceil(float _a) { -#if BX_SIMD_SUPPORTED - if (isConstantEvaluated() ) + if constexpr (kSimdSupported) { - return ceilRef(_a); + if (!isConstantEvaluated() ) + { + return ceilSimd(_a); + } } - return ceilSimd(_a); -#else return ceilRef(_a); -#endif // BX_SIMD_SUPPORTED } inline BX_CONSTEXPR_FUNC double ceil(double _a) { -#if BX_SIMD_SUPPORTED - if (isConstantEvaluated() ) + if constexpr (kSimdSupported) { - return ceilRef(_a); + if (!isConstantEvaluated() ) + { + return ceilSimd(_a); + } } - return ceilSimd(_a); -#else return ceilRef(_a); -#endif // BX_SIMD_SUPPORTED } inline BX_CONSTEXPR_FUNC float round(float _a) { -#if BX_SIMD_SUPPORTED - if (isConstantEvaluated() ) + if constexpr (kSimdSupported) { - return roundRef(_a); + if (!isConstantEvaluated() ) + { + return roundSimd(_a); + } } - return roundSimd(_a); -#else return roundRef(_a); -#endif // BX_SIMD_SUPPORTED } inline BX_CONSTEXPR_FUNC double round(double _a) { -#if BX_SIMD_SUPPORTED - if (isConstantEvaluated() ) + if constexpr (kSimdSupported) { - return roundRef(_a); + if (!isConstantEvaluated() ) + { + return roundSimd(_a); + } } - return roundSimd(_a); -#else return roundRef(_a); -#endif // BX_SIMD_SUPPORTED } inline BX_CONSTEXPR_FUNC float fract(float _a) @@ -1478,24 +1470,46 @@ BX_FP_PRECISE_BEGIN() return result; } + inline BX_CONSTEXPR_FUNC uint64_t mulHi64Ref(uint64_t _a, uint64_t _b) + { + const simd64_t loMask = simd64_splat(uint64_t(UINT32_MAX) ); + const simd64_t aa = simd64_splat(_a); + const simd64_t bb = simd64_splat(_b); + const simd64_t aLo = simd64_and(aa, loMask); + const simd64_t aHi = simd64_x64_srl(aa, 32); + const simd64_t bLo = simd64_and(bb, loMask); + const simd64_t bHi = simd64_x64_srl(bb, 32); + const simd64_t ll = simd64_u64_mul(aLo, bLo); + const simd64_t lh = simd64_u64_mul(aLo, bHi); + const simd64_t hl = simd64_u64_mul(aHi, bLo); + const simd64_t hh = simd64_u64_mul(aHi, bHi); + const simd64_t llHi = simd64_x64_srl(ll, 32); + const simd64_t lhLo = simd64_and(lh, loMask); + const simd64_t hlLo = simd64_and(hl, loMask); + const simd64_t mid0 = simd64_u64_add(llHi, lhLo); + const simd64_t mid = simd64_u64_add(mid0, hlLo); + const simd64_t lhHi = simd64_x64_srl(lh, 32); + const simd64_t hlHi = simd64_x64_srl(hl, 32); + const simd64_t midHi = simd64_x64_srl(mid, 32); + const simd64_t sum0 = simd64_u64_add(hh, lhHi); + const simd64_t sum1 = simd64_u64_add(sum0, hlHi); + const simd64_t result = simd64_u64_add(sum1, midHi); + + return result.u64; + } + inline BX_CONSTEXPR_FUNC uint64_t mulHi64(uint64_t _a, uint64_t _b) { - constexpr uint64_t kLoMask = UINT64_C(0xffffffff); + if (!isConstantEvaluated() ) + { +#if BX_COMPILER_MSVC && BX_ARCH_64BIT + return __umulh(_a, _b); +#elif (BX_COMPILER_GCC || BX_COMPILER_CLANG) && BX_ARCH_64BIT + return uint64_t( ( (unsigned __int128)_a * _b)>>64); +#endif // BX_COMPILER_* + } - const uint64_t aLo = _a & kLoMask; - const uint64_t aHi = _a >> 32; - const uint64_t bLo = _b & kLoMask; - const uint64_t bHi = _b >> 32; - - const uint64_t ll = aLo * bLo; - const uint64_t lh = aLo * bHi; - const uint64_t hl = aHi * bLo; - const uint64_t hh = aHi * bHi; - - const uint64_t mid = (ll >> 32) + (lh & kLoMask) + (hl & kLoMask); - const uint64_t result = hh + (lh >> 32) + (hl >> 32) + (mid >> 32); - - return result; + return mulHi64Ref(_a, _b); } inline BX_CONSTEXPR_FUNC uint64_t twoOverPiWord(int32_t _index) @@ -2751,16 +2765,15 @@ BX_FP_PRECISE_END() inline BX_CONSTEXPR_FUNC float rsqrt(float _a) { -#if BX_SIMD_SUPPORTED - if (isConstantEvaluated() ) + if constexpr (kSimdSupported) { - return rsqrtRef(_a); + if (!isConstantEvaluated() ) + { + return rsqrtSimd(_a); + } } - return rsqrtSimd(_a); -#else return rsqrtRef(_a); -#endif // BX_SIMD_SUPPORTED } inline BX_CONSTEXPR_FUNC double rsqrt(double _a) @@ -2770,30 +2783,28 @@ BX_FP_PRECISE_END() inline BX_CONSTEXPR_FUNC float sqrt(float _a) { -#if BX_SIMD_SUPPORTED - if (isConstantEvaluated() ) + if constexpr (kSimdSupported) { - return sqrtRef(_a); + if (!isConstantEvaluated() ) + { + return sqrtSimd(_a); + } } - return sqrtSimd(_a); -#else return sqrtRef(_a); -#endif // BX_SIMD_SUPPORTED } inline BX_CONSTEXPR_FUNC double sqrt(double _a) { -#if BX_SIMD_SUPPORTED - if (isConstantEvaluated() ) + if constexpr (kSimdSupported) { - return sqrtRef(_a); + if (!isConstantEvaluated() ) + { + return sqrtSimd(_a); + } } - return sqrtSimd(_a); -#else return sqrtRef(_a); -#endif // BX_SIMD_SUPPORTED } inline BX_CONSTEXPR_FUNC bool isEqual(float _a, float _b, float _epsilon) diff --git a/include/bx/math.h b/include/bx/math.h index 182b235c..72370b6b 100644 --- a/include/bx/math.h +++ b/include/bx/math.h @@ -168,6 +168,15 @@ namespace bx /// BX_CONSTEXPR_FUNC double bitsToDouble(uint64_t _a); + /// Returns the high 64 bits of the 128-bit product of _a and _b. + /// + /// @param[in] _a First factor. + /// @param[in] _b Second factor. + /// + /// @returns High 64 bits of `_a * _b`. + /// + BX_CONSTEXPR_FUNC uint64_t mulHi64(uint64_t _a, uint64_t _b); + /// Format constants and bit access for a floating-point type. template struct FloatT; diff --git a/src/bx.cpp b/src/bx.cpp index 4d8de094..dd85de2a 100644 --- a/src/bx.cpp +++ b/src/bx.cpp @@ -244,13 +244,18 @@ namespace bx void memCopy(void* _dst, const void* _src, size_t _numBytes) { -#if BX_SIMD_SUPPORTED - memCopySimd(_dst, _src, _numBytes); -#elif BX_CRT_NONE - memCopyRef(_dst, _src, _numBytes); + if constexpr (kSimdSupported) + { + memCopySimd(_dst, _src, _numBytes); + } + else + { +#if BX_CRT_NONE + memCopyRef(_dst, _src, _numBytes); #else - ::memcpy(_dst, _src, _numBytes); -#endif // BX_* + ::memcpy(_dst, _src, _numBytes); +#endif // BX_CRT_NONE + } } void memCopy( @@ -368,13 +373,18 @@ namespace bx void memMove(void* _dst, const void* _src, size_t _numBytes) { -#if BX_SIMD_SUPPORTED - memMoveSimd(_dst, _src, _numBytes); -#elif BX_CRT_NONE - memMoveRef(_dst, _src, _numBytes); + if constexpr (kSimdSupported) + { + memMoveSimd(_dst, _src, _numBytes); + } + else + { +#if BX_CRT_NONE + memMoveRef(_dst, _src, _numBytes); #else - ::memmove(_dst, _src, _numBytes); -#endif // BX_* + ::memmove(_dst, _src, _numBytes); +#endif // BX_CRT_NONE + } } void memMove( @@ -478,13 +488,18 @@ namespace bx void memSet(void* _dst, uint8_t _ch, size_t _numBytes) { -#if BX_SIMD_SUPPORTED - memSetSimd(_dst, _ch, _numBytes); -#elif BX_CRT_NONE - memSetRef(_dst, _ch, _numBytes); + if constexpr (kSimdSupported) + { + memSetSimd(_dst, _ch, _numBytes); + } + else + { +#if BX_CRT_NONE + memSetRef(_dst, _ch, _numBytes); #else - ::memset(_dst, _ch, _numBytes); -#endif // BX_* + ::memset(_dst, _ch, _numBytes); +#endif // BX_CRT_NONE + } } void memSet(void* _dst, uint32_t _dstStride, uint8_t _ch, uint32_t _stride, uint32_t _num) @@ -602,13 +617,18 @@ namespace bx int32_t memCmp(const void* _lhs, const void* _rhs, size_t _numBytes) { -#if BX_SIMD_SUPPORTED - return memCmpSimd(_lhs, _rhs, _numBytes); -#elif BX_CRT_NONE - return memCmpRef(_lhs, _rhs, _numBytes); + if constexpr (kSimdSupported) + { + return memCmpSimd(_lhs, _rhs, _numBytes); + } + else + { +#if BX_CRT_NONE + return memCmpRef(_lhs, _rhs, _numBytes); #else - return ::memcmp(_lhs, _rhs, _numBytes); -#endif // BX_* + return ::memcmp(_lhs, _rhs, _numBytes); +#endif // BX_CRT_NONE + } } /// diff --git a/tests/math_test.cpp b/tests/math_test.cpp index 41f172c9..649bc466 100644 --- a/tests/math_test.cpp +++ b/tests/math_test.cpp @@ -1841,3 +1841,26 @@ TEST_CASE("limits", "[math]") STATIC_REQUIRE(bx::kFloatSmallest == std::numeric_limits::min() ); STATIC_REQUIRE(bx::kDoubleSmallest == std::numeric_limits::min() ); } + +TEST_CASE("mulHi64", "[math]") +{ + STATIC_REQUIRE(0 == bx::mulHi64(0, 0) ); + STATIC_REQUIRE(0 == bx::mulHi64(UINT64_MAX, 0) ); + STATIC_REQUIRE(0 == bx::mulHi64(UINT64_MAX, 1) ); + STATIC_REQUIRE(1 == bx::mulHi64(UINT64_C(1)<<32, UINT64_C(1)<<32) ); + STATIC_REQUIRE(UINT64_MAX-1 == bx::mulHi64(UINT64_MAX, UINT64_MAX) ); + STATIC_REQUIRE(UINT64_C(0x7641f3080ff92329) == bx::mulHi64(UINT64_C(0x9e3779b97f4a7c15), UINT64_C(0xbf58476d1ce4e5b9) ) ); + + REQUIRE(UINT64_MAX-1 == bx::mulHi64(UINT64_MAX, UINT64_MAX) ); + REQUIRE(UINT64_C(0x7641f3080ff92329) == bx::mulHi64(UINT64_C(0x9e3779b97f4a7c15), UINT64_C(0xbf58476d1ce4e5b9) ) ); + + bx::RngMwc rng; + + for (uint32_t ii = 0; ii < 100000; ++ii) + { + const uint64_t aa = (uint64_t(rng.gen() )<<32) | rng.gen(); + const uint64_t bb = (uint64_t(rng.gen() )<<32) | rng.gen(); + + REQUIRE(bx::mulHi64Ref(aa, bb) == bx::mulHi64(aa, bb) ); + } +}