in your
legendre_symbol
implementation, you computepow(a, (p - 1)/2, p)
. You don't need to subtract1
fromp
, sincep
is odd. Also, you can replacep/2
withp >> 1
, which is faster.in your simple case handling, you can replace
p % 4
withp & 3
and again,pow(a, (p + 1)/4, p)
withpow(a, (p + 1) >> 2, p)
. Since you have checked thatp & 3 == 3
, an equivalent solution would bepow(a, (p >> 2) + 1, p)
, I would go for this one instead. It can make a difference when the right shift effectively reduces the byte size ofp
.there is another simple case you can check for:
p % 8 == 5
otor the equivalentp & 7 == 5
. In that case, couyou can computepow(a, (p >> 3) + 1, p)
, check if it is a solution (it is a solution if and only ifa
is quartic residue modulemodulop
), otherwise multiply that withpow(2, p >> 2, p)
to get a valid solution (and don't forget to calculate% p
after the multiplication of course)in your
while
-loop, you need to find a fittingi
. Let's see what your implementation is doing there ifi
is, for example,34
:pow(t, 2, p) pow(t, 4, p) # calculates pow(t, 2, p) pow(t, 8, p) # calculates pow(t, 4, p), which calculates pow(t, 2, p) pow(t, 16, p) # calculates pow(t, 8, p), which calculates pow(t, 4, p), which calculates pow(t, 2, p)
i, t2i, = 0, t
for i in range(1, m):
t2i = t2i**2t2i * t2i % p
if t2i == 1:
break