RosettaCodeData/Task/Square-form-factorization/Python/square-form-factorization.py

111 lines
2.1 KiB
Python

from math import sqrt, gcd
M = [1, 3, 5, 7, 11]
UINT64_MAX = 18446744073709551615
def isqrt(n: int):
return int(sqrt(n))
def squfof(n: int):
if n % 2 == 0:
return 2
h = int(sqrt(n) + 0.5)
if h ** 2 == n:
return h
for m in M:
if m > 1 and n % m == 0:
return m
if n > UINT64_MAX / m:
break
mn = m * n
r = isqrt(mn)
if r ** 2 > mn:
r -= 1
rn = r
b = r
a = 1
h = ((rn + b) // a) * a - b
c = (mn - h * h) // a
for i in range(2, 4 * isqrt(2 * r)):
a, c = c, a
q = (rn + b) // a
t = b
b = q * a - b
c += q * (t - b)
if i % 2 == 0:
r = int(sqrt(c) + 0.5)
if r ** 2 == c:
q = (rn - b) // r
v = q * r + b
w = (mn - v * v) // r
u = r
while True:
w, u = u, w
r = v
q = (rn + v) // u
v = q * u - v
if v == r:
break
w += q * (r - v)
h = gcd(n, u)
if h != 1:
return h
return 1
data = [
2501,
12851,
13289,
75301,
120787,
967009,
997417,
7091569,
13290059,
42854447,
223553581,
2027651281,
11111111111,
100895598169,
1002742628021,
60012462237239,
287129523414791,
9007199254740931,
11111111111111111,
314159265358979323,
384307168202281507,
419244183493398773,
658812288346769681,
922337203685477563,
1000000000000000127,
1152921505680588799,
1537228672809128917,
4611686018427387877
]
print("N f N/f")
print("======================================")
for n in data:
f = squfof(n)
res = 'fail' if f == 1 else f'{f:<10} {n // f}'
print(f'{n:<22} {res}')