Reputation: 8991
i dont understand why the output of both functions are getting nulled when i output them:
class uint128_t{
private:
uint64_t UPPER, LOWER;
public:
// constructors
uint128_t(){
UPPER = 0;
LOWER = 0;
}
template <typename T>
uint128_t(T rhs){
UPPER = 0;
LOWER = (uint64_t) rhs;
}
template <typename S, typename T>
uint128_t(const S upper_rhs, const T lower_rhs){
UPPER = (uint64_t) upper_rhs;
LOWER = (uint64_t) lower_rhs;
}
uint128_t(const uint128_t & rhs){
UPPER = rhs.UPPER;
LOWER = rhs.LOWER;
}
// RHS input args only
// assignment operator
template <typename T> uint128_t & operator=(T rhs){
UPPER = 0;
LOWER = (uint64_t) rhs;
return *this;
}
uint128_t & operator=(uint128_t & rhs){
UPPER = rhs.UPPER;
LOWER = rhs.LOWER;
return *this;
}
uint128_t operator<<(int shift){
if (shift >= 128)
return uint128_t(0, 0);
else if (shift == 64)
return uint128_t(LOWER, 0);
else if (shift < 64)
return uint128_t((UPPER << shift) + (LOWER >> (64 - shift)), LOWER << shift);
else if ((128 > shift) && (shift > 64)){
uint128_t a =uint128_t(LOWER << (shift - 64), 0);
// a will show the correct values
std::cout << a.upper() << " " << a.lower() << std::endl;
return uint128_t(LOWER << (shift - 64), 0);
// in the program that includes this, printing out the values show 0 0
}
}
uint128_t operator>>(int shift){
if (shift >= 128)
return uint128_t(0, 0);
else if (shift == 64)
return uint128_t(0, UPPER);
else if (shift <= 64)
return uint128_t(UPPER >> shift , ((UPPER << (64 - shift))) + (LOWER >> shift));
else if ((128 > shift) && (shift > 64))
return uint128_t(0, (UPPER >> (shift - 64)));
}
uint128_t operator<<=(int shift){
*this = *this << shift;
return *this;
}
uint128_t operator>>=(int shift){
*this = *this >> shift;
return *this;
}
const uint64_t upper() const {
return UPPER;
}
const uint64_t lower() const {
return LOWER;
}
// lots of other stuff
};
int main(){
uint128_t a(0x123456789abcdef1ULL, 0x123456789abcdef1ULL);
a>>= 127; // or a <<= 127;
std::cout <<a.upper() << " " <<a.lower() << std::endl;
return 0;
}
can anyone figure out why?
Upvotes: 0
Views: 200
Reputation: 19339
The reason is as follows:
The type of UPPER
is a 64-bit integer. Also, you are attempting to shift the integer by 63-bits, and the 64th bit is a zero in your case. So you lose all 63-bits which are actually holding the number.
PS: You said you don't like using a debugger, but if you just used one, this would be really really easy to figure out on your own.
Upvotes: 0
Reputation: 523164
>> 127
means shift-out the right-most 127 bits in the number. Since your uint128_t is 0x1234...., the most significant bit is '0'. After a >>= 127
, the number becomes 0, so the output is 0 0
as expected.
As for <<=
, this is because
uint128_t & operator=(uint128_t & rhs)
doesn't match for an rvalue rhs
, while
template <typename T> uint128_t & operator=(T rhs)
matches when T == uint128_t
also, so in
*this = *this << shift;
the template assignment operator will be chosen, which makes only the lower uint64_t be assigned. You should change the first assignent operator's signature to
uint128_t& operator=(const uint128_t& rhs)
// ^^^^^
Upvotes: 2
Reputation: 20609
Your int is 128 bits, you are shifting it down (right) 127 bits which means the upper most bit will be moved to the lower most position, and all other bits will be 0.
But the int in your example is 0x1....
, 0x1
(the highest nibble) is 0001
in binary, which does not have the upper bit set. So 0 is the correct output.
If you change the 0x1...
to an 0x8...
(or anything higher than 0x7) you will most likely see 0...1 in the output.
Upvotes: 3