def sqrt_mod_iter(a, p, domain=int): """ Iterate over solutions to ``x**2 = a mod p`` Parameters ========== a : integer p : positive integer domain : integer domain, ``int``, ``ZZ`` or ``Integer`` Examples ======== >>> from sympy.ntheory.residue_ntheory import sqrt_mod_iter >>> list(sqrt_mod_iter(11, 43)) [21, 22] """ from sympy.polys.galoistools import gf_crt1, gf_crt2 from sympy.polys.domains import ZZ a, p = as_int(a), abs(as_int(p)) if isprime(p): a = a % p if a == 0: res = _sqrt_mod1(a, p, 1) else: res = _sqrt_mod_prime_power(a, p, 1) if res: if domain is ZZ: for x in res: yield x else: for x in res: yield domain(x) else: f = factorint(p) v = [] pv = [] for px, ex in f.items(): if a % px == 0: rx = _sqrt_mod1(a, px, ex) if not rx: return else: rx = _sqrt_mod_prime_power(a, px, ex) if not rx: return v.append(rx) pv.append(px ** ex) mm, e, s = gf_crt1(pv, ZZ) if domain is ZZ: for vx in _product(*v): r = gf_crt2(vx, pv, mm, e, s, ZZ) yield r else: for vx in _product(*v): r = gf_crt2(vx, pv, mm, e, s, ZZ) yield domain(r)
def sqrt_mod_iter(a, p, domain=int): """ iterate over solutions to ``x**2 = a mod p`` Parameters ========== a : integer p : positive integer domain : integer domain, ``int``, ``ZZ`` or ``Integer`` Examples ======== >>> from sympy.ntheory.residue_ntheory import sqrt_mod_iter >>> list(sqrt_mod_iter(11, 43)) [21, 22] """ from sympy.polys.galoistools import gf_crt1, gf_crt2 from sympy.polys.domains import ZZ a, p = as_int(a), abs(as_int(p)) if isprime(p): a = a % p if a == 0: res = _sqrt_mod1(a, p, 1) else: res = _sqrt_mod_prime_power(a, p, 1) if res: if domain is ZZ: for x in res: yield x else: for x in res: yield domain(x) else: f = factorint(p) v = [] pv = [] for px, ex in f.items(): if a % px == 0: rx = _sqrt_mod1(a, px, ex) if not rx: raise StopIteration else: rx = _sqrt_mod_prime_power(a, px, ex) if not rx: raise StopIteration v.append(rx) pv.append(px**ex) mm, e, s = gf_crt1(pv, ZZ) if domain is ZZ: for vx in _product(*v): r = gf_crt2(vx, pv, mm, e, s, ZZ) yield r else: for vx in _product(*v): r = gf_crt2(vx, pv, mm, e, s, ZZ) yield domain(r)
def crt2(m, v, mm, e, s, symmetric=False): """Second part of Chinese Remainder Theorem, for multiple application. """ result = gf_crt2(v, m, mm, e, s, ZZ) if symmetric: return symmetric_residue(result, mm), mm return result, mm
def test_gf_crt(): U = [49, 76, 65] M = [99, 97, 95] p = 912285 u = 639985 assert gf_crt(U, M, ZZ) == u E = [9215, 9405, 9603] S = [62, 24, 12] assert gf_crt1(M, ZZ) == (p, E, S) assert gf_crt2(U, M, p, E, S, ZZ) == u
def crt2(m, v, mm, e, s, symmetric=False): """Second part of Chinese Remainder Theorem, for multiple application. Examples ======== >>> from sympy.ntheory.modular import crt1, crt2 >>> mm, e, s = crt1([18, 42, 6]) >>> crt2([18, 42, 6], [0, 0, 0], mm, e, s) (0, 4536) """ result = gf_crt2(v, m, mm, e, s, ZZ) if symmetric: return symmetric_residue(result, mm), mm return result, mm