46 lines
1.3 KiB
Python
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
|
|
|