mirror of
https://github.com/bkaradzic/bx.git
synced 2026-06-08 03:03:48 +00:00
Rework SIMD lib. (#386)
This commit is contained in:
committed by
GitHub
parent
0f575d5880
commit
22f7b051b9
@@ -7,7 +7,6 @@
|
|||||||
#define BX_ALLOCATOR_H_HEADER_GUARD
|
#define BX_ALLOCATOR_H_HEADER_GUARD
|
||||||
|
|
||||||
#include "bx.h"
|
#include "bx.h"
|
||||||
#include "uint32_t.h"
|
|
||||||
|
|
||||||
#define BX_NEW(_allocator, _type) BX_PLACEMENT_NEW(bx::alloc(_allocator, sizeof(_type) ), _type)
|
#define BX_NEW(_allocator, _type) BX_PLACEMENT_NEW(bx::alloc(_allocator, sizeof(_type) ), _type)
|
||||||
#define BX_ALIGNED_NEW(_allocator, _type, _align) BX_PLACEMENT_NEW(bx::alloc(_allocator, sizeof(_type), _align), _type)
|
#define BX_ALIGNED_NEW(_allocator, _type, _align) BX_PLACEMENT_NEW(bx::alloc(_allocator, sizeof(_type), _align), _type)
|
||||||
|
|||||||
@@ -399,6 +399,53 @@ namespace bx
|
|||||||
, uint32_t _numStrides
|
, uint32_t _numStrides
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// Greatest common divisor.
|
||||||
|
///
|
||||||
|
BX_CONSTEXPR_FUNC uint32_t gcd(uint32_t _a, uint32_t _b);
|
||||||
|
|
||||||
|
/// Least common multiple.
|
||||||
|
///
|
||||||
|
BX_CONSTEXPR_FUNC uint32_t lcm(uint32_t _a, uint32_t _b);
|
||||||
|
|
||||||
|
/// Align to arbitrary stride.
|
||||||
|
///
|
||||||
|
BX_CONSTEXPR_FUNC uint32_t strideAlign(uint32_t _offset, uint32_t _stride);
|
||||||
|
|
||||||
|
/// Align to arbitrary stride and Min bytes.
|
||||||
|
///
|
||||||
|
template<uint32_t Min>
|
||||||
|
BX_CONSTEXPR_FUNC uint32_t strideAlign(uint32_t _offset, uint32_t _stride);
|
||||||
|
|
||||||
|
/// Returns true if value is aligned to _align boundary.
|
||||||
|
///
|
||||||
|
template<typename Ty>
|
||||||
|
BX_CONSTEXPR_FUNC bool isAligned(Ty _a, size_t _align);
|
||||||
|
|
||||||
|
template<>
|
||||||
|
BX_CONSTEXPR_FUNC bool isAligned(const void* _ptr, size_t _align);
|
||||||
|
|
||||||
|
/// Aligns _a down to nearest multiple of _align.
|
||||||
|
///
|
||||||
|
template<typename Ty>
|
||||||
|
BX_CONSTEXPR_FUNC Ty alignDown(Ty _a, size_t _align);
|
||||||
|
|
||||||
|
template<typename Ty>
|
||||||
|
BX_CONSTEXPR_FUNC Ty* alignDown(Ty* _ptr, size_t _align);
|
||||||
|
|
||||||
|
template<typename Ty>
|
||||||
|
BX_CONSTEXPR_FUNC const Ty* alignDown(const Ty* _ptr, size_t _align);
|
||||||
|
|
||||||
|
/// Aligns _a up to nearest multiple of _align.
|
||||||
|
///
|
||||||
|
template<typename Ty>
|
||||||
|
BX_CONSTEXPR_FUNC Ty alignUp(Ty _a, size_t _align);
|
||||||
|
|
||||||
|
template<typename Ty>
|
||||||
|
BX_CONSTEXPR_FUNC Ty* alignUp(Ty* _ptr, size_t _align);
|
||||||
|
|
||||||
|
template<typename Ty>
|
||||||
|
BX_CONSTEXPR_FUNC const Ty* alignUp(const Ty* _ptr, size_t _align);
|
||||||
|
|
||||||
} // namespace bx
|
} // namespace bx
|
||||||
|
|
||||||
#include "inline/bx.inl"
|
#include "inline/bx.inl"
|
||||||
|
|||||||
@@ -17,10 +17,10 @@ namespace bx
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Multiplies vector `_a` with matrix `_b` ignoring W component of vector `_a`.
|
/// Multiplies vector `_a` with matrix `_b` ignoring W component of vector `_a`.
|
||||||
simd128_t simd_mul_xyz1(simd128_t _a, const float4x4_t* _b);
|
simd128_t simd128_mul_xyz1(simd128_t _a, const float4x4_t* _b);
|
||||||
|
|
||||||
/// Multiplies vector `_a` with matrix `_b`.
|
/// Multiplies vector `_a` with matrix `_b`.
|
||||||
simd128_t simd_mul(simd128_t _a, const float4x4_t* _b);
|
simd128_t simd128_mul(simd128_t _a, const float4x4_t* _b);
|
||||||
|
|
||||||
/// Multiplies two matrices.
|
/// Multiplies two matrices.
|
||||||
void float4x4_mul(float4x4_t* _result, const float4x4_t* _a, const float4x4_t* _b);
|
void float4x4_mul(float4x4_t* _result, const float4x4_t* _a, const float4x4_t* _b);
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#include "bx.h"
|
#include "bx.h"
|
||||||
#include "allocator.h"
|
#include "allocator.h"
|
||||||
#include "uint32_t.h"
|
#include "simd_t.h"
|
||||||
|
|
||||||
namespace bx
|
namespace bx
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -227,6 +227,9 @@ namespace bx
|
|||||||
return __builtin_is_constant_evaluated();
|
return __builtin_is_constant_evaluated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BX_PRAGMA_DIAGNOSTIC_PUSH();
|
||||||
|
BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wpsabi");
|
||||||
|
|
||||||
template <typename Ty, typename FromT>
|
template <typename Ty, typename FromT>
|
||||||
inline constexpr Ty bitCast(const FromT& _from)
|
inline constexpr Ty bitCast(const FromT& _from)
|
||||||
{
|
{
|
||||||
@@ -246,6 +249,8 @@ namespace bx
|
|||||||
return __builtin_bit_cast(Ty, _from);
|
return __builtin_bit_cast(Ty, _from);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BX_PRAGMA_DIAGNOSTIC_POP();
|
||||||
|
|
||||||
template<typename Ty, typename FromT>
|
template<typename Ty, typename FromT>
|
||||||
requires (isInteger< Ty>() || isFloatingPoint< Ty>() )
|
requires (isInteger< Ty>() || isFloatingPoint< Ty>() )
|
||||||
&& (isInteger<FromT>() || isFloatingPoint<FromT>() )
|
&& (isInteger<FromT>() || isFloatingPoint<FromT>() )
|
||||||
@@ -322,4 +327,104 @@ namespace bx
|
|||||||
constexpr float kFloatInfinity = bitCast<float>(kFloatExponentMask);
|
constexpr float kFloatInfinity = bitCast<float>(kFloatExponentMask);
|
||||||
constexpr double kDoubleInfinity = bitCast<double>(kDoubleExponentMask);
|
constexpr double kDoubleInfinity = bitCast<double>(kDoubleExponentMask);
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC uint32_t gcd(uint32_t _a, uint32_t _b)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
const uint32_t tmp = _a % _b;
|
||||||
|
_a = _b;
|
||||||
|
_b = tmp;
|
||||||
|
}
|
||||||
|
while (_b);
|
||||||
|
|
||||||
|
return _a;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC uint32_t lcm(uint32_t _a, uint32_t _b)
|
||||||
|
{
|
||||||
|
return _a * (_b / gcd(_a, _b) );
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC uint32_t strideAlign(uint32_t _offset, uint32_t _stride)
|
||||||
|
{
|
||||||
|
const uint32_t mod = _offset % _stride;
|
||||||
|
const uint32_t add = _stride - mod;
|
||||||
|
const uint32_t tmp = (0 == mod) ? 0 : add;
|
||||||
|
const uint32_t result = _offset + tmp;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<uint32_t Min>
|
||||||
|
inline BX_CONSTEXPR_FUNC uint32_t strideAlign(uint32_t _offset, uint32_t _stride)
|
||||||
|
{
|
||||||
|
const uint32_t align = lcm(Min, _stride);
|
||||||
|
const uint32_t mod = _offset % align;
|
||||||
|
const uint32_t tmp0 = (0 == mod) ? 0 : align;
|
||||||
|
const uint32_t tmp1 = _offset + tmp0;
|
||||||
|
const uint32_t result = tmp1 - mod;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Ty>
|
||||||
|
inline BX_CONSTEXPR_FUNC bool isAligned(Ty _a, size_t _align)
|
||||||
|
{
|
||||||
|
const size_t mask = max<size_t>(1, _align) - 1;
|
||||||
|
return 0 == (size_t(_a) & mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline BX_CONSTEXPR_FUNC bool isAligned(const void* _ptr, size_t _align)
|
||||||
|
{
|
||||||
|
const uintptr_t addr = bitCast<uintptr_t>(_ptr);
|
||||||
|
return isAligned(addr, _align);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Ty>
|
||||||
|
inline BX_CONSTEXPR_FUNC Ty alignDown(Ty _a, size_t _align)
|
||||||
|
{
|
||||||
|
const size_t mask = max<size_t>(1, _align) - 1;
|
||||||
|
return Ty(size_t(_a) & ~mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Ty>
|
||||||
|
inline BX_CONSTEXPR_FUNC Ty* alignDown(Ty* _ptr, size_t _align)
|
||||||
|
{
|
||||||
|
uintptr_t addr = bitCast<uintptr_t>(_ptr);
|
||||||
|
addr = alignDown(addr, _align);
|
||||||
|
return bitCast<Ty*>(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Ty>
|
||||||
|
inline BX_CONSTEXPR_FUNC const Ty* alignDown(const Ty* _ptr, size_t _align)
|
||||||
|
{
|
||||||
|
uintptr_t addr = bitCast<uintptr_t>(_ptr);
|
||||||
|
addr = alignDown(addr, _align);
|
||||||
|
return bitCast<const Ty*>(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Ty>
|
||||||
|
inline BX_CONSTEXPR_FUNC Ty alignUp(Ty _a, size_t _align)
|
||||||
|
{
|
||||||
|
const size_t mask = max<size_t>(1, _align) - 1;
|
||||||
|
return Ty( (size_t(_a) + mask) & ~mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Ty>
|
||||||
|
inline BX_CONSTEXPR_FUNC Ty* alignUp(Ty* _ptr, size_t _align)
|
||||||
|
{
|
||||||
|
uintptr_t addr = bitCast<uintptr_t>(_ptr);
|
||||||
|
addr = alignUp(addr, _align);
|
||||||
|
return bitCast<Ty*>(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Ty>
|
||||||
|
inline BX_CONSTEXPR_FUNC const Ty* alignUp(const Ty* _ptr, size_t _align)
|
||||||
|
{
|
||||||
|
uintptr_t addr = bitCast<uintptr_t>(_ptr);
|
||||||
|
addr = alignUp(addr, _align);
|
||||||
|
return bitCast<const Ty*>(addr);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace bx
|
} // namespace bx
|
||||||
|
|||||||
@@ -9,31 +9,31 @@
|
|||||||
|
|
||||||
namespace bx
|
namespace bx
|
||||||
{
|
{
|
||||||
BX_SIMD_FORCE_INLINE simd128_t simd_mul_xyz1(simd128_t _a, const float4x4_t* _b)
|
BX_SIMD_FORCE_INLINE simd128_t simd128_mul_xyz1(simd128_t _a, const float4x4_t* _b)
|
||||||
{
|
{
|
||||||
const simd128_t xxxx = simd_swiz_xxxx(_a);
|
const simd128_t xxxx = simd128_x32_swiz_xxxx(_a);
|
||||||
const simd128_t yyyy = simd_swiz_yyyy(_a);
|
const simd128_t yyyy = simd128_x32_swiz_yyyy(_a);
|
||||||
const simd128_t zzzz = simd_swiz_zzzz(_a);
|
const simd128_t zzzz = simd128_x32_swiz_zzzz(_a);
|
||||||
const simd128_t col0 = simd_mul(_b->col[0], xxxx);
|
const simd128_t col0 = simd128_f32_mul(_b->col[0], xxxx);
|
||||||
const simd128_t col1 = simd_mul(_b->col[1], yyyy);
|
const simd128_t col1 = simd128_f32_mul(_b->col[1], yyyy);
|
||||||
const simd128_t col2 = simd_madd(_b->col[2], zzzz, col0);
|
const simd128_t col2 = simd128_f32_madd(_b->col[2], zzzz, col0);
|
||||||
const simd128_t col3 = simd_add(_b->col[3], col1);
|
const simd128_t col3 = simd128_f32_add(_b->col[3], col1);
|
||||||
const simd128_t result = simd_add(col2, col3);
|
const simd128_t result = simd128_f32_add(col2, col3);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_t simd_mul(simd128_t _a, const float4x4_t* _b)
|
BX_SIMD_FORCE_INLINE simd128_t simd128_mul(simd128_t _a, const float4x4_t* _b)
|
||||||
{
|
{
|
||||||
const simd128_t xxxx = simd_swiz_xxxx(_a);
|
const simd128_t xxxx = simd128_x32_swiz_xxxx(_a);
|
||||||
const simd128_t yyyy = simd_swiz_yyyy(_a);
|
const simd128_t yyyy = simd128_x32_swiz_yyyy(_a);
|
||||||
const simd128_t zzzz = simd_swiz_zzzz(_a);
|
const simd128_t zzzz = simd128_x32_swiz_zzzz(_a);
|
||||||
const simd128_t wwww = simd_swiz_wwww(_a);
|
const simd128_t wwww = simd128_x32_swiz_wwww(_a);
|
||||||
const simd128_t col0 = simd_mul(_b->col[0], xxxx);
|
const simd128_t col0 = simd128_f32_mul(_b->col[0], xxxx);
|
||||||
const simd128_t col1 = simd_mul(_b->col[1], yyyy);
|
const simd128_t col1 = simd128_f32_mul(_b->col[1], yyyy);
|
||||||
const simd128_t col2 = simd_madd(_b->col[2], zzzz, col0);
|
const simd128_t col2 = simd128_f32_madd(_b->col[2], zzzz, col0);
|
||||||
const simd128_t col3 = simd_madd(_b->col[3], wwww, col1);
|
const simd128_t col3 = simd128_f32_madd(_b->col[3], wwww, col1);
|
||||||
const simd128_t result = simd_add(col2, col3);
|
const simd128_t result = simd128_f32_add(col2, col3);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -41,10 +41,10 @@ namespace bx
|
|||||||
BX_SIMD_INLINE void float4x4_mul(float4x4_t* _result, const float4x4_t* _a, const float4x4_t* _b)
|
BX_SIMD_INLINE void float4x4_mul(float4x4_t* _result, const float4x4_t* _a, const float4x4_t* _b)
|
||||||
{
|
{
|
||||||
#if BX_SIMD_SUPPORTED
|
#if BX_SIMD_SUPPORTED
|
||||||
_result->col[0] = simd_mul(_a->col[0], _b);
|
_result->col[0] = simd128_mul(_a->col[0], _b);
|
||||||
_result->col[1] = simd_mul(_a->col[1], _b);
|
_result->col[1] = simd128_mul(_a->col[1], _b);
|
||||||
_result->col[2] = simd_mul(_a->col[2], _b);
|
_result->col[2] = simd128_mul(_a->col[2], _b);
|
||||||
_result->col[3] = simd_mul(_a->col[3], _b);
|
_result->col[3] = simd128_mul(_a->col[3], _b);
|
||||||
#else
|
#else
|
||||||
const float* aa = (const float*)_a;
|
const float* aa = (const float*)_a;
|
||||||
const float* bb = (const float*)_b;
|
const float* bb = (const float*)_b;
|
||||||
@@ -137,103 +137,103 @@ namespace bx
|
|||||||
|
|
||||||
BX_SIMD_FORCE_INLINE void float4x4_transpose(float4x4_t* _result, const float4x4_t* _mtx)
|
BX_SIMD_FORCE_INLINE void float4x4_transpose(float4x4_t* _result, const float4x4_t* _mtx)
|
||||||
{
|
{
|
||||||
const simd128_t aibj = simd_shuf_xAyB(_mtx->col[0], _mtx->col[2]); // aibj
|
const simd128_t aibj = simd128_x32_shuf_xAyB(_mtx->col[0], _mtx->col[2]); // aibj
|
||||||
const simd128_t emfn = simd_shuf_xAyB(_mtx->col[1], _mtx->col[3]); // emfn
|
const simd128_t emfn = simd128_x32_shuf_xAyB(_mtx->col[1], _mtx->col[3]); // emfn
|
||||||
const simd128_t ckdl = simd_shuf_zCwD(_mtx->col[0], _mtx->col[2]); // ckdl
|
const simd128_t ckdl = simd128_x32_shuf_zCwD(_mtx->col[0], _mtx->col[2]); // ckdl
|
||||||
const simd128_t gohp = simd_shuf_zCwD(_mtx->col[1], _mtx->col[3]); // gohp
|
const simd128_t gohp = simd128_x32_shuf_zCwD(_mtx->col[1], _mtx->col[3]); // gohp
|
||||||
_result->col[0] = simd_shuf_xAyB(aibj, emfn); // aeim
|
_result->col[0] = simd128_x32_shuf_xAyB(aibj, emfn); // aeim
|
||||||
_result->col[1] = simd_shuf_zCwD(aibj, emfn); // bfjn
|
_result->col[1] = simd128_x32_shuf_zCwD(aibj, emfn); // bfjn
|
||||||
_result->col[2] = simd_shuf_xAyB(ckdl, gohp); // cgko
|
_result->col[2] = simd128_x32_shuf_xAyB(ckdl, gohp); // cgko
|
||||||
_result->col[3] = simd_shuf_zCwD(ckdl, gohp); // dhlp
|
_result->col[3] = simd128_x32_shuf_zCwD(ckdl, gohp); // dhlp
|
||||||
}
|
}
|
||||||
|
|
||||||
BX_SIMD_INLINE void float4x4_inverse(float4x4_t* _result, const float4x4_t* _a)
|
BX_SIMD_INLINE void float4x4_inverse(float4x4_t* _result, const float4x4_t* _a)
|
||||||
{
|
{
|
||||||
const simd128_t tmp0 = simd_shuf_xAzC(_a->col[0], _a->col[1]);
|
const simd128_t tmp0 = simd128_x32_shuf_xAzC(_a->col[0], _a->col[1]);
|
||||||
const simd128_t tmp1 = simd_shuf_xAzC(_a->col[2], _a->col[3]);
|
const simd128_t tmp1 = simd128_x32_shuf_xAzC(_a->col[2], _a->col[3]);
|
||||||
const simd128_t tmp2 = simd_shuf_yBwD(_a->col[0], _a->col[1]);
|
const simd128_t tmp2 = simd128_x32_shuf_yBwD(_a->col[0], _a->col[1]);
|
||||||
const simd128_t tmp3 = simd_shuf_yBwD(_a->col[2], _a->col[3]);
|
const simd128_t tmp3 = simd128_x32_shuf_yBwD(_a->col[2], _a->col[3]);
|
||||||
const simd128_t t0 = simd_shuf_xyAB(tmp0, tmp1);
|
const simd128_t t0 = simd128_x32_shuf_xyAB(tmp0, tmp1);
|
||||||
const simd128_t t1 = simd_shuf_xyAB(tmp3, tmp2);
|
const simd128_t t1 = simd128_x32_shuf_xyAB(tmp3, tmp2);
|
||||||
const simd128_t t2 = simd_shuf_zwCD(tmp0, tmp1);
|
const simd128_t t2 = simd128_x32_shuf_zwCD(tmp0, tmp1);
|
||||||
const simd128_t t3 = simd_shuf_zwCD(tmp3, tmp2);
|
const simd128_t t3 = simd128_x32_shuf_zwCD(tmp3, tmp2);
|
||||||
|
|
||||||
const simd128_t t23 = simd_mul(t2, t3);
|
const simd128_t t23 = simd128_f32_mul(t2, t3);
|
||||||
const simd128_t t23_yxwz = simd_swiz_yxwz(t23);
|
const simd128_t t23_yxwz = simd128_x32_swiz_yxwz(t23);
|
||||||
const simd128_t t23_wzyx = simd_swiz_wzyx(t23);
|
const simd128_t t23_wzyx = simd128_x32_swiz_wzyx(t23);
|
||||||
|
|
||||||
simd128_t cof0, cof1, cof2, cof3;
|
simd128_t cof0, cof1, cof2, cof3;
|
||||||
|
|
||||||
const simd128_t zero = simd_zero();
|
const simd128_t zero = simd128_zero();
|
||||||
cof0 = simd_nmsub(t1, t23_yxwz, zero);
|
cof0 = simd128_f32_nmsub(t1, t23_yxwz, zero);
|
||||||
cof0 = simd_madd(t1, t23_wzyx, cof0);
|
cof0 = simd128_f32_madd(t1, t23_wzyx, cof0);
|
||||||
|
|
||||||
cof1 = simd_nmsub(t0, t23_yxwz, zero);
|
cof1 = simd128_f32_nmsub(t0, t23_yxwz, zero);
|
||||||
cof1 = simd_madd(t0, t23_wzyx, cof1);
|
cof1 = simd128_f32_madd(t0, t23_wzyx, cof1);
|
||||||
cof1 = simd_swiz_zwxy(cof1);
|
cof1 = simd128_x32_swiz_zwxy(cof1);
|
||||||
|
|
||||||
const simd128_t t12 = simd_mul(t1, t2);
|
const simd128_t t12 = simd128_f32_mul(t1, t2);
|
||||||
const simd128_t t12_yxwz = simd_swiz_yxwz(t12);
|
const simd128_t t12_yxwz = simd128_x32_swiz_yxwz(t12);
|
||||||
const simd128_t t12_wzyx = simd_swiz_wzyx(t12);
|
const simd128_t t12_wzyx = simd128_x32_swiz_wzyx(t12);
|
||||||
|
|
||||||
cof0 = simd_madd(t3, t12_yxwz, cof0);
|
cof0 = simd128_f32_madd(t3, t12_yxwz, cof0);
|
||||||
cof0 = simd_nmsub(t3, t12_wzyx, cof0);
|
cof0 = simd128_f32_nmsub(t3, t12_wzyx, cof0);
|
||||||
|
|
||||||
cof3 = simd_mul(t0, t12_yxwz);
|
cof3 = simd128_f32_mul(t0, t12_yxwz);
|
||||||
cof3 = simd_nmsub(t0, t12_wzyx, cof3);
|
cof3 = simd128_f32_nmsub(t0, t12_wzyx, cof3);
|
||||||
cof3 = simd_swiz_zwxy(cof3);
|
cof3 = simd128_x32_swiz_zwxy(cof3);
|
||||||
|
|
||||||
const simd128_t t1_zwxy = simd_swiz_zwxy(t1);
|
const simd128_t t1_zwxy = simd128_x32_swiz_zwxy(t1);
|
||||||
const simd128_t t2_zwxy = simd_swiz_zwxy(t2);
|
const simd128_t t2_zwxy = simd128_x32_swiz_zwxy(t2);
|
||||||
|
|
||||||
const simd128_t t13 = simd_mul(t1_zwxy, t3);
|
const simd128_t t13 = simd128_f32_mul(t1_zwxy, t3);
|
||||||
const simd128_t t13_yxwz = simd_swiz_yxwz(t13);
|
const simd128_t t13_yxwz = simd128_x32_swiz_yxwz(t13);
|
||||||
const simd128_t t13_wzyx = simd_swiz_wzyx(t13);
|
const simd128_t t13_wzyx = simd128_x32_swiz_wzyx(t13);
|
||||||
|
|
||||||
cof0 = simd_madd(t2_zwxy, t13_yxwz, cof0);
|
cof0 = simd128_f32_madd(t2_zwxy, t13_yxwz, cof0);
|
||||||
cof0 = simd_nmsub(t2_zwxy, t13_wzyx, cof0);
|
cof0 = simd128_f32_nmsub(t2_zwxy, t13_wzyx, cof0);
|
||||||
|
|
||||||
cof2 = simd_mul(t0, t13_yxwz);
|
cof2 = simd128_f32_mul(t0, t13_yxwz);
|
||||||
cof2 = simd_nmsub(t0, t13_wzyx, cof2);
|
cof2 = simd128_f32_nmsub(t0, t13_wzyx, cof2);
|
||||||
cof2 = simd_swiz_zwxy(cof2);
|
cof2 = simd128_x32_swiz_zwxy(cof2);
|
||||||
|
|
||||||
const simd128_t t01 = simd_mul(t0, t1);
|
const simd128_t t01 = simd128_f32_mul(t0, t1);
|
||||||
const simd128_t t01_yxwz = simd_swiz_yxwz(t01);
|
const simd128_t t01_yxwz = simd128_x32_swiz_yxwz(t01);
|
||||||
const simd128_t t01_wzyx = simd_swiz_wzyx(t01);
|
const simd128_t t01_wzyx = simd128_x32_swiz_wzyx(t01);
|
||||||
|
|
||||||
cof2 = simd_nmsub(t3, t01_yxwz, cof2);
|
cof2 = simd128_f32_nmsub(t3, t01_yxwz, cof2);
|
||||||
cof2 = simd_madd(t3, t01_wzyx, cof2);
|
cof2 = simd128_f32_madd(t3, t01_wzyx, cof2);
|
||||||
|
|
||||||
cof3 = simd_madd(t2_zwxy, t01_yxwz, cof3);
|
cof3 = simd128_f32_madd(t2_zwxy, t01_yxwz, cof3);
|
||||||
cof3 = simd_nmsub(t2_zwxy, t01_wzyx, cof3);
|
cof3 = simd128_f32_nmsub(t2_zwxy, t01_wzyx, cof3);
|
||||||
|
|
||||||
const simd128_t t03 = simd_mul(t0, t3);
|
const simd128_t t03 = simd128_f32_mul(t0, t3);
|
||||||
const simd128_t t03_yxwz = simd_swiz_yxwz(t03);
|
const simd128_t t03_yxwz = simd128_x32_swiz_yxwz(t03);
|
||||||
const simd128_t t03_wzyx = simd_swiz_wzyx(t03);
|
const simd128_t t03_wzyx = simd128_x32_swiz_wzyx(t03);
|
||||||
|
|
||||||
cof1 = simd_nmsub(t2_zwxy, t03_yxwz, cof1);
|
cof1 = simd128_f32_nmsub(t2_zwxy, t03_yxwz, cof1);
|
||||||
cof1 = simd_madd(t2_zwxy, t03_wzyx, cof1);
|
cof1 = simd128_f32_madd(t2_zwxy, t03_wzyx, cof1);
|
||||||
|
|
||||||
cof2 = simd_madd(t1, t03_yxwz, cof2);
|
cof2 = simd128_f32_madd(t1, t03_yxwz, cof2);
|
||||||
cof2 = simd_nmsub(t1, t03_wzyx, cof2);
|
cof2 = simd128_f32_nmsub(t1, t03_wzyx, cof2);
|
||||||
|
|
||||||
const simd128_t t02 = simd_mul(t0, t2_zwxy);
|
const simd128_t t02 = simd128_f32_mul(t0, t2_zwxy);
|
||||||
const simd128_t t02_yxwz = simd_swiz_yxwz(t02);
|
const simd128_t t02_yxwz = simd128_x32_swiz_yxwz(t02);
|
||||||
const simd128_t t02_wzyx = simd_swiz_wzyx(t02);
|
const simd128_t t02_wzyx = simd128_x32_swiz_wzyx(t02);
|
||||||
|
|
||||||
cof1 = simd_madd(t3, t02_yxwz, cof1);
|
cof1 = simd128_f32_madd(t3, t02_yxwz, cof1);
|
||||||
cof1 = simd_nmsub(t3, t02_wzyx, cof1);
|
cof1 = simd128_f32_nmsub(t3, t02_wzyx, cof1);
|
||||||
|
|
||||||
cof3 = simd_nmsub(t1, t02_yxwz, cof3);
|
cof3 = simd128_f32_nmsub(t1, t02_yxwz, cof3);
|
||||||
cof3 = simd_madd(t1, t02_wzyx, cof3);
|
cof3 = simd128_f32_madd(t1, t02_wzyx, cof3);
|
||||||
|
|
||||||
const simd128_t det = simd_dot(t0, cof0);
|
const simd128_t det = simd128_f32_dot(t0, cof0);
|
||||||
const simd128_t invdet = simd_rcp(det);
|
const simd128_t invdet = simd128_f32_rcp(det);
|
||||||
|
|
||||||
_result->col[0] = simd_mul(cof0, invdet);
|
_result->col[0] = simd128_f32_mul(cof0, invdet);
|
||||||
_result->col[1] = simd_mul(cof1, invdet);
|
_result->col[1] = simd128_f32_mul(cof1, invdet);
|
||||||
_result->col[2] = simd_mul(cof2, invdet);
|
_result->col[2] = simd128_f32_mul(cof2, invdet);
|
||||||
_result->col[3] = simd_mul(cof3, invdet);
|
_result->col[3] = simd128_f32_mul(cof3, invdet);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace bx
|
} // namespace bx
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
# error "Must be included from bx/handlealloc.h!"
|
# error "Must be included from bx/handlealloc.h!"
|
||||||
#endif // BX_HANDLE_ALLOC_H_HEADER_GUARD
|
#endif // BX_HANDLE_ALLOC_H_HEADER_GUARD
|
||||||
|
|
||||||
|
#include <bx/simd_t.h>
|
||||||
|
|
||||||
namespace bx
|
namespace bx
|
||||||
{
|
{
|
||||||
inline HandleAlloc::HandleAlloc(uint16_t _maxHandles)
|
inline HandleAlloc::HandleAlloc(uint16_t _maxHandles)
|
||||||
@@ -597,19 +599,25 @@ namespace bx
|
|||||||
template <uint32_t MaxCapacityT, typename KeyT>
|
template <uint32_t MaxCapacityT, typename KeyT>
|
||||||
inline uint32_t HandleHashMapT<MaxCapacityT, KeyT>::mix(uint32_t _x) const
|
inline uint32_t HandleHashMapT<MaxCapacityT, KeyT>::mix(uint32_t _x) const
|
||||||
{
|
{
|
||||||
const uint32_t tmp0 = uint32_mul(_x, UINT32_C(2246822519) );
|
const simd32_t x = simd32_splat(_x);
|
||||||
const uint32_t tmp1 = uint32_rol(tmp0, 13);
|
const simd32_t c0 = simd32_splat(2246822519u);
|
||||||
const uint32_t result = uint32_mul(tmp1, UINT32_C(2654435761) );
|
const simd32_t tmp0 = simd32_u32_mul(x, c0);
|
||||||
return result;
|
const simd32_t tmp1 = simd32_x32_rol(tmp0, 13);
|
||||||
|
const simd32_t c1 = simd32_splat(2654435761u);
|
||||||
|
const simd32_t result = simd32_u32_mul(tmp1, c1);
|
||||||
|
return result.u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <uint32_t MaxCapacityT, typename KeyT>
|
template <uint32_t MaxCapacityT, typename KeyT>
|
||||||
inline uint64_t HandleHashMapT<MaxCapacityT, KeyT>::mix(uint64_t _x) const
|
inline uint64_t HandleHashMapT<MaxCapacityT, KeyT>::mix(uint64_t _x) const
|
||||||
{
|
{
|
||||||
const uint64_t tmp0 = uint64_mul(_x, UINT64_C(14029467366897019727) );
|
const simd64_t x = simd64_splat(_x);
|
||||||
const uint64_t tmp1 = uint64_rol(tmp0, 31);
|
const simd64_t c0 = simd64_splat(uint64_t(14029467366897019727ull) );
|
||||||
const uint64_t result = uint64_mul(tmp1, UINT64_C(11400714785074694791) );
|
const simd64_t tmp0 = simd64_u64_mul(x, c0);
|
||||||
return result;
|
const simd64_t tmp1 = simd64_x64_rol(tmp0, 31);
|
||||||
|
const simd64_t c1 = simd64_splat(uint64_t(11400714785074694791ull) );
|
||||||
|
const simd64_t result = simd64_u64_mul(tmp1, c1);
|
||||||
|
return result.u64;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <uint16_t MaxHandlesT, typename KeyT>
|
template <uint16_t MaxHandlesT, typename KeyT>
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
#endif // BX_MATH_H_HEADER_GUARD
|
#endif // BX_MATH_H_HEADER_GUARD
|
||||||
|
|
||||||
#include <bx/simd_t.h>
|
#include <bx/simd_t.h>
|
||||||
#include <bx/uint32_t.h>
|
|
||||||
|
|
||||||
#if BX_COMPILER_MSVC
|
#if BX_COMPILER_MSVC
|
||||||
extern "C" unsigned char _BitScanReverse(unsigned long* _Index, unsigned long _Mask);
|
extern "C" unsigned char _BitScanReverse(unsigned long* _Index, unsigned long _Mask);
|
||||||
@@ -65,11 +64,14 @@ namespace bx
|
|||||||
// Reference(s):
|
// Reference(s):
|
||||||
// - http://archive.fo/2012.12.08-212402/http://stereopsis.com/radix.html
|
// - http://archive.fo/2012.12.08-212402/http://stereopsis.com/radix.html
|
||||||
//
|
//
|
||||||
const uint32_t tmp0 = uint32_sra(_value, 31);
|
const simd32_t signMask = simd32_splat(kFloatSignMask);
|
||||||
const uint32_t tmp1 = uint32_neg(tmp0);
|
const simd32_t value = simd32_splat(_value);
|
||||||
const uint32_t mask = uint32_or(tmp1, kFloatSignMask);
|
const simd32_t tmp0 = simd32_x32_sra(value, 31);
|
||||||
const uint32_t result = uint32_xor(_value, mask);
|
const simd32_t tmp1 = simd32_i32_neg(tmp0);
|
||||||
return result;
|
const simd32_t mask = simd32_or(tmp1, signMask);
|
||||||
|
const simd32_t result = simd32_xor(value, mask);
|
||||||
|
|
||||||
|
return result.u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC bool isNan(float _f)
|
inline BX_CONSTEXPR_FUNC bool isNan(float _f)
|
||||||
@@ -199,6 +201,51 @@ namespace bx
|
|||||||
return _a - _b;
|
return _a - _b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Ty>
|
||||||
|
inline BX_CONSTEXPR_FUNC Ty satAdd(Ty _a, Ty _b)
|
||||||
|
{
|
||||||
|
static_assert(isInteger<Ty>(), "Type Ty must be an integer type.");
|
||||||
|
|
||||||
|
using UTy = MakeUnsignedType<Ty>;
|
||||||
|
|
||||||
|
const UTy ua = UTy(_a);
|
||||||
|
const UTy ub = UTy(_b);
|
||||||
|
const UTy sum = UTy(ua + ub);
|
||||||
|
|
||||||
|
if constexpr (isSigned<Ty>() )
|
||||||
|
{
|
||||||
|
const UTy signBit = UTy(UTy(1) << (sizeof(Ty)*8 - 1) );
|
||||||
|
const UTy overflow = UTy(~(ua ^ ub) & (ua ^ sum) & signBit);
|
||||||
|
const Ty satVal = (ua & signBit) ? LimitsT<Ty>::min : LimitsT<Ty>::max;
|
||||||
|
return 0 != overflow ? satVal : Ty(sum);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sum < ua ? LimitsT<Ty>::max : Ty(sum);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Ty>
|
||||||
|
inline BX_CONSTEXPR_FUNC Ty satSub(Ty _a, Ty _b)
|
||||||
|
{
|
||||||
|
static_assert(isInteger<Ty>(), "Type Ty must be an integer type.");
|
||||||
|
|
||||||
|
using UTy = MakeUnsignedType<Ty>;
|
||||||
|
|
||||||
|
const UTy ua = UTy(_a);
|
||||||
|
const UTy ub = UTy(_b);
|
||||||
|
const UTy diff = UTy(ua - ub);
|
||||||
|
|
||||||
|
if constexpr (isSigned<Ty>() )
|
||||||
|
{
|
||||||
|
const UTy signBit = UTy(UTy(1) << (sizeof(Ty)*8 - 1) );
|
||||||
|
const UTy overflow = UTy( (ua ^ ub) & (ua ^ diff) & signBit);
|
||||||
|
const Ty satVal = (ua & signBit) ? LimitsT<Ty>::min : LimitsT<Ty>::max;
|
||||||
|
|
||||||
|
return 0 != overflow ? satVal : Ty(diff);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ua > ub ? Ty(diff) : Ty(0);
|
||||||
|
}
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC float mul(float _a, float _b)
|
inline BX_CONSTEXPR_FUNC float mul(float _a, float _b)
|
||||||
{
|
{
|
||||||
return _a * _b;
|
return _a * _b;
|
||||||
@@ -394,16 +441,18 @@ namespace bx
|
|||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC float ldexp(float _a, int32_t _b)
|
inline BX_CONSTEXPR_FUNC float ldexp(float _a, int32_t _b)
|
||||||
{
|
{
|
||||||
const uint32_t ftob = floatToBits(_a);
|
const simd32_t ftob = simd32_splat(floatToBits(_a));
|
||||||
const uint32_t masked = uint32_and(ftob, kFloatSignMask | kFloatExponentMask);
|
const simd32_t signexpmask = simd32_splat(kFloatSignMask | kFloatExponentMask);
|
||||||
const uint32_t expsign0 = uint32_sra(masked, kFloatExponentBitShift);
|
const simd32_t mantmask = simd32_splat(kFloatMantissaMask);
|
||||||
const uint32_t tmp = uint32_iadd(expsign0, _b);
|
const simd32_t b = simd32_splat(_b);
|
||||||
const uint32_t expsign1 = uint32_sll(tmp, kFloatExponentBitShift);
|
const simd32_t masked = simd32_and(ftob, signexpmask);
|
||||||
const uint32_t mantissa = uint32_and(ftob, kFloatMantissaMask);
|
const simd32_t expsign0 = simd32_x32_sra(masked, kFloatExponentBitShift);
|
||||||
const uint32_t bits = uint32_or(mantissa, expsign1);
|
const simd32_t tmp = simd32_i32_add(expsign0, b);
|
||||||
const float result = bitsToFloat(bits);
|
const simd32_t expsign1 = simd32_x32_sll(tmp, kFloatExponentBitShift);
|
||||||
|
const simd32_t mantissa = simd32_and(ftob, mantmask);
|
||||||
|
const simd32_t bits = simd32_or(mantissa, expsign1);
|
||||||
|
|
||||||
return result;
|
return bitsToFloat(bits.u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC float log(float _a)
|
inline BX_CONSTEXPR_FUNC float log(float _a)
|
||||||
@@ -418,15 +467,19 @@ namespace bx
|
|||||||
return -kFloatInfinity;
|
return -kFloatInfinity;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint32_t ftob = floatToBits(_a);
|
const simd32_t ftob = simd32_splat(floatToBits(_a));
|
||||||
|
const simd32_t expmask = simd32_splat(kFloatExponentMask);
|
||||||
|
const simd32_t signmantmask = simd32_splat(kFloatSignMask | kFloatMantissaMask);
|
||||||
|
const simd32_t half = simd32_splat(UINT32_C(0x3f000000));
|
||||||
|
|
||||||
const uint32_t masked0 = uint32_and(ftob, kFloatExponentMask);
|
const simd32_t masked0 = simd32_and(ftob, expmask);
|
||||||
const uint32_t exp0 = uint32_srl(masked0, kFloatExponentBitShift);
|
const simd32_t exp0 = simd32_x32_srl(masked0, kFloatExponentBitShift);
|
||||||
int32_t exp = int32_t(exp0 - 0x7e);
|
|
||||||
|
|
||||||
const uint32_t masked1 = uint32_and(ftob, kFloatSignMask | kFloatMantissaMask);
|
int32_t exp = int32_t(exp0.u32) - 0x7e;
|
||||||
const uint32_t bits = uint32_or(masked1, UINT32_C(0x3f000000) );
|
|
||||||
float ff = bitsToFloat(bits);
|
const simd32_t masked1 = simd32_and(ftob, signmantmask);
|
||||||
|
const simd32_t bits = simd32_or(masked1, half);
|
||||||
|
float ff = bitsToFloat(bits.u32);
|
||||||
|
|
||||||
if (ff < kSqrt2*0.5f)
|
if (ff < kSqrt2*0.5f)
|
||||||
{
|
{
|
||||||
@@ -434,13 +487,13 @@ namespace bx
|
|||||||
--exp;
|
--exp;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr float kLogC0 = 6.666666666666735130e-01f;
|
constexpr float kLogC0 = 6.666666666666735130e-01f;
|
||||||
constexpr float kLogC1 = 3.999999999940941908e-01f;
|
constexpr float kLogC1 = 3.999999999940941908e-01f;
|
||||||
constexpr float kLogC2 = 2.857142874366239149e-01f;
|
constexpr float kLogC2 = 2.857142874366239149e-01f;
|
||||||
constexpr float kLogC3 = 2.222219843214978396e-01f;
|
constexpr float kLogC3 = 2.222219843214978396e-01f;
|
||||||
constexpr float kLogC4 = 1.818357216161805012e-01f;
|
constexpr float kLogC4 = 1.818357216161805012e-01f;
|
||||||
constexpr float kLogC5 = 1.531383769920937332e-01f;
|
constexpr float kLogC5 = 1.531383769920937332e-01f;
|
||||||
constexpr float kLogC6 = 1.479819860511658591e-01f;
|
constexpr float kLogC6 = 1.479819860511658591e-01f;
|
||||||
constexpr float kLogNat2Lo = 1.90821492927058770002e-10f;
|
constexpr float kLogNat2Lo = 1.90821492927058770002e-10f;
|
||||||
|
|
||||||
ff -= 1.0f;
|
ff -= 1.0f;
|
||||||
@@ -541,23 +594,23 @@ namespace bx
|
|||||||
#if BX_COMPILER_GCC || BX_COMPILER_CLANG
|
#if BX_COMPILER_GCC || BX_COMPILER_CLANG
|
||||||
return __builtin_popcount(_val);
|
return __builtin_popcount(_val);
|
||||||
#else
|
#else
|
||||||
const uint32_t tmp0 = uint32_srl(_val, 1);
|
const uint32_t tmp0 = (_val >> 1);
|
||||||
const uint32_t tmp1 = uint32_and(tmp0, 0x55555555);
|
const uint32_t tmp1 = (tmp0 & 0x55555555);
|
||||||
const uint32_t tmp2 = uint32_sub(_val, tmp1);
|
const uint32_t tmp2 = (_val - tmp1);
|
||||||
const uint32_t tmp3 = uint32_and(tmp2, 0xc30c30c3);
|
const uint32_t tmp3 = (tmp2 & 0xc30c30c3);
|
||||||
const uint32_t tmp4 = uint32_srl(tmp2, 2);
|
const uint32_t tmp4 = (tmp2 >> 2);
|
||||||
const uint32_t tmp5 = uint32_and(tmp4, 0xc30c30c3);
|
const uint32_t tmp5 = (tmp4 & 0xc30c30c3);
|
||||||
const uint32_t tmp6 = uint32_srl(tmp2, 4);
|
const uint32_t tmp6 = (tmp2 >> 4);
|
||||||
const uint32_t tmp7 = uint32_and(tmp6, 0xc30c30c3);
|
const uint32_t tmp7 = (tmp6 & 0xc30c30c3);
|
||||||
const uint32_t tmp8 = uint32_add(tmp3, tmp5);
|
const uint32_t tmp8 = (tmp3 + tmp5);
|
||||||
const uint32_t tmp9 = uint32_add(tmp7, tmp8);
|
const uint32_t tmp9 = (tmp7 + tmp8);
|
||||||
const uint32_t tmpA = uint32_srl(tmp9, 6);
|
const uint32_t tmpA = (tmp9 >> 6);
|
||||||
const uint32_t tmpB = uint32_add(tmp9, tmpA);
|
const uint32_t tmpB = (tmp9 + tmpA);
|
||||||
const uint32_t tmpC = uint32_srl(tmpB, 12);
|
const uint32_t tmpC = (tmpB >> 12);
|
||||||
const uint32_t tmpD = uint32_srl(tmpB, 24);
|
const uint32_t tmpD = (tmpB >> 24);
|
||||||
const uint32_t tmpE = uint32_add(tmpB, tmpC);
|
const uint32_t tmpE = (tmpB + tmpC);
|
||||||
const uint32_t tmpF = uint32_add(tmpD, tmpE);
|
const uint32_t tmpF = (tmpD + tmpE);
|
||||||
const uint32_t result = uint32_and(tmpF, 0x3f);
|
const uint32_t result = (tmpF & 0x3f);
|
||||||
|
|
||||||
return uint8_t(result);
|
return uint8_t(result);
|
||||||
#endif // BX_COMPILER_*
|
#endif // BX_COMPILER_*
|
||||||
@@ -607,20 +660,21 @@ namespace bx
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
# endif // BX_COMPILER_MSVC
|
# endif // BX_COMPILER_MSVC
|
||||||
const uint32_t tmp0 = uint32_srl(_val, 1);
|
const simd32_t val = simd32_splat(_val);
|
||||||
const uint32_t tmp1 = uint32_or(tmp0, _val);
|
const simd32_t tmp0 = simd32_x32_srl(val, 1);
|
||||||
const uint32_t tmp2 = uint32_srl(tmp1, 2);
|
const simd32_t tmp1 = simd32_or(tmp0, val);
|
||||||
const uint32_t tmp3 = uint32_or(tmp2, tmp1);
|
const simd32_t tmp2 = simd32_x32_srl(tmp1, 2);
|
||||||
const uint32_t tmp4 = uint32_srl(tmp3, 4);
|
const simd32_t tmp3 = simd32_or(tmp2, tmp1);
|
||||||
const uint32_t tmp5 = uint32_or(tmp4, tmp3);
|
const simd32_t tmp4 = simd32_x32_srl(tmp3, 4);
|
||||||
const uint32_t tmp6 = uint32_srl(tmp5, 8);
|
const simd32_t tmp5 = simd32_or(tmp4, tmp3);
|
||||||
const uint32_t tmp7 = uint32_or(tmp6, tmp5);
|
const simd32_t tmp6 = simd32_x32_srl(tmp5, 8);
|
||||||
const uint32_t tmp8 = uint32_srl(tmp7, 16);
|
const simd32_t tmp7 = simd32_or(tmp6, tmp5);
|
||||||
const uint32_t tmp9 = uint32_or(tmp8, tmp7);
|
const simd32_t tmp8 = simd32_x32_srl(tmp7, 16);
|
||||||
const uint32_t tmpA = uint32_not(tmp9);
|
const simd32_t tmp9 = simd32_or(tmp8, tmp7);
|
||||||
const uint32_t result = uint32_cntbits(tmpA);
|
const simd32_t tmpA = simd32_not(tmp9);
|
||||||
|
const simd32_t result = simd32_x32_cntbits(tmpA);
|
||||||
|
|
||||||
return uint8_t(result);
|
return uint8_t(result.u32);
|
||||||
#endif // BX_COMPILER_*
|
#endif // BX_COMPILER_*
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -676,12 +730,14 @@ namespace bx
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
# endif // BX_COMPILER_MSVC
|
# endif // BX_COMPILER_MSVC
|
||||||
const uint32_t tmp0 = uint32_not(_val);
|
const simd32_t val = simd32_splat(_val);
|
||||||
const uint32_t tmp1 = uint32_dec(_val);
|
const simd32_t one = simd32_splat(1);
|
||||||
const uint32_t tmp2 = uint32_and(tmp0, tmp1);
|
const simd32_t tmp0 = simd32_not(val);
|
||||||
const uint32_t result = uint32_cntbits(tmp2);
|
const simd32_t tmp1 = simd32_u32_sub(val, one);
|
||||||
|
const simd32_t tmp2 = simd32_and(tmp0, tmp1);
|
||||||
|
const simd32_t result = simd32_x32_cntbits(tmp2);
|
||||||
|
|
||||||
return uint8_t(result);
|
return uint8_t(result.u32);
|
||||||
#endif // BX_COMPILER_*
|
#endif // BX_COMPILER_*
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -778,15 +834,11 @@ namespace bx
|
|||||||
return kFloatInfinity;
|
return kFloatInfinity;
|
||||||
}
|
}
|
||||||
|
|
||||||
const simd128_t aa = simd_splat(_a);
|
const simd128_t aa = simd_splat<simd128_t>(_a);
|
||||||
#if BX_SIMD_NEON
|
const simd128_t rsqrta = simd_f32_rsqrt<simd128_t>(aa);
|
||||||
const simd128_t rsqrta = simd_rsqrt_nr(aa);
|
|
||||||
#else
|
|
||||||
const simd128_t rsqrta = simd_rsqrt_ni(aa);
|
|
||||||
#endif // BX_SIMD_NEON
|
|
||||||
|
|
||||||
float result = 0.0f;
|
float result = 0.0f;
|
||||||
simd_stx(&result, rsqrta);
|
simd_x32_st1<simd128_t>(&result, rsqrta);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -812,11 +864,11 @@ namespace bx
|
|||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
const simd128_t aa = simd_splat(_a);
|
const simd128_t aa = simd_splat<simd128_t>(_a);
|
||||||
const simd128_t sqrt = simd_sqrt(aa);
|
const simd128_t sqrt = simd_f32_sqrt<simd128_t>(aa);
|
||||||
|
|
||||||
float result = 0.0f;
|
float result = 0.0f;
|
||||||
simd_stx(&result, sqrt);
|
simd_x32_st1<simd128_t>(&result, sqrt);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -1914,4 +1966,18 @@ namespace bx
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline BX_CONST_FUNC uint16_t halfFromFloat(float _a)
|
||||||
|
{
|
||||||
|
const simd32_t a = { .u32 = bitCast<uint32_t>(_a) };
|
||||||
|
const simd32_t result = simd_f16_fromf32_ni(a);
|
||||||
|
return uint16_t(result.u32);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONST_FUNC float halfToFloat(uint16_t _a)
|
||||||
|
{
|
||||||
|
const simd32_t a = simd32_splat(uint32_t(_a) );
|
||||||
|
const simd32_t result = simd_f16_tof32_ni(a);
|
||||||
|
return bitCast<float>(result.u32);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace bx
|
} // namespace bx
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ namespace bx
|
|||||||
}
|
}
|
||||||
|
|
||||||
int64_t remainder = m_top-m_pos;
|
int64_t remainder = m_top-m_pos;
|
||||||
int32_t size = uint32_min(_size, uint32_t(min<int64_t>(remainder, INT32_MAX) ) );
|
int32_t size = int32_t(max<int64_t>(0, min<int64_t>(_size, remainder, INT32_MAX) ) );
|
||||||
m_pos += size;
|
m_pos += size;
|
||||||
if (size != _size)
|
if (size != _size)
|
||||||
{
|
{
|
||||||
@@ -173,7 +173,7 @@ namespace bx
|
|||||||
BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors.");
|
BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors.");
|
||||||
|
|
||||||
int64_t remainder = m_top-m_pos;
|
int64_t remainder = m_top-m_pos;
|
||||||
int32_t size = uint32_min(_size, uint32_t(min<int64_t>(remainder, INT32_MAX) ) );
|
int32_t size = int32_t(max<int64_t>(0, min<int64_t>(_size, remainder, INT32_MAX) ) );
|
||||||
memCopy(_data, &m_data[m_pos], size);
|
memCopy(_data, &m_data[m_pos], size);
|
||||||
m_pos += size;
|
m_pos += size;
|
||||||
if (size != _size)
|
if (size != _size)
|
||||||
@@ -245,7 +245,7 @@ namespace bx
|
|||||||
}
|
}
|
||||||
|
|
||||||
int64_t remainder = m_size-m_pos;
|
int64_t remainder = m_size-m_pos;
|
||||||
int32_t size = uint32_min(_size, uint32_t(min<int64_t>(remainder, INT32_MAX) ) );
|
int32_t size = int32_t(max<int64_t>(0, min<int64_t>(_size, remainder, INT32_MAX) ) );
|
||||||
memCopy(&m_data[m_pos], _data, size);
|
memCopy(&m_data[m_pos], _data, size);
|
||||||
m_pos += size;
|
m_pos += size;
|
||||||
m_top = max(m_top, m_pos);
|
m_top = max(m_top, m_pos);
|
||||||
@@ -301,16 +301,16 @@ namespace bx
|
|||||||
{
|
{
|
||||||
BX_ERROR_SCOPE(_err);
|
BX_ERROR_SCOPE(_err);
|
||||||
|
|
||||||
const uint32_t tmp0 = uint32_sels(64 - _size, 64, _size);
|
const uint32_t tmp0 = simd32_sels(simd32_splat(64 - _size), simd32_splat( 64), simd32_splat(_size)).u32;
|
||||||
const uint32_t tmp1 = uint32_sels(256 - _size, 256, tmp0);
|
const uint32_t tmp1 = simd32_sels(simd32_splat(256 - _size), simd32_splat( 256), simd32_splat(tmp0 )).u32;
|
||||||
const uint32_t blockSize = uint32_sels(1024 - _size, 1024, tmp1);
|
const uint32_t blockSize = simd32_sels(simd32_splat(1024 - _size), simd32_splat(1024), simd32_splat(tmp1 )).u32;
|
||||||
uint8_t* temp = (uint8_t*)BX_STACK_ALLOC(blockSize);
|
uint8_t* temp = (uint8_t*)BX_STACK_ALLOC(blockSize);
|
||||||
memSet(temp, _byte, blockSize);
|
memSet(temp, _byte, blockSize);
|
||||||
|
|
||||||
int32_t size = 0;
|
int32_t size = 0;
|
||||||
while (0 < _size && _err->isOk() )
|
while (0 < _size && _err->isOk() )
|
||||||
{
|
{
|
||||||
int32_t bytes = write(_writer, temp, uint32_min(blockSize, _size), _err);
|
int32_t bytes = write(_writer, temp, min(blockSize, _size), _err);
|
||||||
size += bytes;
|
size += bytes;
|
||||||
_size -= bytes;
|
_size -= bytes;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,48 +62,67 @@ namespace bx
|
|||||||
|
|
||||||
inline uint32_t RingBufferControl::consume(uint32_t _size)
|
inline uint32_t RingBufferControl::consume(uint32_t _size)
|
||||||
{
|
{
|
||||||
const uint32_t maxSize = distance(m_read, m_current);
|
const simd32_t maxSize = simd32_splat(distance(m_read, m_current) );
|
||||||
const uint32_t sizeNoSign = uint32_and(_size, 0x7fffffff);
|
const simd32_t size = simd32_splat(_size);
|
||||||
const uint32_t test = uint32_sub(sizeNoSign, maxSize);
|
const simd32_t signMask = simd32_splat(0x7fffffffu);
|
||||||
const uint32_t size = uint32_sels(test, _size, maxSize);
|
const simd32_t sizeNoSign = simd32_and(size, signMask);
|
||||||
const uint32_t advance = uint32_add(m_read, size);
|
const simd32_t test = simd32_u32_sub(sizeNoSign, maxSize);
|
||||||
const uint32_t read = uint32_mod(advance, m_size);
|
const simd32_t result = simd32_sels(test, size, maxSize);
|
||||||
m_read = read;
|
const simd32_t readVal = simd32_splat(m_read);
|
||||||
return size;
|
const simd32_t advance = simd32_u32_add(readVal, result);
|
||||||
|
const simd32_t sizeVal = simd32_splat(m_size);
|
||||||
|
const simd32_t read = simd32_u32_mod(advance, sizeVal);
|
||||||
|
m_read = read.u32;
|
||||||
|
return result.u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint32_t RingBufferControl::reserve(uint32_t _size, bool _mustSucceed)
|
inline uint32_t RingBufferControl::reserve(uint32_t _size, bool _mustSucceed)
|
||||||
{
|
{
|
||||||
const uint32_t dist = distance(m_write, m_read)-1;
|
const simd32_t distVal = simd32_splat(distance(m_write, m_read) );
|
||||||
const uint32_t maxSize = uint32_sels(dist, m_size-1, dist);
|
const simd32_t one = simd32_splat(1u);
|
||||||
const uint32_t sizeNoSign = uint32_and(_size, 0x7fffffff);
|
const simd32_t dist = simd32_u32_sub(distVal, one);
|
||||||
const uint32_t test = uint32_sub(sizeNoSign, maxSize);
|
const simd32_t sizeVal = simd32_splat(m_size);
|
||||||
const uint32_t size = uint32_sels(test, _size, _mustSucceed ? 0 : maxSize);
|
const simd32_t sizem1 = simd32_u32_sub(sizeVal, one);
|
||||||
const uint32_t advance = uint32_add(m_write, size);
|
const simd32_t maxSize = simd32_sels(dist, sizem1, dist);
|
||||||
const uint32_t write = uint32_mod(advance, m_size);
|
const simd32_t size = simd32_splat(_size);
|
||||||
m_write = write;
|
const simd32_t signMask = simd32_splat(0x7fffffffu);
|
||||||
return size;
|
const simd32_t sizeNoSign = simd32_and(size, signMask);
|
||||||
|
const simd32_t test = simd32_u32_sub(sizeNoSign, maxSize);
|
||||||
|
const simd32_t zero = simd32_splat(0u);
|
||||||
|
const simd32_t fail = _mustSucceed ? zero : maxSize;
|
||||||
|
const simd32_t result = simd32_sels(test, size, fail);
|
||||||
|
const simd32_t writeVal = simd32_splat(m_write);
|
||||||
|
const simd32_t advance = simd32_u32_add(writeVal, result);
|
||||||
|
const simd32_t write = simd32_u32_mod(advance, sizeVal);
|
||||||
|
m_write = write.u32;
|
||||||
|
return result.u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint32_t RingBufferControl::commit(uint32_t _size)
|
inline uint32_t RingBufferControl::commit(uint32_t _size)
|
||||||
{
|
{
|
||||||
const uint32_t maxSize = distance(m_current, m_write);
|
const simd32_t maxSize = simd32_splat(distance(m_current, m_write) );
|
||||||
const uint32_t sizeNoSign = uint32_and(_size, 0x7fffffff);
|
const simd32_t size = simd32_splat(_size);
|
||||||
const uint32_t test = uint32_sub(sizeNoSign, maxSize);
|
const simd32_t signMask = simd32_splat(0x7fffffffu);
|
||||||
const uint32_t size = uint32_sels(test, _size, maxSize);
|
const simd32_t sizeNoSign = simd32_and(size, signMask);
|
||||||
const uint32_t advance = uint32_add(m_current, size);
|
const simd32_t test = simd32_u32_sub(sizeNoSign, maxSize);
|
||||||
const uint32_t current = uint32_mod(advance, m_size);
|
const simd32_t result = simd32_sels(test, size, maxSize);
|
||||||
m_current = current;
|
const simd32_t currentVal = simd32_splat(m_current);
|
||||||
return size;
|
const simd32_t advance = simd32_u32_add(currentVal, result);
|
||||||
|
const simd32_t sizeVal = simd32_splat(m_size);
|
||||||
|
const simd32_t current = simd32_u32_mod(advance, sizeVal);
|
||||||
|
m_current = current.u32;
|
||||||
|
return result.u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint32_t RingBufferControl::distance(uint32_t _from, uint32_t _to) const
|
inline uint32_t RingBufferControl::distance(uint32_t _from, uint32_t _to) const
|
||||||
{
|
{
|
||||||
const uint32_t diff = uint32_sub(_to, _from);
|
const simd32_t to = simd32_splat(_to);
|
||||||
const uint32_t le = uint32_add(m_size, diff);
|
const simd32_t from = simd32_splat(_from);
|
||||||
const uint32_t result = uint32_sels(diff, le, diff);
|
const simd32_t diff = simd32_u32_sub(to, from);
|
||||||
|
const simd32_t sizeVal = simd32_splat(m_size);
|
||||||
return result;
|
const simd32_t le = simd32_u32_add(sizeVal, diff);
|
||||||
|
const simd32_t result = simd32_sels(diff, le, diff);
|
||||||
|
return result.u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void RingBufferControl::reset()
|
inline void RingBufferControl::reset()
|
||||||
@@ -166,52 +185,71 @@ namespace bx
|
|||||||
|
|
||||||
inline uint32_t SpScRingBufferControl::consume(uint32_t _size)
|
inline uint32_t SpScRingBufferControl::consume(uint32_t _size)
|
||||||
{
|
{
|
||||||
const uint32_t maxSize = distance(m_read, m_current);
|
const simd32_t maxSize = simd32_splat(distance(m_read, m_current) );
|
||||||
const uint32_t sizeNoSign = uint32_and(_size, 0x7fffffff);
|
const simd32_t size = simd32_splat(_size);
|
||||||
const uint32_t test = uint32_sub(sizeNoSign, maxSize);
|
const simd32_t signMask = simd32_splat(0x7fffffffu);
|
||||||
const uint32_t size = uint32_sels(test, _size, maxSize);
|
const simd32_t sizeNoSign = simd32_and(size, signMask);
|
||||||
const uint32_t advance = uint32_add(m_read, size);
|
const simd32_t test = simd32_u32_sub(sizeNoSign, maxSize);
|
||||||
const uint32_t read = uint32_mod(advance, m_size);
|
const simd32_t result = simd32_sels(test, size, maxSize);
|
||||||
m_read = read;
|
const simd32_t readVal = simd32_splat(m_read);
|
||||||
return size;
|
const simd32_t advance = simd32_u32_add(readVal, result);
|
||||||
|
const simd32_t sizeVal = simd32_splat(m_size);
|
||||||
|
const simd32_t read = simd32_u32_mod(advance, sizeVal);
|
||||||
|
m_read = read.u32;
|
||||||
|
return result.u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint32_t SpScRingBufferControl::reserve(uint32_t _size, bool _mustSucceed)
|
inline uint32_t SpScRingBufferControl::reserve(uint32_t _size, bool _mustSucceed)
|
||||||
{
|
{
|
||||||
const uint32_t dist = distance(m_write, m_read)-1;
|
const simd32_t distVal = simd32_splat(distance(m_write, m_read) );
|
||||||
const uint32_t maxSize = uint32_sels(dist, m_size-1, dist);
|
const simd32_t one = simd32_splat(1u);
|
||||||
const uint32_t sizeNoSign = uint32_and(_size, 0x7fffffff);
|
const simd32_t dist = simd32_u32_sub(distVal, one);
|
||||||
const uint32_t test = uint32_sub(sizeNoSign, maxSize);
|
const simd32_t sizeVal = simd32_splat(m_size);
|
||||||
const uint32_t size = uint32_sels(test, _size, _mustSucceed ? 0 : maxSize);
|
const simd32_t sizem1 = simd32_u32_sub(sizeVal, one);
|
||||||
const uint32_t advance = uint32_add(m_write, size);
|
const simd32_t maxSize = simd32_sels(dist, sizem1, dist);
|
||||||
const uint32_t write = uint32_mod(advance, m_size);
|
const simd32_t size = simd32_splat(_size);
|
||||||
m_write = write;
|
const simd32_t signMask = simd32_splat(0x7fffffffu);
|
||||||
return size;
|
const simd32_t sizeNoSign = simd32_and(size, signMask);
|
||||||
|
const simd32_t test = simd32_u32_sub(sizeNoSign, maxSize);
|
||||||
|
const simd32_t zero = simd32_splat(0u);
|
||||||
|
const simd32_t fail = _mustSucceed ? zero : maxSize;
|
||||||
|
const simd32_t result = simd32_sels(test, size, fail);
|
||||||
|
const simd32_t writeVal = simd32_splat(m_write);
|
||||||
|
const simd32_t advance = simd32_u32_add(writeVal, result);
|
||||||
|
const simd32_t write = simd32_u32_mod(advance, sizeVal);
|
||||||
|
m_write = write.u32;
|
||||||
|
return result.u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint32_t SpScRingBufferControl::commit(uint32_t _size)
|
inline uint32_t SpScRingBufferControl::commit(uint32_t _size)
|
||||||
{
|
{
|
||||||
const uint32_t maxSize = distance(m_current, m_write);
|
const simd32_t maxSize = simd32_splat(distance(m_current, m_write) );
|
||||||
const uint32_t sizeNoSign = uint32_and(_size, 0x7fffffff);
|
const simd32_t size = simd32_splat(_size);
|
||||||
const uint32_t test = uint32_sub(sizeNoSign, maxSize);
|
const simd32_t signMask = simd32_splat(0x7fffffffu);
|
||||||
const uint32_t size = uint32_sels(test, _size, maxSize);
|
const simd32_t sizeNoSign = simd32_and(size, signMask);
|
||||||
const uint32_t advance = uint32_add(m_current, size);
|
const simd32_t test = simd32_u32_sub(sizeNoSign, maxSize);
|
||||||
const uint32_t current = uint32_mod(advance, m_size);
|
const simd32_t result = simd32_sels(test, size, maxSize);
|
||||||
|
const simd32_t currentVal = simd32_splat(m_current);
|
||||||
|
const simd32_t advance = simd32_u32_add(currentVal, result);
|
||||||
|
const simd32_t sizeVal = simd32_splat(m_size);
|
||||||
|
const simd32_t current = simd32_u32_mod(advance, sizeVal);
|
||||||
|
|
||||||
// must commit all memory writes before moving m_current pointer
|
// must commit all memory writes before moving m_current pointer
|
||||||
// once m_current pointer moves data is used by consumer thread
|
// once m_current pointer moves data is used by consumer thread
|
||||||
memoryBarrier();
|
memoryBarrier();
|
||||||
m_current = current;
|
m_current = current.u32;
|
||||||
return size;
|
return result.u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint32_t SpScRingBufferControl::distance(uint32_t _from, uint32_t _to) const
|
inline uint32_t SpScRingBufferControl::distance(uint32_t _from, uint32_t _to) const
|
||||||
{
|
{
|
||||||
const uint32_t diff = uint32_sub(_to, _from);
|
const simd32_t to = simd32_splat(_to);
|
||||||
const uint32_t le = uint32_add(m_size, diff);
|
const simd32_t from = simd32_splat(_from);
|
||||||
const uint32_t result = uint32_sels(diff, le, diff);
|
const simd32_t diff = simd32_u32_sub(to, from);
|
||||||
|
const simd32_t sizeVal = simd32_splat(m_size);
|
||||||
return result;
|
const simd32_t le = simd32_u32_add(sizeVal, diff);
|
||||||
|
const simd32_t result = simd32_sels(diff, le, diff);
|
||||||
|
return result.u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void SpScRingBufferControl::reset()
|
inline void SpScRingBufferControl::reset()
|
||||||
|
|||||||
@@ -1,676 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2026 Branimir Karadzic. All rights reserved.
|
|
||||||
* License: https://github.com/bkaradzic/bx/blob/master/LICENSE
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BX_SIMD_T_H_HEADER_GUARD
|
|
||||||
# error "Must be included from bx/simd_t.h!"
|
|
||||||
#endif // BX_SIMD_T_H_HEADER_GUARD
|
|
||||||
|
|
||||||
namespace bx
|
|
||||||
{
|
|
||||||
BX_CONSTEXPR_FUNC float sqrtRef(float);
|
|
||||||
|
|
||||||
#define ELEMx 0
|
|
||||||
#define ELEMy 1
|
|
||||||
#define ELEMz 2
|
|
||||||
#define ELEMw 3
|
|
||||||
#define BX_SIMD128_IMPLEMENT_SWIZZLE(_x, _y, _z, _w) \
|
|
||||||
template<> \
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_swiz_##_x##_y##_z##_w(simd128_langext_t _a) \
|
|
||||||
{ \
|
|
||||||
simd128_langext_t result; \
|
|
||||||
result.vf = __builtin_shufflevector(_a.vf, _a.vf, ELEM##_x, ELEM##_y, ELEM##_z, ELEM##_w); \
|
|
||||||
return result; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "simd128_swizzle.inl"
|
|
||||||
|
|
||||||
#undef BX_SIMD128_IMPLEMENT_SWIZZLE
|
|
||||||
#undef ELEMw
|
|
||||||
#undef ELEMz
|
|
||||||
#undef ELEMy
|
|
||||||
#undef ELEMx
|
|
||||||
|
|
||||||
#define BX_SIMD128_IMPLEMENT_TEST(_xyzw, _mask) \
|
|
||||||
template<> \
|
|
||||||
BX_SIMD_FORCE_INLINE bool simd_test_any_##_xyzw(simd128_langext_t _test) \
|
|
||||||
{ \
|
|
||||||
uint32_t tmp = ( (_test.uxyzw[3]>>31)<<3) \
|
|
||||||
| ( (_test.uxyzw[2]>>31)<<2) \
|
|
||||||
| ( (_test.uxyzw[1]>>31)<<1) \
|
|
||||||
| ( _test.uxyzw[0]>>31) \
|
|
||||||
; \
|
|
||||||
return 0 != (tmp&(_mask) ); \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
template<> \
|
|
||||||
BX_SIMD_FORCE_INLINE bool simd_test_all_##_xyzw(simd128_langext_t _test) \
|
|
||||||
{ \
|
|
||||||
uint32_t tmp = ( (_test.uxyzw[3]>>31)<<3) \
|
|
||||||
| ( (_test.uxyzw[2]>>31)<<2) \
|
|
||||||
| ( (_test.uxyzw[1]>>31)<<1) \
|
|
||||||
| ( _test.uxyzw[0]>>31) \
|
|
||||||
; \
|
|
||||||
return (_mask) == (tmp&(_mask) ); \
|
|
||||||
}
|
|
||||||
|
|
||||||
BX_SIMD128_IMPLEMENT_TEST(x , 0x1);
|
|
||||||
BX_SIMD128_IMPLEMENT_TEST(y , 0x2);
|
|
||||||
BX_SIMD128_IMPLEMENT_TEST(xy , 0x3);
|
|
||||||
BX_SIMD128_IMPLEMENT_TEST(z , 0x4);
|
|
||||||
BX_SIMD128_IMPLEMENT_TEST(xz , 0x5);
|
|
||||||
BX_SIMD128_IMPLEMENT_TEST(yz , 0x6);
|
|
||||||
BX_SIMD128_IMPLEMENT_TEST(xyz , 0x7);
|
|
||||||
BX_SIMD128_IMPLEMENT_TEST(w , 0x8);
|
|
||||||
BX_SIMD128_IMPLEMENT_TEST(xw , 0x9);
|
|
||||||
BX_SIMD128_IMPLEMENT_TEST(yw , 0xa);
|
|
||||||
BX_SIMD128_IMPLEMENT_TEST(xyw , 0xb);
|
|
||||||
BX_SIMD128_IMPLEMENT_TEST(zw , 0xc);
|
|
||||||
BX_SIMD128_IMPLEMENT_TEST(xzw , 0xd);
|
|
||||||
BX_SIMD128_IMPLEMENT_TEST(yzw , 0xe);
|
|
||||||
BX_SIMD128_IMPLEMENT_TEST(xyzw , 0xf);
|
|
||||||
|
|
||||||
#undef BX_SIMD128_IMPLEMENT_TEST
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_shuf_xyAB(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vf = __builtin_shufflevector(_a.vf, _b.vf, 0, 1, 4, 5);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_shuf_ABxy(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vf = __builtin_shufflevector(_a.vf, _b.vf, 4, 5, 0, 1);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_shuf_CDzw(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vf = __builtin_shufflevector(_a.vf, _b.vf, 6, 7, 2, 3);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_shuf_zwCD(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vf = __builtin_shufflevector(_a.vf, _b.vf, 2, 3, 6, 7);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_shuf_xAyB(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vf = __builtin_shufflevector(_a.vf, _b.vf, 0, 4, 1, 5);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_shuf_AxBy(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vf = __builtin_shufflevector(_a.vf, _b.vf, 1, 5, 0, 4);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_shuf_zCwD(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vf = __builtin_shufflevector(_a.vf, _b.vf, 2, 6, 3, 7);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_shuf_CzDw(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vf = __builtin_shufflevector(_a.vf, _b.vf, 6, 2, 7, 3);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_shuf_xAzC(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vf = __builtin_shufflevector(_a.vf, _b.vf, 0, 4, 2, 6);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_shuf_yBwD(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vf = __builtin_shufflevector(_a.vf, _b.vf, 1, 5, 3, 7);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE float simd_x(simd128_langext_t _a)
|
|
||||||
{
|
|
||||||
return _a.fxyzw[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE float simd_y(simd128_langext_t _a)
|
|
||||||
{
|
|
||||||
return _a.fxyzw[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE float simd_z(simd128_langext_t _a)
|
|
||||||
{
|
|
||||||
return _a.fxyzw[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE float simd_w(simd128_langext_t _a)
|
|
||||||
{
|
|
||||||
return _a.fxyzw[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_ld(const void* _ptr)
|
|
||||||
{
|
|
||||||
const uint32_t* input = reinterpret_cast<const uint32_t*>(_ptr);
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.uxyzw[0] = input[0];
|
|
||||||
result.uxyzw[1] = input[1];
|
|
||||||
result.uxyzw[2] = input[2];
|
|
||||||
result.uxyzw[3] = input[3];
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE void simd_st(void* _ptr, simd128_langext_t _a)
|
|
||||||
{
|
|
||||||
uint32_t* result = reinterpret_cast<uint32_t*>(_ptr);
|
|
||||||
result[0] = _a.uxyzw[0];
|
|
||||||
result[1] = _a.uxyzw[1];
|
|
||||||
result[2] = _a.uxyzw[2];
|
|
||||||
result[3] = _a.uxyzw[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE void simd_stx(void* _ptr, simd128_langext_t _a)
|
|
||||||
{
|
|
||||||
uint32_t* result = reinterpret_cast<uint32_t*>(_ptr);
|
|
||||||
result[0] = _a.uxyzw[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE void simd_stream(void* _ptr, simd128_langext_t _a)
|
|
||||||
{
|
|
||||||
uint32_t* result = reinterpret_cast<uint32_t*>(_ptr);
|
|
||||||
result[0] = _a.uxyzw[0];
|
|
||||||
result[1] = _a.uxyzw[1];
|
|
||||||
result[2] = _a.uxyzw[2];
|
|
||||||
result[3] = _a.uxyzw[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_ld(float _x, float _y, float _z, float _w)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vf = (float __attribute__((vector_size(16)))){ _x, _y, _z, _w };
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_ild(uint32_t _x, uint32_t _y, uint32_t _z, uint32_t _w)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vu = (uint32_t __attribute__((vector_size(16)))){ _x, _y, _z, _w };
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_splat(const void* _ptr)
|
|
||||||
{
|
|
||||||
const uint32_t val = *reinterpret_cast<const uint32_t*>(_ptr);
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vu = (uint32_t __attribute__((vector_size(16)))){ val, val, val, val };
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_splat(float _a)
|
|
||||||
{
|
|
||||||
return simd_ld<simd128_langext_t>(_a, _a, _a, _a);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_isplat(uint32_t _a)
|
|
||||||
{
|
|
||||||
return simd_ild<simd128_langext_t>(_a, _a, _a, _a);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_zero()
|
|
||||||
{
|
|
||||||
return simd_ild<simd128_langext_t>(0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_itof(simd128_langext_t _a)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vf = __builtin_convertvector(_a.vi, float __attribute__((vector_size(16))) );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_ftoi(simd128_langext_t _a)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vi = __builtin_convertvector(_a.vf, int32_t __attribute__((vector_size(16))) );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_round(simd128_langext_t _a)
|
|
||||||
{
|
|
||||||
const simd128_langext_t tmp = simd_ftoi(_a);
|
|
||||||
const simd128_langext_t result = simd_itof(tmp);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_add(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vf = _a.vf + _b.vf;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_sub(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vf = _a.vf - _b.vf;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_mul(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vf = _a.vf * _b.vf;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_div(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vf = _a.vf / _b.vf;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_sqrt(simd128_langext_t _a)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vf[0] = sqrtRef(_a.vf[0]);
|
|
||||||
result.vf[1] = sqrtRef(_a.vf[1]);
|
|
||||||
result.vf[2] = sqrtRef(_a.vf[2]);
|
|
||||||
result.vf[3] = sqrtRef(_a.vf[3]);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_rsqrt_est(simd128_langext_t _a)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vf[0] = 1.0f / sqrtRef(_a.vf[0]);
|
|
||||||
result.vf[1] = 1.0f / sqrtRef(_a.vf[1]);
|
|
||||||
result.vf[2] = 1.0f / sqrtRef(_a.vf[2]);
|
|
||||||
result.vf[3] = 1.0f / sqrtRef(_a.vf[3]);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_cmpeq(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vi = _a.vf == _b.vf;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_cmpneq(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vi = _a.vf != _b.vf;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_cmplt(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vi = _a.vf < _b.vf;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_cmple(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vi = _a.vf <= _b.vf;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_cmpgt(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vi = _a.vf > _b.vf;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_cmpge(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vi = _a.vf >= _b.vf;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_and(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vu = _a.vu & _b.vu;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_andc(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vu = _a.vu & ~_b.vu;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_or(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vu = _a.vu | _b.vu;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_xor(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vu = _a.vu ^ _b.vu;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_sll(simd128_langext_t _a, int _count)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
const simd128_langext_t count = simd_isplat<simd128_langext_t>(_count);
|
|
||||||
result.vu = _a.vu << count.vi;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_srl(simd128_langext_t _a, int _count)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
const simd128_langext_t count = simd_isplat<simd128_langext_t>(_count);
|
|
||||||
result.vu = _a.vu >> count.vi;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_sra(simd128_langext_t _a, int _count)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
const simd128_langext_t count = simd_isplat<simd128_langext_t>(_count);
|
|
||||||
result.vi = _a.vi >> count.vi;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_icmpeq(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vi = _a.vi == _b.vi;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_icmplt(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vi = _a.vi < _b.vi;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_icmpgt(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vi = _a.vi > _b.vi;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_iadd(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vi = _a.vi + _b.vi;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_isub(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
simd128_langext_t result;
|
|
||||||
result.vi = _a.vi - _b.vi;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_rcp(simd128_langext_t _a)
|
|
||||||
{
|
|
||||||
return simd_rcp_ni(_a);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_orx(simd128_langext_t _a)
|
|
||||||
{
|
|
||||||
return simd_orx_ni(_a);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_orc(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
return simd_orc_ni(_a, _b);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_neg(simd128_langext_t _a)
|
|
||||||
{
|
|
||||||
return simd_neg_ni(_a);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_madd(simd128_langext_t _a, simd128_langext_t _b, simd128_langext_t _c)
|
|
||||||
{
|
|
||||||
return simd_madd_ni(_a, _b, _c);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_nmsub(simd128_langext_t _a, simd128_langext_t _b, simd128_langext_t _c)
|
|
||||||
{
|
|
||||||
return simd_nmsub_ni(_a, _b, _c);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_div_nr(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
return simd_div_nr_ni(_a, _b);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_selb(simd128_langext_t _mask, simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
return simd_selb_ni(_mask, _a, _b);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_sels(simd128_langext_t _test, simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
return simd_sels_ni(_test, _a, _b);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_not(simd128_langext_t _a)
|
|
||||||
{
|
|
||||||
return simd_not_ni(_a);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_abs(simd128_langext_t _a)
|
|
||||||
{
|
|
||||||
return simd_abs_ni(_a);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_clamp(simd128_langext_t _a, simd128_langext_t _min, simd128_langext_t _max)
|
|
||||||
{
|
|
||||||
return simd_clamp_ni(_a, _min, _max);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_lerp(simd128_langext_t _a, simd128_langext_t _b, simd128_langext_t _s)
|
|
||||||
{
|
|
||||||
return simd_lerp_ni(_a, _b, _s);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_rcp_est(simd128_langext_t _a)
|
|
||||||
{
|
|
||||||
return simd_rcp_ni(_a);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_rsqrt(simd128_langext_t _a)
|
|
||||||
{
|
|
||||||
return simd_rsqrt_ni(_a);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_rsqrt_nr(simd128_langext_t _a)
|
|
||||||
{
|
|
||||||
return simd_rsqrt_nr_ni(_a);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_rsqrt_carmack(simd128_langext_t _a)
|
|
||||||
{
|
|
||||||
return simd_rsqrt_carmack_ni(_a);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_sqrt_nr(simd128_langext_t _a)
|
|
||||||
{
|
|
||||||
return simd_sqrt_nr_ni(_a);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_log2(simd128_langext_t _a)
|
|
||||||
{
|
|
||||||
return simd_log2_ni(_a);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_exp2(simd128_langext_t _a)
|
|
||||||
{
|
|
||||||
return simd_exp2_ni(_a);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_pow(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
return simd_pow_ni(_a, _b);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_cross3(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
return simd_cross3_ni(_a, _b);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_normalize3(simd128_langext_t _a)
|
|
||||||
{
|
|
||||||
return simd_normalize3_ni(_a);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_dot3(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
return simd_dot3_ni(_a, _b);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_dot(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
return simd_dot_ni(_a, _b);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_ceil(simd128_langext_t _a)
|
|
||||||
{
|
|
||||||
return simd_ceil_ni(_a);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_floor(simd128_langext_t _a)
|
|
||||||
{
|
|
||||||
return simd_floor_ni(_a);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_min(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
return simd_min_ni(_a, _b);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_max(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
return simd_max_ni(_a, _b);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_imin(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
return simd_imin_ni(_a, _b);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
BX_SIMD_FORCE_INLINE simd128_langext_t simd_imax(simd128_langext_t _a, simd128_langext_t _b)
|
|
||||||
{
|
|
||||||
return simd_imax_ni(_a, _b);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef simd128_langext_t simd128_t;
|
|
||||||
|
|
||||||
} // namespace bx
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -3,9 +3,9 @@
|
|||||||
* License: https://github.com/bkaradzic/bx/blob/master/LICENSE
|
* License: https://github.com/bkaradzic/bx/blob/master/LICENSE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef BX_SIMD_T_H_HEADER_GUARD
|
#if !defined(BX_SIMD_T_H_HEADER_GUARD)
|
||||||
# error "xmacro file, must be included from simd_*.h"
|
# error "xmacro file, must be included from simd_t.h"
|
||||||
#endif // BX_FLOAT4_T_H_HEADER_GUARD
|
#endif // BX_SIMD_T_H_HEADER_GUARD
|
||||||
|
|
||||||
// included from float4_t.h
|
// included from float4_t.h
|
||||||
BX_SIMD128_IMPLEMENT_SWIZZLE(x, x, x, x)
|
BX_SIMD128_IMPLEMENT_SWIZZLE(x, x, x, x)
|
||||||
|
|||||||
1001
include/bx/inline/simd128_wasm.inl
Normal file
1001
include/bx/inline/simd128_wasm.inl
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
839
include/bx/inline/simd32_ref.inl
Normal file
839
include/bx/inline/simd32_ref.inl
Normal file
@@ -0,0 +1,839 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2026 Branimir Karadzic. All rights reserved.
|
||||||
|
* License: https://github.com/bkaradzic/bx/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BX_SIMD_T_H_HEADER_GUARD
|
||||||
|
# error "Must be included from bx/simd_t.h!"
|
||||||
|
#endif // BX_SIMD_T_H_HEADER_GUARD
|
||||||
|
|
||||||
|
namespace bx
|
||||||
|
{
|
||||||
|
BX_ALIGN_DECL(4, struct) simd32_f32_ref_t { float f32; };
|
||||||
|
BX_ALIGN_DECL(4, struct) simd32_i32_ref_t { int32_t i32; };
|
||||||
|
|
||||||
|
BX_SIMD_FORCE_INLINE simd32_t simd32_ld(const void* _ptr)
|
||||||
|
{
|
||||||
|
simd32_t result;
|
||||||
|
memCopy(&result, _ptr, sizeof(simd32_t) );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_ld(float _x)
|
||||||
|
{
|
||||||
|
const simd32_f32_ref_t result = { .f32 = _x };
|
||||||
|
return bitCast<simd32_t>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_ld(int32_t _x)
|
||||||
|
{
|
||||||
|
return { .u32 = uint32_t(_x) };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_ld(uint32_t _x)
|
||||||
|
{
|
||||||
|
return { .u32 = _x };
|
||||||
|
}
|
||||||
|
|
||||||
|
BX_SIMD_FORCE_INLINE void simd32_st(void* _ptr, simd32_t _a)
|
||||||
|
{
|
||||||
|
memCopy(_ptr, &_a, sizeof(simd32_t) );
|
||||||
|
}
|
||||||
|
|
||||||
|
BX_SIMD_FORCE_INLINE void simd32_x32_st1(void* _ptr, simd32_t _a)
|
||||||
|
{
|
||||||
|
simd32_t* result = reinterpret_cast<simd32_t*>(_ptr);
|
||||||
|
*result = _a;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_zero()
|
||||||
|
{
|
||||||
|
return { .u32 = 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_splat(float _a)
|
||||||
|
{
|
||||||
|
const simd32_f32_ref_t result = { .f32 = _a };
|
||||||
|
return bitCast<simd32_t>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_splat(uint32_t _a)
|
||||||
|
{
|
||||||
|
return { .u32 = _a };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_splat(int32_t _a)
|
||||||
|
{
|
||||||
|
return { .u32 = uint32_t(_a) };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_splat(uint16_t _a)
|
||||||
|
{
|
||||||
|
const uint32_t val = uint32_t(_a);
|
||||||
|
return { .u32 = (val << 16) | val };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_splat(int16_t _a)
|
||||||
|
{
|
||||||
|
return simd32_splat(uint16_t(_a) );
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_splat(uint8_t _a)
|
||||||
|
{
|
||||||
|
const uint32_t val = uint32_t(_a);
|
||||||
|
return { .u32 = (val << 24) | (val << 16) | (val << 8) | val };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_splat(int8_t _a)
|
||||||
|
{
|
||||||
|
return simd32_splat(uint8_t(_a) );
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_f32_add(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
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 result = { .f32 = a.f32 + b.f32 };
|
||||||
|
return bitCast<simd32_t>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_f32_sub(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
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 result = { .f32 = a.f32 - b.f32 };
|
||||||
|
return bitCast<simd32_t>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_f32_mul(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
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 result = { .f32 = a.f32 * b.f32 };
|
||||||
|
return bitCast<simd32_t>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_f32_div(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
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 result = { .f32 = a.f32 / b.f32 };
|
||||||
|
return bitCast<simd32_t>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC int simd32_x32_signbitsmask(simd32_t _a)
|
||||||
|
{
|
||||||
|
return int(_a.u32 >> 31);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC int simd32_x8_signbitsmask(simd32_t _a)
|
||||||
|
{
|
||||||
|
return int( (_a.u32 >> 7) & 1)
|
||||||
|
| (int( (_a.u32 >> 15) & 1) << 1)
|
||||||
|
| (int( (_a.u32 >> 23) & 1) << 2)
|
||||||
|
| (int( _a.u32 >> 31) << 3)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_x8_shuffle(simd32_t _a, simd32_t _indices)
|
||||||
|
{
|
||||||
|
uint32_t out = 0;
|
||||||
|
for (uint32_t ii = 0; ii < 4; ++ii)
|
||||||
|
{
|
||||||
|
const uint32_t idx = (_indices.u32 >> (ii*8) ) & 0xffu;
|
||||||
|
const uint32_t byte = (idx & 0x80u)
|
||||||
|
? 0u
|
||||||
|
: (_a.u32 >> ( (idx & 0x03u) * 8) ) & 0xffu;
|
||||||
|
out |= byte << (ii*8);
|
||||||
|
}
|
||||||
|
return { .u32 = out };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_x8_shuffle(simd32_t _a, simd32_t _b, simd32_t _indices)
|
||||||
|
{
|
||||||
|
uint32_t out = 0;
|
||||||
|
for (uint32_t ii = 0; ii < 4; ++ii)
|
||||||
|
{
|
||||||
|
const uint32_t idx = (_indices.u32 >> (ii*8) ) & 0xffu;
|
||||||
|
uint32_t byte = 0;
|
||||||
|
if (0 == (idx & 0x80u) )
|
||||||
|
{
|
||||||
|
const uint32_t sel = idx & 0x07u;
|
||||||
|
const uint32_t src = sel < 4u ? _a.u32 : _b.u32;
|
||||||
|
byte = (src >> ( (sel & 0x03u) * 8) ) & 0xffu;
|
||||||
|
}
|
||||||
|
out |= byte << (ii*8);
|
||||||
|
}
|
||||||
|
return { .u32 = out };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_f32_neg(simd32_t _a)
|
||||||
|
{
|
||||||
|
const simd32_f32_ref_t a = bitCast<simd32_f32_ref_t>(_a);
|
||||||
|
const simd32_f32_ref_t result = { .f32 = -a.f32 };
|
||||||
|
return bitCast<simd32_t>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_f32_abs(simd32_t _a)
|
||||||
|
{
|
||||||
|
return { .u32 = _a.u32 & (kFloatExponentMask | kFloatMantissaMask) };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_f32_min(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
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 result = { .f32 = a.f32 < b.f32 ? a.f32 : b.f32 };
|
||||||
|
return bitCast<simd32_t>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_f32_max(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
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 result = { .f32 = a.f32 > b.f32 ? a.f32 : b.f32 };
|
||||||
|
return bitCast<simd32_t>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_f32_clamp(simd32_t _a, simd32_t _min, simd32_t _max)
|
||||||
|
{
|
||||||
|
return simd32_f32_min(simd32_f32_max(_a, _min), _max);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_f32_lerp(simd32_t _a, simd32_t _b, simd32_t _s)
|
||||||
|
{
|
||||||
|
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 s = bitCast<simd32_f32_ref_t>(_s);
|
||||||
|
const simd32_f32_ref_t result = { .f32 = a.f32 + (b.f32 - a.f32) * s.f32 };
|
||||||
|
return bitCast<simd32_t>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_f32_rcp(simd32_t _a)
|
||||||
|
{
|
||||||
|
const simd32_f32_ref_t a = bitCast<simd32_f32_ref_t>(_a);
|
||||||
|
const simd32_f32_ref_t result = { .f32 = 1.0f / a.f32 };
|
||||||
|
return bitCast<simd32_t>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_f32_sqrt(simd32_t _a)
|
||||||
|
{
|
||||||
|
const simd32_f32_ref_t a = bitCast<simd32_f32_ref_t>(_a);
|
||||||
|
const simd32_f32_ref_t result = { .f32 = sqrt(a.f32) };
|
||||||
|
return bitCast<simd32_t>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_f32_rsqrt(simd32_t _a)
|
||||||
|
{
|
||||||
|
const simd32_f32_ref_t a = bitCast<simd32_f32_ref_t>(_a);
|
||||||
|
const simd32_f32_ref_t result = { .f32 = 1.0f / sqrt(a.f32) };
|
||||||
|
return bitCast<simd32_t>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_f32_round(simd32_t _a)
|
||||||
|
{
|
||||||
|
const simd32_f32_ref_t a = bitCast<simd32_f32_ref_t>(_a);
|
||||||
|
const simd32_f32_ref_t result = { .f32 = round(a.f32) };
|
||||||
|
return bitCast<simd32_t>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_f32_ceil(simd32_t _a)
|
||||||
|
{
|
||||||
|
const simd32_f32_ref_t a = bitCast<simd32_f32_ref_t>(_a);
|
||||||
|
const simd32_f32_ref_t result = { .f32 = ceil(a.f32) };
|
||||||
|
return bitCast<simd32_t>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_f32_floor(simd32_t _a)
|
||||||
|
{
|
||||||
|
const simd32_f32_ref_t a = bitCast<simd32_f32_ref_t>(_a);
|
||||||
|
const simd32_f32_ref_t result = { .f32 = floor(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);
|
||||||
|
const simd32_f32_ref_t b = bitCast<simd32_f32_ref_t>(_b);
|
||||||
|
return { .u32 = a.f32 == b.f32 ? UINT32_MAX : 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_f32_cmpneq(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
const simd32_f32_ref_t a = bitCast<simd32_f32_ref_t>(_a);
|
||||||
|
const simd32_f32_ref_t b = bitCast<simd32_f32_ref_t>(_b);
|
||||||
|
return { .u32 = a.f32 != b.f32 ? UINT32_MAX : 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_f32_cmplt(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
const simd32_f32_ref_t a = bitCast<simd32_f32_ref_t>(_a);
|
||||||
|
const simd32_f32_ref_t b = bitCast<simd32_f32_ref_t>(_b);
|
||||||
|
return { .u32 = a.f32 < b.f32 ? UINT32_MAX : 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_f32_cmple(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
const simd32_f32_ref_t a = bitCast<simd32_f32_ref_t>(_a);
|
||||||
|
const simd32_f32_ref_t b = bitCast<simd32_f32_ref_t>(_b);
|
||||||
|
return { .u32 = a.f32 <= b.f32 ? UINT32_MAX : 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_f32_cmpgt(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
const simd32_f32_ref_t a = bitCast<simd32_f32_ref_t>(_a);
|
||||||
|
const simd32_f32_ref_t b = bitCast<simd32_f32_ref_t>(_b);
|
||||||
|
return { .u32 = a.f32 > b.f32 ? UINT32_MAX : 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_f32_cmpge(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
const simd32_f32_ref_t a = bitCast<simd32_f32_ref_t>(_a);
|
||||||
|
const simd32_f32_ref_t b = bitCast<simd32_f32_ref_t>(_b);
|
||||||
|
return { .u32 = a.f32 >= b.f32 ? UINT32_MAX : 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_u32_add(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
return { .u32 = _a.u32 + _b.u32 };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_u32_sub(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
return { .u32 = _a.u32 - _b.u32 };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_u32_mul(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
return { .u32 = _a.u32 * _b.u32 };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_u32_div(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
return { .u32 = _a.u32 / _b.u32 };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_u32_mod(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
return { .u32 = _a.u32 % _b.u32 };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_u32_min(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
return { .u32 = _a.u32 < _b.u32 ? _a.u32 : _b.u32 };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_u32_max(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
return { .u32 = _a.u32 > _b.u32 ? _a.u32 : _b.u32 };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_u32_clamp(simd32_t _a, simd32_t _min, simd32_t _max)
|
||||||
|
{
|
||||||
|
return simd32_u32_min(simd32_u32_max(_a, _min), _max);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_i32_add(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
const simd32_i32_ref_t a = bitCast<simd32_i32_ref_t>(_a);
|
||||||
|
const simd32_i32_ref_t b = bitCast<simd32_i32_ref_t>(_b);
|
||||||
|
const simd32_i32_ref_t result = { .i32 = a.i32 + b.i32 };
|
||||||
|
return bitCast<simd32_t>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_i32_sub(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
const simd32_i32_ref_t a = bitCast<simd32_i32_ref_t>(_a);
|
||||||
|
const simd32_i32_ref_t b = bitCast<simd32_i32_ref_t>(_b);
|
||||||
|
const simd32_i32_ref_t result = { .i32 = a.i32 - b.i32 };
|
||||||
|
return bitCast<simd32_t>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_i32_neg(simd32_t _a)
|
||||||
|
{
|
||||||
|
const simd32_i32_ref_t a = bitCast<simd32_i32_ref_t>(_a);
|
||||||
|
const simd32_i32_ref_t result = { .i32 = -a.i32 };
|
||||||
|
return bitCast<simd32_t>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_i32_abs(simd32_t _a)
|
||||||
|
{
|
||||||
|
const simd32_i32_ref_t a = bitCast<simd32_i32_ref_t>(_a);
|
||||||
|
const simd32_i32_ref_t result = { .i32 = a.i32 < 0 ? -a.i32 : a.i32 };
|
||||||
|
return bitCast<simd32_t>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_i32_min(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
const simd32_i32_ref_t a = bitCast<simd32_i32_ref_t>(_a);
|
||||||
|
const simd32_i32_ref_t b = bitCast<simd32_i32_ref_t>(_b);
|
||||||
|
const simd32_i32_ref_t result = { .i32 = a.i32 < b.i32 ? a.i32 : b.i32 };
|
||||||
|
return bitCast<simd32_t>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_i32_max(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
const simd32_i32_ref_t a = bitCast<simd32_i32_ref_t>(_a);
|
||||||
|
const simd32_i32_ref_t b = bitCast<simd32_i32_ref_t>(_b);
|
||||||
|
const simd32_i32_ref_t result = { .i32 = a.i32 > b.i32 ? a.i32 : b.i32 };
|
||||||
|
return bitCast<simd32_t>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_i32_clamp(simd32_t _a, simd32_t _min, simd32_t _max)
|
||||||
|
{
|
||||||
|
return simd32_i32_min(simd32_i32_max(_a, _min), _max);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_u32_cmpeq(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
return { .u32 = uint32_t(-(_a.u32 == _b.u32)) };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_u32_cmpneq(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
return { .u32 = uint32_t(-(_a.u32 != _b.u32)) };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_u32_cmplt(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
return { .u32 = uint32_t(-(_a.u32 < _b.u32)) };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_u32_cmple(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
return { .u32 = uint32_t(-(_a.u32 <= _b.u32)) };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_u32_cmpgt(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
return { .u32 = uint32_t(-(_a.u32 > _b.u32)) };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_u32_cmpge(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
return { .u32 = uint32_t(-(_a.u32 >= _b.u32)) };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_i32_cmpeq(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
const simd32_i32_ref_t a = bitCast<simd32_i32_ref_t>(_a);
|
||||||
|
const simd32_i32_ref_t b = bitCast<simd32_i32_ref_t>(_b);
|
||||||
|
return { .u32 = uint32_t(-(a.i32 == b.i32)) };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_i32_cmplt(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
const simd32_i32_ref_t a = bitCast<simd32_i32_ref_t>(_a);
|
||||||
|
const simd32_i32_ref_t b = bitCast<simd32_i32_ref_t>(_b);
|
||||||
|
return { .u32 = uint32_t(-(a.i32 < b.i32)) };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_i32_cmpgt(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
const simd32_i32_ref_t a = bitCast<simd32_i32_ref_t>(_a);
|
||||||
|
const simd32_i32_ref_t b = bitCast<simd32_i32_ref_t>(_b);
|
||||||
|
return { .u32 = uint32_t(-(a.i32 > b.i32)) };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_i16_add(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
return { .u32 = uint32_t(uint16_t(int16_t(_a.u32) + int16_t(_b.u32)))
|
||||||
|
| (uint32_t(uint16_t(int16_t(_a.u32 >> 16) + int16_t(_b.u32 >> 16))) << 16) };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_i16_sub(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
return { .u32 = uint32_t(uint16_t(int16_t(_a.u32) - int16_t(_b.u32)))
|
||||||
|
| (uint32_t(uint16_t(int16_t(_a.u32 >> 16) - int16_t(_b.u32 >> 16))) << 16) };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_i16_cmpeq(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
return { .u32 = uint32_t(int16_t(_a.u32) == int16_t(_b.u32) ? uint16_t(0xffff) : uint16_t(0))
|
||||||
|
| (uint32_t(int16_t(_a.u32 >> 16) == int16_t(_b.u32 >> 16) ? uint16_t(0xffff) : uint16_t(0)) << 16) };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_x16_sll(simd32_t _a, int _count)
|
||||||
|
{
|
||||||
|
return { .u32 = uint32_t(uint16_t(uint16_t(_a.u32) << _count))
|
||||||
|
| (uint32_t(uint16_t(uint16_t(_a.u32 >> 16) << _count)) << 16) };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_x16_srl(simd32_t _a, int _count)
|
||||||
|
{
|
||||||
|
return { .u32 = uint32_t(uint16_t(uint16_t(_a.u32) >> _count))
|
||||||
|
| (uint32_t(uint16_t(uint16_t(_a.u32 >> 16) >> _count)) << 16) };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_i8_add(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
return { .u32 = uint32_t(uint8_t(int8_t(_a.u32 ) + int8_t(_b.u32 ) ) )
|
||||||
|
| (uint32_t(uint8_t(int8_t(_a.u32 >> 8) + int8_t(_b.u32 >> 8) ) ) << 8)
|
||||||
|
| (uint32_t(uint8_t(int8_t(_a.u32 >> 16) + int8_t(_b.u32 >> 16) ) ) << 16)
|
||||||
|
| (uint32_t(uint8_t(int8_t(_a.u32 >> 24) + int8_t(_b.u32 >> 24) ) ) << 24) };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_i8_sub(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
return { .u32 = uint32_t(uint8_t(int8_t(_a.u32 ) - int8_t(_b.u32 ) ) )
|
||||||
|
| (uint32_t(uint8_t(int8_t(_a.u32 >> 8) - int8_t(_b.u32 >> 8) ) ) << 8)
|
||||||
|
| (uint32_t(uint8_t(int8_t(_a.u32 >> 16) - int8_t(_b.u32 >> 16) ) ) << 16)
|
||||||
|
| (uint32_t(uint8_t(int8_t(_a.u32 >> 24) - int8_t(_b.u32 >> 24) ) ) << 24) };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_u8_satadd(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
simd32_t result{ .u32 = 0 };
|
||||||
|
for (int ii = 0; ii < 4; ++ii)
|
||||||
|
{
|
||||||
|
const uint16_t sum = uint16_t(uint8_t(_a.u32 >> (ii * 8))) + uint8_t(_b.u32 >> (ii * 8));
|
||||||
|
result.u32 |= uint32_t(sum > 255 ? 255 : uint8_t(sum)) << (ii * 8);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_u8_satsub(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
simd32_t result{ .u32 = 0 };
|
||||||
|
for (int ii = 0; ii < 4; ++ii)
|
||||||
|
{
|
||||||
|
const uint8_t a = uint8_t(_a.u32 >> (ii * 8));
|
||||||
|
const uint8_t b = uint8_t(_b.u32 >> (ii * 8));
|
||||||
|
result.u32 |= uint32_t(a > b ? uint8_t(a - b) : uint8_t(0)) << (ii * 8);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_u16_satadd(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
simd32_t result{ .u32 = 0 };
|
||||||
|
for (int ii = 0; ii < 2; ++ii)
|
||||||
|
{
|
||||||
|
const uint32_t sum = uint32_t(uint16_t(_a.u32 >> (ii * 16))) + uint16_t(_b.u32 >> (ii * 16));
|
||||||
|
result.u32 |= uint32_t(sum > 65535 ? 65535 : uint16_t(sum)) << (ii * 16);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_u16_satsub(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
simd32_t result{ .u32 = 0 };
|
||||||
|
for (int ii = 0; ii < 2; ++ii)
|
||||||
|
{
|
||||||
|
const uint16_t a = uint16_t(_a.u32 >> (ii * 16));
|
||||||
|
const uint16_t b = uint16_t(_b.u32 >> (ii * 16));
|
||||||
|
result.u32 |= uint32_t(a > b ? uint16_t(a - b) : uint16_t(0)) << (ii * 16);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_and(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
return { .u32 = _a.u32 & _b.u32 };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_andc(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
return { .u32 = _a.u32 & ~_b.u32 };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_or(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
return { .u32 = _a.u32 | _b.u32 };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_orc(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
return { .u32 = _a.u32 | ~_b.u32 };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_xor(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
return { .u32 = _a.u32 ^ _b.u32 };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_not(simd32_t _a)
|
||||||
|
{
|
||||||
|
return { .u32 = ~_a.u32 };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_x32_sll(simd32_t _a, int _count)
|
||||||
|
{
|
||||||
|
return { .u32 = _a.u32 << _count };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_x32_srl(simd32_t _a, int _count)
|
||||||
|
{
|
||||||
|
return { .u32 = _a.u32 >> _count };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_x32_sra(simd32_t _a, int _count)
|
||||||
|
{
|
||||||
|
const simd32_i32_ref_t a = bitCast<simd32_i32_ref_t>(_a);
|
||||||
|
const simd32_i32_ref_t result = { .i32 = a.i32 >> _count };
|
||||||
|
return bitCast<simd32_t>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_x32_sll(simd32_t _a, simd32_t _count)
|
||||||
|
{
|
||||||
|
return { .u32 = _a.u32 << (_count.u32 & 31u) };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_x32_srl(simd32_t _a, simd32_t _count)
|
||||||
|
{
|
||||||
|
return { .u32 = _a.u32 >> (_count.u32 & 31u) };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_x32_sra(simd32_t _a, simd32_t _count)
|
||||||
|
{
|
||||||
|
const simd32_i32_ref_t a = bitCast<simd32_i32_ref_t>(_a);
|
||||||
|
const simd32_i32_ref_t result = { .i32 = a.i32 >> int32_t(_count.u32 & 31u) };
|
||||||
|
return bitCast<simd32_t>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_selb(simd32_t _mask, simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
return { .u32 = (_a.u32 & _mask.u32) | (_b.u32 & ~_mask.u32) };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_sels(simd32_t _test, simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
const simd32_i32_ref_t test = bitCast<simd32_i32_ref_t>(_test);
|
||||||
|
const uint32_t mask = (uint32_t)(test.i32 >> 31);
|
||||||
|
return { .u32 = (_a.u32 & mask) | (_b.u32 & ~mask) };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC bool simd32_test(simd32_t _test)
|
||||||
|
{
|
||||||
|
return 0 != (_test.u32 >> 31);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_u32_xorl(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
return { .u32 = uint32_t(!_a.u32 != !_b.u32) };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_x32_rol(simd32_t _a, int _count)
|
||||||
|
{
|
||||||
|
return { .u32 = (_a.u32 << _count) | (_a.u32 >> (32 - _count)) };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_x32_ror(simd32_t _a, int _count)
|
||||||
|
{
|
||||||
|
return { .u32 = (_a.u32 >> _count) | (_a.u32 << (32 - _count)) };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_u32_setnz(simd32_t _a)
|
||||||
|
{
|
||||||
|
return { .u32 = uint32_t(-!!_a.u32) };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_u32_satadd(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
const uint32_t add = _a.u32 + _b.u32;
|
||||||
|
return { .u32 = add | -(add < _a.u32) };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_u32_satsub(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
const uint32_t sub = _a.u32 - _b.u32;
|
||||||
|
return { .u32 = sub & -(sub <= _a.u32) };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_u32_satmul(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
const uint64_t mul = (uint64_t)_a.u32 * (uint64_t)_b.u32;
|
||||||
|
const uint32_t hi = uint32_t(mul >> 32);
|
||||||
|
return { .u32 = uint32_t(mul) | uint32_t(-!!hi) };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_u32_incwrap(simd32_t _val, simd32_t _min, simd32_t _max)
|
||||||
|
{
|
||||||
|
simd32_t inc{ .u32 = _val.u32 + 1 };
|
||||||
|
const uint32_t diff = _max.u32 - _val.u32;
|
||||||
|
simd32_t mask{ .u32 = uint32_t(int32_t(diff | uint32_t(-int32_t(diff))) >> 31) };
|
||||||
|
return simd32_selb(mask, inc, _min);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_u32_decwrap(simd32_t _val, simd32_t _min, simd32_t _max)
|
||||||
|
{
|
||||||
|
simd32_t dec{ .u32 = _val.u32 - 1 };
|
||||||
|
const uint32_t diff = _min.u32 - _val.u32;
|
||||||
|
simd32_t mask{ .u32 = uint32_t(int32_t(diff | uint32_t(-int32_t(diff))) >> 31) };
|
||||||
|
return simd32_selb(mask, dec, _max);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_x32_cntbits(simd32_t _a)
|
||||||
|
{
|
||||||
|
simd32_t result;
|
||||||
|
#if BX_COMPILER_GCC || BX_COMPILER_CLANG
|
||||||
|
result.u32 = __builtin_popcount(_a.u32);
|
||||||
|
#else
|
||||||
|
uint32_t val = _a.u32;
|
||||||
|
val = val - ((val >> 1) & 0x55555555u);
|
||||||
|
val = (val & 0x33333333u) + ((val >> 2) & 0x33333333u);
|
||||||
|
val = (val + (val >> 4)) & 0x0f0f0f0fu;
|
||||||
|
result.u32 = (val * 0x01010101u) >> 24;
|
||||||
|
#endif // BX_COMPILER_*
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_x32_cntlz(simd32_t _a)
|
||||||
|
{
|
||||||
|
simd32_t result;
|
||||||
|
#if BX_COMPILER_GCC || BX_COMPILER_CLANG
|
||||||
|
result.u32 = 0 == _a.u32 ? 32 : __builtin_clz(_a.u32);
|
||||||
|
#else
|
||||||
|
uint32_t val = _a.u32;
|
||||||
|
val |= val >> 1;
|
||||||
|
val |= val >> 2;
|
||||||
|
val |= val >> 4;
|
||||||
|
val |= val >> 8;
|
||||||
|
val |= val >> 16;
|
||||||
|
simd32_t tmp{ .u32 = ~val };
|
||||||
|
result = simd32_x32_cntbits(tmp);
|
||||||
|
#endif // BX_COMPILER_*
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_x32_cnttz(simd32_t _a)
|
||||||
|
{
|
||||||
|
simd32_t result;
|
||||||
|
#if BX_COMPILER_GCC || BX_COMPILER_CLANG
|
||||||
|
result.u32 = 0 == _a.u32 ? 32 : __builtin_ctz(_a.u32);
|
||||||
|
#else
|
||||||
|
simd32_t tmp{ .u32 = ~_a.u32 & (_a.u32 - 1) };
|
||||||
|
result = simd32_x32_cntbits(tmp);
|
||||||
|
#endif // BX_COMPILER_*
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_x32_ffs(simd32_t _a)
|
||||||
|
{
|
||||||
|
const simd32_t tz = simd32_x32_cnttz(_a);
|
||||||
|
return { .u32 = 0 == _a.u32 ? 0 : tz.u32 + 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_x32_part1by1(simd32_t _a)
|
||||||
|
{
|
||||||
|
uint32_t val = _a.u32 & 0xffff;
|
||||||
|
val = (val ^ (val << 8)) & 0x00ff00ff;
|
||||||
|
val = (val ^ (val << 4)) & 0x0f0f0f0f;
|
||||||
|
val = (val ^ (val << 2)) & 0x33333333;
|
||||||
|
val = (val ^ (val << 1)) & 0x55555555;
|
||||||
|
return { .u32 = val };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_x32_part1by2(simd32_t _a)
|
||||||
|
{
|
||||||
|
uint32_t val = _a.u32 & 0x3ff;
|
||||||
|
val = (val ^ (val << 16) ) & 0xff0000ff;
|
||||||
|
val = (val ^ (val << 8) ) & 0x0300f00f;
|
||||||
|
val = (val ^ (val << 4) ) & 0x030c30c3;
|
||||||
|
val = (val ^ (val << 2) ) & 0x09249249;
|
||||||
|
return { .u32 = val };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_u32_testpow2(simd32_t _a)
|
||||||
|
{
|
||||||
|
const uint32_t dec = _a.u32 - 1;
|
||||||
|
return { .u32 = uint32_t(-(int32_t( (_a.u32 ^ dec) >> 1 == dec) ) ) };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_u32_nextpow2(simd32_t _a)
|
||||||
|
{
|
||||||
|
uint32_t val = _a.u32 - 1;
|
||||||
|
val |= val >> 1;
|
||||||
|
val |= val >> 2;
|
||||||
|
val |= val >> 4;
|
||||||
|
val |= val >> 8;
|
||||||
|
val |= val >> 16;
|
||||||
|
return { .u32 = val + 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_u32_gcd(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
uint32_t a = _a.u32, b = _b.u32;
|
||||||
|
do { const uint32_t tmp = a % b; a = b; b = tmp; } while (b);
|
||||||
|
return { .u32 = a };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_u32_lcm(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
return { .u32 = _a.u32 * (_b.u32 / simd32_u32_gcd(_a, _b).u32) };
|
||||||
|
}
|
||||||
|
|
||||||
|
BX_SIMD_FORCE_INLINE simd32_t simd32_ldu(const void* _ptr)
|
||||||
|
{
|
||||||
|
return simd32_ld(_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
BX_SIMD_FORCE_INLINE void simd32_stu(void* _ptr, simd32_t _a)
|
||||||
|
{
|
||||||
|
simd32_st(_ptr, _a);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC bool simd32_test_any(simd32_t _test)
|
||||||
|
{
|
||||||
|
return 0 != _test.u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC bool simd32_test_all(simd32_t _test)
|
||||||
|
{
|
||||||
|
return 0 != _test.u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC bool simd32_test_zero(simd32_t _a, simd32_t _b)
|
||||||
|
{
|
||||||
|
return 0 == (_a.u32 & _b.u32);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_f32_ftoi_trunc(simd32_t _a)
|
||||||
|
{
|
||||||
|
const simd32_f32_ref_t a = bitCast<simd32_f32_ref_t>(_a);
|
||||||
|
const simd32_i32_ref_t result = { .i32 = int32_t(a.f32) };
|
||||||
|
return bitCast<simd32_t>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_f32_ftoi_round(simd32_t _a)
|
||||||
|
{
|
||||||
|
const simd32_f32_ref_t a = bitCast<simd32_f32_ref_t>(_a);
|
||||||
|
const simd32_i32_ref_t result = { .i32 = int32_t(round(a.f32) ) };
|
||||||
|
return bitCast<simd32_t>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BX_CONSTEXPR_FUNC simd32_t simd32_i32_itof(simd32_t _a)
|
||||||
|
{
|
||||||
|
const simd32_i32_ref_t a = bitCast<simd32_i32_ref_t>(_a);
|
||||||
|
const simd32_f32_ref_t result = { .f32 = float(a.i32) };
|
||||||
|
return bitCast<simd32_t>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace bx
|
||||||
1296
include/bx/inline/simd64_ref.inl
Normal file
1296
include/bx/inline/simd64_ref.inl
Normal file
File diff suppressed because it is too large
Load Diff
2637
include/bx/inline/simd_impl.inl
Normal file
2637
include/bx/inline/simd_impl.inl
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,868 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2026 Branimir Karadzic. All rights reserved.
|
|
||||||
* License: https://github.com/bkaradzic/bx/blob/master/LICENSE
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Copyright 2006 Mike Acton <macton@gmail.com>
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included
|
|
||||||
// in all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
// THE SOFTWARE
|
|
||||||
|
|
||||||
#ifndef BX_UINT32_T_H_HEADER_GUARD
|
|
||||||
# error "Must be included from bx/uint32_t.h"
|
|
||||||
#endif // BX_UINT32_T_H_HEADER_GUARD
|
|
||||||
|
|
||||||
namespace bx
|
|
||||||
{
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_li(uint32_t _a)
|
|
||||||
{
|
|
||||||
return _a;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_dec(uint32_t _a)
|
|
||||||
{
|
|
||||||
return _a - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_inc(uint32_t _a)
|
|
||||||
{
|
|
||||||
return _a + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_not(uint32_t _a)
|
|
||||||
{
|
|
||||||
return ~_a;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_neg(uint32_t _a)
|
|
||||||
{
|
|
||||||
return -(int32_t)_a;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_ext(uint32_t _a)
|
|
||||||
{
|
|
||||||
return ( (int32_t)_a)>>31;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_and(uint32_t _a, uint32_t _b)
|
|
||||||
{
|
|
||||||
return _a & _b;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_andc(uint32_t _a, uint32_t _b)
|
|
||||||
{
|
|
||||||
return _a & ~_b;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_xor(uint32_t _a, uint32_t _b)
|
|
||||||
{
|
|
||||||
return _a ^ _b;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_xorl(uint32_t _a, uint32_t _b)
|
|
||||||
{
|
|
||||||
return !_a != !_b;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_or(uint32_t _a, uint32_t _b)
|
|
||||||
{
|
|
||||||
return _a | _b;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_orc(uint32_t _a, uint32_t _b)
|
|
||||||
{
|
|
||||||
return _a | ~_b;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_sll(uint32_t _a, int32_t _sa)
|
|
||||||
{
|
|
||||||
return _a << _sa;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_srl(uint32_t _a, int32_t _sa)
|
|
||||||
{
|
|
||||||
return _a >> _sa;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_sra(uint32_t _a, int32_t _sa)
|
|
||||||
{
|
|
||||||
return ( (int32_t)_a) >> _sa;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_rol(uint32_t _a, int32_t _sa)
|
|
||||||
{
|
|
||||||
return ( _a << _sa) | (_a >> (32-_sa) );
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_ror(uint32_t _a, int32_t _sa)
|
|
||||||
{
|
|
||||||
return ( _a >> _sa) | (_a << (32-_sa) );
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_add(uint32_t _a, uint32_t _b)
|
|
||||||
{
|
|
||||||
return _a + _b;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_iadd(uint32_t _a, uint32_t _b)
|
|
||||||
{
|
|
||||||
return int32_t(_a) + int32_t(_b);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_sub(uint32_t _a, uint32_t _b)
|
|
||||||
{
|
|
||||||
return _a - _b;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_isub(uint32_t _a, uint32_t _b)
|
|
||||||
{
|
|
||||||
return int32_t(_a) - int32_t(_b);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_mul(uint32_t _a, uint32_t _b)
|
|
||||||
{
|
|
||||||
return _a * _b;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_div(uint32_t _a, uint32_t _b)
|
|
||||||
{
|
|
||||||
return _a / _b;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_mod(uint32_t _a, uint32_t _b)
|
|
||||||
{
|
|
||||||
return _a % _b;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_cmpeq(uint32_t _a, uint32_t _b)
|
|
||||||
{
|
|
||||||
return -(_a == _b);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_cmpneq(uint32_t _a, uint32_t _b)
|
|
||||||
{
|
|
||||||
return -(_a != _b);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_cmplt(uint32_t _a, uint32_t _b)
|
|
||||||
{
|
|
||||||
return -(_a < _b);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_cmple(uint32_t _a, uint32_t _b)
|
|
||||||
{
|
|
||||||
return -(_a <= _b);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_cmpgt(uint32_t _a, uint32_t _b)
|
|
||||||
{
|
|
||||||
return -(_a > _b);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_cmpge(uint32_t _a, uint32_t _b)
|
|
||||||
{
|
|
||||||
return -(_a >= _b);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_setnz(uint32_t _a)
|
|
||||||
{
|
|
||||||
return -!!_a;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_splat(uint8_t _val)
|
|
||||||
{
|
|
||||||
const uint32_t tmp0 = uint32_sll(_val, 8);
|
|
||||||
const uint32_t tmp1 = uint32_or(tmp0, _val);
|
|
||||||
const uint32_t tmp2 = uint32_sll(tmp1, 16);
|
|
||||||
const uint32_t result = uint32_or(tmp2, tmp1);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_splat(uint16_t _val)
|
|
||||||
{
|
|
||||||
const uint32_t tmp = uint32_sll(_val, 16);
|
|
||||||
const uint32_t result = uint32_or(tmp, _val);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_satadd(uint32_t _a, uint32_t _b)
|
|
||||||
{
|
|
||||||
const uint32_t add = uint32_add(_a, _b);
|
|
||||||
const uint32_t lt = uint32_cmplt(add, _a);
|
|
||||||
const uint32_t result = uint32_or(add, lt);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_satsub(uint32_t _a, uint32_t _b)
|
|
||||||
{
|
|
||||||
const uint32_t sub = uint32_sub(_a, _b);
|
|
||||||
const uint32_t le = uint32_cmple(sub, _a);
|
|
||||||
const uint32_t result = uint32_and(sub, le);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_satmul(uint32_t _a, uint32_t _b)
|
|
||||||
{
|
|
||||||
const uint64_t mul = (uint64_t)_a * (uint64_t)_b;
|
|
||||||
const uint32_t hi = mul >> 32;
|
|
||||||
const uint32_t nz = uint32_setnz(hi);
|
|
||||||
const uint32_t result = uint32_or(uint32_t(mul), nz);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_sels(uint32_t test, uint32_t _a, uint32_t _b)
|
|
||||||
{
|
|
||||||
const uint32_t mask = uint32_ext(test);
|
|
||||||
const uint32_t sel_a = uint32_and(_a, mask);
|
|
||||||
const uint32_t sel_b = uint32_andc(_b, mask);
|
|
||||||
const uint32_t result = uint32_or(sel_a, sel_b);
|
|
||||||
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_selb(uint32_t _mask, uint32_t _a, uint32_t _b)
|
|
||||||
{
|
|
||||||
const uint32_t sel_a = uint32_and(_a, _mask);
|
|
||||||
const uint32_t sel_b = uint32_andc(_b, _mask);
|
|
||||||
const uint32_t result = uint32_or(sel_a, sel_b);
|
|
||||||
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_imin(uint32_t _a, uint32_t _b)
|
|
||||||
{
|
|
||||||
const uint32_t a_sub_b = uint32_sub(_a, _b);
|
|
||||||
const uint32_t result = uint32_sels(a_sub_b, _a, _b);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_imax(uint32_t _a, uint32_t _b)
|
|
||||||
{
|
|
||||||
const uint32_t b_sub_a = uint32_sub(_b, _a);
|
|
||||||
const uint32_t result = uint32_sels(b_sub_a, _a, _b);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_min(uint32_t _a, uint32_t _b)
|
|
||||||
{
|
|
||||||
return _a > _b ? _b : _a;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_min(uint32_t _a, uint32_t _b, uint32_t _c)
|
|
||||||
{
|
|
||||||
return uint32_min(_a, uint32_min(_b, _c) );
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_max(uint32_t _a, uint32_t _b)
|
|
||||||
{
|
|
||||||
return _a > _b ? _a : _b;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_max(uint32_t _a, uint32_t _b, uint32_t _c)
|
|
||||||
{
|
|
||||||
return uint32_max(_a, uint32_max(_b, _c) );
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_clamp(uint32_t _a, uint32_t _min, uint32_t _max)
|
|
||||||
{
|
|
||||||
const uint32_t tmp = uint32_max(_a, _min);
|
|
||||||
const uint32_t result = uint32_min(tmp, _max);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_iclamp(uint32_t _a, uint32_t _min, uint32_t _max)
|
|
||||||
{
|
|
||||||
const uint32_t tmp = uint32_imax(_a, _min);
|
|
||||||
const uint32_t result = uint32_imin(tmp, _max);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_incwrap(uint32_t _val, uint32_t _min, uint32_t _max)
|
|
||||||
{
|
|
||||||
const uint32_t inc = uint32_inc(_val);
|
|
||||||
const uint32_t max_diff = uint32_sub(_max, _val);
|
|
||||||
const uint32_t neg_max_diff = uint32_neg(max_diff);
|
|
||||||
const uint32_t max_or = uint32_or(max_diff, neg_max_diff);
|
|
||||||
const uint32_t max_diff_nz = uint32_ext(max_or);
|
|
||||||
const uint32_t result = uint32_selb(max_diff_nz, inc, _min);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_decwrap(uint32_t _val, uint32_t _min, uint32_t _max)
|
|
||||||
{
|
|
||||||
const uint32_t dec = uint32_dec(_val);
|
|
||||||
const uint32_t min_diff = uint32_sub(_min, _val);
|
|
||||||
const uint32_t neg_min_diff = uint32_neg(min_diff);
|
|
||||||
const uint32_t min_or = uint32_or(min_diff, neg_min_diff);
|
|
||||||
const uint32_t min_diff_nz = uint32_ext(min_or);
|
|
||||||
const uint32_t result = uint32_selb(min_diff_nz, dec, _max);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_cntbits(uint32_t _val)
|
|
||||||
{
|
|
||||||
#if BX_COMPILER_GCC || BX_COMPILER_CLANG
|
|
||||||
return __builtin_popcount(_val);
|
|
||||||
#else
|
|
||||||
const uint32_t tmp0 = uint32_srl(_val, 1);
|
|
||||||
const uint32_t tmp1 = uint32_and(tmp0, 0x55555555);
|
|
||||||
const uint32_t tmp2 = uint32_sub(_val, tmp1);
|
|
||||||
const uint32_t tmp3 = uint32_and(tmp2, 0xc30c30c3);
|
|
||||||
const uint32_t tmp4 = uint32_srl(tmp2, 2);
|
|
||||||
const uint32_t tmp5 = uint32_and(tmp4, 0xc30c30c3);
|
|
||||||
const uint32_t tmp6 = uint32_srl(tmp2, 4);
|
|
||||||
const uint32_t tmp7 = uint32_and(tmp6, 0xc30c30c3);
|
|
||||||
const uint32_t tmp8 = uint32_add(tmp3, tmp5);
|
|
||||||
const uint32_t tmp9 = uint32_add(tmp7, tmp8);
|
|
||||||
const uint32_t tmpA = uint32_srl(tmp9, 6);
|
|
||||||
const uint32_t tmpB = uint32_add(tmp9, tmpA);
|
|
||||||
const uint32_t tmpC = uint32_srl(tmpB, 12);
|
|
||||||
const uint32_t tmpD = uint32_srl(tmpB, 24);
|
|
||||||
const uint32_t tmpE = uint32_add(tmpB, tmpC);
|
|
||||||
const uint32_t tmpF = uint32_add(tmpD, tmpE);
|
|
||||||
const uint32_t result = uint32_and(tmpF, 0x3f);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
#endif // BX_COMPILER_*
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_cntlz(uint32_t _val)
|
|
||||||
{
|
|
||||||
#if BX_COMPILER_GCC || BX_COMPILER_CLANG
|
|
||||||
return 0 == _val ? 32 : __builtin_clz(_val);
|
|
||||||
#else
|
|
||||||
const uint32_t tmp0 = uint32_srl(_val, 1);
|
|
||||||
const uint32_t tmp1 = uint32_or(tmp0, _val);
|
|
||||||
const uint32_t tmp2 = uint32_srl(tmp1, 2);
|
|
||||||
const uint32_t tmp3 = uint32_or(tmp2, tmp1);
|
|
||||||
const uint32_t tmp4 = uint32_srl(tmp3, 4);
|
|
||||||
const uint32_t tmp5 = uint32_or(tmp4, tmp3);
|
|
||||||
const uint32_t tmp6 = uint32_srl(tmp5, 8);
|
|
||||||
const uint32_t tmp7 = uint32_or(tmp6, tmp5);
|
|
||||||
const uint32_t tmp8 = uint32_srl(tmp7, 16);
|
|
||||||
const uint32_t tmp9 = uint32_or(tmp8, tmp7);
|
|
||||||
const uint32_t tmpA = uint32_not(tmp9);
|
|
||||||
const uint32_t result = uint32_cntbits(tmpA);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
#endif // BX_COMPILER_*
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_cnttz(uint32_t _val)
|
|
||||||
{
|
|
||||||
#if BX_COMPILER_GCC || BX_COMPILER_CLANG
|
|
||||||
return 0 == _val ? 32 : __builtin_ctz(_val);
|
|
||||||
#else
|
|
||||||
const uint32_t tmp0 = uint32_not(_val);
|
|
||||||
const uint32_t tmp1 = uint32_dec(_val);
|
|
||||||
const uint32_t tmp2 = uint32_and(tmp0, tmp1);
|
|
||||||
const uint32_t result = uint32_cntbits(tmp2);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
#endif // BX_COMPILER_*
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_ffs(uint32_t _x)
|
|
||||||
{
|
|
||||||
return 0 == _x ? 0 : uint32_cnttz(_x) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_part1by1(uint32_t _a)
|
|
||||||
{
|
|
||||||
// shuffle:
|
|
||||||
// ---- ---- ---- ---- fedc ba98 7654 3210
|
|
||||||
// to:
|
|
||||||
// -f-e -d-c -b-a -9-8 -7-6 -5-4 -3-2 -1-0
|
|
||||||
|
|
||||||
const uint32_t val = uint32_and(_a, 0xffff);
|
|
||||||
|
|
||||||
const uint32_t tmp0 = uint32_sll(val, 8);
|
|
||||||
const uint32_t tmp1 = uint32_xor(val, tmp0);
|
|
||||||
const uint32_t tmp2 = uint32_and(tmp1, 0x00ff00ff);
|
|
||||||
|
|
||||||
const uint32_t tmp3 = uint32_sll(tmp2, 4);
|
|
||||||
const uint32_t tmp4 = uint32_xor(tmp2, tmp3);
|
|
||||||
const uint32_t tmp5 = uint32_and(tmp4, 0x0f0f0f0f);
|
|
||||||
|
|
||||||
const uint32_t tmp6 = uint32_sll(tmp5, 2);
|
|
||||||
const uint32_t tmp7 = uint32_xor(tmp5, tmp6);
|
|
||||||
const uint32_t tmp8 = uint32_and(tmp7, 0x33333333);
|
|
||||||
|
|
||||||
const uint32_t tmp9 = uint32_sll(tmp8, 1);
|
|
||||||
const uint32_t tmpA = uint32_xor(tmp8, tmp9);
|
|
||||||
const uint32_t result = uint32_and(tmpA, 0x55555555);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_part1by2(uint32_t _a)
|
|
||||||
{
|
|
||||||
// shuffle:
|
|
||||||
// ---- ---- ---- ---- ---- --98 7654 3210
|
|
||||||
// to:
|
|
||||||
// ---- 9--8 --7- -6-- 5--4 --3- -2-- 1--0
|
|
||||||
|
|
||||||
const uint32_t val = uint32_and(_a, 0x3ff);
|
|
||||||
|
|
||||||
const uint32_t tmp0 = uint32_sll(val, 16);
|
|
||||||
const uint32_t tmp1 = uint32_xor(val, tmp0);
|
|
||||||
const uint32_t tmp2 = uint32_and(tmp1, 0xff0000ff);
|
|
||||||
|
|
||||||
const uint32_t tmp3 = uint32_sll(tmp2, 8);
|
|
||||||
const uint32_t tmp4 = uint32_xor(tmp2, tmp3);
|
|
||||||
const uint32_t tmp5 = uint32_and(tmp4, 0x0300f00f);
|
|
||||||
|
|
||||||
const uint32_t tmp6 = uint32_sll(tmp5, 4);
|
|
||||||
const uint32_t tmp7 = uint32_xor(tmp5, tmp6);
|
|
||||||
const uint32_t tmp8 = uint32_and(tmp7, 0x030c30c3);
|
|
||||||
|
|
||||||
const uint32_t tmp9 = uint32_sll(tmp8, 2);
|
|
||||||
const uint32_t tmpA = uint32_xor(tmp8, tmp9);
|
|
||||||
const uint32_t result = uint32_and(tmpA, 0x09249249);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_testpow2(uint32_t _a)
|
|
||||||
{
|
|
||||||
const uint32_t tmp0 = uint32_dec(_a);
|
|
||||||
const uint32_t tmp1 = uint32_xor(_a, tmp0);
|
|
||||||
const uint32_t tmp2 = uint32_srl(tmp1, 1);
|
|
||||||
const uint32_t result = uint32_cmpeq(tmp2, tmp0);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_nextpow2(uint32_t _a)
|
|
||||||
{
|
|
||||||
const uint32_t tmp0 = uint32_dec(_a);
|
|
||||||
const uint32_t tmp1 = uint32_srl(tmp0, 1);
|
|
||||||
const uint32_t tmp2 = uint32_or(tmp0, tmp1);
|
|
||||||
const uint32_t tmp3 = uint32_srl(tmp2, 2);
|
|
||||||
const uint32_t tmp4 = uint32_or(tmp2, tmp3);
|
|
||||||
const uint32_t tmp5 = uint32_srl(tmp4, 4);
|
|
||||||
const uint32_t tmp6 = uint32_or(tmp4, tmp5);
|
|
||||||
const uint32_t tmp7 = uint32_srl(tmp6, 8);
|
|
||||||
const uint32_t tmp8 = uint32_or(tmp6, tmp7);
|
|
||||||
const uint32_t tmp9 = uint32_srl(tmp8, 16);
|
|
||||||
const uint32_t tmpA = uint32_or(tmp8, tmp9);
|
|
||||||
const uint32_t result = uint32_inc(tmpA);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint64_t uint64_li(uint64_t _a)
|
|
||||||
{
|
|
||||||
return _a;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint64_t uint64_dec(uint64_t _a)
|
|
||||||
{
|
|
||||||
return _a - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint64_t uint64_inc(uint64_t _a)
|
|
||||||
{
|
|
||||||
return _a + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint64_t uint64_not(uint64_t _a)
|
|
||||||
{
|
|
||||||
return ~_a;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint64_t uint64_neg(uint64_t _a)
|
|
||||||
{
|
|
||||||
return -(int32_t)_a;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint64_t uint64_ext(uint64_t _a)
|
|
||||||
{
|
|
||||||
return ( (int32_t)_a)>>31;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint64_t uint64_and(uint64_t _a, uint64_t _b)
|
|
||||||
{
|
|
||||||
return _a & _b;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint64_t uint64_andc(uint64_t _a, uint64_t _b)
|
|
||||||
{
|
|
||||||
return _a & ~_b;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint64_t uint64_xor(uint64_t _a, uint64_t _b)
|
|
||||||
{
|
|
||||||
return _a ^ _b;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint64_t uint64_xorl(uint64_t _a, uint64_t _b)
|
|
||||||
{
|
|
||||||
return !_a != !_b;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint64_t uint64_or(uint64_t _a, uint64_t _b)
|
|
||||||
{
|
|
||||||
return _a | _b;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint64_t uint64_orc(uint64_t _a, uint64_t _b)
|
|
||||||
{
|
|
||||||
return _a | ~_b;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint64_t uint64_sll(uint64_t _a, int32_t _sa)
|
|
||||||
{
|
|
||||||
return _a << _sa;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint64_t uint64_srl(uint64_t _a, int32_t _sa)
|
|
||||||
{
|
|
||||||
return _a >> _sa;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint64_t uint64_sra(uint64_t _a, int32_t _sa)
|
|
||||||
{
|
|
||||||
return ( (int64_t)_a) >> _sa;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint64_t uint64_rol(uint64_t _a, int32_t _sa)
|
|
||||||
{
|
|
||||||
return ( _a << _sa) | (_a >> (64-_sa) );
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint64_t uint64_ror(uint64_t _a, int32_t _sa)
|
|
||||||
{
|
|
||||||
return ( _a >> _sa) | (_a << (64-_sa) );
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint64_t uint64_add(uint64_t _a, uint64_t _b)
|
|
||||||
{
|
|
||||||
return _a + _b;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint64_t uint64_sub(uint64_t _a, uint64_t _b)
|
|
||||||
{
|
|
||||||
return _a - _b;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint64_t uint64_mul(uint64_t _a, uint64_t _b)
|
|
||||||
{
|
|
||||||
return _a * _b;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline BX_CONSTEXPR_FUNC uint64_t uint64_splat(uint8_t _val)
|
|
||||||
{
|
|
||||||
const uint64_t tmp0 = uint64_sll(_val, 8);
|
|
||||||
const uint64_t tmp1 = uint64_or(tmp0, _val);
|
|
||||||
const uint64_t tmp2 = uint64_sll(tmp1, 16);
|
|
||||||
const uint64_t tmp3 = uint64_or(tmp2, tmp1);
|
|
||||||
const uint64_t tmp4 = uint64_sll(tmp3, 32);
|
|
||||||
const uint64_t result = uint64_or(tmp4, tmp3);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline BX_CONSTEXPR_FUNC uint64_t uint64_splat(uint16_t _val)
|
|
||||||
{
|
|
||||||
const uint64_t tmp0 = uint64_sll(_val, 16);
|
|
||||||
const uint64_t tmp1 = uint64_or(tmp0, _val);
|
|
||||||
const uint64_t tmp2 = uint64_sll(tmp1, 32);
|
|
||||||
const uint64_t result = uint64_or(tmp2, tmp1);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline BX_CONSTEXPR_FUNC uint64_t uint64_splat(uint32_t _val)
|
|
||||||
{
|
|
||||||
const uint64_t tmp = uint64_sll(_val, 32);
|
|
||||||
const uint64_t result = uint64_or(tmp, _val);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint64_t uint64_cntbits(uint64_t _val)
|
|
||||||
{
|
|
||||||
#if BX_COMPILER_GCC || BX_COMPILER_CLANG
|
|
||||||
return __builtin_popcountll(_val);
|
|
||||||
#else
|
|
||||||
const uint32_t lo = uint32_t(_val&UINT32_MAX);
|
|
||||||
const uint32_t hi = uint32_t(_val>>32);
|
|
||||||
|
|
||||||
return uint32_cntbits(lo)
|
|
||||||
+ uint32_cntbits(hi)
|
|
||||||
;
|
|
||||||
#endif // BX_COMPILER_*
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint64_t uint64_cntlz(uint64_t _val)
|
|
||||||
{
|
|
||||||
#if BX_COMPILER_GCC || BX_COMPILER_CLANG
|
|
||||||
return 0 == _val ? 64 : __builtin_clzll(_val);
|
|
||||||
#else
|
|
||||||
return _val & UINT64_C(0xffffffff00000000)
|
|
||||||
? uint32_cntlz(uint32_t(_val>>32) )
|
|
||||||
: uint32_cntlz(uint32_t(_val) ) + 32
|
|
||||||
;
|
|
||||||
#endif // BX_COMPILER_*
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint64_t uint64_cnttz(uint64_t _val)
|
|
||||||
{
|
|
||||||
#if BX_COMPILER_GCC || BX_COMPILER_CLANG
|
|
||||||
return 0 == _val ? 64 : __builtin_ctzll(_val);
|
|
||||||
#else
|
|
||||||
return _val & UINT64_C(0xffffffff)
|
|
||||||
? uint32_cnttz(uint32_t(_val) )
|
|
||||||
: uint32_cnttz(uint32_t(_val>>32) ) + 32
|
|
||||||
;
|
|
||||||
#endif // BX_COMPILER_*
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_gcd(uint32_t _a, uint32_t _b)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
const uint32_t tmp = uint32_mod(_a, _b);
|
|
||||||
_a = _b;
|
|
||||||
_b = tmp;
|
|
||||||
}
|
|
||||||
while (_b);
|
|
||||||
|
|
||||||
return _a;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t uint32_lcm(uint32_t _a, uint32_t _b)
|
|
||||||
{
|
|
||||||
return _a * (_b / uint32_gcd(_a, _b) );
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t strideAlign(uint32_t _offset, uint32_t _stride)
|
|
||||||
{
|
|
||||||
const uint32_t mod = uint32_mod(_offset, _stride);
|
|
||||||
const uint32_t add = uint32_sub(_stride, mod);
|
|
||||||
const uint32_t mask = uint32_cmpeq(mod, 0);
|
|
||||||
const uint32_t tmp = uint32_selb(mask, 0, add);
|
|
||||||
const uint32_t result = uint32_add(_offset, tmp);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<uint32_t Min>
|
|
||||||
inline BX_CONSTEXPR_FUNC uint32_t strideAlign(uint32_t _offset, uint32_t _stride)
|
|
||||||
{
|
|
||||||
const uint32_t align = uint32_lcm(Min, _stride);
|
|
||||||
const uint32_t mod = uint32_mod(_offset, align);
|
|
||||||
const uint32_t mask = uint32_cmpeq(mod, 0);
|
|
||||||
const uint32_t tmp0 = uint32_selb(mask, 0, align);
|
|
||||||
const uint32_t tmp1 = uint32_add(_offset, tmp0);
|
|
||||||
const uint32_t result = uint32_sub(tmp1, mod);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Ty>
|
|
||||||
inline BX_CONSTEXPR_FUNC bool isAligned(Ty _a, size_t _align)
|
|
||||||
{
|
|
||||||
const size_t mask = max<size_t>(1, _align) - 1;
|
|
||||||
return 0 == (size_t(_a) & mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline BX_CONSTEXPR_FUNC bool isAligned(const void* _ptr, size_t _align)
|
|
||||||
{
|
|
||||||
const uintptr_t addr = bitCast<uintptr_t>(_ptr);
|
|
||||||
return isAligned(addr, _align);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Ty>
|
|
||||||
inline BX_CONSTEXPR_FUNC Ty alignDown(Ty _a, size_t _align)
|
|
||||||
{
|
|
||||||
const size_t mask = max<size_t>(1, _align) - 1;
|
|
||||||
return Ty(size_t(_a) & ~mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Ty>
|
|
||||||
inline BX_CONSTEXPR_FUNC Ty* alignDown(Ty* _ptr, size_t _align)
|
|
||||||
{
|
|
||||||
uintptr_t addr = bitCast<uintptr_t>(_ptr);
|
|
||||||
addr = alignDown(addr, _align);
|
|
||||||
return bitCast<Ty*>(addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Ty>
|
|
||||||
inline BX_CONSTEXPR_FUNC const Ty* alignDown(const Ty* _ptr, size_t _align)
|
|
||||||
{
|
|
||||||
uintptr_t addr = bitCast<uintptr_t>(_ptr);
|
|
||||||
addr = alignDown(addr, _align);
|
|
||||||
return bitCast<const Ty*>(addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Ty>
|
|
||||||
inline BX_CONSTEXPR_FUNC Ty alignUp(Ty _a, size_t _align)
|
|
||||||
{
|
|
||||||
const size_t mask = max<size_t>(1, _align) - 1;
|
|
||||||
return Ty( (size_t(_a) + mask) & ~mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Ty>
|
|
||||||
inline BX_CONSTEXPR_FUNC Ty* alignUp(Ty* _ptr, size_t _align)
|
|
||||||
{
|
|
||||||
uintptr_t addr = bitCast<uintptr_t>(_ptr);
|
|
||||||
addr = alignUp(addr, _align);
|
|
||||||
return bitCast<Ty*>(addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Ty>
|
|
||||||
inline BX_CONSTEXPR_FUNC const Ty* alignUp(const Ty* _ptr, size_t _align)
|
|
||||||
{
|
|
||||||
uintptr_t addr = bitCast<uintptr_t>(_ptr);
|
|
||||||
addr = alignUp(addr, _align);
|
|
||||||
return bitCast<const Ty*>(addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONST_FUNC uint16_t halfFromFloat(float _a)
|
|
||||||
{
|
|
||||||
const uint32_t a_as_ui = bitCast<uint32_t>(_a);
|
|
||||||
|
|
||||||
const uint32_t one = uint32_li(0x00000001);
|
|
||||||
const uint32_t f_s_mask = uint32_li(kFloatSignMask);
|
|
||||||
const uint32_t f_e_mask = uint32_li(kFloatExponentMask);
|
|
||||||
const uint32_t f_m_mask = uint32_li(kFloatMantissaMask);
|
|
||||||
const uint32_t f_m_hidden_bit = uint32_li(0x00800000);
|
|
||||||
const uint32_t f_m_round_bit = uint32_li(0x00001000);
|
|
||||||
const uint32_t f_snan_mask = uint32_li(0x7fc00000);
|
|
||||||
const uint32_t f_e_pos = uint32_li(0x00000017);
|
|
||||||
const uint32_t h_e_pos = uint32_li(0x0000000a);
|
|
||||||
const uint32_t h_e_mask = uint32_li(kHalfExponentMask);
|
|
||||||
const uint32_t h_snan_mask = uint32_li(0x00007e00);
|
|
||||||
const uint32_t h_e_mask_value = uint32_li(0x0000001f);
|
|
||||||
const uint32_t f_h_s_pos_offset = uint32_li(0x00000010);
|
|
||||||
const uint32_t f_h_bias_offset = uint32_li(0x00000070);
|
|
||||||
const uint32_t f_h_m_pos_offset = uint32_li(0x0000000d);
|
|
||||||
const uint32_t h_nan_min = uint32_li(0x00007c01);
|
|
||||||
const uint32_t f_h_e_biased_flag = uint32_li(0x0000008f);
|
|
||||||
const uint32_t f_s = uint32_and(a_as_ui, f_s_mask);
|
|
||||||
const uint32_t f_e = uint32_and(a_as_ui, f_e_mask);
|
|
||||||
const uint16_t h_s = (uint16_t)uint32_srl(f_s, f_h_s_pos_offset);
|
|
||||||
const uint32_t f_m = uint32_and(a_as_ui, f_m_mask);
|
|
||||||
const uint16_t f_e_amount = (uint16_t)uint32_srl(f_e, f_e_pos);
|
|
||||||
const uint32_t f_e_half_bias = uint32_sub(f_e_amount, f_h_bias_offset);
|
|
||||||
const uint32_t f_snan = uint32_and(a_as_ui, f_snan_mask);
|
|
||||||
const uint32_t f_m_round_mask = uint32_and(f_m, f_m_round_bit);
|
|
||||||
const uint32_t f_m_round_offset = uint32_sll(f_m_round_mask, one);
|
|
||||||
const uint32_t f_m_rounded = uint32_add(f_m, f_m_round_offset);
|
|
||||||
const uint32_t f_m_denorm_sa = uint32_sub(one, f_e_half_bias);
|
|
||||||
const uint32_t f_m_with_hidden = uint32_or(f_m_rounded, f_m_hidden_bit);
|
|
||||||
const uint32_t f_m_denorm = uint32_srl(f_m_with_hidden, f_m_denorm_sa);
|
|
||||||
const uint32_t h_m_denorm = uint32_srl(f_m_denorm, f_h_m_pos_offset);
|
|
||||||
const uint32_t f_m_rounded_overflow = uint32_and(f_m_rounded, f_m_hidden_bit);
|
|
||||||
const uint32_t m_nan = uint32_srl(f_m, f_h_m_pos_offset);
|
|
||||||
const uint32_t h_em_nan = uint32_or(h_e_mask, m_nan);
|
|
||||||
const uint32_t h_e_norm_overflow_offset = uint32_inc(f_e_half_bias);
|
|
||||||
const uint32_t h_e_norm_overflow = uint32_sll(h_e_norm_overflow_offset, h_e_pos);
|
|
||||||
const uint32_t h_e_norm = uint32_sll(f_e_half_bias, h_e_pos);
|
|
||||||
const uint32_t h_m_norm = uint32_srl(f_m_rounded, f_h_m_pos_offset);
|
|
||||||
const uint32_t h_em_norm = uint32_or(h_e_norm, h_m_norm);
|
|
||||||
const uint32_t is_h_ndenorm_msb = uint32_sub(f_h_bias_offset, f_e_amount);
|
|
||||||
const uint32_t is_f_e_flagged_msb = uint32_sub(f_h_e_biased_flag, f_e_half_bias);
|
|
||||||
const uint32_t is_h_denorm_msb = uint32_not(is_h_ndenorm_msb);
|
|
||||||
const uint32_t is_f_m_eqz_msb = uint32_dec(f_m);
|
|
||||||
const uint32_t is_h_nan_eqz_msb = uint32_dec(m_nan);
|
|
||||||
const uint32_t is_f_inf_msb = uint32_and(is_f_e_flagged_msb, is_f_m_eqz_msb);
|
|
||||||
const uint32_t is_f_nan_underflow_msb = uint32_and(is_f_e_flagged_msb, is_h_nan_eqz_msb);
|
|
||||||
const uint32_t is_e_overflow_msb = uint32_sub(h_e_mask_value, f_e_half_bias);
|
|
||||||
const uint32_t is_h_inf_msb = uint32_or(is_e_overflow_msb, is_f_inf_msb);
|
|
||||||
const uint32_t is_f_nsnan_msb = uint32_sub(f_snan, f_snan_mask);
|
|
||||||
const uint32_t is_m_norm_overflow_msb = uint32_neg(f_m_rounded_overflow);
|
|
||||||
const uint32_t is_f_snan_msb = uint32_not(is_f_nsnan_msb);
|
|
||||||
const uint32_t h_em_overflow_result = uint32_sels(is_m_norm_overflow_msb, h_e_norm_overflow, h_em_norm);
|
|
||||||
const uint32_t h_em_nan_result = uint32_sels(is_f_e_flagged_msb, h_em_nan, h_em_overflow_result);
|
|
||||||
const uint32_t h_em_nan_underflow_result = uint32_sels(is_f_nan_underflow_msb, h_nan_min, h_em_nan_result);
|
|
||||||
const uint32_t h_em_inf_result = uint32_sels(is_h_inf_msb, h_e_mask, h_em_nan_underflow_result);
|
|
||||||
const uint32_t h_em_denorm_result = uint32_sels(is_h_denorm_msb, h_m_denorm, h_em_inf_result);
|
|
||||||
const uint32_t h_em_snan_result = uint32_sels(is_f_snan_msb, h_snan_mask, h_em_denorm_result);
|
|
||||||
const uint32_t h_result = uint32_or(h_s, h_em_snan_result);
|
|
||||||
|
|
||||||
return uint16_t(h_result);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BX_CONST_FUNC float halfToFloat(uint16_t _a)
|
|
||||||
{
|
|
||||||
const uint32_t h_e_mask = uint32_li(kHalfExponentMask);
|
|
||||||
const uint32_t h_m_mask = uint32_li(kHalfMantissaMask);
|
|
||||||
const uint32_t h_s_mask = uint32_li(kHalfSignMask);
|
|
||||||
const uint32_t h_f_s_pos_offset = uint32_li(0x00000010);
|
|
||||||
const uint32_t h_f_e_pos_offset = uint32_li(0x0000000d);
|
|
||||||
const uint32_t h_f_bias_offset = uint32_li(0x0001c000);
|
|
||||||
const uint32_t f_e_mask = uint32_li(kFloatExponentMask);
|
|
||||||
const uint32_t f_m_mask = uint32_li(kFloatMantissaMask);
|
|
||||||
const uint32_t h_f_e_denorm_bias = uint32_li(0x0000007e);
|
|
||||||
const uint32_t h_f_m_denorm_sa_bias = uint32_li(0x00000008);
|
|
||||||
const uint32_t f_e_pos = uint32_li(0x00000017);
|
|
||||||
const uint32_t h_e_mask_minus_one = uint32_li(0x00007bff);
|
|
||||||
const uint32_t h_e = uint32_and(_a, h_e_mask);
|
|
||||||
const uint32_t h_m = uint32_and(_a, h_m_mask);
|
|
||||||
const uint32_t h_s = uint32_and(_a, h_s_mask);
|
|
||||||
const uint32_t h_e_f_bias = uint32_add(h_e, h_f_bias_offset);
|
|
||||||
const uint32_t h_m_nlz = uint32_cntlz(h_m);
|
|
||||||
const uint32_t f_s = uint32_sll(h_s, h_f_s_pos_offset);
|
|
||||||
const uint32_t f_e = uint32_sll(h_e_f_bias, h_f_e_pos_offset);
|
|
||||||
const uint32_t f_m = uint32_sll(h_m, h_f_e_pos_offset);
|
|
||||||
const uint32_t f_em = uint32_or(f_e, f_m);
|
|
||||||
const uint32_t h_f_m_sa = uint32_sub(h_m_nlz, h_f_m_denorm_sa_bias);
|
|
||||||
const uint32_t f_e_denorm_unpacked = uint32_sub(h_f_e_denorm_bias, h_f_m_sa);
|
|
||||||
const uint32_t h_f_m = uint32_sll(h_m, h_f_m_sa);
|
|
||||||
const uint32_t f_m_denorm = uint32_and(h_f_m, f_m_mask);
|
|
||||||
const uint32_t f_e_denorm = uint32_sll(f_e_denorm_unpacked, f_e_pos);
|
|
||||||
const uint32_t f_em_denorm = uint32_or(f_e_denorm, f_m_denorm);
|
|
||||||
const uint32_t f_em_nan = uint32_or(f_e_mask, f_m);
|
|
||||||
const uint32_t is_e_eqz_msb = uint32_dec(h_e);
|
|
||||||
const uint32_t is_m_nez_msb = uint32_neg(h_m);
|
|
||||||
const uint32_t is_e_flagged_msb = uint32_sub(h_e_mask_minus_one, h_e);
|
|
||||||
const uint32_t is_zero_msb = uint32_andc(is_e_eqz_msb, is_m_nez_msb);
|
|
||||||
const uint32_t is_inf_msb = uint32_andc(is_e_flagged_msb, is_m_nez_msb);
|
|
||||||
const uint32_t is_denorm_msb = uint32_and(is_m_nez_msb, is_e_eqz_msb);
|
|
||||||
const uint32_t is_nan_msb = uint32_and(is_e_flagged_msb, is_m_nez_msb);
|
|
||||||
const uint32_t is_zero = uint32_ext(is_zero_msb);
|
|
||||||
const uint32_t f_zero_result = uint32_andc(f_em, is_zero);
|
|
||||||
const uint32_t f_denorm_result = uint32_sels(is_denorm_msb, f_em_denorm, f_zero_result);
|
|
||||||
const uint32_t f_inf_result = uint32_sels(is_inf_msb, f_e_mask, f_denorm_result);
|
|
||||||
const uint32_t f_nan_result = uint32_sels(is_nan_msb, f_em_nan, f_inf_result);
|
|
||||||
const uint32_t f_result = uint32_or(f_s, f_nan_result);
|
|
||||||
|
|
||||||
return bitCast<float>(f_result);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace bx
|
|
||||||
@@ -7,7 +7,6 @@
|
|||||||
#define BX_MATH_H_HEADER_GUARD
|
#define BX_MATH_H_HEADER_GUARD
|
||||||
|
|
||||||
#include "bx.h"
|
#include "bx.h"
|
||||||
#include "uint32_t.h"
|
|
||||||
|
|
||||||
namespace bx
|
namespace bx
|
||||||
{
|
{
|
||||||
@@ -595,6 +594,30 @@ namespace bx
|
|||||||
///
|
///
|
||||||
BX_CONSTEXPR_FUNC float sub(float _a, float _b);
|
BX_CONSTEXPR_FUNC float sub(float _a, float _b);
|
||||||
|
|
||||||
|
/// Saturating integer add. Clamps the result to the representable range
|
||||||
|
/// of `Ty` instead of wrapping around. Supports signed and unsigned
|
||||||
|
/// integer types.
|
||||||
|
///
|
||||||
|
/// @param[in] _a Left operand.
|
||||||
|
/// @param[in] _b Right operand.
|
||||||
|
///
|
||||||
|
/// @returns Sum clamped to `[LimitsT<Ty>::min, LimitsT<Ty>::max]`.
|
||||||
|
///
|
||||||
|
template<typename Ty>
|
||||||
|
BX_CONSTEXPR_FUNC Ty satAdd(Ty _a, Ty _b);
|
||||||
|
|
||||||
|
/// Saturating integer subtract. Clamps the result to the representable
|
||||||
|
/// range of `Ty` instead of wrapping around. Supports signed and
|
||||||
|
/// unsigned integer types.
|
||||||
|
///
|
||||||
|
/// @param[in] _a Left operand.
|
||||||
|
/// @param[in] _b Right operand.
|
||||||
|
///
|
||||||
|
/// @returns Difference clamped to `[LimitsT<Ty>::min, LimitsT<Ty>::max]`.
|
||||||
|
///
|
||||||
|
template<typename Ty>
|
||||||
|
BX_CONSTEXPR_FUNC Ty satSub(Ty _a, Ty _b);
|
||||||
|
|
||||||
/// Returns result of multiply (_a * _b).
|
/// Returns result of multiply (_a * _b).
|
||||||
///
|
///
|
||||||
/// @param[in] _a First value.
|
/// @param[in] _a First value.
|
||||||
@@ -1783,6 +1806,22 @@ namespace bx
|
|||||||
///
|
///
|
||||||
BX_CONSTEXPR_FUNC float toGamma(float _a);
|
BX_CONSTEXPR_FUNC float toGamma(float _a);
|
||||||
|
|
||||||
|
/// Convert float to half-float.
|
||||||
|
///
|
||||||
|
/// @param[in] _a Float value.
|
||||||
|
///
|
||||||
|
/// @returns Half-float value.
|
||||||
|
///
|
||||||
|
BX_CONST_FUNC uint16_t halfFromFloat(float _a);
|
||||||
|
|
||||||
|
/// Convert half-float to float.
|
||||||
|
///
|
||||||
|
/// @param[in] _a Half-float value.
|
||||||
|
///
|
||||||
|
/// @returns Float value.
|
||||||
|
///
|
||||||
|
BX_CONST_FUNC float halfToFloat(uint16_t _a);
|
||||||
|
|
||||||
} // namespace bx
|
} // namespace bx
|
||||||
|
|
||||||
#include "inline/math.inl"
|
#include "inline/math.inl"
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
#define BX_PIXEL_FORMAT_H_HEADER_GUARD
|
#define BX_PIXEL_FORMAT_H_HEADER_GUARD
|
||||||
|
|
||||||
#include "math.h"
|
#include "math.h"
|
||||||
#include "uint32_t.h"
|
|
||||||
|
|
||||||
namespace bx
|
namespace bx
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -202,7 +202,7 @@
|
|||||||
#elif defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__)
|
#elif defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__)
|
||||||
# undef BX_PLATFORM_OSX
|
# undef BX_PLATFORM_OSX
|
||||||
# define BX_PLATFORM_OSX __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
|
# define BX_PLATFORM_OSX __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
|
||||||
#elif defined(__EMSCRIPTEN__)
|
#elif defined(__wasm__)
|
||||||
# include <emscripten/version.h>
|
# include <emscripten/version.h>
|
||||||
# undef BX_PLATFORM_EMSCRIPTEN
|
# undef BX_PLATFORM_EMSCRIPTEN
|
||||||
# define BX_PLATFORM_EMSCRIPTEN (__EMSCRIPTEN_MAJOR__ * 10000 + __EMSCRIPTEN_MINOR__ * 100 + __EMSCRIPTEN_TINY__)
|
# define BX_PLATFORM_EMSCRIPTEN (__EMSCRIPTEN_MAJOR__ * 10000 + __EMSCRIPTEN_MINOR__ * 100 + __EMSCRIPTEN_TINY__)
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
#include "filepath.h"
|
#include "filepath.h"
|
||||||
#include "math.h"
|
#include "math.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "uint32_t.h"
|
|
||||||
|
|
||||||
namespace bx
|
namespace bx
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#include "bx.h"
|
#include "bx.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "uint32_t.h"
|
#include "simd_t.h"
|
||||||
|
|
||||||
namespace bx
|
namespace bx
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
|
|
||||||
#include "bx.h"
|
#include "bx.h"
|
||||||
#include "math.h"
|
#include "math.h"
|
||||||
#include "uint32_t.h"
|
|
||||||
|
|
||||||
namespace bx
|
namespace bx
|
||||||
{
|
{
|
||||||
|
|||||||
1976
include/bx/simd_t.h
1976
include/bx/simd_t.h
File diff suppressed because it is too large
Load Diff
@@ -1,316 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2026 Branimir Karadzic. All rights reserved.
|
|
||||||
* License: https://github.com/bkaradzic/bx/blob/master/LICENSE
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BX_UINT32_T_H_HEADER_GUARD
|
|
||||||
#define BX_UINT32_T_H_HEADER_GUARD
|
|
||||||
|
|
||||||
#include "bx.h"
|
|
||||||
|
|
||||||
namespace bx
|
|
||||||
{
|
|
||||||
constexpr uint16_t kHalfFloatZero = UINT16_C(0);
|
|
||||||
constexpr uint16_t kHalfFloatHalf = UINT16_C(0x3800);
|
|
||||||
constexpr uint16_t kHalfFloatOne = UINT16_C(0x3c00);
|
|
||||||
constexpr uint16_t kHalfFloatTwo = UINT16_C(0x4000);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_li(uint32_t _a);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_dec(uint32_t _a);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_inc(uint32_t _a);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_not(uint32_t _a);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_neg(uint32_t _a);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_ext(uint32_t _a);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_and(uint32_t _a, uint32_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_andc(uint32_t _a, uint32_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_xor(uint32_t _a, uint32_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_xorl(uint32_t _a, uint32_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_or(uint32_t _a, uint32_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_orc(uint32_t _a, uint32_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_sll(uint32_t _a, int32_t _sa);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_srl(uint32_t _a, int32_t _sa);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_sra(uint32_t _a, int32_t _sa);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_rol(uint32_t _a, int32_t _sa);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_ror(uint32_t _a, int32_t _sa);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_add(uint32_t _a, uint32_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_sub(uint32_t _a, uint32_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_mul(uint32_t _a, uint32_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_div(uint32_t _a, uint32_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_mod(uint32_t _a, uint32_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_cmpeq(uint32_t _a, uint32_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_cmpneq(uint32_t _a, uint32_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_cmplt(uint32_t _a, uint32_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_cmple(uint32_t _a, uint32_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_cmpgt(uint32_t _a, uint32_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_cmpge(uint32_t _a, uint32_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_setnz(uint32_t _a);
|
|
||||||
|
|
||||||
///
|
|
||||||
template<typename Ty>
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_splat(Ty _val);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_satadd(uint32_t _a, uint32_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_satsub(uint32_t _a, uint32_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_satmul(uint32_t _a, uint32_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_sels(uint32_t test, uint32_t _a, uint32_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_selb(uint32_t _mask, uint32_t _a, uint32_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_imin(uint32_t _a, uint32_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_imax(uint32_t _a, uint32_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_min(uint32_t _a, uint32_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_min(uint32_t _a, uint32_t _b, uint32_t _c);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_max(uint32_t _a, uint32_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_max(uint32_t _a, uint32_t _b, uint32_t _c);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_clamp(uint32_t _a, uint32_t _min, uint32_t _max);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_iclamp(uint32_t _a, uint32_t _min, uint32_t _max);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_incwrap(uint32_t _val, uint32_t _min, uint32_t _max);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_decwrap(uint32_t _val, uint32_t _min, uint32_t _max);
|
|
||||||
|
|
||||||
/// Count number of bits set.
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_cntbits(uint32_t _val);
|
|
||||||
|
|
||||||
/// Count number of leading zeros.
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_cntlz(uint32_t _val);
|
|
||||||
|
|
||||||
/// Count number of trailing zeros.
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_cnttz(uint32_t _val);
|
|
||||||
|
|
||||||
/// Find first set.
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_ffs(uint32_t _val);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_part1by1(uint32_t _a);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_part1by2(uint32_t _a);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_testpow2(uint32_t _a);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_nextpow2(uint32_t _a);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint64_t uint64_li(uint64_t _a);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint64_t uint64_dec(uint64_t _a);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint64_t uint64_inc(uint64_t _a);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint64_t uint64_not(uint64_t _a);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint64_t uint64_neg(uint64_t _a);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint64_t uint64_ext(uint64_t _a);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint64_t uint64_and(uint64_t _a, uint64_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint64_t uint64_andc(uint64_t _a, uint64_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint64_t uint64_xor(uint64_t _a, uint64_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint64_t uint64_xorl(uint64_t _a, uint64_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint64_t uint64_or(uint64_t _a, uint64_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint64_t uint64_orc(uint64_t _a, uint64_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint64_t uint64_sll(uint64_t _a, int32_t _sa);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint64_t uint64_srl(uint64_t _a, int32_t _sa);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint64_t uint64_sra(uint64_t _a, int32_t _sa);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint64_t uint64_rol(uint64_t _a, int32_t _sa);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint64_t uint64_ror(uint64_t _a, int32_t _sa);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint64_t uint64_add(uint64_t _a, uint64_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint64_t uint64_sub(uint64_t _a, uint64_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint64_t uint64_mul(uint64_t _a, uint64_t _b);
|
|
||||||
|
|
||||||
///
|
|
||||||
template<typename Ty>
|
|
||||||
BX_CONSTEXPR_FUNC uint64_t uint64_splat(Ty _val);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint64_t uint64_cntbits(uint64_t _val);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint64_t uint64_cntlz(uint64_t _val);
|
|
||||||
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint64_t uint64_cnttz(uint64_t _val);
|
|
||||||
|
|
||||||
/// Greatest common divisor.
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_gcd(uint32_t _a, uint32_t _b);
|
|
||||||
|
|
||||||
/// Least common multiple.
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t uint32_lcm(uint32_t _a, uint32_t _b);
|
|
||||||
|
|
||||||
/// Align to arbitrary stride.
|
|
||||||
///
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t strideAlign(uint32_t _offset, uint32_t _stride);
|
|
||||||
|
|
||||||
/// Align to arbitrary stride and Min bytes.
|
|
||||||
///
|
|
||||||
template<uint32_t Min>
|
|
||||||
BX_CONSTEXPR_FUNC uint32_t strideAlign(uint32_t _offset, uint32_t _stride);
|
|
||||||
|
|
||||||
///
|
|
||||||
template<typename Ty>
|
|
||||||
BX_CONSTEXPR_FUNC bool isAligned(Ty _a, size_t _align);
|
|
||||||
|
|
||||||
///
|
|
||||||
template<>
|
|
||||||
BX_CONSTEXPR_FUNC bool isAligned(const void* _ptr, size_t _align);
|
|
||||||
|
|
||||||
///
|
|
||||||
template<typename Ty>
|
|
||||||
BX_CONSTEXPR_FUNC Ty alignDown(Ty _a, size_t _align);
|
|
||||||
|
|
||||||
///
|
|
||||||
template<typename Ty>
|
|
||||||
BX_CONSTEXPR_FUNC Ty* alignDown(Ty* _ptr, size_t _align);
|
|
||||||
|
|
||||||
///
|
|
||||||
template<typename Ty>
|
|
||||||
BX_CONSTEXPR_FUNC const Ty* alignDown(const Ty* _ptr, size_t _align);
|
|
||||||
|
|
||||||
///
|
|
||||||
template<typename Ty>
|
|
||||||
BX_CONSTEXPR_FUNC Ty alignUp(Ty _a, size_t _align);
|
|
||||||
|
|
||||||
///
|
|
||||||
template<typename Ty>
|
|
||||||
BX_CONSTEXPR_FUNC Ty* alignUp(Ty* _ptr, size_t _align);
|
|
||||||
|
|
||||||
///
|
|
||||||
template<typename Ty>
|
|
||||||
BX_CONSTEXPR_FUNC const Ty* alignUp(const Ty* _ptr, size_t _align);
|
|
||||||
|
|
||||||
/// Convert float to half-float.
|
|
||||||
///
|
|
||||||
BX_CONST_FUNC uint16_t halfFromFloat(float _a);
|
|
||||||
|
|
||||||
/// Convert half-float to float.
|
|
||||||
///
|
|
||||||
BX_CONST_FUNC float halfToFloat(uint16_t _a);
|
|
||||||
|
|
||||||
} // namespace bx
|
|
||||||
|
|
||||||
#include "inline/uint32_t.inl"
|
|
||||||
|
|
||||||
#endif // BX_UINT32_T_H_HEADER_GUARD
|
|
||||||
@@ -878,6 +878,10 @@ function toolchain(_buildDir, _libDir)
|
|||||||
"-Wundef",
|
"-Wundef",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buildoptions {
|
||||||
|
"-msimd128",
|
||||||
|
}
|
||||||
|
|
||||||
linkoptions {
|
linkoptions {
|
||||||
"-s MAX_WEBGL_VERSION=2",
|
"-s MAX_WEBGL_VERSION=2",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ namespace bx
|
|||||||
char temp[4096];
|
char temp[4096];
|
||||||
while (0 != size)
|
while (0 != size)
|
||||||
{
|
{
|
||||||
uint32_t len = uint32_min(sizeof(temp)-1, size);
|
uint32_t len = uint32_t(min(sizeof(temp)-1, size) );
|
||||||
memCopy(temp, data, len);
|
memCopy(temp, data, len);
|
||||||
temp[len] = '\0';
|
temp[len] = '\0';
|
||||||
data += len;
|
data += len;
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
#include <bx/cpu.h>
|
#include <bx/cpu.h>
|
||||||
#include <bx/math.h>
|
#include <bx/math.h>
|
||||||
#include <bx/string.h>
|
#include <bx/string.h>
|
||||||
#include <bx/uint32_t.h>
|
|
||||||
|
|
||||||
namespace bx
|
namespace bx
|
||||||
{
|
{
|
||||||
|
|||||||
13
src/hash.cpp
13
src/hash.cpp
@@ -4,6 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <bx/hash.h>
|
#include <bx/hash.h>
|
||||||
|
#include <bx/simd_t.h>
|
||||||
|
|
||||||
namespace bx
|
namespace bx
|
||||||
{
|
{
|
||||||
@@ -333,7 +334,7 @@ struct HashMurmur3Pod
|
|||||||
BX_FORCE_INLINE void mix1(uint32_t _k)
|
BX_FORCE_INLINE void mix1(uint32_t _k)
|
||||||
{
|
{
|
||||||
_k *= kMurmur3Mul1;
|
_k *= kMurmur3Mul1;
|
||||||
_k = uint32_rol(_k, 15);
|
_k = simd32_x32_rol(simd32_splat(_k), 15).u32;
|
||||||
_k *= kMurmur3Mul2;
|
_k *= kMurmur3Mul2;
|
||||||
|
|
||||||
m_hash ^= _k;
|
m_hash ^= _k;
|
||||||
@@ -343,7 +344,7 @@ struct HashMurmur3Pod
|
|||||||
{
|
{
|
||||||
mix1(_k);
|
mix1(_k);
|
||||||
|
|
||||||
m_hash = uint32_rol(m_hash, 13);
|
m_hash = simd32_x32_rol(simd32_splat(m_hash), 13).u32;
|
||||||
m_hash = m_hash*5 + kMurmur3Add;
|
m_hash = m_hash*5 + kMurmur3Add;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -407,7 +408,7 @@ struct HashMurmur3_64Pod
|
|||||||
BX_FORCE_INLINE void mix1(uint64_t _k)
|
BX_FORCE_INLINE void mix1(uint64_t _k)
|
||||||
{
|
{
|
||||||
_k *= kMurmur3Mul1;
|
_k *= kMurmur3Mul1;
|
||||||
_k = uint64_rol(_k, 31);
|
_k = simd64_x64_rol(simd64_splat(_k), 31).u64;
|
||||||
_k *= kMurmur3Mul2;
|
_k *= kMurmur3Mul2;
|
||||||
|
|
||||||
m_hash[0] ^= _k;
|
m_hash[0] ^= _k;
|
||||||
@@ -416,7 +417,7 @@ struct HashMurmur3_64Pod
|
|||||||
BX_FORCE_INLINE void mix2(uint64_t _k)
|
BX_FORCE_INLINE void mix2(uint64_t _k)
|
||||||
{
|
{
|
||||||
_k *= kMurmur3Mul2;
|
_k *= kMurmur3Mul2;
|
||||||
_k = uint64_rol(_k, 33);
|
_k = simd64_x64_rol(simd64_splat(_k), 33).u64;
|
||||||
_k *= kMurmur3Mul1;
|
_k *= kMurmur3Mul1;
|
||||||
|
|
||||||
m_hash[1] ^= _k;
|
m_hash[1] ^= _k;
|
||||||
@@ -426,13 +427,13 @@ struct HashMurmur3_64Pod
|
|||||||
{
|
{
|
||||||
mix1(_k1);
|
mix1(_k1);
|
||||||
|
|
||||||
m_hash[0] = uint64_rol(m_hash[0], 27);
|
m_hash[0] = simd64_x64_rol(simd64_splat(m_hash[0]), 27).u64;
|
||||||
m_hash[0] += m_hash[1];
|
m_hash[0] += m_hash[1];
|
||||||
m_hash[0] = m_hash[0]*5 + kMurmur3Add1;
|
m_hash[0] = m_hash[0]*5 + kMurmur3Add1;
|
||||||
|
|
||||||
mix2(_k2);
|
mix2(_k2);
|
||||||
|
|
||||||
m_hash[1] = uint64_rol(m_hash[1], 31);
|
m_hash[1] = simd64_x64_rol(simd64_splat(m_hash[1]), 31).u64;
|
||||||
m_hash[1] += m_hash[0];
|
m_hash[1] += m_hash[0];
|
||||||
m_hash[1] = m_hash[1]*5 + kMurmur3Add2;
|
m_hash[1] = m_hash[1]*5 + kMurmur3Add2;
|
||||||
}
|
}
|
||||||
|
|||||||
19
src/math.cpp
19
src/math.cpp
@@ -4,23 +4,24 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <bx/math.h>
|
#include <bx/math.h>
|
||||||
#include <bx/uint32_t.h>
|
|
||||||
|
|
||||||
#include <bx/string.h>
|
#include <bx/string.h>
|
||||||
|
|
||||||
namespace bx
|
namespace bx
|
||||||
{
|
{
|
||||||
float frexp(float _a, int32_t* _outExp)
|
float frexp(float _a, int32_t* _outExp)
|
||||||
{
|
{
|
||||||
const uint32_t ftob = floatToBits(_a);
|
const simd32_t expMask = simd32_splat(kFloatExponentMask);
|
||||||
const uint32_t masked0 = uint32_and(ftob, kFloatExponentMask);
|
const simd32_t ftob = simd32_splat(_a);
|
||||||
const uint32_t exp0 = uint32_srl(masked0, kFloatExponentBitShift);
|
const simd32_t masked0 = simd_and(ftob, expMask);
|
||||||
|
const simd32_t exp0 = simd_x32_srl(masked0, kFloatExponentBitShift);
|
||||||
|
|
||||||
const uint32_t masked1 = uint32_and(ftob, kFloatSignMask | kFloatMantissaMask);
|
const simd32_t sMantMask = simd32_splat(kFloatSignMask | kFloatMantissaMask);
|
||||||
const uint32_t bits = uint32_or(masked1, UINT32_C(0x3f000000) );
|
const simd32_t masked1 = simd_and(ftob, sMantMask);
|
||||||
const float result = bitsToFloat(bits);
|
const simd32_t half = simd32_splat(0x3f000000u);
|
||||||
|
const simd32_t bits = simd_or(masked1, half);
|
||||||
|
const float result = bitsToFloat(bits.u32);
|
||||||
|
|
||||||
*_outExp = int32_t(exp0 - 0x7e);
|
*_outExp = int32_t(exp0.u32 - 0x7e);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
#include <bx/string.h>
|
#include <bx/string.h>
|
||||||
#include <bx/os.h>
|
#include <bx/os.h>
|
||||||
#include <bx/uint32_t.h>
|
|
||||||
|
|
||||||
#if BX_CRT_MSVC
|
#if BX_CRT_MSVC
|
||||||
# include <direct.h>
|
# include <direct.h>
|
||||||
@@ -332,7 +331,7 @@ namespace bx
|
|||||||
int32_t len = 0;
|
int32_t len = 0;
|
||||||
for(uint32_t ii = 0; NULL != _argv[ii]; ++ii)
|
for(uint32_t ii = 0; NULL != _argv[ii]; ++ii)
|
||||||
{
|
{
|
||||||
len += snprintf(&temp[len], uint32_imax(0, total-len)
|
len += snprintf(&temp[len], bx::max(0, total-len)
|
||||||
, "%s "
|
, "%s "
|
||||||
, _argv[ii]
|
, _argv[ii]
|
||||||
);
|
);
|
||||||
|
|||||||
84
tests/bx_test.cpp
Normal file
84
tests/bx_test.cpp
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2026 Branimir Karadzic. All rights reserved.
|
||||||
|
* License: https://github.com/bkaradzic/bx/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "test.h"
|
||||||
|
#include <bx/bx.h>
|
||||||
|
|
||||||
|
TEST_CASE("StrideAlign", "[bx]")
|
||||||
|
{
|
||||||
|
REQUIRE(0 == bx::strideAlign(0, 12) );
|
||||||
|
for (uint32_t ii = 0; ii < 12; ++ii)
|
||||||
|
{
|
||||||
|
REQUIRE(12 == bx::strideAlign(ii+1, 12) );
|
||||||
|
}
|
||||||
|
|
||||||
|
REQUIRE(0 == bx::strideAlign<16>(0, 12) );
|
||||||
|
for (uint32_t ii = 0; ii < 12; ++ii)
|
||||||
|
{
|
||||||
|
REQUIRE(48 == bx::strideAlign<16>(ii+1, 12) );
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t offset = 11;
|
||||||
|
offset = bx::strideAlign(offset, 32);
|
||||||
|
REQUIRE(offset == 32);
|
||||||
|
|
||||||
|
offset = bx::strideAlign(offset, 24);
|
||||||
|
REQUIRE(offset == 48);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("gcd", "[bx]")
|
||||||
|
{
|
||||||
|
REQUIRE(1 == bx::gcd(13u, 89u) );
|
||||||
|
REQUIRE(3 == bx::gcd( 3u, 9u) );
|
||||||
|
REQUIRE(8 == bx::gcd( 8u, 64u) );
|
||||||
|
REQUIRE(9 == bx::gcd(18u, 81u) );
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("lcm", "[bx]")
|
||||||
|
{
|
||||||
|
REQUIRE(1157 == bx::lcm(13u, 89u) );
|
||||||
|
REQUIRE( 9 == bx::lcm( 3u, 9u) );
|
||||||
|
REQUIRE( 48 == bx::lcm( 6u, 16u) );
|
||||||
|
REQUIRE( 80 == bx::lcm(16u, 20u) );
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("align", "[bx]")
|
||||||
|
{
|
||||||
|
REQUIRE( bx::isAligned(0, 8) );
|
||||||
|
REQUIRE(!bx::isAligned(7, 8) );
|
||||||
|
REQUIRE( bx::isAligned(64, 8) );
|
||||||
|
REQUIRE(!bx::isAligned(63, 8) );
|
||||||
|
|
||||||
|
for (int32_t ii = 0; ii < 1024; ++ii)
|
||||||
|
{
|
||||||
|
REQUIRE(bx::isAligned(ii, 0) );
|
||||||
|
REQUIRE(ii == bx::alignUp(ii, 0) );
|
||||||
|
REQUIRE(ii == bx::alignDown(ii, 0) );
|
||||||
|
}
|
||||||
|
|
||||||
|
REQUIRE( 0 == bx::alignUp( 0, 16) );
|
||||||
|
REQUIRE( 16 == bx::alignUp( 1, 16) );
|
||||||
|
REQUIRE( 16 == bx::alignUp( 15, 16) );
|
||||||
|
REQUIRE( 16 == bx::alignUp( 16, 16) );
|
||||||
|
REQUIRE(256 == bx::alignUp(255, 16) );
|
||||||
|
REQUIRE( 0 == bx::alignUp(-1, 16) );
|
||||||
|
REQUIRE(-16 == bx::alignUp(-31, 16) );
|
||||||
|
|
||||||
|
REQUIRE( 0 == bx::alignUp( 0, 256) );
|
||||||
|
REQUIRE(256 == bx::alignUp( 1, 256) );
|
||||||
|
REQUIRE(256 == bx::alignUp( 15, 256) );
|
||||||
|
REQUIRE(256 == bx::alignUp(255, 256) );
|
||||||
|
REQUIRE(256 == bx::alignUp(256, 256) );
|
||||||
|
REQUIRE(256 == bx::alignUp(256, 256) );
|
||||||
|
REQUIRE(512 == bx::alignUp(511, 256) );
|
||||||
|
|
||||||
|
REQUIRE( 0 == bx::alignDown( 0, 16) );
|
||||||
|
REQUIRE( 0 == bx::alignDown( 1, 16) );
|
||||||
|
REQUIRE( 0 == bx::alignDown( 15, 16) );
|
||||||
|
REQUIRE( 16 == bx::alignDown( 16, 16) );
|
||||||
|
REQUIRE(240 == bx::alignDown(255, 16) );
|
||||||
|
REQUIRE(-16 == bx::alignDown(-1, 16) );
|
||||||
|
REQUIRE(-32 == bx::alignDown(-31, 16) );
|
||||||
|
}
|
||||||
@@ -111,7 +111,7 @@ TEST_CASE("ceilLog2", "[math]")
|
|||||||
|
|
||||||
for (uint32_t ii = 1; ii < INT32_MAX; ii += rand()%(1<<13)+1)
|
for (uint32_t ii = 1; ii < INT32_MAX; ii += rand()%(1<<13)+1)
|
||||||
{
|
{
|
||||||
REQUIRE(bx::nextPow2(ii) == bx::uint32_nextpow2(ii) );
|
REQUIRE(bx::nextPow2(ii) == bx::simd32_u32_nextpow2(bx::simd32_splat(ii)).u32 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,6 +226,79 @@ TEST_CASE("countBits", "[math]")
|
|||||||
STATIC_REQUIRE(64 == bx::countBits(UINT64_MAX) );
|
STATIC_REQUIRE(64 == bx::countBits(UINT64_MAX) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("satAdd", "[math]")
|
||||||
|
{
|
||||||
|
STATIC_REQUIRE( 0 == bx::satAdd<uint8_t >(0, 0) );
|
||||||
|
STATIC_REQUIRE(200 == bx::satAdd<uint8_t >(100, 100) );
|
||||||
|
STATIC_REQUIRE(255 == bx::satAdd<uint8_t >(UINT8_MAX, 0) );
|
||||||
|
STATIC_REQUIRE(255 == bx::satAdd<uint8_t >(UINT8_MAX, 1) );
|
||||||
|
STATIC_REQUIRE(255 == bx::satAdd<uint8_t >(UINT8_MAX, 10) );
|
||||||
|
STATIC_REQUIRE(255 == bx::satAdd<uint8_t >(254, 254) );
|
||||||
|
STATIC_REQUIRE(255 == bx::satAdd<uint8_t >(200, 100) );
|
||||||
|
|
||||||
|
STATIC_REQUIRE(UINT16_MAX == bx::satAdd<uint16_t>(UINT16_MAX, 0) );
|
||||||
|
STATIC_REQUIRE(UINT16_MAX == bx::satAdd<uint16_t>(UINT16_MAX, 1) );
|
||||||
|
STATIC_REQUIRE(UINT16_MAX == bx::satAdd<uint16_t>(65530, 10) );
|
||||||
|
STATIC_REQUIRE(uint16_t(65534)== bx::satAdd<uint16_t>(65530, 4) );
|
||||||
|
|
||||||
|
STATIC_REQUIRE(UINT32_MAX == bx::satAdd<uint32_t>(UINT32_MAX, 0) );
|
||||||
|
STATIC_REQUIRE(UINT32_MAX == bx::satAdd<uint32_t>(UINT32_MAX, 1) );
|
||||||
|
STATIC_REQUIRE(UINT32_MAX == bx::satAdd<uint32_t>(UINT32_MAX-1, 10) );
|
||||||
|
|
||||||
|
STATIC_REQUIRE(UINT64_MAX == bx::satAdd<uint64_t>(UINT64_MAX, 1) );
|
||||||
|
STATIC_REQUIRE(UINT64_MAX == bx::satAdd<uint64_t>(UINT64_MAX-1, 10) );
|
||||||
|
|
||||||
|
// signed
|
||||||
|
STATIC_REQUIRE( 127 == bx::satAdd<int8_t >( 127, 1) );
|
||||||
|
STATIC_REQUIRE( 127 == bx::satAdd<int8_t >( 100, 100) );
|
||||||
|
STATIC_REQUIRE(-128 == bx::satAdd<int8_t >(-128, -1) );
|
||||||
|
STATIC_REQUIRE(-128 == bx::satAdd<int8_t >(-100,-100) );
|
||||||
|
STATIC_REQUIRE( -1 == bx::satAdd<int8_t >( 127,-128) );
|
||||||
|
|
||||||
|
STATIC_REQUIRE(INT32_MAX == bx::satAdd<int32_t>(INT32_MAX, 1) );
|
||||||
|
STATIC_REQUIRE(INT32_MAX == bx::satAdd<int32_t>(INT32_MAX, INT32_MAX) );
|
||||||
|
STATIC_REQUIRE(INT32_MIN == bx::satAdd<int32_t>(INT32_MIN, -1) );
|
||||||
|
STATIC_REQUIRE(INT32_MIN == bx::satAdd<int32_t>(INT32_MIN, INT32_MIN) );
|
||||||
|
STATIC_REQUIRE( -1 == bx::satAdd<int32_t>(INT32_MAX, INT32_MIN) );
|
||||||
|
|
||||||
|
STATIC_REQUIRE(INT64_MAX == bx::satAdd<int64_t>(INT64_MAX, 1) );
|
||||||
|
STATIC_REQUIRE(INT64_MIN == bx::satAdd<int64_t>(INT64_MIN, -1) );
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("satSub", "[math]")
|
||||||
|
{
|
||||||
|
STATIC_REQUIRE( 0 == bx::satSub<uint8_t >(0, 0) );
|
||||||
|
STATIC_REQUIRE( 0 == bx::satSub<uint8_t >(10, 20) );
|
||||||
|
STATIC_REQUIRE( 0 == bx::satSub<uint8_t >(0, UINT8_MAX) );
|
||||||
|
STATIC_REQUIRE( 10 == bx::satSub<uint8_t >(20, 10) );
|
||||||
|
STATIC_REQUIRE(UINT8_MAX == bx::satSub<uint8_t >(UINT8_MAX, 0) );
|
||||||
|
|
||||||
|
STATIC_REQUIRE( 0 == bx::satSub<uint16_t>(10, 20) );
|
||||||
|
STATIC_REQUIRE( 0 == bx::satSub<uint16_t>(0, UINT16_MAX) );
|
||||||
|
STATIC_REQUIRE(UINT16_MAX == bx::satSub<uint16_t>(UINT16_MAX, 0) );
|
||||||
|
|
||||||
|
STATIC_REQUIRE( 0 == bx::satSub<uint32_t>(10, 20) );
|
||||||
|
STATIC_REQUIRE( 0 == bx::satSub<uint32_t>(0, UINT32_MAX) );
|
||||||
|
STATIC_REQUIRE(UINT32_MAX == bx::satSub<uint32_t>(UINT32_MAX, 0) );
|
||||||
|
|
||||||
|
STATIC_REQUIRE( 0 == bx::satSub<uint64_t>(10, 20) );
|
||||||
|
STATIC_REQUIRE(UINT64_MAX == bx::satSub<uint64_t>(UINT64_MAX, 0) );
|
||||||
|
|
||||||
|
// signed
|
||||||
|
STATIC_REQUIRE(-128 == bx::satSub<int8_t >(-128, 1) );
|
||||||
|
STATIC_REQUIRE( 127 == bx::satSub<int8_t >( 127, -1) );
|
||||||
|
STATIC_REQUIRE( 127 == bx::satSub<int8_t >( 0,-128) );
|
||||||
|
|
||||||
|
STATIC_REQUIRE(INT32_MIN == bx::satSub<int32_t>(INT32_MIN, 1) );
|
||||||
|
STATIC_REQUIRE(INT32_MIN == bx::satSub<int32_t>(INT32_MIN, INT32_MAX) );
|
||||||
|
STATIC_REQUIRE(INT32_MAX == bx::satSub<int32_t>( 0, INT32_MIN) );
|
||||||
|
STATIC_REQUIRE(INT32_MAX == bx::satSub<int32_t>(INT32_MAX, -1) );
|
||||||
|
STATIC_REQUIRE(INT32_MAX == bx::satSub<int32_t>(INT32_MAX, INT32_MIN) );
|
||||||
|
|
||||||
|
STATIC_REQUIRE(INT64_MIN == bx::satSub<int64_t>(INT64_MIN, 1) );
|
||||||
|
STATIC_REQUIRE(INT64_MAX == bx::satSub<int64_t>( 0, INT64_MIN) );
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Ty>
|
template<typename Ty>
|
||||||
static void testFindFirstSet()
|
static void testFindFirstSet()
|
||||||
{
|
{
|
||||||
|
|||||||
95
tests/simd32_test.cpp
Normal file
95
tests/simd32_test.cpp
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2026 Branimir Karadzic. All rights reserved.
|
||||||
|
* License: https://github.com/bkaradzic/bx/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "test.h"
|
||||||
|
#include <bx/simd_t.h>
|
||||||
|
|
||||||
|
TEST_CASE("uint32_part", "[simd_t]")
|
||||||
|
{
|
||||||
|
REQUIRE(UINT32_C(0x55555555) == bx::simd32_x32_part1by1(bx::simd32_splat(uint32_t(UINT16_MAX))).u32 );
|
||||||
|
REQUIRE(UINT32_C(0x09249249) == bx::simd32_x32_part1by2(bx::simd32_splat(uint32_t(0x3ff))).u32 );
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("uint32_splat", "[simd_t]")
|
||||||
|
{
|
||||||
|
REQUIRE(UINT32_C(0x01010101) == bx::simd32_splat(uint8_t(0x01)).u32 );
|
||||||
|
REQUIRE(UINT32_C(0x55555555) == bx::simd32_splat(uint8_t(0x55)).u32 );
|
||||||
|
REQUIRE(UINT32_C(0x13891389) == bx::simd32_splat(uint16_t(0x1389)).u32 );
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("uint64_splat", "[simd_t]")
|
||||||
|
{
|
||||||
|
REQUIRE(UINT64_C(0x0101010101010101) == bx::simd64_splat(uint8_t(0x01)).u64 );
|
||||||
|
REQUIRE(UINT64_C(0x5555555555555555) == bx::simd64_splat(uint8_t(0x55)).u64 );
|
||||||
|
REQUIRE(UINT32_C(0x1389138913891389) == bx::simd64_splat(uint16_t(0x1389)).u64 );
|
||||||
|
REQUIRE(UINT32_C(0x1506138915061389) == bx::simd64_splat(uint32_t(0x15061389)).u64 );
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("uint32_gcd", "[simd_t]")
|
||||||
|
{
|
||||||
|
REQUIRE(1 == bx::simd32_u32_gcd(bx::simd32_splat(uint32_t(13)), bx::simd32_splat(uint32_t(89))).u32 );
|
||||||
|
REQUIRE(3 == bx::simd32_u32_gcd(bx::simd32_splat(uint32_t( 3)), bx::simd32_splat(uint32_t( 9))).u32 );
|
||||||
|
REQUIRE(8 == bx::simd32_u32_gcd(bx::simd32_splat(uint32_t( 8)), bx::simd32_splat(uint32_t(64))).u32 );
|
||||||
|
REQUIRE(9 == bx::simd32_u32_gcd(bx::simd32_splat(uint32_t(18)), bx::simd32_splat(uint32_t(81))).u32 );
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("uint32_lcm", "[simd_t]")
|
||||||
|
{
|
||||||
|
REQUIRE(1157 == bx::simd32_u32_lcm(bx::simd32_splat(uint32_t(13)), bx::simd32_splat(uint32_t(89))).u32 );
|
||||||
|
REQUIRE( 9 == bx::simd32_u32_lcm(bx::simd32_splat(uint32_t( 3)), bx::simd32_splat(uint32_t( 9))).u32 );
|
||||||
|
REQUIRE( 48 == bx::simd32_u32_lcm(bx::simd32_splat(uint32_t( 6)), bx::simd32_splat(uint32_t(16))).u32 );
|
||||||
|
REQUIRE( 80 == bx::simd32_u32_lcm(bx::simd32_splat(uint32_t(16)), bx::simd32_splat(uint32_t(20))).u32 );
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("halfTo/FromFloat", "[simd_t]")
|
||||||
|
{
|
||||||
|
for (uint32_t ii = 0; ii < 0x7c00; ++ii)
|
||||||
|
{
|
||||||
|
const uint16_t orig = uint16_t(ii);
|
||||||
|
const float htf = bx::halfToFloat(orig);
|
||||||
|
const uint16_t hff = bx::halfFromFloat(htf);
|
||||||
|
REQUIRE(orig == hff);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t ii = 0x8000; ii < 0xfc00; ++ii)
|
||||||
|
{
|
||||||
|
const uint16_t orig = uint16_t(ii);
|
||||||
|
const float htf = bx::halfToFloat(orig);
|
||||||
|
const uint16_t hff = bx::halfFromFloat(htf);
|
||||||
|
REQUIRE(orig == hff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("uint32_testpow2", "[simd_t]")
|
||||||
|
{
|
||||||
|
uint32_t shift = 0;
|
||||||
|
uint32_t nextpow2 = bx::simd32_u32_nextpow2(bx::simd32_splat(uint32_t(1))).u32;
|
||||||
|
|
||||||
|
for (uint32_t ii = 1; ii < 1<<24; ++ii)
|
||||||
|
{
|
||||||
|
REQUIRE(nextpow2 == bx::simd32_u32_nextpow2(bx::simd32_splat(ii)).u32 );
|
||||||
|
|
||||||
|
if (bx::simd32_u32_testpow2(bx::simd32_splat(ii)).u32 )
|
||||||
|
{
|
||||||
|
REQUIRE(ii == 1u << shift);
|
||||||
|
++shift;
|
||||||
|
|
||||||
|
REQUIRE(ii == nextpow2);
|
||||||
|
nextpow2 = bx::simd32_u32_nextpow2(bx::simd32_splat(ii+1)).u32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("uint32_roX", "[simd_t]")
|
||||||
|
{
|
||||||
|
REQUIRE(bx::simd32_x32_rol(bx::simd32_splat(uint32_t(0x80000000)), 1).u32 == 1);
|
||||||
|
REQUIRE(bx::simd32_x32_ror(bx::simd32_splat(uint32_t(1)), 1).u32 == 0x80000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("uint64_roX", "[simd_t]")
|
||||||
|
{
|
||||||
|
REQUIRE(bx::simd64_x64_rol(bx::simd64_splat(uint64_t(0x8000000000000000)), 1).u64 == 1);
|
||||||
|
REQUIRE(bx::simd64_x64_ror(bx::simd64_splat(uint64_t(1)), 1).u64 == 0x8000000000000000);
|
||||||
|
}
|
||||||
@@ -26,20 +26,20 @@ void simd_rsqrt_bench(bx::simd128_t* _dst, bx::simd128_t* _src, uint32_t _numVer
|
|||||||
for (uint32_t ii = 0, num = _numVertices/4; ii < num; ++ii)
|
for (uint32_t ii = 0, num = _numVertices/4; ii < num; ++ii)
|
||||||
{
|
{
|
||||||
bx::simd128_t* ptr = &_src[ii*4];
|
bx::simd128_t* ptr = &_src[ii*4];
|
||||||
bx::simd128_t tmp0 = bx::simd_ld(ptr + 0);
|
bx::simd128_t tmp0 = bx::simd128_ld(ptr + 0);
|
||||||
bx::simd128_t tmp1 = bx::simd_ld(ptr + 1);
|
bx::simd128_t tmp1 = bx::simd128_ld(ptr + 1);
|
||||||
bx::simd128_t tmp2 = bx::simd_ld(ptr + 2);
|
bx::simd128_t tmp2 = bx::simd128_ld(ptr + 2);
|
||||||
bx::simd128_t tmp3 = bx::simd_ld(ptr + 3);
|
bx::simd128_t tmp3 = bx::simd128_ld(ptr + 3);
|
||||||
bx::simd128_t rsqrt0 = simdRsqrtFn(tmp0);
|
bx::simd128_t rsqrt0 = simdRsqrtFn(tmp0);
|
||||||
bx::simd128_t rsqrt1 = simdRsqrtFn(tmp1);
|
bx::simd128_t rsqrt1 = simdRsqrtFn(tmp1);
|
||||||
bx::simd128_t rsqrt2 = simdRsqrtFn(tmp2);
|
bx::simd128_t rsqrt2 = simdRsqrtFn(tmp2);
|
||||||
bx::simd128_t rsqrt3 = simdRsqrtFn(tmp3);
|
bx::simd128_t rsqrt3 = simdRsqrtFn(tmp3);
|
||||||
|
|
||||||
ptr = &_dst[ii*4];
|
ptr = &_dst[ii*4];
|
||||||
bx::simd_st(ptr + 0, rsqrt0);
|
bx::simd128_st(ptr + 0, rsqrt0);
|
||||||
bx::simd_st(ptr + 1, rsqrt1);
|
bx::simd128_st(ptr + 1, rsqrt1);
|
||||||
bx::simd_st(ptr + 2, rsqrt2);
|
bx::simd128_st(ptr + 2, rsqrt2);
|
||||||
bx::simd_st(ptr + 3, rsqrt3);
|
bx::simd128_st(ptr + 3, rsqrt3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,10 +53,10 @@ void simd_bench_pass(bx::simd128_t* _dst, bx::simd128_t* _src, uint32_t _numVert
|
|||||||
{
|
{
|
||||||
flushCache();
|
flushCache();
|
||||||
elapsed += -bx::getHPCounter();
|
elapsed += -bx::getHPCounter();
|
||||||
simd_rsqrt_bench<bx::simd_rsqrt_est>(_dst, _src, _numVertices);
|
simd_rsqrt_bench<bx::simd128_f32_rsqrt_est>(_dst, _src, _numVertices);
|
||||||
elapsed += bx::getHPCounter();
|
elapsed += bx::getHPCounter();
|
||||||
}
|
}
|
||||||
printf(" simd_rsqrt_est: %15f\n", double(elapsed) );
|
printf(" simd128_f32_rsqrt_est: %15f\n", double(elapsed) );
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -65,10 +65,10 @@ void simd_bench_pass(bx::simd128_t* _dst, bx::simd128_t* _src, uint32_t _numVert
|
|||||||
{
|
{
|
||||||
flushCache();
|
flushCache();
|
||||||
elapsed += -bx::getHPCounter();
|
elapsed += -bx::getHPCounter();
|
||||||
simd_rsqrt_bench<bx::simd_rsqrt_nr>(_dst, _src, _numVertices);
|
simd_rsqrt_bench<bx::simd128_f32_rsqrt_nr>(_dst, _src, _numVertices);
|
||||||
elapsed += bx::getHPCounter();
|
elapsed += bx::getHPCounter();
|
||||||
}
|
}
|
||||||
printf(" simd_rsqrt_nr: %15f\n", double(elapsed) );
|
printf(" simd128_f32_rsqrt_nr: %15f\n", double(elapsed) );
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -77,10 +77,10 @@ void simd_bench_pass(bx::simd128_t* _dst, bx::simd128_t* _src, uint32_t _numVert
|
|||||||
{
|
{
|
||||||
flushCache();
|
flushCache();
|
||||||
elapsed += -bx::getHPCounter();
|
elapsed += -bx::getHPCounter();
|
||||||
simd_rsqrt_bench<bx::simd_rsqrt_carmack>(_dst, _src, _numVertices);
|
simd_rsqrt_bench<bx::simd128_f32_rsqrt_carmack>(_dst, _src, _numVertices);
|
||||||
elapsed += bx::getHPCounter();
|
elapsed += bx::getHPCounter();
|
||||||
}
|
}
|
||||||
printf("simd_rsqrt_carmack: %15f\n", double(elapsed) );
|
printf("simd128_f32_rsqrt_carmack: %15f\n", double(elapsed) );
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -89,10 +89,10 @@ void simd_bench_pass(bx::simd128_t* _dst, bx::simd128_t* _src, uint32_t _numVert
|
|||||||
{
|
{
|
||||||
flushCache();
|
flushCache();
|
||||||
elapsed += -bx::getHPCounter();
|
elapsed += -bx::getHPCounter();
|
||||||
simd_rsqrt_bench<bx::simd_rsqrt>(_dst, _src, _numVertices);
|
simd_rsqrt_bench<bx::simd128_f32_rsqrt>(_dst, _src, _numVertices);
|
||||||
elapsed += bx::getHPCounter();
|
elapsed += bx::getHPCounter();
|
||||||
}
|
}
|
||||||
printf(" simd_rsqrt: %15f\n", double(elapsed) );
|
printf(" simd128_f32_rsqrt: %15f\n", double(elapsed) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
1750
tests/simd_test.cpp
1750
tests/simd_test.cpp
File diff suppressed because it is too large
Load Diff
@@ -14,8 +14,6 @@ BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4312); // warning C4312 : 'reinterpret_cast' :
|
|||||||
#include <catch/catch_amalgamated.hpp>
|
#include <catch/catch_amalgamated.hpp>
|
||||||
BX_PRAGMA_DIAGNOSTIC_POP();
|
BX_PRAGMA_DIAGNOSTIC_POP();
|
||||||
|
|
||||||
#define TEST(_x) TEST_CASE(#_x, "")
|
|
||||||
|
|
||||||
#if BX_CONFIG_DEBUG
|
#if BX_CONFIG_DEBUG
|
||||||
# define REQUIRE_ASSERTS(_x) REQUIRE_THROWS(_x)
|
# define REQUIRE_ASSERTS(_x) REQUIRE_THROWS(_x)
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -1,156 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2026 Branimir Karadzic. All rights reserved.
|
|
||||||
* License: https://github.com/bkaradzic/bx/blob/master/LICENSE
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "test.h"
|
|
||||||
#include <bx/uint32_t.h>
|
|
||||||
|
|
||||||
TEST_CASE("StrideAlign", "[uint32_t]")
|
|
||||||
{
|
|
||||||
REQUIRE(0 == bx::strideAlign(0, 12) );
|
|
||||||
for (uint32_t ii = 0; ii < 12; ++ii)
|
|
||||||
{
|
|
||||||
REQUIRE(12 == bx::strideAlign(ii+1, 12) );
|
|
||||||
}
|
|
||||||
|
|
||||||
REQUIRE(0 == bx::strideAlign<16>(0, 12) );
|
|
||||||
for (uint32_t ii = 0; ii < 12; ++ii)
|
|
||||||
{
|
|
||||||
REQUIRE(48 == bx::strideAlign<16>(ii+1, 12) );
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t offset = 11;
|
|
||||||
offset = bx::strideAlign(offset, 32);
|
|
||||||
REQUIRE(offset == 32);
|
|
||||||
|
|
||||||
offset = bx::strideAlign(offset, 24);
|
|
||||||
REQUIRE(offset == 48);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("uint32_part", "[uint32_t]")
|
|
||||||
{
|
|
||||||
REQUIRE(UINT32_C(0x55555555) == bx::uint32_part1by1(UINT16_MAX) );
|
|
||||||
REQUIRE(UINT32_C(0x09249249) == bx::uint32_part1by2(0x3ff) );
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("uint32_splat", "[uint32_t]")
|
|
||||||
{
|
|
||||||
REQUIRE(UINT32_C(0x01010101) == bx::uint32_splat<uint8_t>(0x01) );
|
|
||||||
REQUIRE(UINT32_C(0x55555555) == bx::uint32_splat<uint8_t>(0x55) );
|
|
||||||
REQUIRE(UINT32_C(0x13891389) == bx::uint32_splat<uint16_t>(0x1389) );
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("uint64_splat", "[uint32_t]")
|
|
||||||
{
|
|
||||||
REQUIRE(UINT64_C(0x0101010101010101) == bx::uint64_splat<uint8_t>(0x01) );
|
|
||||||
REQUIRE(UINT64_C(0x5555555555555555) == bx::uint64_splat<uint8_t>(0x55) );
|
|
||||||
REQUIRE(UINT32_C(0x1389138913891389) == bx::uint64_splat<uint16_t>(0x1389) );
|
|
||||||
REQUIRE(UINT32_C(0x1506138915061389) == bx::uint64_splat<uint32_t>(0x15061389) );
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("uint32_gcd", "[uint32_t]")
|
|
||||||
{
|
|
||||||
REQUIRE(1 == bx::uint32_gcd(13, 89) );
|
|
||||||
REQUIRE(3 == bx::uint32_gcd( 3, 9) );
|
|
||||||
REQUIRE(8 == bx::uint32_gcd( 8, 64) );
|
|
||||||
REQUIRE(9 == bx::uint32_gcd(18, 81) );
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("uint32_lcm", "[uint32_t]")
|
|
||||||
{
|
|
||||||
REQUIRE(1157 == bx::uint32_lcm(13, 89) );
|
|
||||||
REQUIRE( 9 == bx::uint32_lcm( 3, 9) );
|
|
||||||
REQUIRE( 48 == bx::uint32_lcm( 6, 16) );
|
|
||||||
REQUIRE( 80 == bx::uint32_lcm(16, 20) );
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("halfTo/FromFloat", "[uint32_t]")
|
|
||||||
{
|
|
||||||
for (uint32_t ii = 0; ii < 0x7c00; ++ii)
|
|
||||||
{
|
|
||||||
const uint16_t orig = uint16_t(ii);
|
|
||||||
const float htf = bx::halfToFloat(orig);
|
|
||||||
const uint16_t hff = bx::halfFromFloat(htf);
|
|
||||||
REQUIRE(orig == hff);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint32_t ii = 0x8000; ii < 0xfc00; ++ii)
|
|
||||||
{
|
|
||||||
const uint16_t orig = uint16_t(ii);
|
|
||||||
const float htf = bx::halfToFloat(orig);
|
|
||||||
const uint16_t hff = bx::halfFromFloat(htf);
|
|
||||||
REQUIRE(orig == hff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("uint32_testpow2", "[uint32_t]")
|
|
||||||
{
|
|
||||||
uint32_t shift = 0;
|
|
||||||
uint32_t nextpow2 = bx::uint32_nextpow2(1);
|
|
||||||
|
|
||||||
for (uint32_t ii = 1; ii < 1<<24; ++ii)
|
|
||||||
{
|
|
||||||
REQUIRE(nextpow2 == bx::uint32_nextpow2(ii) );
|
|
||||||
|
|
||||||
if (bx::uint32_testpow2(ii) )
|
|
||||||
{
|
|
||||||
REQUIRE(ii == 1u << shift);
|
|
||||||
++shift;
|
|
||||||
|
|
||||||
REQUIRE(ii == nextpow2);
|
|
||||||
nextpow2 = bx::uint32_nextpow2(ii+1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("uint32_roX", "[uint32_t]")
|
|
||||||
{
|
|
||||||
REQUIRE(bx::uint32_rol(0x80000000, 1) == 1);
|
|
||||||
REQUIRE(bx::uint32_ror(1, 1) == 0x80000000);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("uint64_roX", "[uint32_t]")
|
|
||||||
{
|
|
||||||
REQUIRE(bx::uint64_rol(0x8000000000000000, 1) == 1);
|
|
||||||
REQUIRE(bx::uint64_ror(1, 1) == 0x8000000000000000);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("align", "[uint32_t]")
|
|
||||||
{
|
|
||||||
REQUIRE( bx::isAligned(0, 8) );
|
|
||||||
REQUIRE(!bx::isAligned(7, 8) );
|
|
||||||
REQUIRE( bx::isAligned(64, 8) );
|
|
||||||
REQUIRE(!bx::isAligned(63, 8) );
|
|
||||||
|
|
||||||
for (int32_t ii = 0; ii < 1024; ++ii)
|
|
||||||
{
|
|
||||||
REQUIRE(bx::isAligned(ii, 0) );
|
|
||||||
REQUIRE(ii == bx::alignUp(ii, 0) );
|
|
||||||
REQUIRE(ii == bx::alignDown(ii, 0) );
|
|
||||||
}
|
|
||||||
|
|
||||||
REQUIRE( 0 == bx::alignUp( 0, 16) );
|
|
||||||
REQUIRE( 16 == bx::alignUp( 1, 16) );
|
|
||||||
REQUIRE( 16 == bx::alignUp( 15, 16) );
|
|
||||||
REQUIRE( 16 == bx::alignUp( 16, 16) );
|
|
||||||
REQUIRE(256 == bx::alignUp(255, 16) );
|
|
||||||
REQUIRE( 0 == bx::alignUp(-1, 16) );
|
|
||||||
REQUIRE(-16 == bx::alignUp(-31, 16) );
|
|
||||||
|
|
||||||
REQUIRE( 0 == bx::alignUp( 0, 256) );
|
|
||||||
REQUIRE(256 == bx::alignUp( 1, 256) );
|
|
||||||
REQUIRE(256 == bx::alignUp( 15, 256) );
|
|
||||||
REQUIRE(256 == bx::alignUp(255, 256) );
|
|
||||||
REQUIRE(256 == bx::alignUp(256, 256) );
|
|
||||||
REQUIRE(256 == bx::alignUp(256, 256) );
|
|
||||||
REQUIRE(512 == bx::alignUp(511, 256) );
|
|
||||||
|
|
||||||
REQUIRE( 0 == bx::alignDown( 0, 16) );
|
|
||||||
REQUIRE( 0 == bx::alignDown( 1, 16) );
|
|
||||||
REQUIRE( 0 == bx::alignDown( 15, 16) );
|
|
||||||
REQUIRE( 16 == bx::alignDown( 16, 16) );
|
|
||||||
REQUIRE(240 == bx::alignDown(255, 16) );
|
|
||||||
REQUIRE(-16 == bx::alignDown(-1, 16) );
|
|
||||||
REQUIRE(-32 == bx::alignDown(-31, 16) );
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user