Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

simplify expression k/m%n

Simple question, is it possible to simplify (or replace division or modulo by less-expensive operation)

(k/m)%n

where variables are integers and operators are C style division and modulo operators.

let me rephrase question slightly, except for case where variables are base2, under what conditions (e.g. some variable may be constant) can expression be simplified (or rephrased partially using base2 operations) to remove the division or modulo?

this is way for me to learn number theory, especially base2 tricks, rather than exercise in performance optimization

Thank you

like image 304
Anycorn Avatar asked Jun 10 '10 05:06

Anycorn


4 Answers

For division with small constant denominator, you can use something like this.

k/m=k*(1/m)
x=(1<<16)/m
k/m=(k*x)>>16

The answer may not be precise depending on the inputs.

For division with small odd constant denominator, you can use the multiplicative inverse. The following constants apply to 32 bit division.

3   2863311531      11  3123612579
5   3435973837      13  3303820997
7   3067833783      15  4008636143
9    954437177      17  4042322161

x/11 == x*3123612579 % 2^32

The % 2^32 is of course free on 32 bit integers. To adopt this to even numbers factor out the twos and apply them later.

x/44 == (x*3123612579 % 2^32) >> 2

Hackers Delight has a chapter on integer division.

The simple modulus and division for powers of two.

x%m == x&(m-1)
x/m == x>>log2(m) // assumes log2(m) is known, not calculated
like image 162
drawnonward Avatar answered Nov 11 '22 07:11

drawnonward


For arbitrary-precision integers, I recommend looking at http://documents.epfl.ch/users/k/ka/kaihara/www/papers/ModMulDiv_Binary.pdf

It presents a hardware approach, but it gives pseudocode that you can adapt.

like image 33
Gabe Avatar answered Nov 11 '22 05:11

Gabe


Obvious optimisations:

  1. m == 1 : The answer will just be k % m.
  2. n == 1 : The answer is always 0.
  3. m is a power of 2 : e.g. if m is 4, you can use (k >> 2) % n;
  4. n is a power of 2 : expression becomes (k / m) & (n - 1);

Checking for #1 and #2 is trivial.

Checking for powers of two is done using:

void isPowerOfTwo(unsigned int x)
{
    return x & (x - 1) == 0;
}
like image 42
Peter Alexander Avatar answered Nov 11 '22 05:11

Peter Alexander


Adding to Peter Alexander's answer

0) Of course m != 0 && n != 0 are pre-conditions...

1) k < m : The answer is always 0

2) k == m : The answer is always 1 (unless n is also 1, see 5.)

3) k / m < n: The answer is k / m

4) k < ( m * n ): The answer is always k / m. This particular condition is not very conducive to optimization since m*n would not be reused and it should not be much faster than modulo unless m and/or n are powers of 2 in which case you'd still be better using 7. and/or 8.

For reference adding Peter Alexander's:

5) m == 1 : The answer will just be k % n.

6) n == 1 : The answer is always 0.

7) m is a power of 2 : e.g. if m is 4, you can use (k >> 2) % n;

8) n is a power of 2 : expression becomes (k / m) & (n - 1);

like image 1
njsf Avatar answered Nov 11 '22 05:11

njsf