Skip to content

Instantly share code, notes, and snippets.

@simonlindholm
Created April 18, 2019 20:24
Show Gist options
  • Save simonlindholm/5a7decb29486805d5f3cf15fcddc1db9 to your computer and use it in GitHub Desktop.
Save simonlindholm/5a7decb29486805d5f3cf15fcddc1db9 to your computer and use it in GitHub Desktop.
typedef unsigned long long ull;
struct FastMod {
ull multiplier;
ull divisor;
int shift_size;
int mode = 0;
FastMod(ull divisor) : divisor(divisor) {
shift_size = 64 - __builtin_clzll(divisor) - 1;
if (divisor & (divisor - 1)) {
auto a = (__uint128_t)1 << (shift_size + 64);
multiplier = (ull)(a / divisor);
ull remainder = (ull)(a % divisor);
ull error = divisor - remainder;
mode = 1 + (error >= (1ULL << shift_size));
multiplier *= mode;
multiplier++;
}
else {
multiplier = 1;
mode = 0;
}
}
pair<ull, ull> div_rem(ull numerator) {
ull quotient;
if (mode == 0) {
quotient = numerator >> shift_size;
}
else {
ull up = (ull)((__uint128_t(numerator) * multiplier) >> 64);
if (mode == 1) {
quotient = up >> shift_size;
}
else {
quotient = (up + (numerator - up) / 2) >> shift_size;
}
}
ull remainder = numerator - quotient * divisor;
return {quotient, remainder};
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment