def PolyDivModOverZn(a: poly, b: poly, n: int) -> (poly, poly): if n < 1: raise ValueError if n==1: raise ZeroDivisionError a = poly(np.mod(a.coef, n)) b = poly(np.mod(b.coef, n)) a = a.trim() b = b.trim() deg_a, deg_b = len(a.coef), len(b.coef) if deg_a < deg_b: return poly([0]), a else: f = poly(b.coef[::-1]).trim() g = PolyInverseModOverZn(f, deg_a - deg_b + 1, n) if g is None: raise ZeroDivisionError q = (poly(a.coef[::-1]).trim() * g).truncate(deg_a - deg_b + 1) # q:=rev_n(a)g mod x^(n-m+1) q = poly(np.mod(q.coef, n)) q = poly(q.coef[::-1]).trim() # q:=rev_(n-m)(q) if len(q.coef) < deg_a - deg_b + 1: q.coef = np.concatenate([np.zeros(deg_a - deg_b + 1 - len(q)), q.coef]) bq = poly(np.mod((b * q).coef, n)) r = a - bq r = poly(np.mod(r.coef, n)) q = poly(np.mod(q.coef, n)) r = r.trim() q = q.trim() return q, r
def PolyDivModOverQ(a: poly, b: poly) -> (poly, poly): if not b.coef.any(): #если полином нулевой raise ZeroDivisionError a = a.trim() b = b.trim() n, m = len(a.coef), len(b.coef) # степени полиномов if n < m: return poly([0]), a else: f = poly(b.coef[::-1]).trim() #f:=rev_m(b) g = PolyInverseModOverQ(f, n - m + 1) #q inverse of f modulo x^(n-m+1) q = (poly(a.coef[::-1]).trim() * g).truncate(n - m + 1)#q:=rev_n(a)g mod x^(n-m+1) q = poly(q.coef[::-1]).trim() #q:=rev_(n-m)(q) if len(q.coef) < n - m + 1: q.coef = np.concatenate([np.zeros(n - len(q)), q.coef]) r = a - b * q #r:=a-bq r = r.trim() q = q.trim() return q, r
def PolyDivModOverQ(a: Poly, b: Poly) -> (Poly, Poly): if not b.coef.any(): raise ZeroDivisionError a = a.trim() b = b.trim() n, m = len(a.coef), len(b.coef) if n < m: return Poly([0]), a else: f = rev(b, m) g = PolyInverseModOverQ(f, n - m + 1) q = (rev(a, n) * g).truncate(n - m + 1) q = rev(q, n - m + 1) if len(q.coef) < n - m + 1: q.coef = np.concatenate([np.zeros(n - len(q)), q.coef]) r = a - b * q r = r.trim() q = r.trim() return q, r
def PolyDivModOverZn(a: Poly, b: Poly, mod_r: int) -> (Poly, Poly): if mod_r < 1: raise ValueError if mod_r == 1: raise ZeroDivisionError a = Poly(np.mod(a.coef, mod_r)) b = Poly(np.mod(b.coef, mod_r)) a = a.trim() b = b.trim() n, m = len(a.coef), len(b.coef) if n < m: return Poly([0]), a else: f = rev(b, m) g = PolyInverseModOverZn(f, n - m + 1, mod_r) if g is None: raise ZeroDivisionError q = (rev(a, n) * g).truncate(n - m + 1) q = Poly(np.mod(q.coef, mod_r)) q = rev(q, n - m) if len(q.coef) < n - m + 1: q.coef = np.concatenate([np.zeros(n - m + 1 - len(q)), q.coef]) bq = Poly(np.mod((b * q).coef, mod_r)) r = a - bq r = Poly(np.mod(r.coef, mod_r)) q = Poly(np.mod(q.coef, mod_r)) r = r.trim() q = q.trim() return q, r
def PolyDivModOverZn(a, b: Poly, n: int): #−> (Poly , Poly ): a = a.trim() b = b.trim() if (n < 1): raise ValueError if (a.degree() < b.degree()): return Poly([0]), a m = a.degree() - b.degree() revb = Poly(b.coef[::-1]) rrevb = PolyInverseModOverZn(revb, m + 1, n) if (rrevb is None): raise ZeroDivisionError("") reva = Poly(a.coef[::-1]) q1 = reva * rrevb q1 = q1.truncate(m + 1) q = Poly(q1.coef[::-1]) q = modPoly(q, n) bq = b * q bq = modPoly(bq, n) r = modPoly(a - b * q, n) r = Poly(r.coef[::-1]) r.trim() r = Poly(r.coef[::-1]) return q, r
def PolyInverseModOverQ(f: Poly, r: int): #r=2, предполагаем f0[0] = 1 f = f.trim() if (r < 1): raise ValueError #f = modPoly(f, zn) f0 = f.coef[0] if (f0 != Fraction(1, 1)): f0 = 1 / f0 if (f0 == Fraction(0, 1)): return None g = Poly(f0) l = int(math.ceil(math.log2(r))) for k in range(1, l + 1): g = (2 * g - f * (g**2)) g = g.truncate(2**k) return g
def rev(p: Poly, n: int) -> Poly: p = p.trim() result = p.coef[::-1] if len(p.coef) < n: result = np.concatenate([np.zeros(n - len(p.coef)), result]) return Poly(result)