maths: add signed overloads for renormalise
This commit is contained in:
parent
25e19b5810
commit
da00e77e7e
71
maths.hpp
71
maths.hpp
@ -660,13 +660,18 @@ namespace util {
|
|||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// renormalisation of unit floating point and/or normalised integers
|
/// convert between different representations of normalised quantities.
|
||||||
|
///
|
||||||
|
/// * floating point values must be within [0, 1] (otherwise undefined)
|
||||||
|
/// * signed values are handled by converting to unsigned representations
|
||||||
|
/// * may introduce small biases when expanding values so that low order
|
||||||
|
/// bits have some meaning (particularly when dealing with UINTMAX)
|
||||||
|
|
||||||
// int -> float
|
// uint -> float
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
constexpr
|
constexpr
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
!std::is_floating_point<T>::value && std::is_floating_point<U>::value, U
|
std::is_unsigned<T>::value && std::is_floating_point<U>::value, U
|
||||||
>::type
|
>::type
|
||||||
renormalise (T t)
|
renormalise (T t)
|
||||||
{
|
{
|
||||||
@ -675,11 +680,11 @@ namespace util {
|
|||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// float -> int
|
// float -> uint
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
constexpr
|
constexpr
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
std::is_floating_point<T>::value && !std::is_floating_point<U>::value, U
|
std::is_floating_point<T>::value && std::is_unsigned<U>::value, U
|
||||||
>::type
|
>::type
|
||||||
renormalise (T t)
|
renormalise (T t)
|
||||||
{
|
{
|
||||||
@ -708,7 +713,7 @@ namespace util {
|
|||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// float -> float, avoid identity conversion as we don't want to create
|
// float -> float, avoids identity conversion as we don't want to create
|
||||||
// ambiguous overloads
|
// ambiguous overloads
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
constexpr
|
constexpr
|
||||||
@ -724,12 +729,12 @@ namespace util {
|
|||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// hi_int -> lo_int
|
// hi_uint -> lo_uint
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
constexpr
|
constexpr
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
std::is_integral<T>::value &&
|
std::is_unsigned<T>::value &&
|
||||||
std::is_integral<U>::value &&
|
std::is_unsigned<U>::value &&
|
||||||
(sizeof (T) > sizeof (U)), U
|
(sizeof (T) > sizeof (U)), U
|
||||||
>::type
|
>::type
|
||||||
renormalise (T t)
|
renormalise (T t)
|
||||||
@ -744,12 +749,12 @@ namespace util {
|
|||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// lo_int -> hi_int
|
// lo_uint -> hi_uint
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
constexpr
|
constexpr
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
std::is_integral<T>::value &&
|
std::is_unsigned<T>::value &&
|
||||||
std::is_integral<U>::value &&
|
std::is_unsigned<U>::value &&
|
||||||
sizeof (T) < sizeof (U), U
|
sizeof (T) < sizeof (U), U
|
||||||
>::type
|
>::type
|
||||||
renormalise (T t)
|
renormalise (T t)
|
||||||
@ -775,6 +780,8 @@ namespace util {
|
|||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
|
// identity transformation. must precede the signed cases, as they may rely
|
||||||
|
// on this as a side effect of casts.
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
constexpr
|
constexpr
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
@ -782,6 +789,46 @@ namespace util {
|
|||||||
>::type
|
>::type
|
||||||
renormalise (T t)
|
renormalise (T t)
|
||||||
{ return t; }
|
{ return t; }
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// anything-to-sint
|
||||||
|
template <typename T, typename U>
|
||||||
|
constexpr
|
||||||
|
typename std::enable_if<
|
||||||
|
std::is_signed<U>::value &&
|
||||||
|
std::is_integral<U>::value &&
|
||||||
|
!std::is_same<T,U>::value,
|
||||||
|
U
|
||||||
|
>::type
|
||||||
|
renormalise (T t)
|
||||||
|
{
|
||||||
|
using uint_t = typename std::make_unsigned<U>::type;
|
||||||
|
|
||||||
|
return static_cast<U> (
|
||||||
|
::util::renormalise<T,uint_t> (t) + std::numeric_limits<U>::min ()
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// sint-to-anything
|
||||||
|
template <typename T, typename U>
|
||||||
|
constexpr
|
||||||
|
typename std::enable_if<
|
||||||
|
std::is_signed<T>::value &&
|
||||||
|
std::is_integral<T>::value &&
|
||||||
|
!std::is_same<T,U>::value,
|
||||||
|
U
|
||||||
|
>::type
|
||||||
|
renormalise (T sint)
|
||||||
|
{
|
||||||
|
using uint_t = typename std::make_unsigned<T>::type;
|
||||||
|
|
||||||
|
return ::util::renormalise<uint_t,U> (
|
||||||
|
static_cast<uint_t> (sint) - std::numeric_limits<T>::min ()
|
||||||
|
);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -122,6 +122,24 @@ test_normalisations (util::TAP::logger &tap)
|
|||||||
tap.expect_eq (util::renormalise<uint8_t,uint32_t> (0x00), 0x00000000u, "normalise lo u8-to-u32");
|
tap.expect_eq (util::renormalise<uint8_t,uint32_t> (0x00), 0x00000000u, "normalise lo u8-to-u32");
|
||||||
|
|
||||||
tap.expect_eq (util::renormalise<uint32_t,uint8_t> (0xffffffff), 0xffu, "normalise hi u32-to-u8");
|
tap.expect_eq (util::renormalise<uint32_t,uint8_t> (0xffffffff), 0xffu, "normalise hi u32-to-u8");
|
||||||
|
|
||||||
|
// sint32 to uint32
|
||||||
|
{
|
||||||
|
static const struct {
|
||||||
|
int32_t sint;
|
||||||
|
uint32_t uint;
|
||||||
|
const char *msg;
|
||||||
|
} TESTS[] = {
|
||||||
|
{ std::numeric_limits<int32_t>::min (), std::numeric_limits<uint32_t>::min (), "min" },
|
||||||
|
{ std::numeric_limits<int32_t>::max (), std::numeric_limits<uint32_t>::max (), "max" },
|
||||||
|
{ 0, std::numeric_limits<uint32_t>::max () / 2u + 1, "mid" },
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const auto &t: TESTS) {
|
||||||
|
tap.expect_eq (util::renormalise<int32_t,uint32_t> (t.sint), t.uint, "%s s32-to-u32", t.msg);
|
||||||
|
tap.expect_eq (util::renormalise<uint32_t,int32_t> (t.uint), t.sint, "%s u32-to-s32", t.msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user