mirror of
https://github.com/bkaradzic/bx.git
synced 2026-02-17 20:52:37 +01:00
Added saturateCast. (#354)
This commit is contained in:
committed by
GitHub
parent
5dc415ee2e
commit
4ac903bdcf
@@ -224,6 +224,16 @@ namespace bx
|
|||||||
template <typename Ty, typename FromT>
|
template <typename Ty, typename FromT>
|
||||||
constexpr Ty bitCast(const FromT& _from);
|
constexpr Ty bitCast(const FromT& _from);
|
||||||
|
|
||||||
|
/// Performs `static_cast` of value `_from`, and if value doesn't fit result type `Ty` it clamps
|
||||||
|
/// the value to `Ty` min/max.
|
||||||
|
template<typename Ty, typename FromT>
|
||||||
|
constexpr Ty saturateCast(const FromT& _from);
|
||||||
|
|
||||||
|
/// Performs `static_cast` of value `_from`, and returns true if the value `_from` is
|
||||||
|
/// representable as `Ty`.
|
||||||
|
template<typename Ty, typename FromT>
|
||||||
|
constexpr bool narrowCastTest(Ty* _out, const FromT& _from);
|
||||||
|
|
||||||
/// Performs `static_cast` of value `_from`, and in debug build runtime verifies/asserts
|
/// Performs `static_cast` of value `_from`, and in debug build runtime verifies/asserts
|
||||||
/// that the value didn't change.
|
/// that the value didn't change.
|
||||||
template<typename Ty, typename FromT>
|
template<typename Ty, typename FromT>
|
||||||
|
|||||||
@@ -171,18 +171,71 @@ namespace bx
|
|||||||
return __builtin_bit_cast(Ty, _from);
|
return __builtin_bit_cast(Ty, _from);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Ty, typename FromT>
|
||||||
|
inline constexpr Ty saturateCast(const FromT& _from)
|
||||||
|
{
|
||||||
|
if constexpr (isSame<Ty, FromT>() )
|
||||||
|
{
|
||||||
|
return _from;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Ty mx = max<Ty>();
|
||||||
|
|
||||||
|
if constexpr (isSigned<Ty>() && isSigned<FromT>() )
|
||||||
|
{
|
||||||
|
if constexpr (sizeof(Ty) < sizeof(FromT) )
|
||||||
|
{
|
||||||
|
constexpr FromT mn = min<Ty>();
|
||||||
|
|
||||||
|
if (_from < mn)
|
||||||
|
{
|
||||||
|
return mn;
|
||||||
|
}
|
||||||
|
else if (_from > mx)
|
||||||
|
{
|
||||||
|
return mx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if constexpr (isSigned<FromT>() )
|
||||||
|
{
|
||||||
|
if (_from < FromT(0) )
|
||||||
|
{
|
||||||
|
return Ty(0);
|
||||||
|
}
|
||||||
|
else if (asUnsigned<FromT>(_from) > mx)
|
||||||
|
{
|
||||||
|
return mx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (_from > asUnsigned<Ty>(max<Ty>() ) )
|
||||||
|
{
|
||||||
|
return mx;
|
||||||
|
}
|
||||||
|
|
||||||
|
return static_cast<Ty>(_from);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Ty, typename FromT>
|
template<typename Ty, typename FromT>
|
||||||
inline constexpr bool narrowCastTest(Ty* _out, const FromT& _from)
|
inline constexpr bool narrowCastTest(Ty* _out, const FromT& _from)
|
||||||
{
|
{
|
||||||
*_out = static_cast<Ty>(_from);
|
if constexpr (isSame<Ty, FromT>() )
|
||||||
|
{
|
||||||
|
*_out = _from;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
*_out = saturateCast<Ty>(_from);
|
||||||
return static_cast<FromT>(*_out) == _from;
|
return static_cast<FromT>(*_out) == _from;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Ty, typename FromT>
|
template<typename Ty, typename FromT>
|
||||||
inline Ty narrowCast(const FromT& _from, Location _location)
|
inline Ty narrowCast(const FromT& _from, Location _location)
|
||||||
{
|
{
|
||||||
Ty to = static_cast<Ty>(_from);
|
Ty to;
|
||||||
BX_ASSERT_LOC(_location, static_cast<FromT>(to) == _from
|
const bool result = narrowCastTest(&to, _from);
|
||||||
|
|
||||||
|
BX_ASSERT_LOC(_location, result
|
||||||
, "bx::narrowCast failed! Value is truncated!"
|
, "bx::narrowCast failed! Value is truncated!"
|
||||||
);
|
);
|
||||||
return to;
|
return to;
|
||||||
|
|||||||
@@ -21,3 +21,101 @@ TEST_CASE("Narrow cast", "[cast]")
|
|||||||
REQUIRE_ASSERTS(bx::narrowCast<int8_t>(uint32_t(128) ) );
|
REQUIRE_ASSERTS(bx::narrowCast<int8_t>(uint32_t(128) ) );
|
||||||
REQUIRE(128 == bx::narrowCast<uint8_t>(int32_t(128) ) );
|
REQUIRE(128 == bx::narrowCast<uint8_t>(int32_t(128) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Ty, typename FromT>
|
||||||
|
inline constexpr bool saturateCastTest(Ty _expectedMin, Ty _expectedMax)
|
||||||
|
{
|
||||||
|
return true
|
||||||
|
&& _expectedMin == bx::saturateCast<Ty>(static_cast<FromT>(_expectedMin) )
|
||||||
|
&& _expectedMax == bx::saturateCast<Ty>(static_cast<FromT>(_expectedMax) )
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Saturate cast", "[cast]")
|
||||||
|
{
|
||||||
|
STATIC_REQUIRE(-128 == bx::saturateCast<int8_t >( int32_t( -255) ) );
|
||||||
|
STATIC_REQUIRE( 127 == bx::saturateCast<int8_t >( int32_t( 255) ) );
|
||||||
|
STATIC_REQUIRE( 127 == bx::saturateCast<int8_t >( int32_t( 127) ) );
|
||||||
|
STATIC_REQUIRE( 127 == bx::saturateCast<int8_t >( int32_t( 128) ) );
|
||||||
|
STATIC_REQUIRE( 127 == bx::saturateCast<int8_t >(uint32_t( 128) ) );
|
||||||
|
STATIC_REQUIRE(-128 == bx::saturateCast<int8_t >( float(-1389.9831f) ) );
|
||||||
|
STATIC_REQUIRE( 127 == bx::saturateCast<int8_t >( float( 1389.9831f) ) );
|
||||||
|
STATIC_REQUIRE( 0 == bx::saturateCast<uint8_t>( int32_t( -128) ) );
|
||||||
|
STATIC_REQUIRE( 128 == bx::saturateCast<uint8_t>( int32_t( 128) ) );
|
||||||
|
STATIC_REQUIRE( -13 == bx::saturateCast<int8_t >( float( -13.89f) ) );
|
||||||
|
STATIC_REQUIRE( 13 == bx::saturateCast<int8_t >( float( 13.89f) ) );
|
||||||
|
STATIC_REQUIRE( 0 == bx::saturateCast<uint8_t>( float( -13.89f) ) );
|
||||||
|
STATIC_REQUIRE( 13 == bx::saturateCast<uint8_t>( float( 13.89f) ) );
|
||||||
|
|
||||||
|
STATIC_REQUIRE(saturateCastTest<int8_t, int8_t>(-128, 127) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<int8_t, uint8_t>( 0, 127) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<int8_t, int16_t>(-128, 127) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<int8_t, uint16_t>( 0, 127) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<int8_t, int32_t>(-128, 127) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<int8_t, uint32_t>( 0, 127) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<int8_t, int64_t>(-128, 127) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<int8_t, uint64_t>( 0, 127) );
|
||||||
|
|
||||||
|
STATIC_REQUIRE(saturateCastTest<uint8_t, int8_t>( 0, 127) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<uint8_t, uint8_t>( 0, 255) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<uint8_t, int16_t>( 0, 255) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<uint8_t, uint16_t>( 0, 255) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<uint8_t, int32_t>( 0, 255) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<uint8_t, uint32_t>( 0, 255) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<uint8_t, int64_t>( 0, 255) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<uint8_t, uint64_t>( 0, 255) );
|
||||||
|
|
||||||
|
STATIC_REQUIRE(saturateCastTest<int16_t, int8_t>( -128, 127) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<int16_t, uint8_t>( 0, 255) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<int16_t, int16_t>( -32768, 32767) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<int16_t, uint16_t>( 0, 32767) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<int16_t, int32_t>( -32768, 32767) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<int16_t, uint32_t>( 0, 32767) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<int16_t, int64_t>( -32768, 32767) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<int16_t, uint64_t>( 0, 32767) );
|
||||||
|
|
||||||
|
STATIC_REQUIRE(saturateCastTest<uint16_t, int8_t>( 0, 127) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<uint16_t, uint8_t>( 0, 255) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<uint16_t, int16_t>( 0, 32767) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<uint16_t, uint16_t>( 0, 65535) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<uint16_t, int32_t>( 0, 65535) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<uint16_t, uint32_t>( 0, 65535) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<uint16_t, int64_t>( 0, 65535) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<uint16_t, uint64_t>( 0, 65535) );
|
||||||
|
|
||||||
|
STATIC_REQUIRE(saturateCastTest<int32_t, int8_t>( -128, 127) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<int32_t, uint8_t>( 0, 255) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<int32_t, int16_t>( -32768, 32767) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<int32_t, uint16_t>( 0, 65535) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<int32_t, int32_t>( -2147483648, 2147483647) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<int32_t, uint32_t>( 0, 2147483647) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<int32_t, int64_t>( -2147483648, 2147483647) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<int32_t, uint64_t>( 0, 2147483647) );
|
||||||
|
|
||||||
|
STATIC_REQUIRE(saturateCastTest<uint32_t, int8_t>( 0, 127) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<uint32_t, uint8_t>( 0, 255) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<uint32_t, int16_t>( 0, 32767) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<uint32_t, uint16_t>( 0, 65535) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<uint32_t, int32_t>( 0, 2147483647) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<uint32_t, uint32_t>( 0, 4294967295) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<uint32_t, int64_t>( 0, 4294967295) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<uint32_t, uint64_t>( 0, 4294967295) );
|
||||||
|
|
||||||
|
STATIC_REQUIRE(saturateCastTest<int64_t, int8_t>( -128, 127) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<int64_t, uint8_t>( 0, 255) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<int64_t, int16_t>( -32768, 32767) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<int64_t, uint16_t>( 0, 65535) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<int64_t, int32_t>( -2147483648, 2147483647) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<int64_t, uint32_t>( 0, 4294967295) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<int64_t, int64_t>( -9223372036854775808ll, 9223372036854775807ll) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<int64_t, uint64_t>( 0, 9223372036854775807ll) );
|
||||||
|
|
||||||
|
STATIC_REQUIRE(saturateCastTest<uint64_t, int8_t>( 0, 127) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<uint64_t, uint8_t>( 0, 255) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<uint64_t, int16_t>( 0, 32767) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<uint64_t, uint16_t>( 0, 65535) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<uint64_t, int32_t>( 0, 2147483647) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<uint64_t, uint32_t>( 0, 4294967295) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<uint64_t, int64_t>( 0, 9223372036854775807ull) );
|
||||||
|
STATIC_REQUIRE(saturateCastTest<uint64_t, uint64_t>( 0, 18446744073709551615ull) );
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user