# lucas pseudoprimality test
def gcd(a,b): # euclid's algorithm
if b == 0: return a
return gcd(b, a%b)
def jacobi(a, m):
# assumes a an integer and
# m an odd positive integer
a, t = a % m, 1
while a <> 0:
z = -1 if m % 8 in [3,5] else 1
while a % 2 == 0:
a, t = a / 2, t * z
if a%4 == 3 and m%4 == 3: t = -t
a, m = m % a, a
return t if m == 1 else 0
def selfridge(n):
d, s = 5, 1
while True:
ds = d * s
print "ds = " + str(ds)
if gcd(ds, n) > 1:
print "ALPHA"
return ds, 0, 0
print "jacobi = " + str(jacobi(ds, n))
if jacobi(ds, n) == -1:
print "BETA"
return ds, 1, (1 - ds) / 4
d, s = d + 2, s * -1
def lucasPQ(p, q, m, n):
# nth element of lucas sequence with
# parameters p and q (mod m); ignore
# modulus operation when m is zero
def mod(x):
if m == 0: return x
return x % m
def half(x):
if x % 2 == 1: x = x + m
return mod(x / 2)
un, vn, qn = 1, p, q
u = 0 if n % 2 == 0 else 1
v = 2 if n % 2 == 0 else p
k = 1 if n % 2 == 0 else q
n, d = n // 2, p * p - 4 * q
while n > 0:
u2 = mod(un * vn)
v2 = mod(vn * vn - 2 * qn)
q2 = mod(qn * qn)
n2 = n // 2
#print "12 = " + str(q2)
if n % 2 == 1:
uu = half(u * v2 + u2 * v)
vv = half(v * v2 + d * u * u2)
u, v, k = uu, vv, k * q2
print "u = " + str(u)
un, vn, qn, n = u2, v2, q2, n2
return u, v, k
def isLucasPseudoprime(n):
d, p, q = selfridge(n)
if p == 0: return n == d
print "d = " + str(d)
print "p = " + str(p)
print "q = " + str(q)
u, v, k = lucasPQ(p, q, n, n+1)
print "u = " + str(u)
return u == 0
print "5 % 7 = " + str(5 % 7)
print "-5 % 7 = " + str(-5 % 7)
print "-12 % 7 = " + str(-12 % 7)
print isLucasPseudoprime(1021)
IyBsdWNhcyBwc2V1ZG9wcmltYWxpdHkgdGVzdAoKZGVmIGdjZChhLGIpOiAjIGV1Y2xpZCdzIGFsZ29yaXRobQogICAgaWYgYiA9PSAwOiByZXR1cm4gYQogICAgcmV0dXJuIGdjZChiLCBhJWIpCgpkZWYgamFjb2JpKGEsIG0pOgogICAgIyBhc3N1bWVzIGEgYW4gaW50ZWdlciBhbmQKICAgICMgbSBhbiBvZGQgcG9zaXRpdmUgaW50ZWdlcgogICAgYSwgdCA9IGEgJSBtLCAxCiAgICB3aGlsZSBhIDw+IDA6CiAgICAgICAgeiA9IC0xIGlmIG0gJSA4IGluIFszLDVdIGVsc2UgMQogICAgICAgIHdoaWxlIGEgJSAyID09IDA6CiAgICAgICAgICAgIGEsIHQgPSBhIC8gMiwgdCAqIHoKICAgICAgICBpZiBhJTQgPT0gMyBhbmQgbSU0ID09IDM6IHQgPSAtdAogICAgICAgIGEsIG0gPSBtICUgYSwgYQogICAgcmV0dXJuIHQgaWYgbSA9PSAxIGVsc2UgMAoKZGVmIHNlbGZyaWRnZShuKToKICAgIGQsIHMgPSA1LCAxCiAgICB3aGlsZSBUcnVlOgogICAgICAgIGRzID0gZCAqIHMKICAgICAgICBwcmludCAiZHMgPSAiICsgc3RyKGRzKQogICAgICAgIGlmIGdjZChkcywgbikgPiAxOgogICAgICAgICAgICBwcmludCAiQUxQSEEiCiAgICAgICAgICAgIHJldHVybiBkcywgMCwgMAogICAgICAgIHByaW50ICJqYWNvYmkgPSAiICsgc3RyKGphY29iaShkcywgbikpCiAgICAgICAgaWYgamFjb2JpKGRzLCBuKSA9PSAtMToKICAgICAgICAgICAgcHJpbnQgIkJFVEEiCiAgICAgICAgICAgIHJldHVybiBkcywgMSwgKDEgLSBkcykgLyA0CiAgICAgICAgZCwgcyA9IGQgKyAyLCBzICogLTEKCmRlZiBsdWNhc1BRKHAsIHEsIG0sIG4pOgogICAgIyBudGggZWxlbWVudCBvZiBsdWNhcyBzZXF1ZW5jZSB3aXRoCiAgICAjIHBhcmFtZXRlcnMgcCBhbmQgcSAobW9kIG0pOyBpZ25vcmUKICAgICMgbW9kdWx1cyBvcGVyYXRpb24gd2hlbiBtIGlzIHplcm8KICAgIGRlZiBtb2QoeCk6CiAgICAgICAgaWYgbSA9PSAwOiByZXR1cm4geAogICAgICAgIHJldHVybiB4ICUgbQogICAgZGVmIGhhbGYoeCk6CiAgICAgICAgaWYgeCAlIDIgPT0gMTogeCA9IHggKyBtCiAgICAgICAgcmV0dXJuIG1vZCh4IC8gMikKICAgIHVuLCB2biwgcW4gPSAxLCBwLCBxCiAgICB1ID0gMCBpZiBuICUgMiA9PSAwIGVsc2UgMQogICAgdiA9IDIgaWYgbiAlIDIgPT0gMCBlbHNlIHAKICAgIGsgPSAxIGlmIG4gJSAyID09IDAgZWxzZSBxCiAgICBuLCBkID0gbiAvLyAyLCBwICogcCAtIDQgKiBxCiAgICB3aGlsZSBuID4gMDoKICAgICAgICB1MiA9IG1vZCh1biAqIHZuKQogICAgICAgIHYyID0gbW9kKHZuICogdm4gLSAyICogcW4pCiAgICAgICAgcTIgPSBtb2QocW4gKiBxbikKICAgICAgICBuMiA9IG4gLy8gMgogICAgICAgICNwcmludCAiMTIgPSAiICsgc3RyKHEyKQogICAgICAgIGlmIG4gJSAyID09IDE6CiAgICAgICAgICAgIHV1ID0gaGFsZih1ICogdjIgKyB1MiAqIHYpCiAgICAgICAgICAgIHZ2ID0gaGFsZih2ICogdjIgKyBkICogdSAqIHUyKQogICAgICAgICAgICB1LCB2LCBrID0gdXUsIHZ2LCBrICogcTIKICAgICAgICAgICAgcHJpbnQgInUgPSAiICsgc3RyKHUpCiAgICAgICAgdW4sIHZuLCBxbiwgbiA9IHUyLCB2MiwgcTIsIG4yCiAgICByZXR1cm4gdSwgdiwgawoKZGVmIGlzTHVjYXNQc2V1ZG9wcmltZShuKToKICAgIGQsIHAsIHEgPSBzZWxmcmlkZ2UobikKICAgIGlmIHAgPT0gMDogcmV0dXJuIG4gPT0gZAogICAgcHJpbnQgImQgPSAiICsgc3RyKGQpCiAgICBwcmludCAicCA9ICIgKyBzdHIocCkKICAgIHByaW50ICJxID0gIiArIHN0cihxKQogICAgdSwgdiwgayA9IGx1Y2FzUFEocCwgcSwgbiwgbisxKQogICAgcHJpbnQgInUgPSAiICsgc3RyKHUpCiAgICByZXR1cm4gdSA9PSAwCgpwcmludCAiNSAlIDcgPSAiICsgc3RyKDUgJSA3KQpwcmludCAiLTUgJSA3ID0gIiArIHN0cigtNSAlIDcpCnByaW50ICItMTIgJSA3ID0gIiArIHN0cigtMTIgJSA3KQpwcmludCBpc0x1Y2FzUHNldWRvcHJpbWUoMTAyMSk=