简体   繁体   中英

Transform uint64_t range in uint32_t range

I want transform an uint64_t into an uintw_t with w in { 8, 16, 32} preserving "range":

#include <cstdint>
#include <type_traits>

Idea 1:

f:[a,b]->[c,d] with f(a)=c, f(b)=d

let a = 0, b = 2^64-1, c = 0 and d = 2^w-1.

if f(x) = mx+n with m = (dc)/(ba) = (2^w-1)/(2^64-1) < 1 (we need float or double...), n = 0

template<typename T, typename std::enable_if< std::is_unsigned_v <T>, T>::type = 0>
T transform_a(uint64_t n)
{
   constexpr double factor = static_cast<double>(~T(0)) / ~uint64_t(0);
   return static_cast<T>( factor*n );
}

template<>
uint64_t transform_a(uint64_t n)
{
   return n;
}

Don't work with uint16_t :c.

*Idea 2:

Don't work correctly, i wrongly tested it with 0xffffffffffffffffull...

template<typename T, typename std::enable_if< std::is_unsigned_v <T>, T>::type = 0>
T transform_b(uint64_t n)
{
     return static_cast<T>(n);
}

It cuts the number to its lower bits.

Idea 3:

Group bytes and remap with idea 1. For example 0xabcabcab in uint32_t to uint16_t:

abca -> [x] cabc -> [y] with ffff--> ff and 0000--> 00

Idea 4:

Right shift (CHAR_BIT = 8...)

template<typename T, typename std::enable_if< std::is_unsigned_v <T>, T>::type = 0>
T transform_c(uint64_t n)
{
     return static_cast<T>(n>>(64 - 8*sizeof(T)));
}

template<>
uint64_t transform_c(uint64_t n)
{
   return n;
}

This idea makes the most sense to me, however it rules out the effect of minor bits without any weighting or rounding.

https://quick-bench.com/q/Vs1W4UP35MCpJo5pY1ebXnM7QNo

In "real usage" double and shift versions are equivalent for uint32_t In "individual use without context" shift version is faster for uint32_t

My main question would be, what is the most usual in this type of conversions?

As an additional question, is there any efficient way to perform this process with some kind of rounding?

Shifting is standard; you can get some simple rounding by first adding half of the least-significant preserved bit's value before shifting, although that doesn't implement proper round-to-even and you have to worry about overflow.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM