My goal is to set only the high bit of a general int. I would like to use it as a constant for speed considerations. I can calculate the high bit and it is dependent on whether it is signed or not? I doubt that to be the case, the way I got it to work is the following code. I set a constant value for HIGH_BIT in the template function and the only way that I currently know how to set only the high bit is the following,
you can boolean it..
high bit is simply x&128 (8 bit example).
high_bit = (x&128 != 0);
128 is from 2^(n-1) where n is number of bits in the integer type. 2^7 here.
setting it works similar.
x = x|(128)
or for a conditional assignment
x = x|( (something == other)*128);
the bool conditon becomes 1 or 0. if its true, it ors with 128, setting the bit.
if its zero, it ors with 0 which does nothing at all.
to clear it
you and it with a constant... the constant you get when all the other bits are set, and you can do a similar conditional statement to clear it conditionally as above. Interestingly, the number you want is 1 less than you were using... 128-1 = 127. (because 1000 -1 is 0111 in binary..)
if the type is signed, cast to unsigned to fiddle with bits.
mbozzi - left shift on a 64 bit signed integer causes warnings and does not seem to work. I did use something like meta template programing to come up with the implementation shown. It does work for both signed and unsigned types as it is. Just strange that there isn't something like,
std::numeric_limits< T >::bit_width and std::numeric_limits< T >::high_bit
and I would like to see,
HIGH_BIT = 1 << std::numeric_limits< T >::bit_width;
or simply use the constant high_bit
jonnin - see above mbozzi.
Gando - thanks, yes thank you, it is confusing. I searched before I posted and there seems no simple way to do what I have shown above in this post.
template < std::unsigned_integral N > N set_high_bit( N number )
constexpr std::size_t NBITS = std::numeric_limits<N>::digits ;
std::bitset<NBITS> bitset(number) ;
bitset[NBITS-1] = true ; // set the most significant bit
return N( bitset.to_ullong() ) ;
template < std::signed_integral N > N set_high_bit( N number )
return set_high_bit( std::make_unsigned_t<N>( number ) ) ;
JLBorges - here is a test that hopefully shows the crux of the situation,
std::cout << std::numeric_limits< unsigned long long >::digits << " " << std::numeric_limits< long long >::digits << std::endl;
Produces "64 63", which is close to what I want if I want to use the left shift operator. This is what I got earlier. The high bit depends on whether it is signed or not. Then the left shift operator complains if I try to shift into the high bit of a signed number. I naively though that std::numeric_limits< T >::digits would work and I tried some to get it to work yet it is not so elegant.
mbozzi - ibid
What I have now works for all int types both signed and unsigned.
> The high bit depends on whether it is signed or not.
std::numeric_limits<N>::digits gives the number of bits excluding the sign bit (if any) and padding bits (if any). For instance, in a hypothetical implementation where the object representation of unsigned long long has 64 bits, but its value representation has only 56 bits, std::numeric_limits<unsigned long long>::digits would yield 56 and std::numeric_limits<long long>::digits would yield 55.
JLBorges - yes, I read the standard and was nonplussed. Let me reiterate the original question, is there a way to get the width of all the digits regardless of signedness? Instead of relying CHAR_BITS and sizeof to get the width, I was hoping for a typesafe way to get the total width including the signbit. What I want is not what 'digits' offer.
it could be useful... its the order of magnitude of the number, in binary.
log based 2 would get you there, but I can't see that being faster that bitwise magic, the log circuits are moderately sluggish. There may be hardware specific tricks, but general c++... not seeing anything better.
I'm actually not sure what the goal here is. I don't understand why the answer isn't just sizeof(T) * CHAR_BITS, because an exact example has not been given yet. As far as performance, yeah at best it would be the same speed as any other function that returns a constant number (and with optimizations enabled, there wouldn't even be a function call).
Edit: I guess em's latest post removes any ambiguity if that's what works, and the thread is solved.