from math import gcd, inf from celeste.math.numbers import bigomega, factors from celeste.extern.primefac import ( isprime, primegen as Primes, ) def coprime(n: int, m: int) -> bool: return gcd(n, m) == 1 def almostprime(n: int, k: int) -> bool: ''' A natural n is "k-almost prime" if it has exactly k prime factors (including multiplicity). ''' return (bigomega(n) == k) def semiprime(n: int) -> bool: ''' A semiprime number is one that is 2-almost prime. Ref: https://en.wikipedia.org/wiki/Semiprime ''' return almostprime(n, 2) def eulertotient(x: int | list) -> int: ''' Evaluates Euler's Totient function. Input: `x: int` is prime factorised by Lucas A. Brown's primefac.py else `x: list` is assumed to the prime factorisation of `x: int` ''' pfactors = x if isinstance(x, list) else factors(n) return prod((p-1)*(p**(e-1)) for (p, e) in pfactors) # def eulertotient(n: int) -> int: # ''' # Uses trial division to compute # Euler's Totient (Phi) Function. # ''' # phi = int(n > 1 and n) # for p in range(2, int(n ** .5) + 1): # if not n % p: # phi -= phi // p # while not n % p: # n //= p # #if n is > 1 it means it is prime # if n > 1: phi -= phi // n # return phi