imp/celeste/math/factor/pftrialdivision.py

46 lines
1.3 KiB
Python

'''
The trial division algorithm is essentially the idea that
all factors of an integer n are less than or equal to isqrt(n),
where isqrt is floor(sqrt(n)).
Moreover, if p divides n, then all other factors of n must
be factors of n//p. Hence they must be <= isqrt(n//p).
'''
from math import isqrt # integer square root
# Returns the "multiplicity" of a prime factor
def pf_multiplicity(n: int, p: int) -> int:
mult = 0
while n % p == 0:
n //= p
mult += 1
return n, mult
'''
Trial division prime factorisation algorithm.
Returns a list of tuples (p, m) where p is
a prime factor and m is its multiplicity.
'''
def trial_division(n: int) -> list[tuple[int, int]]:
factors = []
# determine multiplicity of the only even prime (2)
n, mult_2 = pf_multiplicity(n, 2)
if mult_2: factors.append((2, mult_2))
# determine odd factors and their multiplicities
p = 3
mult = 0
limit = isqrt(n)
while p <= limit:
n, mult = pf_multiplicity(n, p)
if mult:
factors.append((p, mult))
limit = isqrt(n) # recalculate limit
mult = 0 # reset
else:
p += 2
# if n is still greater than 1, then n is a prime factor
if n > 1:
factors.append((n, 1))
return factors