Source code for py3nt.functions.unary.divisor_functions

"""Divisor functions."""


import numpy as np

from py3nt.core.factorize import FactorizationFactory
from py3nt.polynomial.binomial import homogeneous_binomial


[docs] def sigma_kth( n: int, k: int, factorizer: FactorizationFactory | None, factorization: None | dict[int, int] = None, ) -> int: r"""Calculate the divisor sum function :math:`\sigma_{k}(n)=\sum_{d\mid n}d^{k}`. Parameters ---------- n : ``int`` A positive integer. k: ``int`` A positive integer. factorizer : ``FactorizationFactory`` If a factorizer object is provided, then it is used to factorize :math:`n` first. The prime factorization is used to calculate the divisor sum. Otherwise all positive integers not exceeding :math:`n` are checked. Returns ------- ``int`` Divisor sigma function :math:`\sum_{d\mid n}d^{k}`. """ if not factorization: if factorizer: factorization = factorizer.factorize(n=n) if factorization: if k == 0: return np.prod(a=np.array(list(factorization.values())) + 1) divisor_sigma = 1 for prime, multiplicity in factorization.items(): divisor_sigma *= homogeneous_binomial( a=pow(prime, k), b=1, n=multiplicity + 1 ) return divisor_sigma root = int(np.floor(np.sqrt(n * 1.0))) divisor_sigma = 0 for i in range(1, root + 1): if (n % i) == 0: divisor_sigma += pow(i, k) j = n // i if i != j: divisor_sigma += pow(j, k) return divisor_sigma
[docs] def number_of_divisors( n: int, factorizer: None | FactorizationFactory, factorization: None | dict[int, int] = None, ) -> int: """ Parameters ---------- n : ``int`` A positive integer. factorizer : ``FactorizationFactory`` If a factorizer object is provided, then it is used to factorize :math:`n` first. The prime factorization is used to calculate the divisor sum. Otherwise all positive integers not exceeding :math:`n` are checked. Returns ------- ``int`` Number of divisors of :math:`n`. """ return sigma_kth(n=n, k=0, factorizer=factorizer, factorization=factorization)
[docs] def sum_of_divisors( n: int, factorizer: None | FactorizationFactory, factorization: None | dict[int, int] = None, ) -> int: """ Parameters ---------- n : ``int`` A positive integer. factorizer : ``FactorizationFactory`` If a factorizer object is provided, then it is used to factorize :math:`n` first. The prime factorization is used to calculate the divisor sum. Otherwise all positive integers not exceeding :math:`n` are checked. Returns ------- ``int`` Sum of divisors of :math:`n`. """ return sigma_kth(n=n, k=1, factorizer=factorizer, factorization=factorization)
[docs] def generate_divisors( n: int, factorizer: None | FactorizationFactory = None, factorization: None | dict[int, int] = None, ) -> np.ndarray: r"""Generate all positive divisors of a positive integer. Parameters ---------- n : ``int`` A positive integer. factorizer : ``Optional[FactorizationFactory], optional`` If specified, ``factorizer`` is used to factorize :math:`n`, by default ``None``. factorization : ``Optional[dict[int, int]]``, optional If specified, used as prime factorization of :math:`n`, by default ``None``. Cannot be ``None`` if ``factorizer`` is also ``None``. Returns ------- ``np.ndarray`` An unsorted numpy array of divisors: :math:`{d\in\mathbb{N}:d\mid n}`. Raises ------ ``ValueError`` If both ``factorizer`` and ``factorizer`` are ``None``. """ if not factorization: if not factorizer: raise ValueError("`factorizer` cannot be None") factorization = factorizer.factorize(n=n) divisors = np.empty( shape=(number_of_divisors(n=n, factorization=factorization, factorizer=None)), dtype=int, ) tau = 1 divisors[0] = 1 for prime, multiplicity in factorization.items(): cur = 1 tau_tmp = tau for _ in range(multiplicity): cur *= prime for i in range(tau_tmp): divisors[tau] = divisors[i] * cur tau += 1 return divisors