Source code for py3nt.congruence.quadratic

"""Quadratic residues and symbols."""


import numpy as np


[docs] def legendre_symbol(a: int, p: int) -> int: r"""Calculate Legendre symbol. Parameters ---------- a : ``int`` An integer. p : ``int`` A prime. Returns ------- ``int`` Legendre symbol :math:`(\frac{a}{p})\in\{-1,0,1\}`. """ a %= p if not a: return 0 if pow(a, (p - 1) >> 1, p) == 1: return 1 return -1
[docs] def jacobi_symbol(a: int, n: int) -> int: r"""Calculate Jacobi symbol. Parameters ---------- a : ``int`` An integer. n : ``int`` A positive odd integer. Returns ------- ``int`` Jacobi symbol :math:`(\frac{a}{n})\in\{-1,0,1\}`. Raises ------ ValueError If :math:`n` is not positive or odd. """ if n <= 0: raise ValueError(f"{n} must be positive.") if (n & 1) == 0: raise ValueError(f"{n} is not odd.") if a < 0 or a > n: a %= n if not a: return int(n == 1) if n == 1 or a == 1: return 1 if np.gcd(a, n) != 1: return 0 jacobi = 1 while a != 0: while (a & 1) == 0 and a > 0: a >>= 1 if n % 8 in [3, 5]: jacobi = -jacobi a, n = n, a if a % 4 == n % 4 == 3: jacobi = -jacobi a %= n return jacobi