mirror of
https://github.com/bkaradzic/bx.git
synced 2026-10-23 09:11:03 +00:00
Added a constexpr double math surface, and made fromString exact. (#451)
This commit is contained in:
committed by
GitHub
parent
59a1e105b6
commit
89eb1775db
@@ -83,6 +83,51 @@ namespace bx
|
||||
/// Floating-point infinity.
|
||||
// constexpr float kFloatInfinity;
|
||||
|
||||
/// The reciprocal of ln(2). 1/ln(2)
|
||||
constexpr float kFloatInvLn2 = kInvLogNat2;
|
||||
|
||||
/// The reciprocal of ln(10). 1/ln(10)
|
||||
constexpr float kFloatInvLn10 = 1.0f/kLogNat10;
|
||||
|
||||
/// Leading part of ln(2), with the trailing mantissa bits cleared.
|
||||
constexpr float kFloatLn2Hi = 6.9314575195e-01f;
|
||||
|
||||
/// What is left of ln(2) after kFloatLn2Hi.
|
||||
constexpr float kFloatLn2Lo = 1.4286067653e-06f;
|
||||
|
||||
/// Largest argument exp can answer with a finite number.
|
||||
constexpr float kFloatExpOverflow = 88.7228394f;
|
||||
|
||||
/// Smallest argument exp can answer with a non-zero number.
|
||||
constexpr float kFloatExpUnderflow = -103.972084f;
|
||||
|
||||
/// Exponent of the square root of the scale expHalf splits its result by.
|
||||
constexpr int32_t kFloatExpHalfShift = 235;
|
||||
|
||||
/// Argument reduction expHalf pairs with kFloatExpHalfShift. ln(2)*kFloatExpHalfShift/2
|
||||
constexpr float kFloatExpHalfLn2 = 1.62889587431602213e+02f;
|
||||
|
||||
/// Below this the hyperbolic functions take their series instead of exp.
|
||||
constexpr float kFloatHypSmall = 0.0625f;
|
||||
|
||||
/// Above this exp(-_a) no longer contributes to sinh and cosh.
|
||||
constexpr float kFloatHypBig = 9.0f;
|
||||
|
||||
/// Above this half of exp(_a) overflows, and expHalf takes over.
|
||||
constexpr float kFloatHypNoFit = 88.0f;
|
||||
|
||||
/// Above this tanh is 1.
|
||||
constexpr float kFloatTanhLarge = 10.0f;
|
||||
|
||||
/// Below this the arc hyperbolic functions answer with the argument.
|
||||
constexpr float kFloatArcHypTiny = 0.000244140625f;
|
||||
|
||||
/// Above this asinh and acosh are log(_a) + ln(2).
|
||||
constexpr float kFloatArcHypHuge = 4096.0f;
|
||||
|
||||
/// Seed for the reciprocal square root iteration.
|
||||
constexpr uint32_t kFloatRsqrtSeed = UINT32_C(0x5f3759df);
|
||||
|
||||
///
|
||||
constexpr uint8_t kDoubleSignNumBits = 1;
|
||||
constexpr uint8_t kDoubleSignBitShift = 63;
|
||||
@@ -104,6 +149,51 @@ namespace bx
|
||||
// Double-precision floating-point infinity.
|
||||
// constexpr double kDoubleInfinity;
|
||||
|
||||
/// The reciprocal of ln(2). 1/ln(2)
|
||||
constexpr double kDoubleInvLn2 = 1.44269504088896338700;
|
||||
|
||||
/// The reciprocal of ln(10). 1/ln(10)
|
||||
constexpr double kDoubleInvLn10 = 4.34294481903251827651e-01;
|
||||
|
||||
/// Leading part of ln(2), with the trailing mantissa bits cleared.
|
||||
constexpr double kDoubleLn2Hi = 6.93147180369123816490e-01;
|
||||
|
||||
/// What is left of ln(2) after kDoubleLn2Hi.
|
||||
constexpr double kDoubleLn2Lo = 1.90821492927058770002e-10;
|
||||
|
||||
/// Largest argument exp can answer with a finite number.
|
||||
constexpr double kDoubleExpOverflow = 7.09782712893383973096e+02;
|
||||
|
||||
/// Smallest argument exp can answer with a non-zero number.
|
||||
constexpr double kDoubleExpUnderflow = -7.45133219101941108420e+02;
|
||||
|
||||
/// Exponent of the square root of the scale expHalf splits its result by.
|
||||
constexpr int32_t kDoubleExpHalfShift = 2043;
|
||||
|
||||
/// Argument reduction expHalf pairs with kDoubleExpHalfShift. ln(2)*kDoubleExpHalfShift/2
|
||||
constexpr double kDoubleExpHalfLn2 = 1.41609968988396828e+03;
|
||||
|
||||
/// Below this the hyperbolic functions take their series instead of exp.
|
||||
constexpr double kDoubleHypSmall = 0.03125;
|
||||
|
||||
/// Above this exp(-_a) no longer contributes to sinh and cosh.
|
||||
constexpr double kDoubleHypBig = 22.0;
|
||||
|
||||
/// Above this half of exp(_a) overflows, and expHalf takes over.
|
||||
constexpr double kDoubleHypNoFit = 709.0;
|
||||
|
||||
/// Above this tanh is 1.
|
||||
constexpr double kDoubleTanhLarge = 20.0;
|
||||
|
||||
/// Below this the arc hyperbolic functions answer with the argument.
|
||||
constexpr double kDoubleArcHypTiny = 3.72529029846191406250e-09;
|
||||
|
||||
/// Above this asinh and acosh are log(_a) + ln(2).
|
||||
constexpr double kDoubleArcHypHuge = 2.68435456e+08;
|
||||
|
||||
/// Seed for the reciprocal square root iteration.
|
||||
constexpr uint64_t kDoubleRsqrtSeed = UINT64_C(0x5fe6eb50c7b537a9);
|
||||
|
||||
} // namespace bx
|
||||
|
||||
#endif // BX_CONSTANTS_H_HEADER_GUARD
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -17,6 +17,7 @@ namespace bx
|
||||
BX_ALIGN_DECL(16, struct) simd128_i64_ref_t { int64_t i64[2]; };
|
||||
BX_ALIGN_DECL(16, struct) simd128_u8_ref_t { uint8_t u8[16]; };
|
||||
BX_ALIGN_DECL(16, struct) simd128_u16_ref_t { uint16_t u16[8]; };
|
||||
BX_ALIGN_DECL(16, struct) simd128_u32_ref_t { uint32_t u32[4]; };
|
||||
BX_ALIGN_DECL(16, struct) simd128_u64_ref_t { uint64_t u64[2]; };
|
||||
|
||||
#if BX_SIMD_LANGEXT
|
||||
@@ -672,15 +673,15 @@ namespace bx
|
||||
inline BX_CONSTEXPR_FUNC simd128_ref_t simd128_i32_add(simd128_ref_t _a, simd128_ref_t _b)
|
||||
{
|
||||
#if BX_SIMD_LANGEXT
|
||||
const simd128_i32_langext_t a = bitCast<simd128_i32_langext_t>(_a);
|
||||
const simd128_i32_langext_t b = bitCast<simd128_i32_langext_t>(_b);
|
||||
const simd128_i32_langext_t sum = a + b;
|
||||
const simd128_u32_langext_t a = bitCast<simd128_u32_langext_t>(_a);
|
||||
const simd128_u32_langext_t b = bitCast<simd128_u32_langext_t>(_b);
|
||||
const simd128_u32_langext_t sum = a + b;
|
||||
const simd128_ref_t result = bitCast<simd128_ref_t>(sum);
|
||||
return result;
|
||||
#else
|
||||
const simd128_i32_ref_t a = bitCast<simd128_i32_ref_t>(_a);
|
||||
const simd128_i32_ref_t b = bitCast<simd128_i32_ref_t>(_b);
|
||||
const simd128_i32_ref_t result = { { a.i32[0] + b.i32[0], a.i32[1] + b.i32[1], a.i32[2] + b.i32[2], a.i32[3] + b.i32[3] } };
|
||||
const simd128_u32_ref_t a = bitCast<simd128_u32_ref_t>(_a);
|
||||
const simd128_u32_ref_t b = bitCast<simd128_u32_ref_t>(_b);
|
||||
const simd128_u32_ref_t result = { { a.u32[0] + b.u32[0], a.u32[1] + b.u32[1], a.u32[2] + b.u32[2], a.u32[3] + b.u32[3] } };
|
||||
return bitCast<simd128_ref_t>(result);
|
||||
#endif // BX_SIMD_LANGEXT
|
||||
}
|
||||
@@ -689,15 +690,15 @@ namespace bx
|
||||
inline BX_CONSTEXPR_FUNC simd128_ref_t simd128_i32_sub(simd128_ref_t _a, simd128_ref_t _b)
|
||||
{
|
||||
#if BX_SIMD_LANGEXT
|
||||
const simd128_i32_langext_t a = bitCast<simd128_i32_langext_t>(_a);
|
||||
const simd128_i32_langext_t b = bitCast<simd128_i32_langext_t>(_b);
|
||||
const simd128_i32_langext_t diff = a - b;
|
||||
const simd128_u32_langext_t a = bitCast<simd128_u32_langext_t>(_a);
|
||||
const simd128_u32_langext_t b = bitCast<simd128_u32_langext_t>(_b);
|
||||
const simd128_u32_langext_t diff = a - b;
|
||||
const simd128_ref_t result = bitCast<simd128_ref_t>(diff);
|
||||
return result;
|
||||
#else
|
||||
const simd128_i32_ref_t a = bitCast<simd128_i32_ref_t>(_a);
|
||||
const simd128_i32_ref_t b = bitCast<simd128_i32_ref_t>(_b);
|
||||
const simd128_i32_ref_t result = { { a.i32[0] - b.i32[0], a.i32[1] - b.i32[1], a.i32[2] - b.i32[2], a.i32[3] - b.i32[3] } };
|
||||
const simd128_u32_ref_t a = bitCast<simd128_u32_ref_t>(_a);
|
||||
const simd128_u32_ref_t b = bitCast<simd128_u32_ref_t>(_b);
|
||||
const simd128_u32_ref_t result = { { a.u32[0] - b.u32[0], a.u32[1] - b.u32[1], a.u32[2] - b.u32[2], a.u32[3] - b.u32[3] } };
|
||||
return bitCast<simd128_ref_t>(result);
|
||||
#endif // BX_SIMD_LANGEXT
|
||||
}
|
||||
@@ -985,16 +986,16 @@ namespace bx
|
||||
inline BX_CONSTEXPR_FUNC simd128_ref_t simd128_i16_add(simd128_ref_t _a, simd128_ref_t _b)
|
||||
{
|
||||
#if BX_SIMD_LANGEXT
|
||||
const simd128_i16_langext_t a = bitCast<simd128_i16_langext_t>(_a);
|
||||
const simd128_i16_langext_t b = bitCast<simd128_i16_langext_t>(_b);
|
||||
const simd128_i16_langext_t sum = a + b;
|
||||
const simd128_u16_langext_t a = bitCast<simd128_u16_langext_t>(_a);
|
||||
const simd128_u16_langext_t b = bitCast<simd128_u16_langext_t>(_b);
|
||||
const simd128_u16_langext_t sum = a + b;
|
||||
const simd128_ref_t result = bitCast<simd128_ref_t>(sum);
|
||||
return result;
|
||||
#else
|
||||
const simd128_i16_ref_t a = bitCast<simd128_i16_ref_t>(_a);
|
||||
const simd128_i16_ref_t b = bitCast<simd128_i16_ref_t>(_b);
|
||||
simd128_i16_ref_t result;
|
||||
for (int ii = 0; ii < 8; ++ii) { result.i16[ii] = a.i16[ii] + b.i16[ii]; }
|
||||
const simd128_u16_ref_t a = bitCast<simd128_u16_ref_t>(_a);
|
||||
const simd128_u16_ref_t b = bitCast<simd128_u16_ref_t>(_b);
|
||||
simd128_u16_ref_t result;
|
||||
for (int ii = 0; ii < 8; ++ii) { result.u16[ii] = a.u16[ii] + b.u16[ii]; }
|
||||
return bitCast<simd128_ref_t>(result);
|
||||
#endif // BX_SIMD_LANGEXT
|
||||
}
|
||||
@@ -1003,16 +1004,16 @@ namespace bx
|
||||
inline BX_CONSTEXPR_FUNC simd128_ref_t simd128_i16_sub(simd128_ref_t _a, simd128_ref_t _b)
|
||||
{
|
||||
#if BX_SIMD_LANGEXT
|
||||
const simd128_i16_langext_t a = bitCast<simd128_i16_langext_t>(_a);
|
||||
const simd128_i16_langext_t b = bitCast<simd128_i16_langext_t>(_b);
|
||||
const simd128_i16_langext_t diff = a - b;
|
||||
const simd128_u16_langext_t a = bitCast<simd128_u16_langext_t>(_a);
|
||||
const simd128_u16_langext_t b = bitCast<simd128_u16_langext_t>(_b);
|
||||
const simd128_u16_langext_t diff = a - b;
|
||||
const simd128_ref_t result = bitCast<simd128_ref_t>(diff);
|
||||
return result;
|
||||
#else
|
||||
const simd128_i16_ref_t a = bitCast<simd128_i16_ref_t>(_a);
|
||||
const simd128_i16_ref_t b = bitCast<simd128_i16_ref_t>(_b);
|
||||
simd128_i16_ref_t result;
|
||||
for (int ii = 0; ii < 8; ++ii) { result.i16[ii] = a.i16[ii] - b.i16[ii]; }
|
||||
const simd128_u16_ref_t a = bitCast<simd128_u16_ref_t>(_a);
|
||||
const simd128_u16_ref_t b = bitCast<simd128_u16_ref_t>(_b);
|
||||
simd128_u16_ref_t result;
|
||||
for (int ii = 0; ii < 8; ++ii) { result.u16[ii] = a.u16[ii] - b.u16[ii]; }
|
||||
return bitCast<simd128_ref_t>(result);
|
||||
#endif // BX_SIMD_LANGEXT
|
||||
}
|
||||
@@ -1021,16 +1022,16 @@ namespace bx
|
||||
inline BX_CONSTEXPR_FUNC simd128_ref_t simd128_i16_mullo(simd128_ref_t _a, simd128_ref_t _b)
|
||||
{
|
||||
#if BX_SIMD_LANGEXT
|
||||
const simd128_i16_langext_t a = bitCast<simd128_i16_langext_t>(_a);
|
||||
const simd128_i16_langext_t b = bitCast<simd128_i16_langext_t>(_b);
|
||||
const simd128_i16_langext_t prod = a * b;
|
||||
const simd128_u16_langext_t a = bitCast<simd128_u16_langext_t>(_a);
|
||||
const simd128_u16_langext_t b = bitCast<simd128_u16_langext_t>(_b);
|
||||
const simd128_u16_langext_t prod = a * b;
|
||||
const simd128_ref_t result = bitCast<simd128_ref_t>(prod);
|
||||
return result;
|
||||
#else
|
||||
const simd128_i16_ref_t a = bitCast<simd128_i16_ref_t>(_a);
|
||||
const simd128_i16_ref_t b = bitCast<simd128_i16_ref_t>(_b);
|
||||
simd128_i16_ref_t result;
|
||||
for (int ii = 0; ii < 8; ++ii) { result.i16[ii] = (int16_t)(a.i16[ii] * b.i16[ii]); }
|
||||
const simd128_u16_ref_t a = bitCast<simd128_u16_ref_t>(_a);
|
||||
const simd128_u16_ref_t b = bitCast<simd128_u16_ref_t>(_b);
|
||||
simd128_u16_ref_t result;
|
||||
for (int ii = 0; ii < 8; ++ii) { result.u16[ii] = uint16_t(a.u16[ii] * b.u16[ii]); }
|
||||
return bitCast<simd128_ref_t>(result);
|
||||
#endif // BX_SIMD_LANGEXT
|
||||
}
|
||||
@@ -1103,16 +1104,16 @@ namespace bx
|
||||
inline BX_CONSTEXPR_FUNC simd128_ref_t simd128_i8_add(simd128_ref_t _a, simd128_ref_t _b)
|
||||
{
|
||||
#if BX_SIMD_LANGEXT
|
||||
const simd128_i8_langext_t a = bitCast<simd128_i8_langext_t>(_a);
|
||||
const simd128_i8_langext_t b = bitCast<simd128_i8_langext_t>(_b);
|
||||
const simd128_i8_langext_t sum = a + b;
|
||||
const simd128_u8_langext_t a = bitCast<simd128_u8_langext_t>(_a);
|
||||
const simd128_u8_langext_t b = bitCast<simd128_u8_langext_t>(_b);
|
||||
const simd128_u8_langext_t sum = a + b;
|
||||
const simd128_ref_t result = bitCast<simd128_ref_t>(sum);
|
||||
return result;
|
||||
#else
|
||||
const simd128_i8_ref_t a = bitCast<simd128_i8_ref_t>(_a);
|
||||
const simd128_i8_ref_t b = bitCast<simd128_i8_ref_t>(_b);
|
||||
simd128_i8_ref_t result;
|
||||
for (int ii = 0; ii < 16; ++ii) { result.i8[ii] = a.i8[ii] + b.i8[ii]; }
|
||||
const simd128_u8_ref_t a = bitCast<simd128_u8_ref_t>(_a);
|
||||
const simd128_u8_ref_t b = bitCast<simd128_u8_ref_t>(_b);
|
||||
simd128_u8_ref_t result;
|
||||
for (int ii = 0; ii < 16; ++ii) { result.u8[ii] = a.u8[ii] + b.u8[ii]; }
|
||||
return bitCast<simd128_ref_t>(result);
|
||||
#endif // BX_SIMD_LANGEXT
|
||||
}
|
||||
@@ -1121,16 +1122,16 @@ namespace bx
|
||||
inline BX_CONSTEXPR_FUNC simd128_ref_t simd128_i8_sub(simd128_ref_t _a, simd128_ref_t _b)
|
||||
{
|
||||
#if BX_SIMD_LANGEXT
|
||||
const simd128_i8_langext_t a = bitCast<simd128_i8_langext_t>(_a);
|
||||
const simd128_i8_langext_t b = bitCast<simd128_i8_langext_t>(_b);
|
||||
const simd128_i8_langext_t diff = a - b;
|
||||
const simd128_u8_langext_t a = bitCast<simd128_u8_langext_t>(_a);
|
||||
const simd128_u8_langext_t b = bitCast<simd128_u8_langext_t>(_b);
|
||||
const simd128_u8_langext_t diff = a - b;
|
||||
const simd128_ref_t result = bitCast<simd128_ref_t>(diff);
|
||||
return result;
|
||||
#else
|
||||
const simd128_i8_ref_t a = bitCast<simd128_i8_ref_t>(_a);
|
||||
const simd128_i8_ref_t b = bitCast<simd128_i8_ref_t>(_b);
|
||||
simd128_i8_ref_t result;
|
||||
for (int ii = 0; ii < 16; ++ii) { result.i8[ii] = a.i8[ii] - b.i8[ii]; }
|
||||
const simd128_u8_ref_t a = bitCast<simd128_u8_ref_t>(_a);
|
||||
const simd128_u8_ref_t b = bitCast<simd128_u8_ref_t>(_b);
|
||||
simd128_u8_ref_t result;
|
||||
for (int ii = 0; ii < 16; ++ii) { result.u8[ii] = a.u8[ii] - b.u8[ii]; }
|
||||
return bitCast<simd128_ref_t>(result);
|
||||
#endif // BX_SIMD_LANGEXT
|
||||
}
|
||||
@@ -1870,15 +1871,15 @@ namespace bx
|
||||
inline BX_CONSTEXPR_FUNC simd128_ref_t simd128_i64_add(simd128_ref_t _a, simd128_ref_t _b)
|
||||
{
|
||||
#if BX_SIMD_LANGEXT
|
||||
const simd128_i64_langext_t a = bitCast<simd128_i64_langext_t>(_a);
|
||||
const simd128_i64_langext_t b = bitCast<simd128_i64_langext_t>(_b);
|
||||
const simd128_i64_langext_t sum = a + b;
|
||||
const simd128_u64_langext_t a = bitCast<simd128_u64_langext_t>(_a);
|
||||
const simd128_u64_langext_t b = bitCast<simd128_u64_langext_t>(_b);
|
||||
const simd128_u64_langext_t sum = a + b;
|
||||
const simd128_ref_t result = bitCast<simd128_ref_t>(sum);
|
||||
return result;
|
||||
#else
|
||||
const simd128_i64_ref_t a = bitCast<simd128_i64_ref_t>(_a);
|
||||
const simd128_i64_ref_t b = bitCast<simd128_i64_ref_t>(_b);
|
||||
const simd128_i64_ref_t result = { { a.i64[0] + b.i64[0], a.i64[1] + b.i64[1] } };
|
||||
const simd128_u64_ref_t a = bitCast<simd128_u64_ref_t>(_a);
|
||||
const simd128_u64_ref_t b = bitCast<simd128_u64_ref_t>(_b);
|
||||
const simd128_u64_ref_t result = { { a.u64[0] + b.u64[0], a.u64[1] + b.u64[1] } };
|
||||
return bitCast<simd128_ref_t>(result);
|
||||
#endif // BX_SIMD_LANGEXT
|
||||
}
|
||||
@@ -1887,15 +1888,15 @@ namespace bx
|
||||
inline BX_CONSTEXPR_FUNC simd128_ref_t simd128_i64_sub(simd128_ref_t _a, simd128_ref_t _b)
|
||||
{
|
||||
#if BX_SIMD_LANGEXT
|
||||
const simd128_i64_langext_t a = bitCast<simd128_i64_langext_t>(_a);
|
||||
const simd128_i64_langext_t b = bitCast<simd128_i64_langext_t>(_b);
|
||||
const simd128_i64_langext_t diff = a - b;
|
||||
const simd128_u64_langext_t a = bitCast<simd128_u64_langext_t>(_a);
|
||||
const simd128_u64_langext_t b = bitCast<simd128_u64_langext_t>(_b);
|
||||
const simd128_u64_langext_t diff = a - b;
|
||||
const simd128_ref_t result = bitCast<simd128_ref_t>(diff);
|
||||
return result;
|
||||
#else
|
||||
const simd128_i64_ref_t a = bitCast<simd128_i64_ref_t>(_a);
|
||||
const simd128_i64_ref_t b = bitCast<simd128_i64_ref_t>(_b);
|
||||
const simd128_i64_ref_t result = { { a.i64[0] - b.i64[0], a.i64[1] - b.i64[1] } };
|
||||
const simd128_u64_ref_t a = bitCast<simd128_u64_ref_t>(_a);
|
||||
const simd128_u64_ref_t b = bitCast<simd128_u64_ref_t>(_b);
|
||||
const simd128_u64_ref_t result = { { a.u64[0] - b.u64[0], a.u64[1] - b.u64[1] } };
|
||||
return bitCast<simd128_ref_t>(result);
|
||||
#endif // BX_SIMD_LANGEXT
|
||||
}
|
||||
|
||||
@@ -520,9 +520,9 @@ namespace bx
|
||||
inline BX_CONSTEXPR_FUNC simd256_ref_t simd256_i32_add(simd256_ref_t _a, simd256_ref_t _b)
|
||||
{
|
||||
#if BX_SIMD256_LANGEXT
|
||||
const simd256_i32_langext_t a = bitCast<simd256_i32_langext_t>(_a);
|
||||
const simd256_i32_langext_t b = bitCast<simd256_i32_langext_t>(_b);
|
||||
const simd256_i32_langext_t sum = a + b;
|
||||
const simd256_u32_langext_t a = bitCast<simd256_u32_langext_t>(_a);
|
||||
const simd256_u32_langext_t b = bitCast<simd256_u32_langext_t>(_b);
|
||||
const simd256_u32_langext_t sum = a + b;
|
||||
const simd256_ref_t result = bitCast<simd256_ref_t>(sum);
|
||||
return result;
|
||||
#else
|
||||
@@ -537,9 +537,9 @@ namespace bx
|
||||
inline BX_CONSTEXPR_FUNC simd256_ref_t simd256_i32_sub(simd256_ref_t _a, simd256_ref_t _b)
|
||||
{
|
||||
#if BX_SIMD256_LANGEXT
|
||||
const simd256_i32_langext_t a = bitCast<simd256_i32_langext_t>(_a);
|
||||
const simd256_i32_langext_t b = bitCast<simd256_i32_langext_t>(_b);
|
||||
const simd256_i32_langext_t diff = a - b;
|
||||
const simd256_u32_langext_t a = bitCast<simd256_u32_langext_t>(_a);
|
||||
const simd256_u32_langext_t b = bitCast<simd256_u32_langext_t>(_b);
|
||||
const simd256_u32_langext_t diff = a - b;
|
||||
const simd256_ref_t result = bitCast<simd256_ref_t>(diff);
|
||||
return result;
|
||||
#else
|
||||
@@ -554,8 +554,8 @@ namespace bx
|
||||
inline BX_CONST_FUNC simd256_ref_t simd256_i32_neg(simd256_ref_t _a)
|
||||
{
|
||||
#if BX_SIMD256_LANGEXT
|
||||
const simd256_i32_langext_t a = bitCast<simd256_i32_langext_t>(_a);
|
||||
const simd256_i32_langext_t neg = -a;
|
||||
const simd256_u32_langext_t a = bitCast<simd256_u32_langext_t>(_a);
|
||||
const simd256_u32_langext_t neg = -a;
|
||||
const simd256_ref_t result = bitCast<simd256_ref_t>(neg);
|
||||
return result;
|
||||
#else
|
||||
@@ -1315,9 +1315,9 @@ namespace bx
|
||||
inline BX_CONSTEXPR_FUNC simd256_ref_t simd256_i64_add(simd256_ref_t _a, simd256_ref_t _b)
|
||||
{
|
||||
#if BX_SIMD256_LANGEXT
|
||||
const simd256_i64_langext_t a = bitCast<simd256_i64_langext_t>(_a);
|
||||
const simd256_i64_langext_t b = bitCast<simd256_i64_langext_t>(_b);
|
||||
const simd256_i64_langext_t sum = a + b;
|
||||
const simd256_u64_langext_t a = bitCast<simd256_u64_langext_t>(_a);
|
||||
const simd256_u64_langext_t b = bitCast<simd256_u64_langext_t>(_b);
|
||||
const simd256_u64_langext_t sum = a + b;
|
||||
const simd256_ref_t result = bitCast<simd256_ref_t>(sum);
|
||||
return result;
|
||||
#else
|
||||
@@ -1332,9 +1332,9 @@ namespace bx
|
||||
inline BX_CONSTEXPR_FUNC simd256_ref_t simd256_i64_sub(simd256_ref_t _a, simd256_ref_t _b)
|
||||
{
|
||||
#if BX_SIMD256_LANGEXT
|
||||
const simd256_i64_langext_t a = bitCast<simd256_i64_langext_t>(_a);
|
||||
const simd256_i64_langext_t b = bitCast<simd256_i64_langext_t>(_b);
|
||||
const simd256_i64_langext_t diff = a - b;
|
||||
const simd256_u64_langext_t a = bitCast<simd256_u64_langext_t>(_a);
|
||||
const simd256_u64_langext_t b = bitCast<simd256_u64_langext_t>(_b);
|
||||
const simd256_u64_langext_t diff = a - b;
|
||||
const simd256_ref_t result = bitCast<simd256_ref_t>(diff);
|
||||
return result;
|
||||
#else
|
||||
@@ -1383,9 +1383,9 @@ namespace bx
|
||||
inline BX_CONSTEXPR_FUNC simd256_ref_t simd256_i16_add(simd256_ref_t _a, simd256_ref_t _b)
|
||||
{
|
||||
#if BX_SIMD256_LANGEXT
|
||||
const simd256_i16_langext_t a = bitCast<simd256_i16_langext_t>(_a);
|
||||
const simd256_i16_langext_t b = bitCast<simd256_i16_langext_t>(_b);
|
||||
const simd256_i16_langext_t sum = a + b;
|
||||
const simd256_u16_langext_t a = bitCast<simd256_u16_langext_t>(_a);
|
||||
const simd256_u16_langext_t b = bitCast<simd256_u16_langext_t>(_b);
|
||||
const simd256_u16_langext_t sum = a + b;
|
||||
const simd256_ref_t result = bitCast<simd256_ref_t>(sum);
|
||||
return result;
|
||||
#else
|
||||
@@ -1400,9 +1400,9 @@ namespace bx
|
||||
inline BX_CONSTEXPR_FUNC simd256_ref_t simd256_i16_sub(simd256_ref_t _a, simd256_ref_t _b)
|
||||
{
|
||||
#if BX_SIMD256_LANGEXT
|
||||
const simd256_i16_langext_t a = bitCast<simd256_i16_langext_t>(_a);
|
||||
const simd256_i16_langext_t b = bitCast<simd256_i16_langext_t>(_b);
|
||||
const simd256_i16_langext_t diff = a - b;
|
||||
const simd256_u16_langext_t a = bitCast<simd256_u16_langext_t>(_a);
|
||||
const simd256_u16_langext_t b = bitCast<simd256_u16_langext_t>(_b);
|
||||
const simd256_u16_langext_t diff = a - b;
|
||||
const simd256_ref_t result = bitCast<simd256_ref_t>(diff);
|
||||
return result;
|
||||
#else
|
||||
@@ -1417,9 +1417,9 @@ namespace bx
|
||||
inline BX_CONSTEXPR_FUNC simd256_ref_t simd256_i16_mullo(simd256_ref_t _a, simd256_ref_t _b)
|
||||
{
|
||||
#if BX_SIMD256_LANGEXT
|
||||
const simd256_i16_langext_t a = bitCast<simd256_i16_langext_t>(_a);
|
||||
const simd256_i16_langext_t b = bitCast<simd256_i16_langext_t>(_b);
|
||||
const simd256_i16_langext_t prod = a * b;
|
||||
const simd256_u16_langext_t a = bitCast<simd256_u16_langext_t>(_a);
|
||||
const simd256_u16_langext_t b = bitCast<simd256_u16_langext_t>(_b);
|
||||
const simd256_u16_langext_t prod = a * b;
|
||||
const simd256_ref_t result = bitCast<simd256_ref_t>(prod);
|
||||
return result;
|
||||
#else
|
||||
@@ -1483,9 +1483,9 @@ namespace bx
|
||||
inline BX_CONSTEXPR_FUNC simd256_ref_t simd256_i8_add(simd256_ref_t _a, simd256_ref_t _b)
|
||||
{
|
||||
#if BX_SIMD256_LANGEXT
|
||||
const simd256_i8_langext_t a = bitCast<simd256_i8_langext_t>(_a);
|
||||
const simd256_i8_langext_t b = bitCast<simd256_i8_langext_t>(_b);
|
||||
const simd256_i8_langext_t sum = a + b;
|
||||
const simd256_u8_langext_t a = bitCast<simd256_u8_langext_t>(_a);
|
||||
const simd256_u8_langext_t b = bitCast<simd256_u8_langext_t>(_b);
|
||||
const simd256_u8_langext_t sum = a + b;
|
||||
const simd256_ref_t result = bitCast<simd256_ref_t>(sum);
|
||||
return result;
|
||||
#else
|
||||
@@ -1500,9 +1500,9 @@ namespace bx
|
||||
inline BX_CONSTEXPR_FUNC simd256_ref_t simd256_i8_sub(simd256_ref_t _a, simd256_ref_t _b)
|
||||
{
|
||||
#if BX_SIMD256_LANGEXT
|
||||
const simd256_i8_langext_t a = bitCast<simd256_i8_langext_t>(_a);
|
||||
const simd256_i8_langext_t b = bitCast<simd256_i8_langext_t>(_b);
|
||||
const simd256_i8_langext_t diff = a - b;
|
||||
const simd256_u8_langext_t a = bitCast<simd256_u8_langext_t>(_a);
|
||||
const simd256_u8_langext_t b = bitCast<simd256_u8_langext_t>(_b);
|
||||
const simd256_u8_langext_t diff = a - b;
|
||||
const simd256_ref_t result = bitCast<simd256_ref_t>(diff);
|
||||
return result;
|
||||
#else
|
||||
|
||||
@@ -516,22 +516,50 @@ namespace bx
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_f32_ldexp_ni(Ty _a, Ty _b)
|
||||
{
|
||||
const Ty signexpmask = simd_splat<Ty>(uint32_t(kFloatSignMask | kFloatExponentMask) );
|
||||
const Ty mantmask = simd_splat<Ty>(kFloatMantissaMask);
|
||||
const Ty masked = simd_and(_a, signexpmask);
|
||||
const Ty expsign0 = simd_x32_sra(masked, kFloatExponentBitShift);
|
||||
const Ty tmp = simd_i32_add(expsign0, _b);
|
||||
const Ty expsign1 = simd_x32_sll(tmp, kFloatExponentBitShift);
|
||||
const Ty mantissa = simd_and(_a, mantmask);
|
||||
const Ty result = simd_or(mantissa, expsign1);
|
||||
constexpr int32_t kMinStep = 1 - int32_t(kFloatExponentBias);
|
||||
constexpr int32_t kMaxStep = int32_t(kFloatExponentBias);
|
||||
constexpr int32_t kLimit = 2*int32_t(kFloatExponentBias) + int32_t(kFloatMantissaNumBits) + 2;
|
||||
|
||||
const Ty minStep = simd_splat<Ty>(uint32_t(kMinStep) );
|
||||
const Ty maxStep = simd_splat<Ty>(uint32_t(kMaxStep) );
|
||||
const Ty limitHi = simd_splat<Ty>(uint32_t(kLimit) );
|
||||
const Ty limitLo = simd_splat<Ty>(uint32_t(-kLimit) );
|
||||
const Ty bias = simd_splat<Ty>(uint32_t(kFloatExponentBias) );
|
||||
|
||||
const Ty totalLo = simd_i32_max(_b, limitLo);
|
||||
const Ty total = simd_i32_min(totalLo, limitHi);
|
||||
|
||||
const Ty step0Lo = simd_i32_max(total, minStep);
|
||||
const Ty step0 = simd_i32_min(step0Lo, maxStep);
|
||||
const Ty rest0 = simd_i32_sub(total, step0);
|
||||
|
||||
const Ty step1Lo = simd_i32_max(rest0, minStep);
|
||||
const Ty step1 = simd_i32_min(step1Lo, maxStep);
|
||||
const Ty rest1 = simd_i32_sub(rest0, step1);
|
||||
|
||||
const Ty step2Lo = simd_i32_max(rest1, minStep);
|
||||
const Ty step2 = simd_i32_min(step2Lo, maxStep);
|
||||
|
||||
const Ty exp0 = simd_i32_add(step0, bias);
|
||||
const Ty exp1 = simd_i32_add(step1, bias);
|
||||
const Ty exp2 = simd_i32_add(step2, bias);
|
||||
|
||||
const Ty scale0 = simd_x32_sll(exp0, kFloatExponentBitShift);
|
||||
const Ty scale1 = simd_x32_sll(exp1, kFloatExponentBitShift);
|
||||
const Ty scale2 = simd_x32_sll(exp2, kFloatExponentBitShift);
|
||||
|
||||
const Ty tmp0 = simd_f32_mul(_a, scale0);
|
||||
const Ty tmp1 = simd_f32_mul(tmp0, scale1);
|
||||
const Ty result = simd_f32_mul(tmp1, scale2);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
BX_FP_PRECISE_BEGIN()
|
||||
|
||||
/// cos(_a) for _bias 0, sin(_a) for _bias 3, matching bx::sinCosPiHalf.
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_f32_cos_ni(Ty _a)
|
||||
BX_SIMD_INLINE Ty simd_f32_sincos_pi_half_ni(Ty _a, uint32_t _bias)
|
||||
{
|
||||
const Ty two_over_pi = simd_splat<Ty>(2.0f * kInvPi);
|
||||
const Ty pi_half = simd_splat<Ty>(kPiHalf);
|
||||
@@ -540,8 +568,10 @@ BX_FP_PRECISE_BEGIN()
|
||||
const Ty tmp_rp = simd_f32_mul(real, pi_half);
|
||||
const Ty xx = simd_f32_sub(_a, tmp_rp);
|
||||
const Ty ireal = simd_f32_ftoi_trunc(real);
|
||||
const Ty ibias = simd_splat<Ty>(_bias);
|
||||
const Ty ibiased = simd_i32_add(ireal, ibias);
|
||||
const Ty three = simd_splat<Ty>(uint32_t(3) );
|
||||
const Ty ibits = simd_and(ireal, three);
|
||||
const Ty ibits = simd_and(ibiased, three);
|
||||
const Ty ione = simd_splat<Ty>(uint32_t(1) );
|
||||
const Ty izero = simd_zero<Ty>();
|
||||
const Ty bit0 = simd_and(ibits, ione);
|
||||
@@ -579,13 +609,16 @@ BX_FP_PRECISE_BEGIN()
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_f32_cos_ni(Ty _a)
|
||||
{
|
||||
return simd_f32_sincos_pi_half_ni(_a, 0);
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_f32_sin_ni(Ty _a)
|
||||
{
|
||||
const Ty pi_half = simd_splat<Ty>(kPiHalf);
|
||||
const Ty shifted = simd_f32_sub(_a, pi_half);
|
||||
const Ty result = simd_f32_cos(shifted);
|
||||
return result;
|
||||
return simd_f32_sincos_pi_half_ni(_a, 3);
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
@@ -745,12 +778,52 @@ BX_FP_PRECISE_BEGIN()
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_f32_sinh_ni(Ty _a)
|
||||
{
|
||||
const Ty half = simd_splat<Ty>(0.5f);
|
||||
const Ty na = simd_f32_neg(_a);
|
||||
const Ty ea = simd_f32_exp(_a);
|
||||
const Ty ena = simd_f32_exp(na);
|
||||
const Ty diff = simd_f32_sub(ea, ena);
|
||||
const Ty result = simd_f32_mul(half, diff);
|
||||
const Ty half = simd_splat<Ty>(0.5f);
|
||||
const Ty one = simd_splat<Ty>(1.0f);
|
||||
const Ty small = simd_splat<Ty>(0.0625f);
|
||||
const Ty big = simd_splat<Ty>(9.0f);
|
||||
const Ty noFit = simd_splat<Ty>(88.0f);
|
||||
const Ty kC3 = simd_splat<Ty>(1.0f/6.0f);
|
||||
const Ty kC5 = simd_splat<Ty>(1.0f/120.0f);
|
||||
const Ty kC7 = simd_splat<Ty>(1.0f/5040.0f);
|
||||
const Ty signmask = simd_splat<Ty>(uint32_t(kFloatSignMask) );
|
||||
|
||||
const Ty absA = simd_f32_abs(_a);
|
||||
const Ty nabsA = simd_f32_neg(absA);
|
||||
|
||||
const Ty zz = simd_f32_mul(absA, absA);
|
||||
const Ty inn0 = simd_f32_madd(zz, kC7, kC5);
|
||||
const Ty inn1 = simd_f32_madd(zz, inn0, kC3);
|
||||
const Ty poly = simd_f32_madd(zz, inn1, one);
|
||||
const Ty magSmall = simd_f32_mul(absA, poly);
|
||||
|
||||
const Ty ep = simd_f32_exp(absA);
|
||||
const Ty en = simd_f32_exp(nabsA);
|
||||
const Ty diff = simd_f32_sub(ep, en);
|
||||
const Ty magMid = simd_f32_mul(half, diff);
|
||||
|
||||
const Ty magBig = simd_f32_mul(half, ep);
|
||||
|
||||
constexpr int32_t kShift = 235;
|
||||
constexpr uint32_t kBits = uint32_t(int32_t(kFloatExponentBias) + kShift/2) << kFloatExponentBitShift;
|
||||
|
||||
const Ty kKLn2 = simd_splat<Ty>(1.62889587431602213e+02f);
|
||||
const Ty kScale = simd_splat<Ty>(kBits);
|
||||
const Ty reduced = simd_f32_sub(absA, kKLn2);
|
||||
const Ty ee = simd_f32_exp(reduced);
|
||||
const Ty once = simd_f32_mul(ee, kScale);
|
||||
const Ty magNoFit = simd_f32_mul(once, kScale);
|
||||
|
||||
const Ty smallMask = simd_f32_cmplt(absA, small);
|
||||
const Ty bigMask = simd_f32_cmplt(absA, big);
|
||||
const Ty noFitMask = simd_f32_cmplt(absA, noFit);
|
||||
const Ty mag0 = simd_selb(noFitMask, magBig, magNoFit);
|
||||
const Ty mag1 = simd_selb(bigMask, magMid, mag0);
|
||||
const Ty magnitude = simd_selb(smallMask, magSmall, mag1);
|
||||
|
||||
const Ty sign = simd_and(_a, signmask);
|
||||
const Ty result = simd_or(magnitude, sign);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -769,38 +842,82 @@ BX_FP_PRECISE_BEGIN()
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_f32_tanh_ni(Ty _a)
|
||||
{
|
||||
const Ty one = simd_splat<Ty>(1.0f);
|
||||
const Ty two = simd_splat<Ty>(2.0f);
|
||||
const Ty twoA = simd_f32_mul(two, _a);
|
||||
const Ty tmp0 = simd_f32_exp(twoA);
|
||||
const Ty tmp1 = simd_f32_sub(tmp0, one);
|
||||
const Ty tmp2 = simd_f32_add(tmp0, one);
|
||||
const Ty result = simd_f32_div(tmp1, tmp2);
|
||||
const Ty one = simd_splat<Ty>(1.0f);
|
||||
const Ty two = simd_splat<Ty>(2.0f);
|
||||
const Ty small = simd_splat<Ty>(0.0625f);
|
||||
const Ty large = simd_splat<Ty>(10.0f);
|
||||
const Ty kC3 = simd_splat<Ty>( -1.0f/3.0f);
|
||||
const Ty kC5 = simd_splat<Ty>( 2.0f/15.0f);
|
||||
const Ty kC7 = simd_splat<Ty>(-17.0f/315.0f);
|
||||
const Ty signmask = simd_splat<Ty>(uint32_t(kFloatSignMask) );
|
||||
|
||||
const Ty absA = simd_f32_abs(_a);
|
||||
const Ty zz = simd_f32_mul(absA, absA);
|
||||
const Ty inn0 = simd_f32_madd(zz, kC7, kC5);
|
||||
const Ty inn1 = simd_f32_madd(zz, inn0, kC3);
|
||||
const Ty poly = simd_f32_madd(zz, inn1, one);
|
||||
const Ty magSmall = simd_f32_mul(absA, poly);
|
||||
|
||||
const Ty twoA = simd_f32_mul(two, absA);
|
||||
const Ty ee = simd_f32_exp(twoA);
|
||||
const Ty num = simd_f32_sub(ee, one);
|
||||
const Ty den = simd_f32_add(ee, one);
|
||||
const Ty magMid = simd_f32_div(num, den);
|
||||
|
||||
const Ty smallMask = simd_f32_cmplt(absA, small);
|
||||
const Ty largeMask = simd_f32_cmplt(absA, large);
|
||||
const Ty mag0 = simd_selb(largeMask, magMid, one);
|
||||
const Ty magnitude = simd_selb(smallMask, magSmall, mag0);
|
||||
|
||||
const Ty sign = simd_and(_a, signmask);
|
||||
const Ty signed0 = simd_or(magnitude, sign);
|
||||
|
||||
const Ty self_eq = simd_f32_cmpeq(_a, _a);
|
||||
const Ty nan_mask = simd_not(self_eq);
|
||||
const Ty result = simd_selb(nan_mask, _a, signed0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
BX_SIMD_INLINE Ty simd_f32_log_ni(Ty _a)
|
||||
{
|
||||
const Ty zero = simd_zero<Ty>();
|
||||
const Ty one = simd_splat<Ty>(1.0f);
|
||||
const Ty nanmask = simd_f32_cmpneq(_a, _a);
|
||||
const Ty negmask = simd_f32_cmplt(_a, zero);
|
||||
const Ty zeromask = simd_f32_cmpeq(_a, zero);
|
||||
const Ty pos_inf = simd_splat<Ty>(uint32_t(kFloatExponentMask) );
|
||||
const Ty infmask = simd_f32_cmpeq(_a, pos_inf);
|
||||
const Ty nan_val = simd_splat<Ty>(uint32_t(kFloatSignMask | kFloatExponentMask | kFloatMantissaMask) );
|
||||
const Ty neg_inf = simd_splat<Ty>(uint32_t(kFloatSignMask | kFloatExponentMask) );
|
||||
const Ty expmask_c = simd_splat<Ty>(kFloatExponentMask);
|
||||
const Ty mantmask_c = simd_splat<Ty>(kFloatMantissaMask);
|
||||
const Ty exp_half = simd_splat<Ty>(uint32_t(0x3f000000) );
|
||||
const Ty bias_126 = simd_splat<Ty>(uint32_t(kFloatExponentBias - 1) );
|
||||
const Ty aexp = simd_and(_a, expmask_c);
|
||||
|
||||
constexpr int32_t kSubnormalShift = int32_t(kFloatMantissaNumBits) + 2;
|
||||
constexpr uint32_t kSubnormalExp = uint32_t(int32_t(kFloatExponentBias) + kSubnormalShift);
|
||||
constexpr uint32_t kSubnormalBits = kSubnormalExp << kFloatExponentBitShift;
|
||||
|
||||
const Ty smallest = simd_splat<Ty>(uint32_t(uint32_t(1) << kFloatExponentBitShift) );
|
||||
const Ty magnitude = simd_and(_a, simd_splat<Ty>(uint32_t(~kFloatSignMask) ) );
|
||||
const Ty submask = simd_i32_cmplt(magnitude, smallest);
|
||||
const Ty subscale = simd_splat<Ty>(kSubnormalBits);
|
||||
const Ty subscaled = simd_f32_mul(_a, subscale);
|
||||
const Ty value = simd_selb(submask, subscaled, _a);
|
||||
const Ty subshift = simd_splat<Ty>(uint32_t(kSubnormalShift) );
|
||||
const Ty subadj = simd_and(submask, subshift);
|
||||
|
||||
const Ty aexp = simd_and(value, expmask_c);
|
||||
const Ty rawexp = simd_x32_srl(aexp, kFloatExponentBitShift);
|
||||
const Ty exp_i0 = simd_i32_sub(rawexp, bias_126);
|
||||
const Ty mant = simd_and(_a, mantmask_c);
|
||||
const Ty exp_n = simd_i32_sub(rawexp, bias_126);
|
||||
const Ty exp_i0 = simd_i32_sub(exp_n, subadj);
|
||||
const Ty mant = simd_and(value, mantmask_c);
|
||||
const Ty ff0 = simd_or(mant, exp_half);
|
||||
const Ty sqrt2_half = simd_splat<Ty>(kSqrt2 * 0.5f);
|
||||
const Ty sqrt2_half = simd_splat<Ty>(7.07106781186547524401e-01f);
|
||||
const Ty adj_mask = simd_f32_cmplt(ff0, sqrt2_half);
|
||||
const Ty two = simd_splat<Ty>(2.0f);
|
||||
const Ty ff_dbl = simd_f32_mul(ff0, two);
|
||||
const Ty ff_dbl = simd_f32_add(ff0, ff0);
|
||||
const Ty ff1 = simd_selb(adj_mask, ff_dbl, ff0);
|
||||
const Ty ione = simd_splat<Ty>(uint32_t(1) );
|
||||
const Ty adj_one = simd_and(adj_mask, ione);
|
||||
@@ -812,8 +929,8 @@ BX_FP_PRECISE_BEGIN()
|
||||
const Ty kC4 = simd_splat<Ty>(1.818357216161805012e-01f);
|
||||
const Ty kC5 = simd_splat<Ty>(1.531383769920937332e-01f);
|
||||
const Ty kC6 = simd_splat<Ty>(1.479819860511658591e-01f);
|
||||
const Ty log2lo = simd_splat<Ty>(1.90821492927058770002e-10f);
|
||||
const Ty lognat2 = simd_splat<Ty>(kLogNat2);
|
||||
const Ty log2lo = simd_splat<Ty>(kFloatLn2Lo);
|
||||
const Ty lognat2 = simd_splat<Ty>(kFloatLn2Hi);
|
||||
const Ty half = simd_splat<Ty>(0.5f);
|
||||
const Ty ff = simd_f32_sub(ff1, one);
|
||||
const Ty kk = simd_i32_itof(exp_i);
|
||||
@@ -840,7 +957,9 @@ BX_FP_PRECISE_BEGIN()
|
||||
const Ty inff = simd_f32_sub(inner, ff);
|
||||
const Ty raw = simd_f32_sub(hi, inff);
|
||||
const Ty rz = simd_selb(zeromask, neg_inf, raw);
|
||||
const Ty result = simd_selb(negmask, nan_val, rz);
|
||||
const Ty ri = simd_selb(infmask, _a, rz);
|
||||
const Ty rn = simd_selb(negmask, nan_val, ri);
|
||||
const Ty result = simd_selb(nanmask, _a, rn);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -850,29 +969,31 @@ BX_FP_PRECISE_BEGIN()
|
||||
{
|
||||
const Ty zero = simd_zero<Ty>();
|
||||
const Ty one = simd_splat<Ty>(1.0f);
|
||||
const Ty two = simd_splat<Ty>(2.0f);
|
||||
const Ty inf = simd_splat<Ty>(uint32_t(kFloatExponentMask) );
|
||||
const Ty near_zero = simd_splat<Ty>(kNearZero);
|
||||
const Ty absa = simd_f32_abs(_a);
|
||||
const Ty near_mask = simd_f32_cmple(absa, near_zero);
|
||||
const Ty near_result = simd_f32_add(_a, one);
|
||||
const Ty exp_min = simd_splat<Ty>(-87.33654475f);
|
||||
const Ty clamp_mask = simd_f32_cmple(_a, exp_min);
|
||||
const Ty exp_max = simd_splat<Ty>(88.72283905f);
|
||||
const Ty inf = simd_splat<Ty>(kFloatInfinity);
|
||||
const Ty inf_mask = simd_f32_cmpge(_a, exp_max);
|
||||
const Ty overflow = simd_splat<Ty>( 88.7228394f);
|
||||
const Ty underflow = simd_splat<Ty>(-103.972084f);
|
||||
const Ty over_mask = simd_f32_cmpgt(_a, overflow);
|
||||
const Ty under_mask = simd_f32_cmplt(_a, underflow);
|
||||
const Ty self_eq = simd_f32_cmpeq(_a, _a);
|
||||
const Ty nan_mask = simd_not(self_eq);
|
||||
const Ty kC0 = simd_splat<Ty>( 1.66666666666666019037e-01f);
|
||||
const Ty kC1 = simd_splat<Ty>(-2.77777777770155933842e-03f);
|
||||
const Ty kC2 = simd_splat<Ty>( 6.61375632143793436117e-05f);
|
||||
const Ty kC3 = simd_splat<Ty>(-1.65339022054652515390e-06f);
|
||||
const Ty kC4 = simd_splat<Ty>( 4.13813679705723846039e-08f);
|
||||
const Ty log2lo = simd_splat<Ty>(1.90821492927058770002e-10f);
|
||||
const Ty lognat2 = simd_splat<Ty>(kLogNat2);
|
||||
const Ty ln2Hi = simd_splat<Ty>(6.9314575195e-01f);
|
||||
const Ty ln2Lo = simd_splat<Ty>(1.4286067653e-06f);
|
||||
const Ty invlognat2 = simd_splat<Ty>(kInvLogNat2);
|
||||
const Ty two = simd_splat<Ty>(2.0f);
|
||||
const Ty amul = simd_f32_mul(_a, invlognat2);
|
||||
const Ty kk = simd_f32_round(amul);
|
||||
const Ty kkln = simd_f32_mul(kk, lognat2);
|
||||
const Ty kkln = simd_f32_mul(kk, ln2Hi);
|
||||
const Ty hi = simd_f32_sub(_a, kkln);
|
||||
const Ty lo = simd_f32_mul(kk, log2lo);
|
||||
const Ty lo = simd_f32_mul(kk, ln2Lo);
|
||||
const Ty hml = simd_f32_sub(hi, lo);
|
||||
const Ty hmlsq = simd_f32_mul(hml, hml);
|
||||
const Ty tmp0 = simd_f32_madd(kC4, hmlsq, kC3);
|
||||
@@ -889,9 +1010,10 @@ BX_FP_PRECISE_BEGIN()
|
||||
const Ty tmp6 = simd_f32_sub(one, tmp5b);
|
||||
const Ty ikk = simd_f32_ftoi_trunc(kk);
|
||||
const Ty raw = simd_f32_ldexp_ni(tmp6, ikk);
|
||||
const Ty rc = simd_selb(clamp_mask, zero, raw);
|
||||
const Ty ri = simd_selb(inf_mask, inf, rc);
|
||||
const Ty result = simd_selb(near_mask, near_result, ri);
|
||||
const Ty rNear = simd_selb(near_mask, near_result, raw);
|
||||
const Ty rUnder = simd_selb(under_mask, zero, rNear);
|
||||
const Ty rOver = simd_selb(over_mask, inf, rUnder);
|
||||
const Ty result = simd_selb(nan_mask, _a, rOver);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -919,21 +1041,43 @@ BX_FP_PRECISE_BEGIN()
|
||||
{
|
||||
const Ty zero = simd_zero<Ty>();
|
||||
const Ty one = simd_splat<Ty>(1.0f);
|
||||
const Ty smallest = simd_splat<Ty>(kFloatSmallest);
|
||||
const Ty signmask = simd_splat<Ty>(kFloatSignMask);
|
||||
const Ty half = simd_splat<Ty>(0.5f);
|
||||
const Ty nan = simd_splat<Ty>(uint32_t(kFloatExponentMask | kFloatMantissaMask) );
|
||||
const Ty inf = simd_splat<Ty>(uint32_t(kFloatExponentMask) );
|
||||
|
||||
const Ty absa = simd_f32_abs(_a);
|
||||
const Ty absb = simd_f32_abs(_b);
|
||||
const Ty loga = simd_f32_log(absa);
|
||||
const Ty bloga = simd_f32_mul(_b, loga);
|
||||
const Ty pw = simd_f32_exp(bloga);
|
||||
const Ty asign = simd_and(_a, signmask);
|
||||
const Ty pwabs = simd_f32_abs(pw);
|
||||
const Ty result0 = simd_or(pwabs, asign);
|
||||
const Ty bmask = simd_f32_cmplt(absb, smallest);
|
||||
const Ty amask = simd_f32_cmplt(absa, smallest);
|
||||
const Ty result1 = simd_selb(amask, zero, result0);
|
||||
const Ty result = simd_selb(bmask, one, result1);
|
||||
const Ty mag = simd_f32_exp(bloga);
|
||||
|
||||
const Ty halfB = simd_f32_mul(half, _b);
|
||||
const Ty truncB = simd_f32_trunc(_b);
|
||||
const Ty truncH = simd_f32_trunc(halfB);
|
||||
const Ty integral = simd_f32_cmpeq(_b, truncB);
|
||||
const Ty halfEq = simd_f32_cmpeq(halfB, truncH);
|
||||
const Ty odd = simd_not(halfEq);
|
||||
|
||||
const Ty negA = simd_f32_cmplt(_a, zero);
|
||||
const Ty negOdd = simd_and(negA, odd);
|
||||
const Ty negMag = simd_f32_neg(mag);
|
||||
const Ty signed0 = simd_selb(negOdd, negMag, mag);
|
||||
|
||||
const Ty negNoInt = simd_andc(negA, integral);
|
||||
const Ty result0 = simd_selb(negNoInt, nan, signed0);
|
||||
|
||||
const Ty zeroA = simd_f32_cmpeq(absa, zero);
|
||||
const Ty bNeg = simd_f32_cmplt(_b, zero);
|
||||
const Ty zeroMag = simd_selb(bNeg, inf, zero);
|
||||
const Ty result1 = simd_selb(zeroA, zeroMag, result0);
|
||||
|
||||
const Ty zeroB = simd_f32_cmpeq(_b, zero);
|
||||
const Ty result2 = simd_selb(zeroB, one, result1);
|
||||
|
||||
const Ty aEq = simd_f32_cmpeq(_a, _a);
|
||||
const Ty bEq = simd_f32_cmpeq(_b, _b);
|
||||
const Ty bothEq = simd_and(aEq, bEq);
|
||||
const Ty nanIn = simd_not(bothEq);
|
||||
const Ty result = simd_selb(nanIn, nan, result2);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -168,6 +168,86 @@ namespace bx
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double bitsToDouble(uint64_t _a);
|
||||
|
||||
/// Format constants and bit access for a floating-point type.
|
||||
template<typename Ty>
|
||||
struct FloatT;
|
||||
|
||||
/// `FloatT` for `float`.
|
||||
template<>
|
||||
struct FloatT<float>
|
||||
{
|
||||
using Type = float;
|
||||
using Bits = uint32_t;
|
||||
using Int = int32_t;
|
||||
|
||||
static constexpr int32_t kExponentBias = int32_t(kFloatExponentBias);
|
||||
static constexpr int32_t kExponentBitShift = int32_t(kFloatExponentBitShift);
|
||||
static constexpr int32_t kMantissaNumBits = int32_t(kFloatMantissaNumBits);
|
||||
static constexpr Bits kSignMask = kFloatSignMask;
|
||||
static constexpr Bits kExponentMask = kFloatExponentMask;
|
||||
static constexpr Bits kMantissaMask = kFloatMantissaMask;
|
||||
static constexpr Type kSmallest = kFloatSmallest;
|
||||
static constexpr Type kLargest = kFloatLargest;
|
||||
static constexpr Type kInfinity = kFloatInfinity;
|
||||
static constexpr Type kInvLn2 = kFloatInvLn2;
|
||||
static constexpr Type kInvLn10 = kFloatInvLn10;
|
||||
static constexpr Type kLn2Hi = kFloatLn2Hi;
|
||||
static constexpr Type kLn2Lo = kFloatLn2Lo;
|
||||
static constexpr Type kExpOverflow = kFloatExpOverflow;
|
||||
static constexpr Type kExpUnderflow = kFloatExpUnderflow;
|
||||
static constexpr int32_t kExpHalfShift = kFloatExpHalfShift;
|
||||
static constexpr Type kExpHalfLn2 = kFloatExpHalfLn2;
|
||||
static constexpr Type kHypSmall = kFloatHypSmall;
|
||||
static constexpr Type kHypBig = kFloatHypBig;
|
||||
static constexpr Type kHypNoFit = kFloatHypNoFit;
|
||||
static constexpr Type kTanhLarge = kFloatTanhLarge;
|
||||
static constexpr Type kArcHypTiny = kFloatArcHypTiny;
|
||||
static constexpr Type kArcHypHuge = kFloatArcHypHuge;
|
||||
static constexpr Bits kRsqrtSeed = kFloatRsqrtSeed;
|
||||
static constexpr Type kTanhPoly[] = { -17.0f/315.0f, 2.0f/15.0f, -1.0f/3.0f };
|
||||
|
||||
static BX_CONSTEXPR_FUNC Bits toBits(Type _a) { return floatToBits(_a); }
|
||||
static BX_CONSTEXPR_FUNC Type fromBits(Bits _a) { return bitsToFloat(_a); }
|
||||
};
|
||||
|
||||
/// `FloatT` for `double`.
|
||||
template<>
|
||||
struct FloatT<double>
|
||||
{
|
||||
using Type = double;
|
||||
using Bits = uint64_t;
|
||||
using Int = int64_t;
|
||||
|
||||
static constexpr int32_t kExponentBias = int32_t(kDoubleExponentBias);
|
||||
static constexpr int32_t kExponentBitShift = int32_t(kDoubleExponentShift);
|
||||
static constexpr int32_t kMantissaNumBits = int32_t(kDoubleMantissaNumBits);
|
||||
static constexpr Bits kSignMask = kDoubleSignMask;
|
||||
static constexpr Bits kExponentMask = kDoubleExponentMask;
|
||||
static constexpr Bits kMantissaMask = kDoubleMantissaMask;
|
||||
static constexpr Type kSmallest = kDoubleSmallest;
|
||||
static constexpr Type kLargest = kDoubleLargest;
|
||||
static constexpr Type kInfinity = kDoubleInfinity;
|
||||
static constexpr Type kInvLn2 = kDoubleInvLn2;
|
||||
static constexpr Type kInvLn10 = kDoubleInvLn10;
|
||||
static constexpr Type kLn2Hi = kDoubleLn2Hi;
|
||||
static constexpr Type kLn2Lo = kDoubleLn2Lo;
|
||||
static constexpr Type kExpOverflow = kDoubleExpOverflow;
|
||||
static constexpr Type kExpUnderflow = kDoubleExpUnderflow;
|
||||
static constexpr int32_t kExpHalfShift = kDoubleExpHalfShift;
|
||||
static constexpr Type kExpHalfLn2 = kDoubleExpHalfLn2;
|
||||
static constexpr Type kHypSmall = kDoubleHypSmall;
|
||||
static constexpr Type kHypBig = kDoubleHypBig;
|
||||
static constexpr Type kHypNoFit = kDoubleHypNoFit;
|
||||
static constexpr Type kTanhLarge = kDoubleTanhLarge;
|
||||
static constexpr Type kArcHypTiny = kDoubleArcHypTiny;
|
||||
static constexpr Type kArcHypHuge = kDoubleArcHypHuge;
|
||||
static constexpr Bits kRsqrtSeed = kDoubleRsqrtSeed;
|
||||
static constexpr Type kTanhPoly[] = { 62.0/2835.0, -17.0/315.0, 2.0/15.0, -1.0/3.0 };
|
||||
|
||||
static BX_CONSTEXPR_FUNC Bits toBits(Type _a) { return doubleToBits(_a); }
|
||||
static BX_CONSTEXPR_FUNC Type fromBits(Bits _a) { return bitsToDouble(_a); }
|
||||
};
|
||||
|
||||
/// Returns sortable floating point value.
|
||||
///
|
||||
/// @param[in] _value Float bits as uint32_t.
|
||||
@@ -232,6 +312,14 @@ namespace bx
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float floor(float _f);
|
||||
|
||||
/// Returns the largest integer value not greater than _a.
|
||||
///
|
||||
/// @param[in] _a Input value.
|
||||
///
|
||||
/// @returns Floor of _a.
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double floor(double _a);
|
||||
|
||||
/// Returns the smallest integer value not less than _f.
|
||||
///
|
||||
/// @param[in] _f Input value.
|
||||
@@ -240,7 +328,15 @@ namespace bx
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float ceil(float _f);
|
||||
|
||||
/// Returns the nearest integer value to _f, rounding halfway cases away from zero.
|
||||
/// Returns the smallest integer value not less than _a.
|
||||
///
|
||||
/// @param[in] _a Input value.
|
||||
///
|
||||
/// @returns Ceiling of _a.
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double ceil(double _a);
|
||||
|
||||
/// Returns the nearest integer value to _f, rounding halfway cases to even.
|
||||
///
|
||||
/// @param[in] _f Input value.
|
||||
///
|
||||
@@ -248,6 +344,14 @@ namespace bx
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float round(float _f);
|
||||
|
||||
/// Returns the nearest integer value to _a, rounding halfway cases to even.
|
||||
///
|
||||
/// @param[in] _a Input value.
|
||||
///
|
||||
/// @returns Rounded value.
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double round(double _a);
|
||||
|
||||
/// Returns linear interpolation between two values _a and _b.
|
||||
///
|
||||
/// @param[in] _a Start value.
|
||||
@@ -276,6 +380,14 @@ namespace bx
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float sign(float _a);
|
||||
|
||||
/// Returns the sign of _a as -1.0, 0.0 or 1.0.
|
||||
///
|
||||
/// @param[in] _a Input value.
|
||||
///
|
||||
/// @returns Sign of _a.
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double sign(double _a);
|
||||
|
||||
/// Returns `true` if the velue `_a` is negative.
|
||||
///
|
||||
/// @param[in] _a Value.
|
||||
@@ -293,6 +405,15 @@ namespace bx
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float copySign(float _value, float _sign);
|
||||
|
||||
/// Returns the magnitude of _value with the sign of _sign.
|
||||
///
|
||||
/// @param[in] _value Value to take the magnitude from.
|
||||
/// @param[in] _sign Value to take the sign from.
|
||||
///
|
||||
/// @returns |_value| with the sign of _sign.
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double copySign(double _value, double _sign);
|
||||
|
||||
/// Returns the absolute of _a.
|
||||
///
|
||||
/// @param[in] _a Input value.
|
||||
@@ -301,6 +422,14 @@ namespace bx
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float abs(float _a);
|
||||
|
||||
/// Returns the absolute value of _a.
|
||||
///
|
||||
/// @param[in] _a Input value.
|
||||
///
|
||||
/// @returns |_a|.
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double abs(double _a);
|
||||
|
||||
/// Returns the square of _a.
|
||||
///
|
||||
/// @param[in] _a Input value.
|
||||
@@ -309,6 +438,14 @@ namespace bx
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float square(float _a);
|
||||
|
||||
/// Returns _a squared.
|
||||
///
|
||||
/// @param[in] _a Input value.
|
||||
///
|
||||
/// @returns _a * _a.
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double square(double _a);
|
||||
|
||||
/// Returns the both sine and cosine of the argument _a.
|
||||
///
|
||||
/// @param[out] _outSinApprox Output approximate sine value.
|
||||
@@ -328,6 +465,14 @@ namespace bx
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float sin(float _a);
|
||||
|
||||
/// Returns the sine of _a.
|
||||
///
|
||||
/// @param[in] _a Angle in radians.
|
||||
///
|
||||
/// @returns sin(_a).
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double sin(double _a);
|
||||
|
||||
/// Returns hyperbolic sine of the argument _a.
|
||||
///
|
||||
/// @param[in] _a Input value.
|
||||
@@ -336,6 +481,14 @@ namespace bx
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float sinh(float _a);
|
||||
|
||||
/// Returns the hyperbolic sine of _a.
|
||||
///
|
||||
/// @param[in] _a Input value.
|
||||
///
|
||||
/// @returns sinh(_a).
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double sinh(double _a);
|
||||
|
||||
/// Returns radian angle between -pi/2 and +pi/2 whose sine is _a.
|
||||
///
|
||||
/// @param[in] _a Sine value [-1, 1].
|
||||
@@ -344,6 +497,14 @@ namespace bx
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float asin(float _a);
|
||||
|
||||
/// Returns the arc sine of _a.
|
||||
///
|
||||
/// @param[in] _a Input value in [-1, 1].
|
||||
///
|
||||
/// @returns asin(_a) in radians, or NaN if _a is outside [-1, 1].
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double asin(double _a);
|
||||
|
||||
/// Returns the cosine of the argument _a.
|
||||
///
|
||||
/// @param[in] _a Angle in radians.
|
||||
@@ -352,6 +513,14 @@ namespace bx
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float cos(float _a);
|
||||
|
||||
/// Returns the cosine of _a.
|
||||
///
|
||||
/// @param[in] _a Angle in radians.
|
||||
///
|
||||
/// @returns cos(_a).
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double cos(double _a);
|
||||
|
||||
/// Returns hyperbolic cosine of the argument _a.
|
||||
///
|
||||
/// @param[in] _a Input value.
|
||||
@@ -360,6 +529,14 @@ namespace bx
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float cosh(float _a);
|
||||
|
||||
/// Returns the hyperbolic cosine of _a.
|
||||
///
|
||||
/// @param[in] _a Input value.
|
||||
///
|
||||
/// @returns cosh(_a).
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double cosh(double _a);
|
||||
|
||||
/// Returns radian angle between 0 and pi whose cosine is _a.
|
||||
///
|
||||
/// @param[in] _a Cosine value [-1, 1].
|
||||
@@ -368,6 +545,14 @@ namespace bx
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float acos(float _a);
|
||||
|
||||
/// Returns the arc cosine of _a.
|
||||
///
|
||||
/// @param[in] _a Input value in [-1, 1].
|
||||
///
|
||||
/// @returns acos(_a) in radians, or NaN if _a is outside [-1, 1].
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double acos(double _a);
|
||||
|
||||
/// Returns the circular tangent of the radian argument _a.
|
||||
///
|
||||
/// @param[in] _a Angle in radians.
|
||||
@@ -376,6 +561,14 @@ namespace bx
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float tan(float _a);
|
||||
|
||||
/// Returns the tangent of _a.
|
||||
///
|
||||
/// @param[in] _a Angle in radians.
|
||||
///
|
||||
/// @returns tan(_a).
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double tan(double _a);
|
||||
|
||||
/// Returns hyperbolic tangent of the argument _a.
|
||||
///
|
||||
/// @param[in] _a Input value.
|
||||
@@ -384,6 +577,80 @@ namespace bx
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float tanh(float _a);
|
||||
|
||||
/// Returns the hyperbolic tangent of _a.
|
||||
///
|
||||
/// @param[in] _a Input value.
|
||||
///
|
||||
/// @returns tanh(_a).
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double tanh(double _a);
|
||||
|
||||
/// Returns the natural logarithm of 1 + _a, without the precision loss that
|
||||
/// log(1.0f + _a) has for a small _a.
|
||||
///
|
||||
/// @param[in] _a Input value (must be >= -1).
|
||||
///
|
||||
/// @returns ln(1 + _a).
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float log1p(float _a);
|
||||
|
||||
/// Returns the natural logarithm of 1 + _a, without the precision loss that
|
||||
/// log(1.0 + _a) has for a small _a.
|
||||
///
|
||||
/// @param[in] _a Input value (must be >= -1).
|
||||
///
|
||||
/// @returns ln(1 + _a).
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double log1p(double _a);
|
||||
|
||||
/// Returns the inverse hyperbolic sine of _a.
|
||||
///
|
||||
/// @param[in] _a Input value.
|
||||
///
|
||||
/// @returns asinh(_a).
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float asinh(float _a);
|
||||
|
||||
/// Returns the inverse hyperbolic sine of _a.
|
||||
///
|
||||
/// @param[in] _a Input value.
|
||||
///
|
||||
/// @returns asinh(_a).
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double asinh(double _a);
|
||||
|
||||
/// Returns the inverse hyperbolic cosine of _a.
|
||||
///
|
||||
/// @param[in] _a Input value (must be >= 1).
|
||||
///
|
||||
/// @returns acosh(_a), or NaN if _a < 1.
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float acosh(float _a);
|
||||
|
||||
/// Returns the inverse hyperbolic cosine of _a.
|
||||
///
|
||||
/// @param[in] _a Input value (must be >= 1).
|
||||
///
|
||||
/// @returns acosh(_a), or NaN if _a < 1.
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double acosh(double _a);
|
||||
|
||||
/// Returns the inverse hyperbolic tangent of _a.
|
||||
///
|
||||
/// @param[in] _a Input value in [-1, 1].
|
||||
///
|
||||
/// @returns atanh(_a), or NaN if |_a| > 1.
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float atanh(float _a);
|
||||
|
||||
/// Returns the inverse hyperbolic tangent of _a.
|
||||
///
|
||||
/// @param[in] _a Input value in [-1, 1].
|
||||
///
|
||||
/// @returns atanh(_a), or NaN if |_a| > 1.
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double atanh(double _a);
|
||||
|
||||
/// Returns radian angle between -pi/2 and +pi/2 whose tangent is _a.
|
||||
///
|
||||
/// @param[in] _a Tangent value.
|
||||
@@ -392,6 +659,14 @@ namespace bx
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float atan(float _a);
|
||||
|
||||
/// Returns the arc tangent of _a.
|
||||
///
|
||||
/// @param[in] _a Input value.
|
||||
///
|
||||
/// @returns atan(_a) in radians.
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double atan(double _a);
|
||||
|
||||
/// Returns the inverse tangent of _y/_x.
|
||||
///
|
||||
/// @param[in] _y Y component.
|
||||
@@ -401,6 +676,15 @@ namespace bx
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float atan2(float _y, float _x);
|
||||
|
||||
/// Returns the arc tangent of _y / _x, using their signs to pick the quadrant.
|
||||
///
|
||||
/// @param[in] _y Numerator.
|
||||
/// @param[in] _x Denominator.
|
||||
///
|
||||
/// @returns atan2(_y, _x) in radians.
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double atan2(double _y, double _x);
|
||||
|
||||
/// Computes _a raised to the _b power.
|
||||
///
|
||||
/// @param[in] _a Base.
|
||||
@@ -410,6 +694,16 @@ namespace bx
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float pow(float _a, float _b);
|
||||
|
||||
/// Returns _a raised to the _b power. If _a is negative _b must be integral,
|
||||
/// otherwise the result is NaN.
|
||||
///
|
||||
/// @param[in] _a Base.
|
||||
/// @param[in] _b Exponent.
|
||||
///
|
||||
/// @returns _a^_b.
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double pow(double _a, double _b);
|
||||
|
||||
/// Returns the result of multiplying _a by 2 raised to the power of the exponent `_a * (2^_b)`.
|
||||
///
|
||||
/// @param[in] _a Significand.
|
||||
@@ -419,6 +713,15 @@ namespace bx
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float ldexp(float _a, int32_t _b);
|
||||
|
||||
/// Returns _a multiplied by 2 raised to the power _b.
|
||||
///
|
||||
/// @param[in] _a Significand.
|
||||
/// @param[in] _b Exponent.
|
||||
///
|
||||
/// @returns _a * 2^_b.
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double ldexp(double _a, int32_t _b);
|
||||
|
||||
/// Returns decomposed given floating point value _a into a normalized fraction and
|
||||
/// an integral power of two.
|
||||
///
|
||||
@@ -427,7 +730,17 @@ namespace bx
|
||||
///
|
||||
/// @returns Normalized fraction in [0.5, 1.0).
|
||||
///
|
||||
float frexp(float _a, int32_t* _outExp);
|
||||
constexpr float frexp(float _a, int32_t* _outExp);
|
||||
|
||||
/// Returns decomposed given floating point value _a into a normalized fraction and
|
||||
/// an integral power of two.
|
||||
///
|
||||
/// @param[in] _a Input value.
|
||||
/// @param[out] _outExp Output exponent.
|
||||
///
|
||||
/// @returns Normalized fraction in [0.5, 1.0).
|
||||
///
|
||||
constexpr double frexp(double _a, int32_t* _outExp);
|
||||
|
||||
/// Returns e (2.71828...) raised to the _a power.
|
||||
///
|
||||
@@ -437,6 +750,14 @@ namespace bx
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float exp(float _a);
|
||||
|
||||
/// Returns e (2.71828...) raised to the _a power.
|
||||
///
|
||||
/// @param[in] _a Exponent.
|
||||
///
|
||||
/// @returns e^_a.
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double exp(double _a);
|
||||
|
||||
/// Returns 2 raised to the _a power.
|
||||
///
|
||||
/// @param[in] _a Exponent.
|
||||
@@ -445,6 +766,14 @@ namespace bx
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float exp2(float _a);
|
||||
|
||||
/// Returns 2 raised to the _a power.
|
||||
///
|
||||
/// @param[in] _a Exponent.
|
||||
///
|
||||
/// @returns 2^_a.
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double exp2(double _a);
|
||||
|
||||
/// Returns the base e (2.71828...) logarithm of _a.
|
||||
///
|
||||
/// @param[in] _a Input value (must be > 0).
|
||||
@@ -453,6 +782,14 @@ namespace bx
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float log(float _a);
|
||||
|
||||
/// Returns the base e (2.71828...) logarithm of _a.
|
||||
///
|
||||
/// @param[in] _a Input value (must be > 0).
|
||||
///
|
||||
/// @returns ln(_a).
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double log(double _a);
|
||||
|
||||
/// Returns the base 2 logarithm of _a.
|
||||
///
|
||||
/// @param[in] _a Input value (must be > 0).
|
||||
@@ -461,6 +798,220 @@ namespace bx
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float log2(float _a);
|
||||
|
||||
/// Returns the base 2 logarithm of _a.
|
||||
///
|
||||
/// @param[in] _a Input value (must be > 0).
|
||||
///
|
||||
/// @returns log2(_a).
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double log2(double _a);
|
||||
|
||||
/// Returns the base 10 logarithm of _a.
|
||||
///
|
||||
/// @param[in] _a Input value (must be > 0).
|
||||
///
|
||||
/// @returns log10(_a).
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float log10(float _a);
|
||||
|
||||
/// Returns the base 10 logarithm of _a.
|
||||
///
|
||||
/// @param[in] _a Input value (must be > 0).
|
||||
///
|
||||
/// @returns log10(_a).
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double log10(double _a);
|
||||
|
||||
/// Returns the nearest integer not greater in magnitude than _a.
|
||||
///
|
||||
/// @param[in] _a Input value.
|
||||
///
|
||||
/// @returns Truncated value.
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float trunc(float _a);
|
||||
|
||||
/// Returns _a truncated towards zero.
|
||||
///
|
||||
/// @param[in] _a Input value.
|
||||
///
|
||||
/// @returns Integer part of _a.
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double trunc(double _a);
|
||||
|
||||
/// Returns the fractional (or decimal) part of _a, which is greater than or equal to 0
|
||||
/// and less than 1.
|
||||
///
|
||||
/// @param[in] _a Input value.
|
||||
///
|
||||
/// @returns Fractional part of _a.
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float fract(float _a);
|
||||
|
||||
/// Returns the fractional part of _a, with the sign of _a.
|
||||
///
|
||||
/// @param[in] _a Input value.
|
||||
///
|
||||
/// @returns _a - trunc(_a).
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double fract(double _a);
|
||||
|
||||
/// Returns the absolute of integer _a.
|
||||
///
|
||||
/// @param[in] _a Input value.
|
||||
///
|
||||
/// @returns Absolute value of _a.
|
||||
///
|
||||
template<typename Ty>
|
||||
requires (isInteger<Ty>() )
|
||||
constexpr Ty abs(Ty _a);
|
||||
|
||||
/// Returns true if the sign bit of _a is set.
|
||||
///
|
||||
/// @param[in] _a Input value.
|
||||
///
|
||||
/// @returns True if _a is negative, including negative zero.
|
||||
///
|
||||
BX_CONSTEXPR_FUNC bool signBit(double _a);
|
||||
|
||||
/// Returns true if _a and _b are equal within _epsilon tolerance.
|
||||
///
|
||||
/// @param[in] _a First value.
|
||||
/// @param[in] _b Second value.
|
||||
/// @param[in] _epsilon Tolerance.
|
||||
///
|
||||
/// @returns True if _a and _b are within _epsilon of each other.
|
||||
///
|
||||
BX_CONSTEXPR_FUNC bool isEqual(double _a, double _b, double _epsilon);
|
||||
|
||||
/// Returns the fractional part of _a, and stores the integral part in _outIntegral.
|
||||
///
|
||||
/// @param[in] _a Input value.
|
||||
/// @param[out] _outIntegral Output integral part, truncated towards zero.
|
||||
///
|
||||
/// @returns Fractional part of _a, with the sign of _a.
|
||||
///
|
||||
constexpr float modf(float _a, float* _outIntegral);
|
||||
|
||||
/// Returns the fractional part of _a, and stores the integral part in _outIntegral.
|
||||
///
|
||||
/// @param[in] _a Input value.
|
||||
/// @param[out] _outIntegral Output integral part, truncated towards zero.
|
||||
///
|
||||
/// @returns Fractional part of _a, with the sign of _a.
|
||||
///
|
||||
constexpr double modf(double _a, double* _outIntegral);
|
||||
|
||||
/// Returns the remainder of _a / _b, truncated towards zero. The result has the
|
||||
/// sign of _a. Unlike mod, which truncates the quotient towards negative infinity.
|
||||
///
|
||||
/// @param[in] _a Numerator.
|
||||
/// @param[in] _b Denominator.
|
||||
///
|
||||
/// @returns _a - _b * trunc(_a / _b).
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float fmod(float _a, float _b);
|
||||
|
||||
/// Returns the remainder of _a / _b, truncated towards zero. The result has the
|
||||
/// sign of _a. Unlike mod, which truncates the quotient towards negative infinity.
|
||||
///
|
||||
/// @param[in] _a Numerator.
|
||||
/// @param[in] _b Denominator.
|
||||
///
|
||||
/// @returns _a - _b * trunc(_a / _b).
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double fmod(double _a, double _b);
|
||||
|
||||
/// Returns the remainder of _a / _b, with the sign of _b.
|
||||
///
|
||||
/// @param[in] _a Numerator.
|
||||
/// @param[in] _b Denominator.
|
||||
///
|
||||
/// @returns _a - _b * floor(_a / _b).
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float mod(float _a, float _b);
|
||||
|
||||
/// Returns the remainder of _a / _b, with the sign of _b.
|
||||
///
|
||||
/// @param[in] _a Numerator.
|
||||
/// @param[in] _b Denominator.
|
||||
///
|
||||
/// @returns _a - _b * floor(_a / _b).
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double mod(double _a, double _b);
|
||||
|
||||
/// Returns the square root of _a.
|
||||
///
|
||||
/// @param[in] _a Input value (must be >= 0).
|
||||
///
|
||||
/// @returns Square root of _a.
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float sqrt(float _a);
|
||||
|
||||
/// Returns the square root of _a.
|
||||
///
|
||||
/// @param[in] _a Input value (must be >= 0).
|
||||
///
|
||||
/// @returns sqrt(_a).
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double sqrt(double _a);
|
||||
|
||||
/// Returns reciprocal square root of _a.
|
||||
///
|
||||
/// @param[in] _a Input value (must be > 0).
|
||||
///
|
||||
/// @returns 1 / sqrt(_a).
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float rsqrt(float _a);
|
||||
|
||||
/// Returns the reciprocal square root of _a.
|
||||
///
|
||||
/// @param[in] _a Input value (must be > 0).
|
||||
///
|
||||
/// @returns 1/sqrt(_a).
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double rsqrt(double _a);
|
||||
|
||||
/// Returns result of multiply and add (_a * _b + _c).
|
||||
///
|
||||
/// @param[in] _a First factor.
|
||||
/// @param[in] _b Second factor.
|
||||
/// @param[in] _c Addend.
|
||||
///
|
||||
/// @returns _a * _b + _c.
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float mad(float _a, float _b, float _c);
|
||||
|
||||
/// Returns the result of multiply and add. (_a * _b + _c)
|
||||
///
|
||||
/// @param[in] _a First factor.
|
||||
/// @param[in] _b Second factor.
|
||||
/// @param[in] _c Addend.
|
||||
///
|
||||
/// @returns _a * _b + _c.
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double mad(double _a, double _b, double _c);
|
||||
|
||||
/// Returns result of negated multiply-sub operation -(_a * _b - _c) -> _c - _a * _b,
|
||||
/// rounded like mad.
|
||||
///
|
||||
/// @param[in] _a First factor.
|
||||
/// @param[in] _b Second factor.
|
||||
/// @param[in] _c Value to subtract from.
|
||||
///
|
||||
/// @returns _c - _a * _b.
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float nms(float _a, float _b, float _c);
|
||||
|
||||
/// Returns the result of negated multiply and add. (_c - _a * _b)
|
||||
///
|
||||
/// @param[in] _a First factor.
|
||||
/// @param[in] _b Second factor.
|
||||
/// @param[in] _c Addend.
|
||||
///
|
||||
/// @returns _c - _a * _b.
|
||||
///
|
||||
BX_CONSTEXPR_FUNC double nms(double _a, double _b, double _c);
|
||||
|
||||
/// Count number of bits set.
|
||||
///
|
||||
/// @param[in] _val Input value.
|
||||
@@ -533,50 +1084,6 @@ namespace bx
|
||||
template<typename Ty>
|
||||
BX_CONSTEXPR_FUNC Ty nextPow2(Ty _a);
|
||||
|
||||
/// Returns the square root of _a.
|
||||
///
|
||||
/// @param[in] _a Input value (must be >= 0).
|
||||
///
|
||||
/// @returns Square root of _a.
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float sqrt(float _a);
|
||||
|
||||
/// Returns reciprocal square root of _a.
|
||||
///
|
||||
/// @param[in] _a Input value (must be > 0).
|
||||
///
|
||||
/// @returns 1 / sqrt(_a).
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float rsqrt(float _a);
|
||||
|
||||
/// Returns the nearest integer not greater in magnitude than _a.
|
||||
///
|
||||
/// @param[in] _a Input value.
|
||||
///
|
||||
/// @returns Truncated value.
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float trunc(float _a);
|
||||
|
||||
/// Returns the fractional (or decimal) part of _a, which is greater than or equal to 0
|
||||
/// and less than 1.
|
||||
///
|
||||
/// @param[in] _a Input value.
|
||||
///
|
||||
/// @returns Fractional part of _a.
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float fract(float _a);
|
||||
|
||||
/// Returns result of negated multiply-sub operation -(_a * _b - _c) -> _c - _a * _b,
|
||||
/// rounded like mad.
|
||||
///
|
||||
/// @param[in] _a First factor.
|
||||
/// @param[in] _b Second factor.
|
||||
/// @param[in] _c Value to subtract from.
|
||||
///
|
||||
/// @returns _c - _a * _b.
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float nms(float _a, float _b, float _c);
|
||||
|
||||
/// Returns result of addition (_a + _b).
|
||||
///
|
||||
/// @param[in] _a First value.
|
||||
@@ -628,16 +1135,6 @@ namespace bx
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float mul(float _a, float _b);
|
||||
|
||||
/// Returns result of multiply and add (_a * _b + _c).
|
||||
///
|
||||
/// @param[in] _a First factor.
|
||||
/// @param[in] _b Second factor.
|
||||
/// @param[in] _c Addend.
|
||||
///
|
||||
/// @returns _a * _b + _c.
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float mad(float _a, float _b, float _c);
|
||||
|
||||
/// Returns reciprocal of _a.
|
||||
///
|
||||
/// @param[in] _a Input value.
|
||||
@@ -672,15 +1169,6 @@ namespace bx
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float divSafe(float _a, float _b);
|
||||
|
||||
/// Returns the floating-point remainder of the division operation _a/_b.
|
||||
///
|
||||
/// @param[in] _a Numerator.
|
||||
/// @param[in] _b Denominator.
|
||||
///
|
||||
/// @returns Remainder of _a / _b.
|
||||
///
|
||||
BX_CONSTEXPR_FUNC float mod(float _a, float _b);
|
||||
|
||||
/// Returns true if _a and _b are equal within _epsilon tolerance.
|
||||
///
|
||||
/// @param[in] _a First value.
|
||||
|
||||
@@ -151,7 +151,7 @@ extern "C" double fabs(double _x)
|
||||
|
||||
extern "C" double ldexp(double _x, int _exp)
|
||||
{
|
||||
return bx::ldexp(float(_x), _exp);
|
||||
return bx::ldexp(_x, _exp);
|
||||
}
|
||||
|
||||
extern "C" float expf(float _x)
|
||||
@@ -159,15 +159,29 @@ extern "C" float expf(float _x)
|
||||
return bx::exp(_x);
|
||||
}
|
||||
|
||||
extern "C" double exp(double _x)
|
||||
{
|
||||
return bx::exp(_x);
|
||||
}
|
||||
|
||||
extern "C" float logf(float _x)
|
||||
{
|
||||
return bx::log(_x);
|
||||
}
|
||||
|
||||
extern "C" double log(double _x)
|
||||
{
|
||||
return bx::log(_x);
|
||||
}
|
||||
|
||||
extern "C" float log10f(float _x)
|
||||
{
|
||||
BX_UNUSED(_x);
|
||||
return 0.0f;
|
||||
return bx::log10(_x);
|
||||
}
|
||||
|
||||
extern "C" double log10(double _x)
|
||||
{
|
||||
return bx::log10(_x);
|
||||
}
|
||||
|
||||
extern "C" float powf(float _x, float _y)
|
||||
@@ -175,7 +189,7 @@ extern "C" float powf(float _x, float _y)
|
||||
return bx::pow(_x, _y);
|
||||
}
|
||||
|
||||
extern "C" double pow(double _x, float _y)
|
||||
extern "C" double pow(double _x, double _y)
|
||||
{
|
||||
return bx::pow(_x, _y);
|
||||
}
|
||||
@@ -185,21 +199,41 @@ extern "C" float sinf(float _x)
|
||||
return bx::sin(_x);
|
||||
}
|
||||
|
||||
extern "C" double sin(double _x)
|
||||
{
|
||||
return bx::sin(_x);
|
||||
}
|
||||
|
||||
extern "C" float cosf(float _x)
|
||||
{
|
||||
return bx::cos(_x);
|
||||
}
|
||||
|
||||
extern "C" double cos(double _x)
|
||||
{
|
||||
return bx::cos(_x);
|
||||
}
|
||||
|
||||
extern "C" float tanf(float _x)
|
||||
{
|
||||
return bx::tan(_x);
|
||||
}
|
||||
|
||||
extern "C" double tan(double _x)
|
||||
{
|
||||
return bx::tan(_x);
|
||||
}
|
||||
|
||||
extern "C" float atan2f(float _y, float _x)
|
||||
{
|
||||
return bx::atan2(_y, _x);
|
||||
}
|
||||
|
||||
extern "C" double atan2(double _y, double _x)
|
||||
{
|
||||
return bx::atan2(_y, _x);
|
||||
}
|
||||
|
||||
extern "C" float sqrtf(float _x)
|
||||
{
|
||||
return bx::sqrt(_x);
|
||||
@@ -235,9 +269,19 @@ extern "C" float acosf(float _x)
|
||||
return bx::acos(_x);
|
||||
}
|
||||
|
||||
extern "C" double acos(double _x)
|
||||
{
|
||||
return bx::acos(_x);
|
||||
}
|
||||
|
||||
extern "C" float fmodf(float _numer, float _denom)
|
||||
{
|
||||
return bx::mod(_numer, _denom);
|
||||
return bx::fmod(_numer, _denom);
|
||||
}
|
||||
|
||||
extern "C" double fmod(double _numer, double _denom)
|
||||
{
|
||||
return bx::fmod(_numer, _denom);
|
||||
}
|
||||
|
||||
extern "C" int atoi(const char* _str)
|
||||
|
||||
907
src/dtoa.cpp
907
src/dtoa.cpp
File diff suppressed because it is too large
Load Diff
@@ -162,7 +162,7 @@ void mixTail32(Ty& _self, const uint8_t*& _data, int32_t& _len)
|
||||
|
||||
if (4 == _self.m_count)
|
||||
{
|
||||
uint32_t kk = *( (uint32_t*)&_self.m_tail[0]);
|
||||
uint32_t kk = loadUnaligned<uint32_t>(&_self.m_tail[0]);
|
||||
_self.mix(kk);
|
||||
_self.m_count = 0;
|
||||
}
|
||||
@@ -217,8 +217,8 @@ void mixTail128(Ty& _self, const uint8_t*& _data, int32_t& _len)
|
||||
|
||||
if (16 == _self.m_count)
|
||||
{
|
||||
const uint64_t kk1 = *( (uint64_t*)&_self.m_tail[0]);
|
||||
const uint64_t kk2 = *( (uint64_t*)&_self.m_tail[8]);
|
||||
const uint64_t kk1 = loadUnaligned<uint64_t>(&_self.m_tail[0]);
|
||||
const uint64_t kk2 = loadUnaligned<uint64_t>(&_self.m_tail[8]);
|
||||
_self.mix(kk1, kk2);
|
||||
_self.m_count = 0;
|
||||
}
|
||||
|
||||
18
src/math.cpp
18
src/math.cpp
@@ -8,24 +8,6 @@
|
||||
|
||||
namespace bx
|
||||
{
|
||||
float frexp(float _a, int32_t* _outExp)
|
||||
{
|
||||
const simd32_t expMask = simd32_splat(kFloatExponentMask);
|
||||
const simd32_t ftob = simd32_splat(_a);
|
||||
const simd32_t masked0 = simd_and(ftob, expMask);
|
||||
const simd32_t exp0 = simd_x32_srl(masked0, kFloatExponentBitShift);
|
||||
|
||||
const simd32_t sMantMask = simd32_splat(kFloatSignMask | kFloatMantissaMask);
|
||||
const simd32_t masked1 = simd_and(ftob, sMantMask);
|
||||
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.u32 - 0x7e);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void mtxLookAt(float* _result, const Vec3& _eye, const Vec3& _at, const Vec3& _up, Handedness::Enum _handedness)
|
||||
{
|
||||
const Vec3 view = normalize(
|
||||
|
||||
@@ -949,12 +949,18 @@ namespace bx
|
||||
char* fracBegin = &str[dot - str + min(prec + _param.spec, 1)];
|
||||
const int32_t curPrec = int32_t(fracEnd - fracBegin);
|
||||
|
||||
const int32_t outPrec = 'g' == _param.fmt ? min(prec, curPrec) : prec;
|
||||
const int32_t exponentLen = int32_t(strEnd - fracEnd);
|
||||
const int32_t maxPrec = int32_t(sizeof(str) ) - 1
|
||||
- int32_t(fracBegin - str)
|
||||
- exponentLen
|
||||
;
|
||||
|
||||
const int32_t reqPrec = 'g' == _param.fmt ? min(prec, curPrec) : prec;
|
||||
const int32_t outPrec = min(reqPrec, maxPrec);
|
||||
|
||||
// Move exponent to its final location after trimming or adding extra 0s.
|
||||
if (fracEnd != strEnd)
|
||||
{
|
||||
const int32_t exponentLen = int32_t(strEnd - fracEnd);
|
||||
char* finalExponentPtr = &fracBegin[outPrec];
|
||||
memMove(finalExponentPtr, fracEnd, exponentLen);
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ uint32_t MurmurHash2A(const void * key, int len, uint32_t seed = 0)
|
||||
|
||||
while(len >= 4)
|
||||
{
|
||||
uint32_t k = *(uint32_t*)data;
|
||||
uint32_t k = bx::loadUnaligned<uint32_t>(data);
|
||||
|
||||
mmix(h,k);
|
||||
|
||||
@@ -206,11 +206,11 @@ uint32_t MurmurHash3_x86_32(const void * key, int len, uint32_t seed)
|
||||
//----------
|
||||
// body
|
||||
|
||||
const uint32_t * blocks = (const uint32_t *)(data + nblocks*4);
|
||||
const uint8_t * blocks = data + nblocks*4;
|
||||
|
||||
for(int i = -nblocks; i; i++)
|
||||
{
|
||||
uint32_t k1 = blocks[i];
|
||||
uint32_t k1 = bx::loadUnaligned<uint32_t>(blocks + i*4);
|
||||
|
||||
k1 *= c1;
|
||||
k1 = rotl32(k1,15);
|
||||
|
||||
@@ -735,9 +735,9 @@ TEST_CASE("pow", "[math][libm]")
|
||||
STATIC_REQUIRE(0.0f == bx::pow(0.0f, 2.0f) );
|
||||
|
||||
STATIC_REQUIRE( 4.0f == bx::pow( 2.0f, 2.0f) );
|
||||
STATIC_REQUIRE( -4.0f == bx::pow(-2.0f, 2.0f) );
|
||||
STATIC_REQUIRE( 4.0f == bx::pow(-2.0f, 2.0f) );
|
||||
STATIC_REQUIRE( 0.25f == bx::pow( 2.0f, -2.0f) );
|
||||
STATIC_REQUIRE( -0.25f == bx::pow(-2.0f, -2.0f) );
|
||||
STATIC_REQUIRE( 0.25f == bx::pow(-2.0f, -2.0f) );
|
||||
STATIC_REQUIRE( 8.0f == bx::pow( 2.0f, 3.0f) );
|
||||
STATIC_REQUIRE( -8.0f == bx::pow(-2.0f, 3.0f) );
|
||||
STATIC_REQUIRE( 0.125f == bx::pow( 2.0f, -3.0f) );
|
||||
@@ -968,6 +968,622 @@ TEST_CASE("copySign", "[math][libm]")
|
||||
STATIC_REQUIRE(-bx::kFloatInfinity == bx::copySign(bx::kFloatInfinity, -1389) );
|
||||
}
|
||||
|
||||
typedef double (*MathDoubleFn)(double);
|
||||
|
||||
template<MathDoubleFn BxT, MathDoubleFn CrtT>
|
||||
static void testMathFunc1Double(double _value)
|
||||
{
|
||||
REQUIRE(CrtT(_value) == BxT(_value) );
|
||||
}
|
||||
|
||||
TEST_CASE("floor, ceil, trunc, round double", "[math][libm]")
|
||||
{
|
||||
STATIC_REQUIRE( 13.0 == bx::floor( 13.89) );
|
||||
STATIC_REQUIRE(-14.0 == bx::floor(-13.89) );
|
||||
STATIC_REQUIRE( 14.0 == bx::ceil( 13.89) );
|
||||
STATIC_REQUIRE(-13.0 == bx::ceil( -13.89) );
|
||||
STATIC_REQUIRE( 13.0 == bx::trunc( 13.89) );
|
||||
STATIC_REQUIRE(-13.0 == bx::trunc(-13.89) );
|
||||
|
||||
STATIC_REQUIRE( 2.0 == bx::round( 2.5) );
|
||||
STATIC_REQUIRE( 4.0 == bx::round( 3.5) );
|
||||
STATIC_REQUIRE( -2.0 == bx::round( -2.5) );
|
||||
STATIC_REQUIRE( 0.0 == bx::round( 0.49999999999999994) );
|
||||
|
||||
STATIC_REQUIRE( 1.0e300 == bx::trunc( 1.0e300) );
|
||||
STATIC_REQUIRE(-1.0e300 == bx::floor(-1.0e300) );
|
||||
STATIC_REQUIRE( 0x1p52 == bx::round(0x1p52) );
|
||||
|
||||
STATIC_REQUIRE(bx::kDoubleSignMask == bx::bitCast<uint64_t>(bx::trunc(-0.5) ) );
|
||||
STATIC_REQUIRE(bx::kDoubleSignMask == bx::bitCast<uint64_t>(bx::ceil( -0.5) ) );
|
||||
STATIC_REQUIRE(bx::kDoubleSignMask == bx::bitCast<uint64_t>(bx::round(-0.4) ) );
|
||||
STATIC_REQUIRE(bx::kDoubleExponentMask == bx::bitCast<uint64_t>(bx::floor(bx::kDoubleInfinity) ) );
|
||||
|
||||
testMathFunc1Double<bx::floor, ::floor>( 13.89);
|
||||
testMathFunc1Double<bx::floor, ::floor>(-13.89);
|
||||
testMathFunc1Double<bx::ceil, ::ceil >( 13.89);
|
||||
testMathFunc1Double<bx::ceil, ::ceil >(-13.89);
|
||||
testMathFunc1Double<bx::trunc, ::trunc>( 13.89);
|
||||
testMathFunc1Double<bx::trunc, ::trunc>(-13.89);
|
||||
|
||||
bx::RngMwc rng;
|
||||
|
||||
for (uint32_t ii = 0; ii < 100000; ++ii)
|
||||
{
|
||||
const uint64_t hi = uint64_t(rng.gen() );
|
||||
const uint64_t lo = uint64_t(rng.gen() );
|
||||
const uint64_t bits = (hi<<32) | lo;
|
||||
const double vv = bx::bitsToDouble(bits);
|
||||
|
||||
if (bx::isNan(vv) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
REQUIRE(::floor(vv) == bx::floor(vv) );
|
||||
REQUIRE(::ceil(vv) == bx::ceil(vv) );
|
||||
REQUIRE(::trunc(vv) == bx::trunc(vv) );
|
||||
REQUIRE(::nearbyint(vv) == bx::round(vv) );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("abs, sign, copySign double", "[math][libm]")
|
||||
{
|
||||
STATIC_REQUIRE(13.89 == bx::abs(-13.89) );
|
||||
STATIC_REQUIRE(13.89 == bx::abs( 13.89) );
|
||||
STATIC_REQUIRE(0.0 == bx::abs(-0.0) );
|
||||
STATIC_REQUIRE(!bx::signBit(bx::abs(-0.0) ) );
|
||||
|
||||
STATIC_REQUIRE(-1 == bx::sign(-0.1389) );
|
||||
STATIC_REQUIRE( 0 == bx::sign( 0.0000) );
|
||||
STATIC_REQUIRE( 1 == bx::sign( 0.1389) );
|
||||
|
||||
STATIC_REQUIRE( bx::signBit(-0.0) );
|
||||
STATIC_REQUIRE(!bx::signBit( 0.0) );
|
||||
STATIC_REQUIRE( bx::signBit(-bx::kDoubleInfinity) );
|
||||
|
||||
STATIC_REQUIRE(-13.89 == bx::copySign(13.89, -1.0) );
|
||||
STATIC_REQUIRE( 13.89 == bx::copySign(13.89, 1.0) );
|
||||
STATIC_REQUIRE(bx::signBit(bx::copySign(0.0, -1.0) ) );
|
||||
}
|
||||
|
||||
TEST_CASE("ldexp double", "[math][libm]")
|
||||
{
|
||||
STATIC_REQUIRE(48.0 == bx::ldexp(3.0, 4) );
|
||||
STATIC_REQUIRE(0.4375 == bx::ldexp(7.0, -4) );
|
||||
STATIC_REQUIRE(0x1p1023 == bx::ldexp(1.0, 1023) );
|
||||
STATIC_REQUIRE(0x1p-1022 == bx::ldexp(1.0, -1022) );
|
||||
|
||||
STATIC_REQUIRE(0x1p-1074 == bx::ldexp(1.0, -1074) );
|
||||
STATIC_REQUIRE(0.0 == bx::ldexp(1.0, -1200) );
|
||||
STATIC_REQUIRE(1.0 == bx::ldexp(0x1p-1074, 1074) );
|
||||
REQUIRE(bx::kDoubleInfinity == bx::ldexp(1.0, 1200) );
|
||||
STATIC_REQUIRE(bx::signBit(bx::ldexp(-0.0, 10) ) );
|
||||
|
||||
for (int32_t yy = -1100; yy < 1100; ++yy)
|
||||
{
|
||||
for (double xx = -100.0; xx < 100.0; xx += 7.3)
|
||||
{
|
||||
REQUIRE(::ldexp(xx, yy) == bx::ldexp(xx, yy) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("frexp", "[math][libm]")
|
||||
{
|
||||
constexpr auto frexpConst = []()
|
||||
{
|
||||
int32_t exp = 0;
|
||||
const double frac = bx::frexp(12.0, &exp);
|
||||
|
||||
return 0.75 == frac && 4 == exp;
|
||||
}();
|
||||
STATIC_REQUIRE(frexpConst);
|
||||
|
||||
bx::RngMwc rng;
|
||||
|
||||
for (uint32_t ii = 0; ii < 100000; ++ii)
|
||||
{
|
||||
const uint64_t hi = uint64_t(rng.gen() );
|
||||
const uint64_t lo = uint64_t(rng.gen() );
|
||||
const uint64_t bits = (hi<<32) | lo;
|
||||
const double vv = bx::bitsToDouble(bits);
|
||||
|
||||
if (bx::isNan(vv) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int32_t mine = 0;
|
||||
int theirs = 0;
|
||||
const double fa = bx::frexp(vv, &mine);
|
||||
const double fb = ::frexp(vv, &theirs);
|
||||
|
||||
REQUIRE(fa == fb);
|
||||
REQUIRE(mine == theirs);
|
||||
}
|
||||
|
||||
for (uint32_t ii = 0; ii < 100000; ++ii)
|
||||
{
|
||||
const float vv = bx::bitsToFloat(rng.gen() );
|
||||
|
||||
if (bx::isNan(vv) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int32_t mine = 0;
|
||||
int theirs = 0;
|
||||
const float fa = bx::frexp(vv, &mine);
|
||||
const float fb = ::frexpf(vv, &theirs);
|
||||
|
||||
REQUIRE(fa == fb);
|
||||
REQUIRE(mine == theirs);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("modf, fmod, mod double", "[math][libm]")
|
||||
{
|
||||
constexpr auto modfConst = []()
|
||||
{
|
||||
double integral = 0.0;
|
||||
const double frac = bx::modf(-2.5, &integral);
|
||||
|
||||
return -2.0 == integral && -0.5 == frac;
|
||||
}();
|
||||
STATIC_REQUIRE(modfConst);
|
||||
|
||||
STATIC_REQUIRE(-1.0 == bx::fmod(-7.0, 3.0) );
|
||||
STATIC_REQUIRE( 2.0 == bx::mod( -7.0, 3.0) );
|
||||
STATIC_REQUIRE( 1.0 == bx::fmod( 7.0, -3.0) );
|
||||
STATIC_REQUIRE( 1.0 == bx::fmod( 7.0, 3.0) );
|
||||
STATIC_REQUIRE( 1.0 == bx::mod( 7.0, 3.0) );
|
||||
|
||||
STATIC_REQUIRE(-1.0f == bx::fmod(-7.0f, 3.0f) );
|
||||
STATIC_REQUIRE( 2.0f == bx::mod( -7.0f, 3.0f) );
|
||||
}
|
||||
|
||||
TEST_CASE("sqrt, log, exp double", "[math][libm]")
|
||||
{
|
||||
STATIC_REQUIRE(4.0 == bx::sqrt(16.0) );
|
||||
STATIC_REQUIRE(0.0 == bx::sqrt(0.0) );
|
||||
STATIC_REQUIRE(bx::signBit(bx::sqrt(-0.0) ) );
|
||||
STATIC_REQUIRE(bx::isNan(bx::sqrt(-1.0) ) );
|
||||
STATIC_REQUIRE(bx::isEqual(1.4142135623730951, bx::sqrt(2.0), 1.0e-15) );
|
||||
|
||||
STATIC_REQUIRE(bx::isEqual(0.0, bx::log(1.0), 1.0e-15) );
|
||||
STATIC_REQUIRE(bx::isEqual(1.0, bx::log(2.71828182845904524), 1.0e-15) );
|
||||
STATIC_REQUIRE(bx::isEqual(0.69314718055994531, bx::log(2.0), 1.0e-15) );
|
||||
STATIC_REQUIRE(-bx::kDoubleInfinity == bx::log(0.0) );
|
||||
STATIC_REQUIRE(bx::isNan(bx::log(-1.0) ) );
|
||||
|
||||
STATIC_REQUIRE( 8.0 == bx::log2(256.0) );
|
||||
STATIC_REQUIRE(10.0 == bx::log2(1024.0) );
|
||||
|
||||
STATIC_REQUIRE(bx::isEqual(1.0, bx::exp(0.0), 1.0e-15) );
|
||||
STATIC_REQUIRE(bx::isEqual(2.71828182845904524, bx::exp(1.0), 1.0e-15) );
|
||||
STATIC_REQUIRE(0.0 == bx::exp(-800.0) );
|
||||
STATIC_REQUIRE(bx::kDoubleInfinity == bx::exp(800.0) );
|
||||
|
||||
STATIC_REQUIRE(1024.0 == bx::exp2(10.0) );
|
||||
|
||||
STATIC_REQUIRE( 81.0 == bx::pow( 3.0, 4.0) );
|
||||
STATIC_REQUIRE( -8.0 == bx::pow(-2.0, 3.0) );
|
||||
STATIC_REQUIRE( 4.0 == bx::pow(-2.0, 2.0) );
|
||||
STATIC_REQUIRE(0.0625 == bx::pow( 2.0, -4.0) );
|
||||
STATIC_REQUIRE( 1.0 == bx::pow( 7.0, 0.0) );
|
||||
STATIC_REQUIRE(bx::isNan(bx::pow(-2.0, 0.5) ) );
|
||||
STATIC_REQUIRE(bx::isEqual(1.4142135623730951, bx::pow(2.0, 0.5), 1.0e-15) );
|
||||
|
||||
for (double xx = 0.125; xx < 1.0e12; xx *= 1.7)
|
||||
{
|
||||
REQUIRE(bx::isEqual(::sqrt(xx), bx::sqrt(xx), 1.0e-15*xx) );
|
||||
REQUIRE(bx::isEqual(::log(xx), bx::log(xx), 1.0e-14) );
|
||||
}
|
||||
|
||||
for (double xx = -700.0; xx < 700.0; xx += 3.1)
|
||||
{
|
||||
const double ref = ::exp(xx);
|
||||
|
||||
REQUIRE(bx::isEqual(ref, bx::exp(xx), 1.0e-14*ref) );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("sin, cos, tan double", "[math][libm]")
|
||||
{
|
||||
STATIC_REQUIRE(0.0 == bx::sin(0.0) );
|
||||
STATIC_REQUIRE(1.0 == bx::cos(0.0) );
|
||||
STATIC_REQUIRE(0.0 == bx::tan(0.0) );
|
||||
|
||||
for (double xx = -100.0; xx < 100.0; xx += 0.37)
|
||||
{
|
||||
REQUIRE(bx::isEqual(::sin(xx), bx::sin(xx), 1.0e-14) );
|
||||
REQUIRE(bx::isEqual(::cos(xx), bx::cos(xx), 1.0e-14) );
|
||||
}
|
||||
|
||||
REQUIRE(bx::isEqual(::sin(1.0e6), bx::sin(1.0e6), 1.0e-12) );
|
||||
REQUIRE(bx::isEqual(::cos(1.0e6), bx::cos(1.0e6), 1.0e-12) );
|
||||
}
|
||||
|
||||
TEST_CASE("asin, acos, atan double", "[math][libm]")
|
||||
{
|
||||
STATIC_REQUIRE(0.0 == bx::asin(0.0) );
|
||||
STATIC_REQUIRE(0.0 == bx::atan(0.0) );
|
||||
STATIC_REQUIRE(0.0 == bx::acos(1.0) );
|
||||
STATIC_REQUIRE(bx::isNan(bx::asin(1.5) ) );
|
||||
STATIC_REQUIRE(bx::isNan(bx::acos(1.5) ) );
|
||||
|
||||
STATIC_REQUIRE(bx::isEqual(1.57079632679489662, bx::asin(1.0), 1.0e-15) );
|
||||
STATIC_REQUIRE(bx::isEqual(3.14159265358979324, bx::acos(-1.0), 1.0e-15) );
|
||||
STATIC_REQUIRE(bx::isEqual(0.78539816339744831, bx::atan(1.0), 1.0e-15) );
|
||||
STATIC_REQUIRE(bx::isEqual(0.78539816339744831, bx::atan2(1.0,1.0), 1.0e-15) );
|
||||
|
||||
for (double xx = -1.0; xx < 1.0; xx += 0.013)
|
||||
{
|
||||
REQUIRE(bx::isEqual(::asin(xx), bx::asin(xx), 1.0e-14) );
|
||||
REQUIRE(bx::isEqual(::acos(xx), bx::acos(xx), 1.0e-14) );
|
||||
}
|
||||
|
||||
for (double xx = -1000.0; xx < 1000.0; xx += 7.3)
|
||||
{
|
||||
REQUIRE(bx::isEqual(::atan(xx), bx::atan(xx), 1.0e-14) );
|
||||
}
|
||||
|
||||
for (double yy = -10.0; yy < 10.0; yy += 1.3)
|
||||
{
|
||||
for (double xx = -10.0; xx < 10.0; xx += 1.3)
|
||||
{
|
||||
REQUIRE(bx::isEqual(::atan2(yy, xx), bx::atan2(yy, xx), 1.0e-14) );
|
||||
}
|
||||
}
|
||||
|
||||
REQUIRE(::atan2( 0.0, 1.0) == bx::atan2( 0.0, 1.0) );
|
||||
REQUIRE(::atan2(-0.0, 1.0) == bx::atan2(-0.0, 1.0) );
|
||||
REQUIRE(::atan2( 0.0, -1.0) == bx::atan2( 0.0, -1.0) );
|
||||
REQUIRE(::atan2(-0.0, -1.0) == bx::atan2(-0.0, -1.0) );
|
||||
REQUIRE(::atan2( 1.0, 0.0) == bx::atan2( 1.0, 0.0) );
|
||||
REQUIRE(::atan2(-1.0, 0.0) == bx::atan2(-1.0, 0.0) );
|
||||
}
|
||||
|
||||
TEST_CASE("sinh, cosh, tanh double", "[math][libm]")
|
||||
{
|
||||
STATIC_REQUIRE(0.0 == bx::sinh(0.0) );
|
||||
STATIC_REQUIRE(1.0 == bx::cosh(0.0) );
|
||||
STATIC_REQUIRE(0.0 == bx::tanh(0.0) );
|
||||
|
||||
for (double xx = -20.0; xx < 20.0; xx += 0.17)
|
||||
{
|
||||
const double sh = ::sinh(xx);
|
||||
const double ch = ::cosh(xx);
|
||||
|
||||
REQUIRE(bx::isEqual(sh, bx::sinh(xx), 1.0e-13*bx::abs(sh) ) );
|
||||
REQUIRE(bx::isEqual(ch, bx::cosh(xx), 1.0e-13*ch) );
|
||||
REQUIRE(bx::isEqual(::tanh(xx), bx::tanh(xx), 1.0e-14) );
|
||||
}
|
||||
|
||||
for (double xx = 1.0e-9; xx < 0.1; xx *= 1.3)
|
||||
{
|
||||
REQUIRE(bx::isEqual(::sinh(xx), bx::sinh(xx), 1.0e-13*xx) );
|
||||
REQUIRE(bx::isEqual(::tanh(xx), bx::tanh(xx), 1.0e-13*xx) );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("log1p, asinh, acosh, atanh", "[math][libm]")
|
||||
{
|
||||
STATIC_REQUIRE(0.0 == bx::log1p(0.0) );
|
||||
STATIC_REQUIRE(0.0 == bx::asinh(0.0) );
|
||||
STATIC_REQUIRE(0.0 == bx::acosh(1.0) );
|
||||
STATIC_REQUIRE(0.0 == bx::atanh(0.0) );
|
||||
STATIC_REQUIRE(-bx::kDoubleInfinity == bx::log1p(-1.0) );
|
||||
STATIC_REQUIRE(bx::kDoubleInfinity == bx::atanh(1.0) );
|
||||
STATIC_REQUIRE(bx::isNan(bx::acosh(0.5) ) );
|
||||
STATIC_REQUIRE(bx::isNan(bx::atanh(1.5) ) );
|
||||
|
||||
STATIC_REQUIRE(bx::isEqual(0.88137358701954303, bx::asinh(1.0), 1.0e-15) );
|
||||
STATIC_REQUIRE(bx::isEqual(1.31695789692481670, bx::acosh(2.0), 1.0e-15) );
|
||||
STATIC_REQUIRE(bx::isEqual(0.54930614433405489, bx::atanh(0.5), 1.0e-15) );
|
||||
|
||||
for (double xx = 1.0e-9; xx < 1.0e9; xx *= 1.7)
|
||||
{
|
||||
REQUIRE(bx::isEqual(::log1p(xx), bx::log1p(xx), 1.0e-14*bx::abs(::log1p(xx) ) ) );
|
||||
REQUIRE(bx::isEqual(::asinh(xx), bx::asinh(xx), 1.0e-14*::asinh(xx) ) );
|
||||
REQUIRE(bx::isEqual(::asinh(-xx), bx::asinh(-xx), 1.0e-14*::asinh(xx) ) );
|
||||
}
|
||||
|
||||
for (double xx = 0.0; xx < 1.0; xx += 0.0131)
|
||||
{
|
||||
REQUIRE(bx::isEqual(::atanh(xx), bx::atanh(xx), 1.0e-14) );
|
||||
}
|
||||
|
||||
for (double tt = 0x1p-40; tt < 0x1p-18; tt *= 2.0)
|
||||
{
|
||||
const double xx = 1.0 + tt;
|
||||
const double poly = 1.0 - tt/12.0 + 3.0*tt*tt/160.0;
|
||||
const double ref = bx::sqrt(2.0*tt) * poly;
|
||||
|
||||
REQUIRE(bx::isEqual(ref, bx::acosh(xx), 1.0e-14*ref) );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("ldexp float range", "[math][libm]")
|
||||
{
|
||||
STATIC_REQUIRE(0x1p127f == bx::ldexp(1.0f, 127) );
|
||||
STATIC_REQUIRE(0x1p-126f == bx::ldexp(1.0f, -126) );
|
||||
STATIC_REQUIRE(0x1p-149f == bx::ldexp(1.0f, -149) );
|
||||
STATIC_REQUIRE(0.0f == bx::ldexp(1.0f, -150) );
|
||||
STATIC_REQUIRE(0.0f == bx::ldexp(1.0f, -400) );
|
||||
STATIC_REQUIRE(1.0f == bx::ldexp(0x1p-149f, 149) );
|
||||
STATIC_REQUIRE(bx::signBit(bx::ldexp(-0.0f, 10) ) );
|
||||
|
||||
REQUIRE(bx::isInfinite(bx::ldexp(1.0f, 128) ) );
|
||||
REQUIRE(bx::isInfinite(bx::ldexp(1.0f, 400) ) );
|
||||
|
||||
for (int32_t yy = -300; yy < 300; ++yy)
|
||||
{
|
||||
for (float xx = -100.0f; xx < 100.0f; xx += 3.7f)
|
||||
{
|
||||
REQUIRE(::ldexpf(xx, yy) == bx::ldexp(xx, yy) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("exp float overflow", "[math][libm]")
|
||||
{
|
||||
REQUIRE(bx::isInfinite(bx::exp( 89.0f) ) );
|
||||
REQUIRE(bx::isInfinite(bx::exp(100.0f) ) );
|
||||
REQUIRE(bx::isInfinite(bx::exp(500.0f) ) );
|
||||
REQUIRE(0.0f == bx::exp(-500.0f) );
|
||||
|
||||
REQUIRE(bx::isInfinite(bx::exp( 800.0) ) );
|
||||
REQUIRE(0.0 == bx::exp(-800.0) );
|
||||
}
|
||||
|
||||
TEST_CASE("sinh, cosh, tanh saturation", "[math][libm]")
|
||||
{
|
||||
REQUIRE( 1.0f == bx::tanh( 90.0f) );
|
||||
REQUIRE(-1.0f == bx::tanh(-90.0f) );
|
||||
REQUIRE( 1.0 == bx::tanh( 9876.0) );
|
||||
REQUIRE(-1.0 == bx::tanh(-9876.0) );
|
||||
|
||||
REQUIRE(bx::isFinite(bx::cosh(88.5f) ) );
|
||||
REQUIRE(bx::isFinite(bx::sinh(88.5f) ) );
|
||||
REQUIRE(bx::isFinite(bx::cosh(710.0) ) );
|
||||
REQUIRE(bx::isFinite(bx::sinh(710.0) ) );
|
||||
REQUIRE(bx::isInfinite(bx::cosh(720.0) ) );
|
||||
|
||||
for (float xx = 1.0e-7f; xx < 1.0f; xx *= 1.3f)
|
||||
{
|
||||
const float ref = float(bx::tanh(double(xx) ) );
|
||||
|
||||
REQUIRE(bx::isEqual(ref, bx::tanh(xx), 1.0e-6f*ref) );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("log1p, asinh, acosh, atanh float", "[math][libm]")
|
||||
{
|
||||
STATIC_REQUIRE(0.0f == bx::log1p(0.0f) );
|
||||
STATIC_REQUIRE(0.0f == bx::asinh(0.0f) );
|
||||
STATIC_REQUIRE(0.0f == bx::acosh(1.0f) );
|
||||
STATIC_REQUIRE(0.0f == bx::atanh(0.0f) );
|
||||
STATIC_REQUIRE(-bx::kFloatInfinity == bx::log1p(-1.0f) );
|
||||
STATIC_REQUIRE( bx::kFloatInfinity == bx::atanh(1.0f) );
|
||||
STATIC_REQUIRE(bx::isNan(bx::acosh(0.5f) ) );
|
||||
STATIC_REQUIRE(bx::isNan(bx::atanh(1.5f) ) );
|
||||
|
||||
for (float xx = 1.0e-6f; xx < 1.0e6f; xx *= 1.7f)
|
||||
{
|
||||
const float rl = float(bx::log1p(double(xx) ) );
|
||||
const float ra = float(bx::asinh(double(xx) ) );
|
||||
|
||||
REQUIRE(bx::isEqual(rl, bx::log1p(xx), 1.0e-6f*bx::abs(rl) ) );
|
||||
REQUIRE(bx::isEqual(ra, bx::asinh(xx), 1.0e-6f*ra) );
|
||||
REQUIRE(bx::isEqual(-ra, bx::asinh(-xx), 1.0e-6f*ra) );
|
||||
}
|
||||
|
||||
for (float tt = 1.0e-6f; tt < 100.0f; tt *= 1.7f)
|
||||
{
|
||||
const float xx = 1.0f + tt;
|
||||
const float ref = float(bx::acosh(double(xx) ) );
|
||||
|
||||
REQUIRE(bx::isEqual(ref, bx::acosh(xx), 1.0e-6f*ref) );
|
||||
}
|
||||
|
||||
for (float xx = 0.0f; xx < 1.0f; xx += 0.013f)
|
||||
{
|
||||
const float ref = float(bx::atanh(double(xx) ) );
|
||||
|
||||
REQUIRE(bx::isEqual(ref, bx::atanh(xx), 1.0e-6f) );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("odd and even symmetry", "[math][libm]")
|
||||
{
|
||||
bx::RngMwc rng;
|
||||
|
||||
for (uint32_t ii = 0; ii < 20000; ++ii)
|
||||
{
|
||||
const double uu = double(rng.gen() ) / 4294967296.0;
|
||||
const double xx = bx::pow(10.0, uu*14.0 - 7.0);
|
||||
|
||||
REQUIRE(bx::sin(-xx) == -bx::sin(xx) );
|
||||
REQUIRE(bx::cos(-xx) == bx::cos(xx) );
|
||||
REQUIRE(bx::tan(-xx) == -bx::tan(xx) );
|
||||
REQUIRE(bx::sinh(-xx) == -bx::sinh(xx) );
|
||||
REQUIRE(bx::cosh(-xx) == bx::cosh(xx) );
|
||||
REQUIRE(bx::tanh(-xx) == -bx::tanh(xx) );
|
||||
REQUIRE(bx::atan(-xx) == -bx::atan(xx) );
|
||||
REQUIRE(bx::asinh(-xx) == -bx::asinh(xx) );
|
||||
REQUIRE(bx::atan2(-xx, 3.0) == -bx::atan2(xx, 3.0) );
|
||||
REQUIRE(bx::atan2(-xx,-3.0) == -bx::atan2(xx,-3.0) );
|
||||
|
||||
const double ss = uu*2.0 - 1.0;
|
||||
|
||||
REQUIRE(bx::asin(-ss) == -bx::asin(ss) );
|
||||
REQUIRE(bx::atanh(-ss*0.999) == -bx::atanh(ss*0.999) );
|
||||
}
|
||||
|
||||
STATIC_REQUIRE(bx::signBit(bx::sin(-0.0) ) );
|
||||
STATIC_REQUIRE(bx::signBit(bx::tan(-0.0) ) );
|
||||
STATIC_REQUIRE(bx::signBit(bx::asin(-0.0) ) );
|
||||
STATIC_REQUIRE(bx::signBit(bx::atan(-0.0) ) );
|
||||
STATIC_REQUIRE(bx::signBit(bx::sinh(-0.0) ) );
|
||||
STATIC_REQUIRE(bx::signBit(bx::tanh(-0.0) ) );
|
||||
STATIC_REQUIRE(bx::signBit(bx::asinh(-0.0) ) );
|
||||
STATIC_REQUIRE(bx::signBit(bx::atanh(-0.0) ) );
|
||||
STATIC_REQUIRE(bx::signBit(bx::log1p(-0.0) ) );
|
||||
STATIC_REQUIRE(bx::signBit(bx::log1p(-0.0f) ) );
|
||||
|
||||
for (double xx = 1.0e-9; xx < 0.4375; xx *= 1.3)
|
||||
{
|
||||
REQUIRE(bx::atan(-xx) == -bx::atan(xx) );
|
||||
REQUIRE(bx::isEqual(::atan(-xx), bx::atan(-xx), 1.0e-14) );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("pow negative base", "[math][libm]")
|
||||
{
|
||||
STATIC_REQUIRE( 4.0f == bx::pow(-2.0f, 2.0f) );
|
||||
STATIC_REQUIRE( -8.0f == bx::pow(-2.0f, 3.0f) );
|
||||
STATIC_REQUIRE( 16.0f == bx::pow(-2.0f, 4.0f) );
|
||||
STATIC_REQUIRE(-0.125f == bx::pow(-2.0f, -3.0f) );
|
||||
STATIC_REQUIRE(bx::isNan(bx::pow(-2.0f, 0.5f) ) );
|
||||
STATIC_REQUIRE(bx::isNan(bx::pow(-2.0f, 1.5f) ) );
|
||||
|
||||
STATIC_REQUIRE( 4.0 == bx::pow(-2.0, 2.0) );
|
||||
STATIC_REQUIRE( -8.0 == bx::pow(-2.0, 3.0) );
|
||||
STATIC_REQUIRE(bx::isNan(bx::pow(-2.0, 0.5) ) );
|
||||
|
||||
STATIC_REQUIRE( 81.0f == bx::pow(3.0f, 4.0f) );
|
||||
STATIC_REQUIRE( 1024.0f == bx::pow(2.0f, 10.0f) );
|
||||
STATIC_REQUIRE( 0.0625f == bx::pow(2.0f, -4.0f) );
|
||||
STATIC_REQUIRE( 1024.0f == bx::exp2(10.0f) );
|
||||
STATIC_REQUIRE( 1.0f == bx::pow(7.0f, 0.0f) );
|
||||
STATIC_REQUIRE( 4.0f == bx::sqrt(16.0f) );
|
||||
|
||||
STATIC_REQUIRE(bx::kFloatInfinity == bx::pow(0.0f, -2.0f) );
|
||||
STATIC_REQUIRE(0.0f == bx::pow(0.0f, 2.0f) );
|
||||
}
|
||||
|
||||
TEST_CASE("exp float accuracy", "[math][libm]")
|
||||
{
|
||||
for (float xx = -103.0f; xx < 88.0f; xx += 0.37f)
|
||||
{
|
||||
const float ref = float(bx::exp(double(xx) ) );
|
||||
|
||||
if (ref >= bx::kFloatSmallest)
|
||||
{
|
||||
REQUIRE(bx::isEqual(ref, bx::exp(xx), 1.0e-6f*ref) );
|
||||
}
|
||||
}
|
||||
|
||||
REQUIRE(::expf(-100.0f) == bx::exp(-100.0f) );
|
||||
REQUIRE(::expf(-103.9f) == bx::exp(-103.9f) );
|
||||
REQUIRE(0.0f == bx::exp(-104.1f) );
|
||||
REQUIRE(bx::isFinite(bx::exp(88.7f) ) );
|
||||
REQUIRE(bx::isInfinite(bx::exp(88.8f) ) );
|
||||
}
|
||||
|
||||
TEST_CASE("sinh, cosh near overflow", "[math][libm]")
|
||||
{
|
||||
for (float xx = 88.0f; xx < 89.4f; xx += 0.013f)
|
||||
{
|
||||
const float rs = float(bx::sinh(double(xx) ) );
|
||||
const float rc = float(bx::cosh(double(xx) ) );
|
||||
|
||||
if (bx::isFinite(rs) )
|
||||
{
|
||||
REQUIRE(bx::isEqual(rs, bx::sinh(xx), 1.0e-6f*rs) );
|
||||
REQUIRE(bx::isEqual(rc, bx::cosh(xx), 1.0e-6f*rc) );
|
||||
}
|
||||
}
|
||||
|
||||
REQUIRE(bx::isFinite(bx::sinh(709.5) ) );
|
||||
REQUIRE(bx::isFinite(bx::cosh(709.5) ) );
|
||||
REQUIRE(bx::isInfinite(bx::cosh(711.0) ) );
|
||||
REQUIRE(bx::signBit(bx::sinh(-709.5) ) );
|
||||
}
|
||||
|
||||
TEST_CASE("trig large argument reduction", "[math][libm]")
|
||||
{
|
||||
REQUIRE(bx::isFinite(bx::sin(1.0e308) ) );
|
||||
REQUIRE(bx::isFinite(bx::cos(1.0e308) ) );
|
||||
REQUIRE(bx::isFinite(bx::tan(1.0e308) ) );
|
||||
REQUIRE(bx::isFinite(bx::sin(7.8145278949113378e+202) ) );
|
||||
REQUIRE(bx::isFinite(bx::cos(7.8145278949113378e+202) ) );
|
||||
|
||||
{
|
||||
int32_t quadrant = 0;
|
||||
const double reduced = bx::reducePiHalfLarge(1.0e16, &quadrant);
|
||||
|
||||
REQUIRE(1 == quadrant);
|
||||
REQUIRE(bx::isEqual(0.4307553505349006*1.5707963267948966, reduced, 1.0e-16) );
|
||||
}
|
||||
|
||||
{
|
||||
int32_t quadrant = 0;
|
||||
const double reduced = bx::reducePiHalfLarge(1.0e22, &quadrant);
|
||||
|
||||
REQUIRE(3 == quadrant);
|
||||
REQUIRE(bx::isEqual(0.35053490057448137839*1.5707963267948966, reduced, 1.0e-16) );
|
||||
}
|
||||
|
||||
for (double xx = 1.0e3; xx < 1.6e6; xx *= 1.3)
|
||||
{
|
||||
int32_t quadrant = 0;
|
||||
|
||||
const double large = bx::reducePiHalfLarge(xx, &quadrant);
|
||||
const double small = bx::sin(xx);
|
||||
|
||||
switch (quadrant)
|
||||
{
|
||||
case 0: REQUIRE(bx::isEqual(small, bx::sinPiQuarter(large), 1.0e-15) ); break;
|
||||
case 1: REQUIRE(bx::isEqual(small, bx::cosPiQuarter(large), 1.0e-15) ); break;
|
||||
case 2: REQUIRE(bx::isEqual(small, -bx::sinPiQuarter(large), 1.0e-15) ); break;
|
||||
default: REQUIRE(bx::isEqual(small, -bx::cosPiQuarter(large), 1.0e-15) ); break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int32_t pp = 21; pp <= 52; ++pp)
|
||||
{
|
||||
const double xx = bx::ldexp(1.0, pp) + 1.0;
|
||||
const double dd = bx::ldexp(1.0, -8);
|
||||
|
||||
if (xx + dd - xx != dd)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const double lhs = bx::sin(xx + dd);
|
||||
const double rhs = bx::sin(xx)*bx::cos(dd) + bx::cos(xx)*bx::sin(dd);
|
||||
|
||||
REQUIRE(bx::isEqual(lhs, rhs, 1.0e-15) );
|
||||
}
|
||||
|
||||
bx::RngMwc rng;
|
||||
|
||||
for (uint32_t ii = 0; ii < 50000; ++ii)
|
||||
{
|
||||
const uint64_t hi = uint64_t(rng.gen() );
|
||||
const uint64_t lo = uint64_t(rng.gen() );
|
||||
const uint64_t bits = (hi<<32) | lo;
|
||||
const double xx = bx::bitsToDouble(bits);
|
||||
|
||||
if (bx::isNan(xx) || bx::isInfinite(xx) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const double ss = bx::sin(xx);
|
||||
const double cc = bx::cos(xx);
|
||||
|
||||
REQUIRE(bx::isFinite(ss) );
|
||||
REQUIRE(bx::isFinite(cc) );
|
||||
REQUIRE(bx::abs(ss) <= 1.0);
|
||||
REQUIRE(bx::abs(cc) <= 1.0);
|
||||
REQUIRE(bx::isEqual(1.0, ss*ss + cc*cc, 1.0e-15) );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("bitsToFloat, floatToBits, bitsToDouble, doubleToBits", "[math]")
|
||||
{
|
||||
STATIC_REQUIRE(0x12345678u == bx::floatToBits( bx::bitsToFloat (0x12345678u) ) );
|
||||
|
||||
@@ -710,6 +710,116 @@ static void parity2(const char* _name, SimdFn _simd, ScalarFn _scalar, float _lo
|
||||
CHECK(0 == bad);
|
||||
}
|
||||
|
||||
static float accuracyInput(bx::RngMwc& _rng, float _lo, float _hi)
|
||||
{
|
||||
const uint32_t r = _rng.gen();
|
||||
|
||||
switch (r & 31)
|
||||
{
|
||||
case 0: return 0.0f;
|
||||
case 1: return clamp( 1.0f, _lo, _hi);
|
||||
case 2: return clamp(-1.0f, _lo, _hi);
|
||||
case 3: return clamp( 0.5f, _lo, _hi);
|
||||
case 4: return _lo;
|
||||
case 5: return _hi;
|
||||
default: break;
|
||||
}
|
||||
|
||||
const float t = float(_rng.gen() & 0xffffff) * (1.0f/16777216.0f);
|
||||
|
||||
return _lo + (_hi - _lo) * t;
|
||||
}
|
||||
|
||||
template<typename Ty, typename SimdFn, typename RefFn, typename ScaleFn>
|
||||
static void accuracy1(const char* _name, SimdFn _simd, RefFn _ref, ScaleFn _scale, double _tol, float _lo, float _hi)
|
||||
{
|
||||
constexpr uint32_t kNumLanes = sizeof(Ty)/sizeof(float);
|
||||
bx::RngMwc rng;
|
||||
double maxErr = 0.0;
|
||||
float badIn = 0.0f;
|
||||
|
||||
for (uint32_t ii = 0; ii < 2048; ++ii)
|
||||
{
|
||||
alignas(sizeof(Ty) ) float in[kNumLanes];
|
||||
alignas(sizeof(Ty) ) float out[kNumLanes];
|
||||
|
||||
for (uint32_t jj = 0; jj < kNumLanes; ++jj)
|
||||
{
|
||||
in[jj] = accuracyInput(rng, _lo, _hi);
|
||||
}
|
||||
|
||||
simd_st(out, _simd(simd_ld<Ty>(in) ) );
|
||||
|
||||
for (uint32_t jj = 0; jj < kNumLanes; ++jj)
|
||||
{
|
||||
const double ref = _ref(double(in[jj]) );
|
||||
|
||||
if (bx::abs(ref) > double(bx::kFloatLargest) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const double err = bx::abs(double(out[jj]) - ref) / _scale(ref);
|
||||
|
||||
if (err > maxErr)
|
||||
{
|
||||
maxErr = err;
|
||||
badIn = in[jj];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INFO(_name << " lanes=" << kNumLanes << ": worst " << maxErr << " at " << badIn << ", budget " << _tol);
|
||||
CHECK(maxErr <= _tol);
|
||||
}
|
||||
|
||||
template<typename Ty, typename SimdFn, typename RefFn, typename ScaleFn>
|
||||
static void accuracy2(const char* _name, SimdFn _simd, RefFn _ref, ScaleFn _scale, double _tol, float _lo0, float _hi0, float _lo1, float _hi1)
|
||||
{
|
||||
constexpr uint32_t kNumLanes = sizeof(Ty)/sizeof(float);
|
||||
bx::RngMwc rng;
|
||||
double maxErr = 0.0;
|
||||
float badIn0 = 0.0f;
|
||||
float badIn1 = 0.0f;
|
||||
|
||||
for (uint32_t ii = 0; ii < 2048; ++ii)
|
||||
{
|
||||
alignas(sizeof(Ty) ) float in0[kNumLanes];
|
||||
alignas(sizeof(Ty) ) float in1[kNumLanes];
|
||||
alignas(sizeof(Ty) ) float out[kNumLanes];
|
||||
|
||||
for (uint32_t jj = 0; jj < kNumLanes; ++jj)
|
||||
{
|
||||
in0[jj] = accuracyInput(rng, _lo0, _hi0);
|
||||
in1[jj] = accuracyInput(rng, _lo1, _hi1);
|
||||
}
|
||||
|
||||
simd_st(out, _simd(simd_ld<Ty>(in0), simd_ld<Ty>(in1) ) );
|
||||
|
||||
for (uint32_t jj = 0; jj < kNumLanes; ++jj)
|
||||
{
|
||||
const double ref = _ref(double(in0[jj]), double(in1[jj]) );
|
||||
|
||||
if (bx::abs(ref) > double(bx::kFloatLargest) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const double err = bx::abs(double(out[jj]) - ref) / _scale(ref);
|
||||
|
||||
if (err > maxErr)
|
||||
{
|
||||
maxErr = err;
|
||||
badIn0 = in0[jj];
|
||||
badIn1 = in1[jj];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INFO(_name << " lanes=" << kNumLanes << ": worst " << maxErr << " at " << badIn0 << ", " << badIn1 << ", budget " << _tol);
|
||||
CHECK(maxErr <= _tol);
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
static void parityAll()
|
||||
{
|
||||
@@ -721,21 +831,21 @@ static void parityAll()
|
||||
parity1<Ty>("fract", [](Ty a ) { return simd_f32_fract(a); }, [](float a ) { return bx::fract(a); }, -1.0e6f, 1.0e6f);
|
||||
parity1<Ty>("sign", [](Ty a ) { return simd_f32_sign(a); }, [](float a ) { return bx::sign(a); }, -10.0f, 10.0f, false);
|
||||
parity1<Ty>("smoothstep", [](Ty a ) { return simd_f32_smoothstep(a); }, [](float a ) { return bx::smoothStep(a); }, -2.0f, 2.0f);
|
||||
parity1<Ty>("cos", [](Ty a ) { return simd_f32_cos(a); }, [](float a ) { return bx::cos(a); }, -100.0f, 100.0f);
|
||||
parity1<Ty>("sin", [](Ty a ) { return simd_f32_sin(a); }, [](float a ) { return bx::sin(a); }, -100.0f, 100.0f);
|
||||
parity1<Ty>("tan", [](Ty a ) { return simd_f32_tan(a); }, [](float a ) { return bx::tan(a); }, -100.0f, 100.0f);
|
||||
accuracy1<Ty>("cos", [](Ty a) { return simd_f32_cos(a); }, [](double a) { return bx::cos(a); }, [](double ) { return 1.0; }, 1.0e-5, -100.0f, 100.0f);
|
||||
accuracy1<Ty>("sin", [](Ty a) { return simd_f32_sin(a); }, [](double a) { return bx::sin(a); }, [](double ) { return 1.0; }, 1.0e-5, -100.0f, 100.0f);
|
||||
accuracy1<Ty>("tan", [](Ty a) { return simd_f32_tan(a); }, [](double a) { return bx::tan(a); }, [](double _r ) { return 1.0 + _r*_r; }, 1.0e-5, -100.0f, 100.0f);
|
||||
parity1<Ty>("exp", [](Ty a ) { return simd_f32_exp(a); }, [](float a ) { return bx::exp(a); }, -90.0f, 90.0f);
|
||||
parity1<Ty>("log", [](Ty a ) { return simd_f32_log(a); }, [](float a ) { return bx::log(a); }, 1.0e-30f, 1.0e30f, false);
|
||||
parity1<Ty>("exp2", [](Ty a ) { return simd_f32_exp2(a); }, [](float a ) { return bx::exp2(a); }, -120.0f, 120.0f, false);
|
||||
parity1<Ty>("log2", [](Ty a ) { return simd_f32_log2(a); }, [](float a ) { return bx::log2(a); }, 1.0e-30f, 1.0e30f, false);
|
||||
parity1<Ty>("acos", [](Ty a ) { return simd_f32_acos(a); }, [](float a ) { return bx::acos(a); }, -1.5f, 1.5f);
|
||||
parity1<Ty>("asin", [](Ty a ) { return simd_f32_asin(a); }, [](float a ) { return bx::asin(a); }, -1.5f, 1.5f);
|
||||
parity1<Ty>("atan", [](Ty a ) { return simd_f32_atan(a); }, [](float a ) { return bx::atan(a); }, -1000.0f, 1000.0f, false);
|
||||
accuracy1<Ty>("acos", [](Ty a) { return simd_f32_acos(a); }, [](double a) { return bx::acos(a); }, [](double ) { return 1.0; }, 1.0e-4, -1.5f, 1.5f);
|
||||
accuracy1<Ty>("asin", [](Ty a) { return simd_f32_asin(a); }, [](double a) { return bx::asin(a); }, [](double ) { return 1.0; }, 1.0e-4, -1.5f, 1.5f);
|
||||
accuracy1<Ty>("atan", [](Ty a) { return simd_f32_atan(a); }, [](double a) { return bx::atan(a); }, [](double ) { return 1.0; }, 5.0e-6, -1000.0f, 1000.0f);
|
||||
parity1<Ty>("sinh", [](Ty a ) { return simd_f32_sinh(a); }, [](float a ) { return bx::sinh(a); }, -30.0f, 30.0f);
|
||||
parity1<Ty>("cosh", [](Ty a ) { return simd_f32_cosh(a); }, [](float a ) { return bx::cosh(a); }, -30.0f, 30.0f);
|
||||
parity1<Ty>("tanh", [](Ty a ) { return simd_f32_tanh(a); }, [](float a ) { return bx::tanh(a); }, -30.0f, 30.0f);
|
||||
parity2<Ty>("pow", [](Ty a, Ty b) { return simd_f32_pow(a, b); }, [](float a, float b) { return bx::pow(a, b); }, 0.01f, 100.0f, -10.0f, 10.0f, false);
|
||||
parity2<Ty>("atan2", [](Ty y, Ty x) { return simd_f32_atan2(y, x); }, [](float y, float x) { return bx::atan2(y, x); }, -100.0f, 100.0f, -100.0f, 100.0f, false);
|
||||
accuracy2<Ty>("pow", [](Ty a, Ty b) { return simd_f32_pow(a, b); }, [](double a, double b) { return bx::pow(a, b); }, [](double _r) { return bx::abs(_r); }, 1.0e-5, 0.01f, 100.0f, -10.0f, 10.0f);
|
||||
accuracy2<Ty>("atan2", [](Ty y, Ty x) { return simd_f32_atan2(y, x); }, [](double y, double x) { return bx::atan2(y, x); }, [](double ) { return 1.0; }, 5.0e-6, -100.0f, 100.0f, -100.0f, 100.0f);
|
||||
parity2<Ty>("step", [](Ty e, Ty a) { return simd_f32_step(e, a); }, [](float e, float a) { return bx::step(e, a); }, -10.0f, 10.0f, -10.0f, 10.0f);
|
||||
parity2<Ty>("mod", [](Ty a, Ty b) { return simd_f32_mod(a, b); }, [](float a, float b) { return bx::mod(a, b); }, -100.0f, 100.0f, -10.0f, 10.0f);
|
||||
}
|
||||
|
||||
@@ -514,6 +514,156 @@ TEST_CASE("fromString hex float", "[string]")
|
||||
REQUIRE(f == bx::kFloatSmallest);
|
||||
}
|
||||
|
||||
TEST_CASE("fromString round half to even", "[string]")
|
||||
{
|
||||
double d = 0.0;
|
||||
|
||||
REQUIRE(bx::fromString(&d, "1e23") );
|
||||
REQUIRE(bx::doubleToBits(d) == UINT64_C(0x44b52d02c7e14af6) );
|
||||
|
||||
REQUIRE(bx::fromString(&d, "9007199254740993") );
|
||||
REQUIRE(d == 9007199254740992.0);
|
||||
|
||||
REQUIRE(bx::fromString(&d, "7.2057594037927933e16") );
|
||||
REQUIRE(d == 72057594037927936.0);
|
||||
|
||||
REQUIRE(bx::fromString(&d, "9007199254740992.5") );
|
||||
REQUIRE(d == 9007199254740992.0);
|
||||
|
||||
REQUIRE(bx::fromString(&d, "9007199254740993.5") );
|
||||
REQUIRE(d == 9007199254740994.0);
|
||||
|
||||
REQUIRE(bx::fromString(&d, "1.00000000000000011102230246251565404236316680908203125") );
|
||||
REQUIRE(d == 1.0);
|
||||
|
||||
REQUIRE(bx::fromString(&d, "1.000000000000000111022302462515654042363166809082031250000001") );
|
||||
REQUIRE(d == 1.0000000000000002);
|
||||
|
||||
REQUIRE(bx::fromString(&d, "1.00000000000000011102230246251565404236316680908203124999999") );
|
||||
REQUIRE(d == 1.0);
|
||||
}
|
||||
|
||||
TEST_CASE("fromString subnormal", "[string]")
|
||||
{
|
||||
double d = 1.0;
|
||||
|
||||
REQUIRE(bx::fromString(&d, "5e-324") );
|
||||
REQUIRE(d == 0x1p-1074);
|
||||
|
||||
REQUIRE(bx::fromString(&d, "2.5e-324") );
|
||||
REQUIRE(d == 0x1p-1074);
|
||||
|
||||
REQUIRE(bx::fromString(&d, "2e-324") );
|
||||
REQUIRE(d == 0.0);
|
||||
|
||||
REQUIRE(bx::fromString(&d, "1e-320") );
|
||||
REQUIRE(bx::doubleToBits(d) == UINT64_C(0x00000000000007e8) );
|
||||
|
||||
REQUIRE(bx::fromString(&d, "1e-308") );
|
||||
REQUIRE(bx::doubleToBits(d) == UINT64_C(0x000730d67819e8d2) );
|
||||
|
||||
for (int32_t exp = -1022; exp >= -1074; --exp)
|
||||
{
|
||||
char tmp[1200];
|
||||
const double value = bx::ldexp(1.0, exp);
|
||||
|
||||
bx::toString(tmp, BX_COUNTOF(tmp), value);
|
||||
|
||||
double read = 0.0;
|
||||
REQUIRE(bx::fromString(&read, tmp) );
|
||||
REQUIRE(read == value);
|
||||
}
|
||||
|
||||
float f = 1.0f;
|
||||
|
||||
REQUIRE(bx::fromString(&f, "1e-45") );
|
||||
REQUIRE(f == 0x1p-149f);
|
||||
|
||||
REQUIRE(bx::fromString(&f, "1e-46") );
|
||||
REQUIRE(f == 0.0f);
|
||||
}
|
||||
|
||||
TEST_CASE("fromString rejects malformed", "[string]")
|
||||
{
|
||||
const char* bad[] = { "", "abc", "+", "-", ".", "e10", " ", "0x", "-0x", "+.e5" };
|
||||
|
||||
for (const char* str : bad)
|
||||
{
|
||||
double d = 1234.5;
|
||||
float f = 1234.5f;
|
||||
|
||||
REQUIRE(!bx::fromString(&d, str) );
|
||||
REQUIRE(!bx::fromString(&f, str) );
|
||||
}
|
||||
|
||||
double d = 0.0;
|
||||
REQUIRE(bx::fromString(&d, "12abc") );
|
||||
REQUIRE(d == 12.0);
|
||||
}
|
||||
|
||||
TEST_CASE("fromString float rounds once", "[string]")
|
||||
{
|
||||
float f = 0.0f;
|
||||
|
||||
REQUIRE(bx::fromString(&f, "1e23") );
|
||||
REQUIRE(bx::floatToBits(f) == UINT32_C(0x65a96816) );
|
||||
|
||||
REQUIRE(bx::fromString(&f, "0.1") );
|
||||
REQUIRE(f == 0.1f);
|
||||
|
||||
REQUIRE(bx::fromString(&f, "16777217") );
|
||||
REQUIRE(f == 16777216.0f);
|
||||
|
||||
REQUIRE(bx::fromString(&f, "3.4028234663852886e+38") );
|
||||
REQUIRE(f == bx::kFloatLargest);
|
||||
|
||||
REQUIRE(bx::fromString(&f, "1e39") );
|
||||
REQUIRE(bx::isInfinite(f) );
|
||||
}
|
||||
|
||||
TEST_CASE("fromString long digit strings", "[string]")
|
||||
{
|
||||
const double values[] =
|
||||
{
|
||||
1.0, 0.1, 1.0e-300, 1.0e300, 0x1p-1074, 2.2250738585072014e-308,
|
||||
1.7976931348623157e308, 3.141592653589793, -79.39773355813419,
|
||||
};
|
||||
|
||||
for (double value : values)
|
||||
{
|
||||
char tmp[1200];
|
||||
bx::snprintf(tmp, BX_COUNTOF(tmp), "%.760e", value);
|
||||
|
||||
double read = 0.0;
|
||||
REQUIRE(bx::fromString(&read, tmp) );
|
||||
REQUIRE(read == value);
|
||||
}
|
||||
|
||||
double d = 0.0;
|
||||
REQUIRE(bx::fromString(&d, "1.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001") );
|
||||
REQUIRE(d == 1.0);
|
||||
}
|
||||
|
||||
TEST_CASE("fromString hex wide mantissa", "[string]")
|
||||
{
|
||||
double d = 0.0;
|
||||
|
||||
REQUIRE(bx::fromString(&d, "0x1fffffffffffffp0") );
|
||||
REQUIRE(d == 9007199254740991.0);
|
||||
|
||||
REQUIRE(bx::fromString(&d, "0x1ffffffffffffff80p0") );
|
||||
REQUIRE(d == 36893488147419103232.0);
|
||||
|
||||
REQUIRE(bx::fromString(&d, "0x1p-1074") );
|
||||
REQUIRE(d == 0x1p-1074);
|
||||
|
||||
REQUIRE(bx::fromString(&d, "0x1p-1075") );
|
||||
REQUIRE(d == 0.0);
|
||||
|
||||
REQUIRE(bx::fromString(&d, "0x3p-1075") );
|
||||
REQUIRE(d == 0x1p-1073);
|
||||
}
|
||||
|
||||
static bool testFromString(int32_t _value, const char* _input)
|
||||
{
|
||||
char tmp[1024];
|
||||
|
||||
Reference in New Issue
Block a user