Efficient divisibility testing
Published
Here’s bit tricks for efficient divisibility testing.
Efficient divisibility testing
The example
Here is a low computational cost method to test if an integer $x$ is divisible by another integer $d$, useful in C-like languages (assembly included). It replaces a possibly costly modulus % operation with a usually lower cost multiplication *.
Here is an example illustrating the method for divisibility by 5:
|
|
What trickery is this? How does it work? Where do the constants 3435973837U and 858993459U come from?
Note the magic numbers depend on the type of $x$. The above example requires $x$ is an unsigned 32 bit integer, and the language has multiplication overflow computed modulus 32. Many common languages (C,C++,C#,Java, ..) do this.
The values
Before giving the details, here is a table of the magic constants for divisibility testing of odd integers from 3 to 101 inclusive. The bitsize is the size of the unsigned integer $x$, and the test is then x*p <= q.
| d | 16-bit p | 16-bit q | 32-bit p | 32-bit q | 64-bit p | 64-bit q |
|---|---|---|---|---|---|---|
| 3 | 43691 | 21845 | 2863311531 | 1431655765 | 12297829382473034411 | 6148914691236517205 |
| 5 | 52429 | 13107 | 3435973837 | 858993459 | 14757395258967641293 | 3689348814741910323 |
| 7 | 28087 | 9362 | 3067833783 | 613566756 | 7905747460161236407 | 2635249153387078802 |
| 9 | 36409 | 7281 | 954437177 | 477218588 | 10248191152060862009 | 2049638230412172401 |
| 11 | 35747 | 5957 | 3123612579 | 390451572 | 3353953467947191203 | 1676976733973595601 |
| 13 | 20165 | 5041 | 3303820997 | 330382099 | 5675921253449092805 | 1418980313362273201 |
| 15 | 61167 | 4369 | 4008636143 | 286331153 | 17216961135462248175 | 1229782938247303441 |
| 17 | 61681 | 3855 | 4042322161 | 252645135 | 17361641481138401521 | 1085102592571150095 |
| 19 | 51739 | 3449 | 678152731 | 226050910 | 9708812670373448219 | 970881267037344821 |
| 21 | 53053 | 3120 | 1022611261 | 204522252 | 14933078535860113213 | 878416384462359600 |
| 23 | 14247 | 2849 | 3921491879 | 186737708 | 15238614669586151335 | 802032351030850070 |
| 25 | 23593 | 2621 | 3264175145 | 171798691 | 10330176681277348905 | 737869762948382064 |
| 27 | 55827 | 2427 | 1749801491 | 159072862 | 9564978408590137875 | 683212743470724133 |
| 29 | 49717 | 2259 | 1332920885 | 148102320 | 3816567739388183093 | 636094623231363848 |
| 31 | 31711 | 2114 | 3186588639 | 138547332 | 17256631552825064415 | 595056260442243600 |
| 33 | 33761 | 1985 | 1041204193 | 130150524 | 1117984489315730401 | 558992244657865200 |
| 35 | 44939 | 1872 | 2331553675 | 122713351 | 12649195936257978251 | 527049830677415760 |
| 37 | 7085 | 1771 | 2437684141 | 116080197 | 1495681951922396077 | 498560650640798692 |
| 39 | 28567 | 1680 | 2532929431 | 110127366 | 8040888442386214807 | 472993437787424400 |
| 41 | 39961 | 1598 | 3247414297 | 104755299 | 10348173504763894809 | 449920587163647600 |
| 43 | 48771 | 1524 | 799063683 | 99882960 | 9437869060967677571 | 428994048225803525 |
| 45 | 20389 | 1456 | 2767867813 | 95443717 | 5738987045154082725 | 409927646082434480 |
| 47 | 18127 | 1394 | 1736263375 | 91382282 | 5887258746928580303 | 392483916461905353 |
| 49 | 22737 | 1337 | 438261969 | 87652393 | 9035139954469984465 | 376464164769582686 |
| 51 | 64251 | 1285 | 4210752251 | 84215045 | 18085043209519168251 | 361700864190383365 |
| 53 | 21021 | 1236 | 2350076445 | 81037118 | 2436362424829563421 | 348051774975651917 |
| 55 | 46471 | 1191 | 1483715975 | 78090314 | 8049488323073258887 | 335395346794719120 |
| 57 | 60937 | 1149 | 3089362441 | 75350303 | 9385185581360999945 | 323627089012448273 |
| 59 | 55539 | 1110 | 2693454067 | 72796055 | 14694863923124558067 | 312656679215416129 |
| 61 | 38677 | 1074 | 3238827797 | 70409299 | 5745707170499696405 | 302405640552615600 |
| 63 | 61375 | 1040 | 3204181951 | 68174084 | 17275522227759738815 | 292805461487453200 |
| 65 | 4033 | 1008 | 3237744577 | 66076419 | 1135184250689818561 | 283796062672454640 |
| 67 | 19563 | 978 | 128207979 | 64103989 | 17345445920055250027 | 275324538413575397 |
| 69 | 4749 | 949 | 2738819725 | 62245902 | 17377367605668418189 | 267344117010283356 |
| 71 | 43383 | 923 | 3811027319 | 60492497 | 1818693077689674103 | 259813296812810586 |
| 73 | 61945 | 897 | 3353604601 | 58835168 | 9097024474706080249 | 252695124297391118 |
| 75 | 51555 | 873 | 2519714147 | 57266230 | 3443392227092449635 | 245956587649460688 |
| 77 | 14469 | 851 | 1059797125 | 55778796 | 5749634516480899205 | 239568104853370800 |
| 79 | 5807 | 829 | 1631000239 | 54366674 | 11208148297950107311 | 233503089540627235 |
| 81 | 18609 | 809 | 2014922929 | 53024287 | 3188326136196712625 | 227737581156908044 |
| 83 | 17371 | 789 | 724452315 | 51746593 | 11779246215742243803 | 222249928598910260 |
| 85 | 64765 | 771 | 4244438269 | 50529027 | 18229723555195321597 | 217020518514230019 |
| 87 | 60263 | 753 | 1875962727 | 49367440 | 7421103937699244903 | 212031541077121282 |
| 89 | 18409 | 736 | 4198451177 | 48258059 | 17617676924329347049 | 207266787345051141 |
| 91 | 12243 | 720 | 3539808211 | 47197442 | 3446095046736949203 | 202711473337467600 |
| 93 | 54261 | 704 | 1062196213 | 46182444 | 5752210517608354805 | 198352086814081200 |
| 95 | 23455 | 689 | 3571604383 | 45210182 | 5631111348816599967 | 194176253407468964 |
| 97 | 41889 | 675 | 1594008481 | 44278013 | 11790702397628785569 | 190172619316593315 |
| 99 | 33099 | 661 | 3210379595 | 43383508 | 12670490878911611211 | 186330748219288400 |
| 101 | 45421 | 648 | 2083697005 | 42524428 | 4200743699953660269 | 182641030432767837 |
This table is generated by the Mathematica code
|
|
The method
Here is how it works, and how you can compute your own values.
Suppose $x$ is an $n$-bit unsigned integer, and write $N=2^n$. Then for any odd integer divisor $d < N$ there is always an integer $p$ depending on $d$ (called a multiplicative inverse mod $N$) so that $pd$ is one more than a multiple of $N$, i.e., $pd=1 + N k$ for some positive integer $k$. This $p$ can be found via the Extended Euclidean algorithm for computing a GCD [1].
The value $q$ to compare against is computed as $q=\lfloor N/d \rfloor$, where $\lfloor y \rfloor$ is the floor function (largest integer less than or equal to $y$).
Ok, so those are the values to use. How does it work? Here is the rough idea, then a proof.
The idea
In the ring of integers mod $N$, multiplying by $p$ acts like dividing by $d$, since for any integer $x$, $(xp)d\equiv x(pd)\equiv x (1)\equiv x$ mod $N$. So think of $xp$ as $x/d$ mod $N$.
The comparison value is the value $N/d$, taken again in the ring of integers mod $N$. The multiplication by $p$ “shuffles” the integers in the ring, so those divisible by $d$ are ordered first, then those with “residue” 1, then those with residue 2, etc. It’s weird, but it works.
The proof
Here is a proof of why it works. Write $\left[t\right]$ to treat the integer $t$ mod $N$ as an integer again for comparison purposes. We need to show $d$ divides $x$ if and only if $[x\cdot p]\leq q$, with $p$ and $q$ as above.
Let $b$ be the remainder of $xp$ divided by $N$, i.e., there is an integer $a$ and an integer integer $0\leq b Assume $d$ divides $x$ (i.e., $x= t d$ for some integer $t$). Then $[xp]=[tdp]=[t]=t$, and $x Conversely, suppose $[xp]\leq q$. Then $xp=Na+b$ implies (expanding two ways) $xpd = x(1+Nk)=x+Nkx$ and $xpd=(Na+b)d =bd + Nad$. Thus $x+Nkx = bd + Nad$. But $b=[xp]\leq q$ implies $bd\leq qd = \lfloor N/d\rfloor d < N$. The strict inequality follows from $N$ and $d$ being relatively prime. Thus, since $0\leq bd < N$, taking both sides of the double expansion mod $N$, we get $x=bd$. Q.E.D. This can be extended to divisibility testing against any $d$ (odd or even) by first testing $x$ against the largest power of 2 dividing $d$, then shifting that out if it passed and testing the odd part. [1] https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm
The end
Comments