Computing A mod d (for small odd d without division and multiplication)

marco.bodrato at tutanota.com marco.bodrato at tutanota.com
Mon Mar 9 21:47:10 CET 2026


Ciao Niels,

9 mar 2026, 16:47 da nisse at lysator.liu.se:

> Torbjörn Granlund <tg at gmplib.org> writes:
>
>> There are numbers d for which B^k = 1 for any k for our common B of 2^32
>> and 2^64.  Examples are 3, 5, 15, 17, 51, 85, 255, and 257.  These will
>> just use rems[0], and many other d values will have a "cycle length" of
>> just 3.
>>
>
> I'm a bit rust on group/number theory, but the order of the
> multiplicative group mod d is phi(d), and the possible (and the likely)
> orders of 2 modulo d are determined by the prime factors of phi(d). And
> since B is a power of two, factors of two in the order (or in phi(d))
> don't matter much.
>

Exact.


> And small numbers seem rather common, as you observed. In pari/gp, I get
>

Yes, of course if d is small, the order can not be large, and since, as you said,
the factors 2 are always removed from the Euler-phi of d, it always is smaller,
by at least a factor 2.


> ? forstep(n = 1, 101, 2, print(n, "\t", znorder(Mod(2^64, n)), "\t", factor(eulerphi(n))))
>
> Worst case is (d - 1)/2, possible for prime d, as I think Marco said
>

Right.

But I'd also print the order of 2 modulo d.

? forstep(d = 1, 101, 2, print(d, "\t", znorder(Mod(2^64, d)), "\t", znorder(Mod(2, d))))
1       1       1                                                                                                        
3       1       2
5       1       4
7       3       3
9       3       6
11      5       10
13      3       12
15      1       4
17      1       8
19      9       18
21      3       6
23      11      11
25      5       20
27      9       18
29      7       28
31      5       5
33      5       10
35      3       12
37      9       36
39      3       12
41      5       20
43      7       14
45      3       12
47      23      23
49      21      21
51      1       8
53      13      52
55      5       20
57      9       18
59      29      58
61      15      60
63      3       6
65      3       12
67      33      66
69      11      22
71      35      35
73      9       9
75      5       20
77      15      30
79      39      39
81      27      54
83      41      82
85      1       8
87      7       28
89      11      11
91      3       12
93      5       10
95      9       36
97      3       48
99      15      30
101     25      100

Let's take some examples:
 - 47, the order of 2^64 mod 47 is 23, and also the order of 2 is 23;
   this means that 23 divides 2^(23*2)-1;
   should we really perform a 23-passes computation with 23 multiplications and modulus,
   or should we better reduce the number modulo 2^46-1 with some bit trickery,
   and perform a single last step mod 47?
   With 46<64 .
 - 83, the order of 2^64 mod 83 is 41, and the order of 2 is 82;
   should we really perform a 41-passes computation with a few multiplications for each pass,
   or should we better reduce the number modulo 2^82-1 with some bit trickery,
   and perform a single last step mod 83?
   With 64<82<128 .
8 mar 2026, 19:59 da tg at gmplib.org:

> (If we use the "nails feature of GMP, B = 2^60 is interesting, as now
> lots of d give short cycles.)
>
It should not be too difficult to implement a function computing at first the modulo mod 2^60-1 or 2^120-1 and then the modulo of the 1 or 2 limbs residue.
> (but for some reason, my email client doesn't like Marco's recent
> messages).
>

Could you read them only partially?
Unfortunately, I do not have many options I can play with on this server.

Ĝis,
mb



More information about the gmp-devel mailing list