calccrypto
calccrypto

Reputation: 8991

operator>> and << output being nulled when outputted

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;
}

http://ideone.com/jnZI9

can anyone figure out why?

Upvotes: 0

Views: 200

Answers (3)

Ken Wayne VanderLinde
Ken Wayne VanderLinde

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

kennytm
kennytm

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

SoapBox
SoapBox

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

Related Questions