Source code for mutwo.utilities.prime_factors
"""Prime number calculations.
The functions "factorise" and "factors" are copied from the `pyprimes
library <https://github.com/uzumaxy/pyprimes/blob/master/src/pyprimes/factors.py>`_.
In mutwo the function :func:`pyprimes.primes` has been replaced by
:class:`primesieve.Iterator()`, which improves speed by a factor of 10.
"""
import typing
import primesieve # type: ignore
__all__ = ("factorise", "factors", "is_prime")
class PrimeGenerator(object):
"""Generator that yields the rising series of primes starting from 2."""
def __init__(self):
self.it = primesieve.Iterator()
def __next__(self) -> int:
return self.it.next_prime()
def __iter__(self) -> typing.Iterator:
return self
[docs]def factorise(n: int) -> typing.List[int]:
"""factorise(integer) -> [list of factors]
:param n: The number which shall be factorised.
:return: Returns a list of the (mostly) prime factors of integer n. For negative
integers, -1 is included as a factor. If n is 0, 1 or -1, [n] is
returned as the only factor. Otherwise all the factors will be prime.
**Example:**
>>> factorise(-693)
[-1, 3, 3, 7, 11]
>>> factorise(55614)
[2, 3, 13, 23, 31]
"""
result = []
for p, count in factors(n):
result.extend([p] * count)
return result
[docs]def factors(n: int):
"""factors(integer) -> yield factors of integer lazily
Yields tuples of (factor, count) where each factor is unique and usually
prime, and count is an integer 1 or larger.
The factors are prime, except under the following circumstances: if the
argument n is negative, -1 is included as a factor; if n is 0 or 1, it
is given as the only factor. For all other integer n, all of the factors
returned are prime.
**Example:**
>>> list(factors(3*7*7*7*11))
[(3, 1), (7, 3), (11, 1)]
"""
if n in (0, 1, -1):
yield (n, 1)
return
elif n < 0:
yield (-1, 1)
n = -n
assert n >= 2
for p in PrimeGenerator():
if p * p > n:
break
count = 0
while n % p == 0:
count += 1
n //= p
if count:
yield (p, count)
if n != 1:
yield (n, 1)
[docs]def is_prime(n: int) -> bool:
"""Test if number is prime or not.
:param n: The number which shall be tested.
:return: True if number is prime and False if number isn't a Prime.
(`has been copied from here
<https://www.geeksforgeeks.org/python-program-to-check-
whether-a-number-is-prime-or-not/>`_)
"""
# Corner cases
if n <= 1:
return False
if n <= 3:
return True
# This is checked so that we can skip
# middle five numbers in below loop
if n % 2 == 0 or n % 3 == 0:
return False
i = 5
while i * i <= n:
if n % i == 0 or n % (i + 2) == 0:
return False
i = i + 6
return True