def conv_mul_mod(a, b, n, q): if len(a) < n: a = extend(a, n) if len(b) < n: b = extend(b, n) c = np.zeros(n) for i in range(n): for j in range(n): k = mod(i + j, n) c[k] = mod(c[k] + a[i] * b[k - i], q) return c
def poly_egcd(a, b, q): a = mod(a, q) b = mod(b, q) r0 = a r1 = b x1 = y0 = np.array([0]) y1 = x0 = np.array([1]) while r1.any(): k, _ = poly_divmod(r0, r1, q) r0, r1 = poly_update_egcd(r0, r1, k, q) x0, x1 = poly_update_egcd(x0, x1, k, q) y0, y1 = poly_update_egcd(y0, y1, k, q) return reduce(r0), reduce(x0), reduce(y0)
def poly_divmod(a, b, q): n = deg(a) d = deg(b) a = mod(a, q) b = mod(b, q) b = b[:d + 1] r = a[:n + 1] e = deg(r) k = np.zeros(n + 1) while e >= d and not (e == 0 and r[0] == 0): temp = np.zeros(e - d + 1) temp[e - d] = mod(r[e] * inverse_mod(b[d], q), q) k = add_mod(k, temp, q) r = subtract_mod(r, poly_mul_mod(temp, b, q), q) e = deg(r) return k, r
def poly_mul_mod(a, b, q): n = deg(a) m = deg(b) c = np.zeros(n + m + 1) ac = np.zeros(n + m + 1) bc = np.zeros(n + m + 1) ac[:n + 1] = a[:n + 1] bc[:m + 1] = b[:m + 1] for i in range(deg(a) + 1): c += ac[i] * bc c = mod(c, q) bc = np.roll(bc, 1) return c
from addition import add from subtraction import sub from multiplication import multi from division import div from modulo import mod print ("a=6, b=4") print ("sum:", add(6, 4)) print ("difference:", sub(6, 4)) print ("product:", multi(6, 4)) print ("quotient:", div(6, 4)) print ("remainder:", mod(6, 4))
def add_mod(a, b, q): return mod(add(a, b), q)
def subtract_mod(a, b, q): return mod(subtract(a, b), q)
def center_lift(a, q): a = mod(a, q) a[a > q / 2] = a[a > q / 2] - q return np.array(a)