How does one get the width of an general int

Pages: 12
Sep 25, 2021 at 1:57am
10 years ago I worked as a developer in c++, my fundamentals are great. Anyway, here is the code I have been playing with to come up to speed.

#include <concepts>
#include <limits>
#include <iostream>

// bit_width including the sign-bit
template < std::integral N > consteval std::size_t bit_width(N = {}) noexcept
{
return std::numeric_limits< std::make_unsigned_t<N> >::digits;
}

// set the most significan bit (including the sign-bit)
template < std::integral N > constexpr N set_msb(N n = 0 ) noexcept
{
return n | (N(1) << (bit_width<N>() - 1));
}

template < std::integral TypeOfInt >
TypeOfInt reverse(TypeOfInt toReverse) noexcept
{
constexpr TypeOfInt HIGH_BIT = set_msb< TypeOfInt >();

TypeOfInt reversed(0);
TypeOfInt countBit(1);

while (toReverse)
{
if (toReverse & HIGH_BIT)
{
reversed |= countBit;
}
toReverse <<= 1;
countBit <<= 1;
}

return reversed;
}

template<>
unsigned int reverse(unsigned int toReverse) noexcept
{
// swap odd and even bits
toReverse = ((toReverse >> 1) & 0x55555555) | ((toReverse & 0x55555555) << 1);
// swap consecutive pairs
toReverse = ((toReverse >> 2) & 0x33333333) | ((toReverse & 0x33333333) << 2);
// swap nibbles ...
toReverse = ((toReverse >> 4) & 0x0F0F0F0F) | ((toReverse & 0x0F0F0F0F) << 4);
// swap bytes
toReverse = ((toReverse >> 8) & 0x00FF00FF) | ((toReverse & 0x00FF00FF) << 8);
// swap 2-byte long pairs
toReverse = (toReverse >> 16) | (toReverse << 16);

return toReverse;
}

template<>
int reverse(int toReverse)
{
return reverse<unsigned int>(toReverse);
}

template<>
unsigned long long reverse(unsigned long long toReverse) noexcept
{
// swap odd and even bits
toReverse = ((toReverse >> 1) & 0x5555555555555555) | ((toReverse & 0x5555555555555555) << 1);
// swap consecutive pairs
toReverse = ((toReverse >> 2) & 0x3333333333333333) | ((toReverse & 0x3333333333333333) << 2);
// swap nibbles ...
toReverse = ((toReverse >> 4) & 0x0F0F0F0F0F0F0F0F) | ((toReverse & 0x0F0F0F0F0F0F0F0F) << 4);
// swap bytes
toReverse = ((toReverse >> 8) & 0x00FF00FF00FF00FF) | ((toReverse & 0x00FF00FF00FF00FF) << 8);
// swap 2-byte long pairs
toReverse = ((toReverse >> 16) & 0x0000FFFF0000FFFF) | ((toReverse & 0x0000FFFF0000FFFF) << 16);
toReverse = (toReverse >> 32) | (toReverse << 32);

return toReverse;
}

template<>
long long reverse(long long toReverse) noexcept
{
return reverse<unsigned long long>(toReverse);
}

int
main(int, char **)
{
std::cout << std::hex << reverse<unsigned char>(0x39) << std::endl;
std::cout << std::hex << reverse<char>(0x39) << std::endl;
std::cout << std::hex << reverse<unsigned short>(0x39) << std::endl;
std::cout << std::hex << reverse<short>(0x39) << std::endl;
std::cout << std::hex << reverse<unsigned int>(0x39) << std::endl;
std::cout << std::hex << reverse<int>(0x39) << std::endl;
std::cout << std::hex << reverse<unsigned long long>(0x39) << std::endl;
std::cout << std::hex << reverse<long long>(0x39) << std::endl;
return 0;
}

Emily@DESKTOP-K2S7IMO ~/programming/Reverse
$ ./Reverse.exe


9c00
9c00
9c000000
9c000000
9c00000000000000
9c00000000000000

Feel free to let me know what you think.
Sep 25, 2021 at 2:09am
PLEASE learn to use code tags, they make reading and commenting on source code MUCH easier.

http://www.cplusplus.com/articles/jEywvCM9/
http://www.cplusplus.com/articles/z13hAqkS/

HINT: you can edit your post and add code tags.

Some formatting & indentation would not hurt either
Sep 25, 2021 at 6:42am
Reverse bits in constant values at compile-time:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <concepts>
#include <limits>

// bit_width including the sign-bit
template < std::integral N > consteval std::size_t bit_width( N = {}  ) noexcept
{
    return std::numeric_limits< std::make_unsigned_t<N> >::digits ;
}

// swap the bits at the two positions
template < std::unsigned_integral N >
constexpr N swap_bits( N number, std::size_t pos_high, std::size_t pos_low ) noexcept
{
    const N bit_one = ( number >> pos_high ) & 1U ;
    const N bit_two = ( number >> pos_low ) & 1U ;
    const N x = bit_one ^ bit_two ;
    const N y = ( x << pos_high ) | ( x << pos_low ) ;
    return number ^ y ;
}

namespace compile_time
{
    // reverse all bits (by recursively swapping bits)
    template < std::unsigned_integral N >
    constexpr N reverse_bits( N number, std::size_t pos_high, std::size_t pos_low ) noexcept
    {
        if( pos_high <= pos_low ) return number ;
        else return reverse_bits( swap_bits(number,pos_high,pos_low), pos_high-1, pos_low+1 ) ;
    }
}

namespace run_time
{
    // reverse all bits efficiently at run-time
    template < std::integral N >
    N reverse_bits( N number ) noexcept ; // *** not implemented
}

template < std::integral N >
constexpr N reverse_bits( N number ) noexcept
{
    if( std::is_constant_evaluated() )
       return compile_time::reverse_bits( std::make_unsigned_t<N>(number), bit_width<N>()-1, 0 ) ;
    else
       return run_time::reverse_bits(number) ;
}

https://gcc.godbolt.org/z/hcnToav15

With a trivial test frame: http://coliru.stacked-crooked.com/a/4e2b015ee4c7ae75
Sep 25, 2021 at 7:11am
Implementing a Fourier transform?
Topic archived. No new replies allowed.
Pages: 12