Cipolla's algorithm: Difference between revisions
Content added Content deleted
(→{{header|FreeBASIC}}: added GMP version) |
m (→{{header|Sage}}: Fixed a few stray bugs and updated algorithm for cases where p is not prime.) |
||
Line 827: | Line 827: | ||
return ((x1*x2 + y1*y2*u) % p), ((x1*y2 + x2*y1) % p) |
return ((x1*x2 + y1*y2*u) % p), ((x1*y2 + x2*y1) % p) |
||
def cipollaAlgorithm(a, p |
def cipollaAlgorithm(a, p): |
||
a = pow(a, 1, p) |
|||
⚫ | |||
print "❌ " + str(p) + " is not a prime." |
|||
⚫ | |||
if eulerCriterion(a, p) == -1: |
if eulerCriterion(a, p) == -1: |
||
print "❌ " + str(a) + " is not a quadratic residue modulo " + str(p) |
print "❌ " + str(a) + " is not a quadratic residue modulo " + str(p) |
||
return False |
return False |
||
⚫ | |||
⚫ | |||
if not is_prime(p): |
|||
conglst = [] #congruence list |
|||
⚫ | |||
crtlst = [] |
|||
factors = [] |
|||
for k in list(factor(p)): |
|||
⚫ | |||
for f in factors: |
|||
conglst.append(cipollaAlgorithm(a, f)) |
|||
for i in Permutations([0, 1] * len(factors), len(factors)).list(): |
|||
for j in range(len(factors)): |
|||
crtlst.append(int(conglst[ j ][ i[j] ])) |
|||
out.append(crt(crtlst, factors)) |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
return [temp, p - temp] |
|||
t = randrange(2, p) |
|||
⚫ | |||
⚫ | |||
t = randrange(2, p) |
t = randrange(2, p) |
||
u = pow(t**2 - a, 1, p) |
u = pow(t**2 - a, 1, p) |
||
⚫ | |||
⚫ | |||
⚫ | |||
x0, y0 = t, 1 |
|||
x, y = t, 1 |
|||
for i in range(int((p + 1) / 2) - 1): |
|||
x, y = cipollaMult(x, y, x0, y0, u, p) |
|||
out.extend([x, pow(-x, 1, p)]) |
|||
⚫ | |||
return sorted(out) |
return sorted(out) |