I'm trying to do division on a uint128_t
that is made up of 2 uint64_t
s. Weirdly enough, the function works for uint64_t
s with only the lower value set and the upper value = 0. I don't understand why.
Here's the code for the division and bit shift
class uint128_t{
private:
uint64_t UPPER, LOWER;
public:
// lots of stuff
uint128_t operator<<(int shift){
uint128_t out;
if (shift >= 128)
out = uint128_t(0, 0);
else if ((128 > shift) && (shift >= 64))
out = uint128_t(LOWER << (64 - shift), 0);
else if (shift < 64)
out = uint128_t((UPPER << shift) + (LOWER >> (64 - shift)), LOWER << shift);
return out;
}
uint128_t operator<<=(int shift){
*this = *this << shift;
return *this;
}
uint128_t operator/(uint128_t rhs){
// copy of numerator = copyn
uint128_t copyn(*this), quotient = 0;// constructor: uint128_t(T), uint128_t(S, T), uint128_t(uint128_t), etc
while (copyn >= rhs){
// copy of denomiator = copyd
// temp is the current quotient bit being worked with
uint128_t copyd(rhs), temp(1);
// shift the divosr to the highest bit
while (copyn > (copyd << 1)){
copyd <<= 1;
temp <<= 1;
}
copyn -= copyd;
quotient += temp;
}
return quotient;
}
// more stuff
};
Please ignore my blatant disregard for memory management.
out = uint128_t(LOWER << (64 - shift), 0);
is wrong - it should be shift - 64
instead.
As a style note, ALL_CAPITALS are usually reserved for constants only. Variables and members should use mostly lowercase.
anyway, this version is a little bit faster :)
ensure, 4000 iterations against 127:
uint128_t divident = uint128_t(0xffffffffffffffffULL, 0xffffffffffffffffULL);
uint128_t divisor = 10;
{
uint32_t iter_count = 0;
uint128_t copyn(divident), quotient = 0;
while (copyn >= divisor)
{
++iter_count;
uint128_t copyd(divisor), temp(1);
while ((copyn >> 1) > copyd) { ++iter_count; copyd <<= 1; temp <<= 1; }
copyn -= copyd;
quotient += temp;
}
std::cout << "iterations: " << std::dec << iter_count << std::endl;
}
{
uint32_t iter_count = 0;
uint128_t bit_pos = dtl::bits::upper_bit(divident);
uint128_t tmp = 1, quotient = 0;
do
{
++iter_count;
bit_pos >>= 1;
tmp <<= 1;
if(divident & bit_pos) tmp |= 1;
quotient <<= 1;
if(tmp >= divisor) { tmp -= divisor; quotient |= 1; }
}
while (bit_pos != 1);
std::cout << "iterations: " << std::dec << iter_count << std::endl;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With