mathematicskit.number_theory#
The extended Euclidean algorithm and modular inverses; fast modular
exponentiation; primality testing (trial division, Miller-Rabin) and
prime generation (sieve of Eratosthenes); the Chinese Remainder Theorem;
continued-fraction expansion and best rational approximations; Euler’s
totient function and other multiplicative functions (Mobius,
divisor-sum); and linear and Pell Diophantine equation solvers. Every
algorithm is hand-rolled – exact-integer number theory has no
numpy/scipy equivalent.
mathematicskit.number_theory: elementary and computational number theory.
Every algorithm here is hand-rolled from its textbook definition –
exact-integer arithmetic has no numpy/scipy equivalent. The
extended Euclidean algorithm and modular inverses; fast modular
exponentiation; primality testing (trial division, Miller-Rabin) and
prime generation (sieve of Eratosthenes); the Chinese Remainder Theorem;
continued-fraction expansion and best rational approximations; Euler’s
totient function and other multiplicative number-theoretic functions
(Mobius, divisor-sum); and linear and Pell Diophantine equation solvers;
the Lucas-Lehmer test for Mersenne primes; Pollard’s rho factorization;
Legendre and Jacobi symbols and Tonelli-Shanks modular square roots;
sums of two and four squares; Euler’s product for the zeta function
(checked against scipy.special.zeta); and the prime-counting
function, logarithmic integral (scipy.special.expi), and primes in
arithmetic progressions.
- class mathematicskit.number_theory.BezoutResult(gcd, x, y)[source]#
Bases:
objectContainer for the extended Euclidean algorithm’s output: Bezout’s identity.
- class mathematicskit.number_theory.CRTResult(residue, modulus)[source]#
Bases:
objectContainer for the Chinese Remainder Theorem’s combined solution.
- class mathematicskit.number_theory.ContinuedFractionResult(terms, convergents)[source]#
Bases:
objectContainer for a continued-fraction expansion and its convergents.
- class mathematicskit.number_theory.LinearDiophantineResult(has_solution, x0=None, y0=None, gcd=0, x_step=0, y_step=0)[source]#
Bases:
objectContainer for a linear Diophantine equation’s solution family.
- gcd: int = 0#
\(\gcd(a, b)\), or
0in the degeneratea == b == 0case, where there is no gcd to speak of.- Type:
- has_solution: bool#
Whether \(ax + by = c\) has an integer solution (equivalently, whether \(\gcd(a,b)\) divides
c).- Type:
- x0: int | None = None#
The
xof one particular solution, orNonewhen has_solution isFalse.- Type:
int, optional
- class mathematicskit.number_theory.PellResult(x, y, d, extra=<factory>)[source]#
Bases:
objectContainer for the fundamental solution of Pell’s equation \(x^2 - Dy^2 = 1\).
- class mathematicskit.number_theory.PollardRhoResult(factor, cofactor, iterations, c)[source]#
Bases:
objectContainer for a factor found by Pollard’s rho method.
- mathematicskit.number_theory.best_rational_approximation(x, max_denominator)[source]#
Best rational approximation to
xwith denominator \(\leq\) max_denominator.Expands
x’s continued fraction and takes the last convergent \(p_k/q_k\) with \(q_k \leq\) max_denominator, then compares it against the best semiconvergent (or “intermediate fraction”) \(\dfrac{p_{k-1} + t\,p_k}{q_{k-1} + t\,q_k}\) that still fits under the denominator bound, returning whichever is closer tox.Both candidates are needed: a convergent is only guaranteed to be the best approximation among fractions with denominator at most its own \(q_k\), and the next convergent’s denominator can jump far past max_denominator, leaving room for a semiconvergent in between. For \(x=\pi\) with
max_denominator=57, for instance, the last convergent is \(22/7\) but the semiconvergent \(179/57\) (between \(22/7\) and \(333/106\)) is genuinely closer. See Niven, Zuckerman & Montgomery, An Introduction to the Theory of Numbers, 5th ed., Theorem 7.13 and Sec. 7.4.- Parameters:
- Return type:
- Returns:
(int, int) –
(p, q)withq <= max_denominator.
Examples
>>> # The classic approximation pi ~ 355/113 (denominator <= 200). >>> best_rational_approximation(3.14159265358979, max_denominator=200) (355, 113) >>> # Under 57, the best fraction is the semiconvergent 179/57, not 22/7. >>> best_rational_approximation(3.14159265358979, max_denominator=57) (179, 57) >>> abs(179 / 57 - 3.14159265358979) < abs(22 / 7 - 3.14159265358979) True
- mathematicskit.number_theory.chinese_remainder_theorem(remainders, moduli)[source]#
Solve the system \(x \equiv r_i \pmod{m_i}\) for pairwise-coprime \(m_i\).
Combines the congruences two at a time: given a solution \(x \equiv r_1 \pmod{m_1}\) and a new congruence \(x \equiv r_2 \pmod{m_2}\), the combined solution modulo \(m_1 m_2\) is found via the extended Euclidean algorithm’s Bezout coefficients for \((m_1, m_2)\). See Niven, Zuckerman & Montgomery, An Introduction to the Theory of Numbers, 5th ed., Theorem 2.18.
- Parameters:
- Return type:
- Returns:
CRTResult
Examples
>>> # x = 2 mod 3, x = 3 mod 5, x = 2 mod 7 -> x = 23 mod 105 (a classic example). >>> result = chinese_remainder_theorem([2, 3, 2], [3, 5, 7]) >>> result.residue 23 >>> result.modulus 105
- mathematicskit.number_theory.continued_fraction_expansion(x, max_terms=20, tol=1e-10)[source]#
Expand
xas a (simple) continued fraction \([a_0; a_1, a_2, \dots]\).\(a_0 = \lfloor x\rfloor\), then repeatedly takes the reciprocal of the remaining fractional part and floors it again, stopping early once the fractional part is within tol of zero (an exact rational input) or after max_terms. Each successive convergent \(p_k/q_k\) (via the standard recurrence \(p_k = a_k p_{k-1} + p_{k-2}\), \(q_k = a_k q_{k-1} + q_{k-2}\)) is the best rational approximation to
xamong all fractions with denominator \(\leq q_k\). See Niven, Zuckerman & Montgomery, An Introduction to the Theory of Numbers, 5th ed., Sec. 7.1-7.4.- Parameters:
- Return type:
- Returns:
ContinuedFractionResult
Examples
>>> result = continued_fraction_expansion(3.245, max_terms=10) >>> result.terms[:3] [3, 4, 12] >>> p, q = result.convergents[-1] >>> abs(p / q - 3.245) < 1e-9 True >>> # The golden ratio's continued fraction is famously all 1s. >>> phi = (1 + 5**0.5) / 2 >>> continued_fraction_expansion(phi, max_terms=8).terms [1, 1, 1, 1, 1, 1, 1, 1]
- mathematicskit.number_theory.divisor_sum(n, power=1)[source]#
The divisor-power-sum function \(\sigma_k(n) = \sum_{d \mid n} d^k\).
power=0gives the number of divisors \(d(n)\);power=1(the default) gives the ordinary sum of divisors \(\sigma(n)\) (a perfect number satisfies \(\sigma(n) = 2n\)). Multiplicative, computed fromprime_factorization()via \(\sigma_k(p^e) = \sum_{j=0}^{e} p^{jk}\). See Niven, Zuckerman & Montgomery, An Introduction to the Theory of Numbers, 5th ed., Sec. 4.2.Examples
>>> divisor_sum(6) # 1 + 2 + 3 + 6 = 12 = 2*6: a perfect number 12 >>> divisor_sum(28) # also perfect 56 >>> divisor_sum(12, power=0) # 1, 2, 3, 4, 6, 12: 6 divisors 6
- mathematicskit.number_theory.euler_product(s, limit)[source]#
Truncated Euler product \(\prod_{p \le N} (1 - p^{-s})^{-1}\).
Euler (1737) showed that for \(s > 1\)
\[\zeta(s) = \sum_{n=1}^{\infty} \frac{1}{n^s} = \prod_{p\ \mathrm{prime}} \frac{1}{1 - p^{-s}},\]which is unique factorization written analytically. Truncating the product at primes \(p \le N\) converges to \(\zeta(s)\) as \(N \to \infty\); at \(s = 1\) it diverges like \(e^{\gamma}\ln N\) (Mertens’ third theorem), reproving that there are infinitely many primes.
- Parameters:
- Return type:
- Returns:
float
Examples
>>> import math >>> from scipy.special import zeta >>> abs(euler_product(2.0, 10**5) - math.pi**2 / 6) < 1e-5 # the Basel problem True >>> bool(abs(euler_product(3.0, 1000) - zeta(3.0)) < 1e-6) True
- mathematicskit.number_theory.euler_totient(n)[source]#
Euler’s totient \(\varphi(n)\): count of integers in
[1, n]coprime ton.Multiplicative: \(\varphi(n) = n\prod_{p \mid n}(1 - 1/p)\) over
n’s distinct prime factors (fromprime_factorization()). See Niven, Zuckerman & Montgomery, An Introduction to the Theory of Numbers, 5th ed., Sec. 4.2, Theorem 4.11.Examples
>>> euler_totient(1) 1 >>> euler_totient(9) 6 >>> euler_totient(17) # prime: phi(p) = p - 1 16
- mathematicskit.number_theory.extended_gcd(a, b)[source]#
Extended Euclidean algorithm: find \(\gcd(a,b)\) and Bezout coefficients.
Returns integers \(g, x, y\) with \(ax + by = g = \gcd(a,b)\), computed by unwinding the ordinary Euclidean algorithm’s recursion. See Niven, Zuckerman & Montgomery, An Introduction to the Theory of Numbers, 5th ed., Sec. 1.2, Theorem 1.3.
- Parameters:
- Return type:
- Returns:
BezoutResult
Examples
>>> result = extended_gcd(240, 46) >>> result.gcd 2 >>> 240 * result.x + 46 * result.y == result.gcd True
- mathematicskit.number_theory.fast_mod_pow(base, exponent, modulus)[source]#
Fast modular exponentiation via repeated squaring: \(\text{base}^{\text{exponent}} \bmod \text{modulus}\).
\(O(\log(\text{exponent}))\) multiplications, by writing the exponent in binary and squaring the running result once per bit (multiplying it in whenever that bit is 1) – versus the naive \(O(\text{exponent})\) repeated multiplication. Equivalent to Python’s built-in three-argument
pow(base, exponent, modulus)(used as a cross-check in this module’s tests), reimplemented here since exposing the square-and-multiply algorithm itself is the point. See Cormen et al., Introduction to Algorithms, 3rd ed., Ch. 31.6.- Parameters:
- Return type:
- Returns:
int
Examples
>>> fast_mod_pow(7, 128, 13) 3 >>> fast_mod_pow(2, 10, 1000) 24
- mathematicskit.number_theory.gcd(a, b)[source]#
Greatest common divisor via the Euclidean algorithm.
\(\gcd(a,b) = \gcd(b, a \bmod b)\), terminating when the second argument reaches 0. See Niven, Zuckerman & Montgomery, An Introduction to the Theory of Numbers, 5th ed., Sec. 1.2.
Examples
>>> gcd(48, 18) 6 >>> gcd(17, 5) 1
- mathematicskit.number_theory.is_prime_miller_rabin(n, k=40, seed=0)[source]#
Probabilistic primality test (Miller-Rabin).
Writes \(n-1 = 2^r d\) with
dodd, and for each ofkrandom witnessesachecks whether \(a^d \equiv 1\) or \(a^{2^i d} \equiv -1 \pmod n\) for some \(0\leq i<r\); if neither holds,nis certainly composite (”ais a witness to compositeness”), otherwisenis declared probably prime. Each round has failure probability \(\leq 1/4\) for compositen, so \(k=40\) rounds give false-positive probability \(\leq 4^{-40}\) – negligible in practice, but this remains a probabilistic (not certificate) test, unlikeis_prime_trial_division(). See Cormen et al., Introduction to Algorithms, 3rd ed., Ch. 31.8.- Parameters:
- Return type:
- Returns:
bool
Examples
>>> is_prime_miller_rabin(97) True >>> is_prime_miller_rabin(91) # 91 = 7 * 13 False >>> is_prime_miller_rabin(2**61 - 1) # a known Mersenne prime True >>> is_prime_miller_rabin(2**89 - 1) # arbitrary precision: no 64-bit ceiling True
- mathematicskit.number_theory.is_prime_trial_division(n)[source]#
Primality test by trial division up to \(\sqrt n\).
\(O(\sqrt n)\): a composite
nmust have a factor \(\leq\sqrt n\), so it suffices to check candidate divisors up to there (only 2 and odd numbers, after handling 2 separately). See Niven, Zuckerman & Montgomery, An Introduction to the Theory of Numbers, 5th ed., Sec. 1.1.Examples
>>> [k for k in range(2, 30) if is_prime_trial_division(k)] [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
- mathematicskit.number_theory.jacobi_symbol(a, n)[source]#
The Jacobi symbol \(\left(\frac{a}{n}\right)\) for odd
n > 0.The multiplicative extension of the Legendre symbol to odd composite moduli. Computed without factoring
nby the Euclid-like algorithm that quadratic reciprocity makes possible: pull out factors of 2 with \(\left(\frac{2}{n}\right) = (-1)^{(n^2-1)/8}\) and flip the symbol with \(\left(\frac{a}{n}\right) \left(\frac{n}{a}\right) = (-1)^{\frac{a-1}{2}\frac{n-1}{2}}\). See Cohen, A Course in Computational Algebraic Number Theory, Algorithm 1.4.10.Examples
>>> jacobi_symbol(1001, 9907) -1 >>> jacobi_symbol(2, 15) # = (2/3)(2/5) = (-1)(-1), yet 2 is not a square mod 15 1
- mathematicskit.number_theory.lcm(a, b)[source]#
Least common multiple: \(\mathrm{lcm}(a,b) = |ab|/\gcd(a,b)\).
Examples
>>> lcm(4, 6) 12 >>> lcm(21, 6) 42
- mathematicskit.number_theory.legendre_symbol(a, p)[source]#
The Legendre symbol \(\left(\frac{a}{p}\right)\) via Euler’s criterion.
For an odd prime
p, \(\left(\frac{a}{p}\right) \equiv a^{(p-1)/2} \pmod p\) is1whenais a nonzero square modulop,-1when it is not, and0whenpdividesa. See Niven, Zuckerman & Montgomery, 5th ed., Sec. 3.1, Theorem 3.1.- Parameters:
- Return type:
- Returns:
int – One of
-1,0,1.
Examples
>>> [legendre_symbol(a, 7) for a in range(7)] # squares mod 7: 1, 2, 4 [0, 1, 1, -1, 1, -1, -1]
- mathematicskit.number_theory.logarithmic_integral(x)[source]#
The logarithmic integral \(\operatorname{li}(x) = \int_0^x \frac{dt}{\ln t}\).
The (Cauchy principal value) integral equals \(\operatorname{Ei}(\ln x)\), evaluated with
scipy.special.expi(). Gauss’s conjectured approximation to \(\pi(x)\): the prime number theorem (Hadamard and de la Vallée Poussin, 1896) states \(\pi(x) \sim \operatorname{li}(x) \sim x/\ln x\).- Parameters:
x (float or array_like) –
x > 0.- Returns:
float or ndarray
Examples
>>> round(float(logarithmic_integral(2.0)), 6) # li(2), the Ramanujan-Soldner offset 1.045164 >>> round(float(logarithmic_integral(1e6))) # vs. pi(10**6) = 78498 78628
- mathematicskit.number_theory.lucas_lehmer(p)[source]#
Lucas-Lehmer test: is the Mersenne number \(M_p = 2^p - 1\) prime?
For an odd prime
p, set \(s_0 = 4\) and \(s_{k+1} = s_k^2 - 2 \bmod M_p\); then \(M_p\) is prime if and only if \(s_{p-2} \equiv 0 \pmod{M_p}\) (Lucas, 1878; Lehmer, 1930). Onlyp - 2modular squarings are needed, so the test is a deterministic proof of primality far faster than any general method – it is why the largest known primes are almost all Mersenne primes. See Crandall & Pomerance, Prime Numbers: A Computational Perspective, 2nd ed., Theorem 4.2.6.- Parameters:
p (
int) – Exponent,p >= 2. A compositepgives a composite \(M_p\) and returnsFalseimmediately;p = 2(where \(M_2 = 3\)) is handled as a special case.- Return type:
- Returns:
bool
Examples
>>> [p for p in range(2, 130) if lucas_lehmer(p)] # exponents of Mersenne primes [2, 3, 5, 7, 13, 17, 19, 31, 61, 89, 107, 127]
- mathematicskit.number_theory.mobius(n)[source]#
The Mobius function \(\mu(n)\).
\(\mu(1)=1\); \(\mu(n)=0\) if
nhas any squared prime factor; otherwise \(\mu(n)=(-1)^k\) forkdistinct prime factors. See Niven, Zuckerman & Montgomery, An Introduction to the Theory of Numbers, 5th ed., Sec. 4.2.Examples
>>> [mobius(k) for k in range(1, 11)] [1, -1, -1, 0, -1, 1, -1, 0, 0, 1]
- mathematicskit.number_theory.mod_inverse(a, m)[source]#
Modular inverse of
amodulom: thexwith \(ax \equiv 1 \pmod m\).Exists iff \(\gcd(a,m)=1\), found via
extended_gcd(). See Niven, Zuckerman & Montgomery, An Introduction to the Theory of Numbers, 5th ed., Sec. 2.1.- Parameters:
- Return type:
- Returns:
int – In the range
[0, m).- Raises:
ValueError – If
gcd(a, m) != 1(no inverse exists).
Examples
>>> mod_inverse(3, 11) 4 >>> (3 * mod_inverse(3, 11)) % 11 1
- mathematicskit.number_theory.pollard_rho(n, c=1, x0=2, max_iter=10000000)[source]#
Find a nontrivial factor of composite
nwith Pollard’s rho method.Iterates the pseudo-random map \(x \mapsto x^2 + c \bmod n\). Reduced modulo an unknown prime factor \(p\) of
n, the sequence must repeat within about \(\sqrt{\pi p/2}\) steps (the birthday paradox), tracing out the Greek letter \(\rho\). Floyd’s tortoise-and-hare cycle detection finds that repeat by comparing \(x_i\) with \(x_{2i}\) and testing \(\gcd(|x_i - x_{2i}|, n)\). The expected cost is \(O(\sqrt p) \le O(n^{1/4})\) steps, compared with \(O(\sqrt n)\) for trial division. If the cycle closes modulo every factor at once (the gcd isnitself), the constantcis incremented and the search restarted.- Parameters:
- Return type:
- Returns:
PollardRhoResult
Examples
>>> result = pollard_rho(8051) # Pollard's own worked example: 83 * 97 >>> sorted([result.factor, result.cofactor]) [83, 97] >>> result = pollard_rho(2**64 + 1) # Landry, 1880: 274177 * 67280421310721 >>> sorted([result.factor, result.cofactor]) [274177, 67280421310721]
- mathematicskit.number_theory.prime_counting(x)[source]#
The prime-counting function \(\pi(x)\): the number of primes \(\le x\).
Sieves once up to
max(x)and counts withnumpy.searchsorted(), so a whole array ofxcosts a single sieve.- Parameters:
- Return type:
- Returns:
int or ndarray of int – Same shape as x.
Examples
>>> int(prime_counting(100)) 25 >>> prime_counting([10, 100, 1000, 10000]) array([ 4, 25, 168, 1229])
- mathematicskit.number_theory.prime_factorization(n)[source]#
Prime factorization of
nvia trial division: \(n = \prod_i p_i^{e_i}\).- Parameters:
n (
int) –n >= 1.- Return type:
- Returns:
dict –
{prime: exponent}, empty forn == 1.
Examples
>>> prime_factorization(360) {2: 3, 3: 2, 5: 1}
- mathematicskit.number_theory.primes_in_progression(a, q, limit)[source]#
Primes \(p \le\) limit with \(p \equiv a \pmod q\).
Dirichlet’s theorem (1837) guarantees infinitely many such primes whenever \(\gcd(a, q) = 1\); the prime number theorem for arithmetic progressions sharpens this to each of the \(\varphi(q)\) coprime residue classes receiving an asymptotic share \(1/\varphi(q)\) of all primes.
- Parameters:
- Return type:
- Returns:
ndarray of int – The primes in
[2, limit]congruent toamodq, ascending.
Examples
>>> primes_in_progression(3, 4, 50) array([ 3, 7, 11, 19, 23, 31, 43, 47]) >>> primes_in_progression(2, 4, 1000) # gcd(2, 4) = 2: only the prime 2 array([2])
- mathematicskit.number_theory.sieve_of_eratosthenes(limit)[source]#
All primes up to and including limit, via the sieve of Eratosthenes.
Marks composites by striking out multiples of each prime found, from 2 upward – \(O(n\log\log n)\), far faster than testing each number individually. See Niven, Zuckerman & Montgomery, An Introduction to the Theory of Numbers, 5th ed., Sec. 1.1.
- Parameters:
limit (
int)- Return type:
- Returns:
ndarray, int – Primes in
[2, limit], ascending.
Examples
>>> sieve_of_eratosthenes(30) array([ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29])
- mathematicskit.number_theory.solve_linear_diophantine(a, b, c)[source]#
Solve \(ax + by = c\) in integers.
A solution exists iff \(\gcd(a,b) \mid c\); given a particular solution \((x_0, y_0)\) (scaled up from
extended_gcd()’s Bezout coefficients), the general solution is \((x_0 + k\,b/g,\ y_0 - k\,a/g)\) for any integerk. See Niven, Zuckerman & Montgomery, An Introduction to the Theory of Numbers, 5th ed., Theorem 2.9.- Parameters:
- Return type:
- Returns:
LinearDiophantineResult
Examples
>>> result = solve_linear_diophantine(3, 5, 1) >>> 3 * result.x0 + 5 * result.y0 == 1 True >>> # Every (x0 + k*x_step, y0 - k*y_step) is also a solution. >>> k = 7 >>> x, y = result.x0 + k * result.x_step, result.y0 - k * result.y_step >>> 3 * x + 5 * y == 1 True >>> solve_linear_diophantine(2, 4, 3).has_solution # gcd(2,4)=2 does not divide 3 False >>> solve_linear_diophantine(0, 0, 5).has_solution # 0x + 0y = 5 is unsolvable False >>> solve_linear_diophantine(0, 0, 0).has_solution # ... but 0x + 0y = 0 holds for every (x, y) True
- mathematicskit.number_theory.solve_pell_equation(d)[source]#
Fundamental solution of Pell’s equation \(x^2 - Dy^2 = 1\),
Dnot a perfect square.The continued fraction of \(\sqrt D\) is eventually periodic; the fundamental (smallest positive) solution is given by one of its convergents \(p/q\). Unlike
continued_fraction_expansion()(which works from a floating-point value), this function tracks the continued fraction of \(\sqrt D\) with the standard exact-integer recurrence for quadratic irrationals, since Pell periods can run to dozens of terms (e.g. \(D=61\) has period 11) – far beyondfloat64’s precision. See Niven, Zuckerman & Montgomery, An Introduction to the Theory of Numbers, 5th ed., Sec. 7.8, Theorem 7.26.- Parameters:
d (
int) – Not a perfect square.- Return type:
- Returns:
PellResult
Examples
>>> result = solve_pell_equation(2) >>> (result.x, result.y) (3, 2) >>> result.x**2 - 2 * result.y**2 1 >>> result2 = solve_pell_equation(61) # a famously large fundamental solution >>> result2.x**2 - 61 * result2.y**2 1
- mathematicskit.number_theory.sqrt_mod(a, p)[source]#
A square root of
amodulo an odd primep(Tonelli-Shanks).Writes \(p - 1 = 2^s q\) with
qodd, starts from the candidate \(a^{(q+1)/2}\), and repeatedly corrects it with powers of a quadratic non-residue until the error term has order 1 (Tonelli, 1891; Shanks, 1973). Runs in \(O(\log^2 p)\) modular multiplications. See Cohen, Algorithm 1.5.1.- Parameters:
- Return type:
- Returns:
int – The root
xin[0, p // 2]; the other root isp - x.
Examples
>>> sqrt_mod(10, 13) # 6*6 = 36 = 10 (mod 13) 6 >>> x = sqrt_mod(2, 2**61 - 1) >>> x * x % (2**61 - 1) 2
- mathematicskit.number_theory.sum_of_four_squares(n)[source]#
Write
nas \(a^2 + b^2 + c^2 + d^2\) (Lagrange’s four-square theorem).Lagrange proved in 1770 that every non-negative integer is a sum of four squares, so this function always succeeds. The search tries \(a \ge b \ge c\) in decreasing order and solves for
d; fornup to a few million it returns almost immediately. The number of ordered, signed representations is given by Jacobi’s (1829) formula \(r_4(n) = 8\sum_{d \mid n,\ 4 \nmid d} d\).- Parameters:
n (
int) –n >= 0.- Return type:
- Returns:
tuple of (int, int, int, int) –
(a, b, c, d)witha >= b >= c >= d >= 0and squares summing ton.
Examples
>>> sum_of_four_squares(7) # 7 = 4 + 1 + 1 + 1 needs all four squares (2, 1, 1, 1) >>> sum_of_four_squares(310) (17, 4, 2, 1)
- mathematicskit.number_theory.sum_of_two_squares(n)[source]#
Write
nas \(a^2 + b^2\) with \(0 \le a \le b\), if possible.By Fermat’s two-squares theorem (stated 1640, first proved by Euler in 1749) an odd prime \(p\) is a sum of two squares exactly when \(p \equiv 1 \pmod 4\); more generally
nis a sum of two squares exactly when every prime \(q \equiv 3 \pmod 4\) dividesnto an even power (Hardy & Wright, 6th ed., Theorem 366). The search runs over \(a \le \sqrt{n/2}\) – \(O(\sqrt n)\) – and returns the representation with the smallesta.- Parameters:
n (
int) –n >= 0.- Return type:
- Returns:
tuple of (int, int) or None –
(a, b)witha*a + b*b == nanda <= b, orNonewhen no representation exists.
Examples
>>> sum_of_two_squares(13) # 13 = 1 (mod 4): 4 + 9 (2, 3) >>> sum_of_two_squares(7) is None # 7 = 3 (mod 4) True >>> sum_of_two_squares(2**31 - 1) is None # a Mersenne prime is always 3 (mod 4) True