Faster Remainder by Direct Computation
introduction in general, on common processor machine, Integer multiplication is many times faster than division. So dividing a numerator n by a divisor d is mathematically equivalent to multiplication by the inverse of the divisor
n / d = n * (1/d)
faster remainder algorithm for detail, see paperFaster Remainder by Direct Computation Applications to Compilers and Software Libraries
the faster remainder algorithm implemented in c is following(unsigned and signed):
1
2
3
4
5
6
7
8
9
10uint32_t d = ...; // your divisor > 0
// c = ceil ( (1 < <64) / d ) ; we take L = N
uint64_t c = UINT64_C (0xFFFFFFFFFFFFFFFF ) / d + 1;
// fastmod computes (n mod d) given precomputed c
uint32_t fastmod ( uint32_t n /* , uint64_t c, uint32_t d */) {
uint64_t lowbits = c * n;
return (( __uint128_t ) lowbits * d) >> 64;
}
1 | int32_t d = ...; // your non - zero divisor in [ -2147483647 ,2147483647] |
judge divisiablility 1
2
3
4
5
6
7
8
9// calculate c for use in lkk_divisible
uint64_t lkk_cvalue ( uint32_t d) {
return 1 + UINT64_C (0xffffffffffffffff ) / d;
}
// given precomputed c, checks whether n % d == 0
bool lkk_divisible ( uint32_t n, uint64_t c) {
// rhs is large when c ==0
return n * c <= c - 1;
}
1 | // rotate n by e bits , avoiding undefined behaviors |