def dup_zz_hensel_lift(p, f, f_list, l, K): """ Multifactor Hensel lifting in `Z[x]`. Given a prime `p`, polynomial `f` over `Z[x]` such that `lc(f)` is a unit modulo `p`, monic pair-wise coprime polynomials `f_i` over `Z[x]` satisfying:: f = lc(f) f_1 ... f_r (mod p) and a positive integer `l`, returns a list of monic polynomials `F_1`, `F_2`, ..., `F_r` satisfying:: f = lc(f) F_1 ... F_r (mod p**l) F_i = f_i (mod p), i = 1..r References ========== 1. [Gathen99]_ """ r = len(f_list) lc = dup_LC(f, K) if r == 1: F = dup_mul_ground(f, K.gcdex(lc, p**l)[0], K) return [ dup_trunc(F, p**l, K) ] m = p k = r // 2 d = int(_ceil(_log(l, 2))) g = gf_from_int_poly([lc], p) for f_i in f_list[:k]: g = gf_mul(g, gf_from_int_poly(f_i, p), p, K) h = gf_from_int_poly(f_list[k], p) for f_i in f_list[k + 1:]: h = gf_mul(h, gf_from_int_poly(f_i, p), p, K) s, t, _ = gf_gcdex(g, h, p, K) g = gf_to_int_poly(g, p) h = gf_to_int_poly(h, p) s = gf_to_int_poly(s, p) t = gf_to_int_poly(t, p) for _ in range(1, d + 1): (g, h, s, t), m = dup_zz_hensel_step(m, f, g, h, s, t, K), m**2 return dup_zz_hensel_lift(p, g, f_list[:k], l, K) \ + dup_zz_hensel_lift(p, h, f_list[k:], l, K)
def dup_zz_hensel_lift(p, f, f_list, l, K): """ Multifactor Hensel lifting in `Z[x]`. Given a prime `p`, polynomial `f` over `Z[x]` such that `lc(f)` is a unit modulo `p`, monic pair-wise coprime polynomials `f_i` over `Z[x]` satisfying:: f = lc(f) f_1 ... f_r (mod p) and a positive integer `l`, returns a list of monic polynomials `F_1`, `F_2`, ..., `F_r` satisfying:: f = lc(f) F_1 ... F_r (mod p**l) F_i = f_i (mod p), i = 1..r References ========== 1. [Gathen99]_ """ r = len(f_list) lc = dup_LC(f, K) if r == 1: F = dup_mul_ground(f, K.gcdex(lc, p**l)[0], K) return [dup_trunc(F, p**l, K)] m = p k = r // 2 d = int(_ceil(_log(l, 2))) g = gf_from_int_poly([lc], p) for f_i in f_list[:k]: g = gf_mul(g, gf_from_int_poly(f_i, p), p, K) h = gf_from_int_poly(f_list[k], p) for f_i in f_list[k + 1:]: h = gf_mul(h, gf_from_int_poly(f_i, p), p, K) s, t, _ = gf_gcdex(g, h, p, K) g = gf_to_int_poly(g, p) h = gf_to_int_poly(h, p) s = gf_to_int_poly(s, p) t = gf_to_int_poly(t, p) for _ in range(1, d + 1): (g, h, s, t), m = dup_zz_hensel_step(m, f, g, h, s, t, K), m**2 return dup_zz_hensel_lift(p, g, f_list[:k], l, K) \ + dup_zz_hensel_lift(p, h, f_list[k:], l, K)
def test_gf_irreducible_p(): assert gf_irred_p_ben_or([7], 11, ZZ) == True assert gf_irred_p_ben_or([7, 3], 11, ZZ) == True assert gf_irred_p_ben_or([7, 3, 1], 11, ZZ) == False assert gf_irred_p_rabin([7], 11, ZZ) == True assert gf_irred_p_rabin([7, 3], 11, ZZ) == True assert gf_irred_p_rabin([7, 3, 1], 11, ZZ) == False assert gf_irreducible_p([7], 11, ZZ, method='ben-or') == True assert gf_irreducible_p([7, 3], 11, ZZ, method='ben-or') == True assert gf_irreducible_p([7, 3, 1], 11, ZZ, method='ben-or') == False assert gf_irreducible_p([7], 11, ZZ, method='rabin') == True assert gf_irreducible_p([7, 3], 11, ZZ, method='rabin') == True assert gf_irreducible_p([7, 3, 1], 11, ZZ, method='rabin') == False raises(KeyError, "gf_irreducible_p([7], 11, ZZ, method='other')") f = [1, 9, 9, 13, 16, 15, 6, 7, 7, 7, 10] g = [1, 7, 16, 7, 15, 13, 13, 11, 16, 10, 9] h = gf_mul(f, g, 17, ZZ) assert gf_irred_p_ben_or(f, 17, ZZ) == True assert gf_irred_p_ben_or(g, 17, ZZ) == True assert gf_irred_p_ben_or(h, 17, ZZ) == False assert gf_irred_p_rabin(f, 17, ZZ) == True assert gf_irred_p_rabin(g, 17, ZZ) == True assert gf_irred_p_rabin(h, 17, ZZ) == False
def test_gf_irreducible_p(): assert gf_irred_p_ben_or([7], 11, ZZ) == True assert gf_irred_p_ben_or([7,3], 11, ZZ) == True assert gf_irred_p_ben_or([7,3,1], 11, ZZ) == False assert gf_irred_p_rabin([7], 11, ZZ) == True assert gf_irred_p_rabin([7,3], 11, ZZ) == True assert gf_irred_p_rabin([7,3,1], 11, ZZ) == False assert gf_irreducible_p([7], 11, ZZ, method='ben-or') == True assert gf_irreducible_p([7,3], 11, ZZ, method='ben-or') == True assert gf_irreducible_p([7,3,1], 11, ZZ, method='ben-or') == False assert gf_irreducible_p([7], 11, ZZ, method='rabin') == True assert gf_irreducible_p([7,3], 11, ZZ, method='rabin') == True assert gf_irreducible_p([7,3,1], 11, ZZ, method='rabin') == False raises(KeyError, "gf_irreducible_p([7], 11, ZZ, method='other')") f = [1, 9, 9, 13, 16, 15, 6, 7, 7, 7, 10] g = [1, 7, 16, 7, 15, 13, 13, 11, 16, 10, 9] h = gf_mul(f, g, 17, ZZ) assert gf_irred_p_ben_or(f, 17, ZZ) == True assert gf_irred_p_ben_or(g, 17, ZZ) == True assert gf_irred_p_ben_or(h, 17, ZZ) == False assert gf_irred_p_rabin(f, 17, ZZ) == True assert gf_irred_p_rabin(g, 17, ZZ) == True assert gf_irred_p_rabin(h, 17, ZZ) == False
def test_gf_irreducible_p(): assert gf_irred_p_ben_or([7], 11, ZZ) == True assert gf_irred_p_ben_or([7,3], 11, ZZ) == True assert gf_irred_p_ben_or([7,3,1], 11, ZZ) == False assert gf_irred_p_rabin([7], 11, ZZ) == True assert gf_irred_p_rabin([7,3], 11, ZZ) == True assert gf_irred_p_rabin([7,3,1], 11, ZZ) == False config.setup('GF_IRRED_METHOD', 'ben-or') assert gf_irreducible_p([7], 11, ZZ) == True assert gf_irreducible_p([7,3], 11, ZZ) == True assert gf_irreducible_p([7,3,1], 11, ZZ) == False config.setup('GF_IRRED_METHOD', 'rabin') assert gf_irreducible_p([7], 11, ZZ) == True assert gf_irreducible_p([7,3], 11, ZZ) == True assert gf_irreducible_p([7,3,1], 11, ZZ) == False config.setup('GF_IRRED_METHOD', 'other') raises(KeyError, lambda: gf_irreducible_p([7], 11, ZZ)) config.setup('GF_IRRED_METHOD') f = [1, 9, 9, 13, 16, 15, 6, 7, 7, 7, 10] g = [1, 7, 16, 7, 15, 13, 13, 11, 16, 10, 9] h = gf_mul(f, g, 17, ZZ) assert gf_irred_p_ben_or(f, 17, ZZ) == True assert gf_irred_p_ben_or(g, 17, ZZ) == True assert gf_irred_p_ben_or(h, 17, ZZ) == False assert gf_irred_p_rabin(f, 17, ZZ) == True assert gf_irred_p_rabin(g, 17, ZZ) == True assert gf_irred_p_rabin(h, 17, ZZ) == False
def test_gf_irreducible_p(): assert gf_irred_p_ben_or(ZZ.map([7]), 11, ZZ) is True assert gf_irred_p_ben_or(ZZ.map([7, 3]), 11, ZZ) is True assert gf_irred_p_ben_or(ZZ.map([7, 3, 1]), 11, ZZ) is False assert gf_irred_p_rabin(ZZ.map([7]), 11, ZZ) is True assert gf_irred_p_rabin(ZZ.map([7, 3]), 11, ZZ) is True assert gf_irred_p_rabin(ZZ.map([7, 3, 1]), 11, ZZ) is False config.setup("GF_IRRED_METHOD", "ben-or") assert gf_irreducible_p(ZZ.map([7]), 11, ZZ) is True assert gf_irreducible_p(ZZ.map([7, 3]), 11, ZZ) is True assert gf_irreducible_p(ZZ.map([7, 3, 1]), 11, ZZ) is False config.setup("GF_IRRED_METHOD", "rabin") assert gf_irreducible_p(ZZ.map([7]), 11, ZZ) is True assert gf_irreducible_p(ZZ.map([7, 3]), 11, ZZ) is True assert gf_irreducible_p(ZZ.map([7, 3, 1]), 11, ZZ) is False config.setup("GF_IRRED_METHOD", "other") raises(KeyError, lambda: gf_irreducible_p([7], 11, ZZ)) config.setup("GF_IRRED_METHOD") f = ZZ.map([1, 9, 9, 13, 16, 15, 6, 7, 7, 7, 10]) g = ZZ.map([1, 7, 16, 7, 15, 13, 13, 11, 16, 10, 9]) h = gf_mul(f, g, 17, ZZ) assert gf_irred_p_ben_or(f, 17, ZZ) is True assert gf_irred_p_ben_or(g, 17, ZZ) is True assert gf_irred_p_ben_or(h, 17, ZZ) is False assert gf_irred_p_rabin(f, 17, ZZ) is True assert gf_irred_p_rabin(g, 17, ZZ) is True assert gf_irred_p_rabin(h, 17, ZZ) is False
def mul(self, x, y): return gf_rem(gf_mul(x, y, self.p, ZZ), self.reducing, self.p, ZZ)
def test_gf_arith(): assert gf_neg([], 11, ZZ) == [] assert gf_neg([1], 11, ZZ) == [10] assert gf_neg([1,2,3], 11, ZZ) == [10,9,8] assert gf_add_ground([], 0, 11, ZZ) == [] assert gf_sub_ground([], 0, 11, ZZ) == [] assert gf_add_ground([], 3, 11, ZZ) == [3] assert gf_sub_ground([], 3, 11, ZZ) == [8] assert gf_add_ground([1], 3, 11, ZZ) == [4] assert gf_sub_ground([1], 3, 11, ZZ) == [9] assert gf_add_ground([8], 3, 11, ZZ) == [] assert gf_sub_ground([3], 3, 11, ZZ) == [] assert gf_add_ground([1,2,3], 3, 11, ZZ) == [1,2,6] assert gf_sub_ground([1,2,3], 3, 11, ZZ) == [1,2,0] assert gf_mul_ground([], 0, 11, ZZ) == [] assert gf_mul_ground([], 1, 11, ZZ) == [] assert gf_mul_ground([1], 0, 11, ZZ) == [] assert gf_mul_ground([1], 1, 11, ZZ) == [1] assert gf_mul_ground([1,2,3], 0, 11, ZZ) == [] assert gf_mul_ground([1,2,3], 1, 11, ZZ) == [1,2,3] assert gf_mul_ground([1,2,3], 7, 11, ZZ) == [7,3,10] assert gf_add([], [], 11, ZZ) == [] assert gf_add([1], [], 11, ZZ) == [1] assert gf_add([], [1], 11, ZZ) == [1] assert gf_add([1], [1], 11, ZZ) == [2] assert gf_add([1], [2], 11, ZZ) == [3] assert gf_add([1,2], [1], 11, ZZ) == [1,3] assert gf_add([1], [1,2], 11, ZZ) == [1,3] assert gf_add([1,2,3], [8,9,10], 11, ZZ) == [9,0,2] assert gf_sub([], [], 11, ZZ) == [] assert gf_sub([1], [], 11, ZZ) == [1] assert gf_sub([], [1], 11, ZZ) == [10] assert gf_sub([1], [1], 11, ZZ) == [] assert gf_sub([1], [2], 11, ZZ) == [10] assert gf_sub([1,2], [1], 11, ZZ) == [1,1] assert gf_sub([1], [1,2], 11, ZZ) == [10,10] assert gf_sub([3,2,1], [8,9,10], 11, ZZ) == [6,4,2] assert gf_add_mul([1,5,6], [7,3], [8,0,6,1], 11, ZZ) == [1,2,10,8,9] assert gf_sub_mul([1,5,6], [7,3], [8,0,6,1], 11, ZZ) == [10,9,3,2,3] assert gf_mul([], [], 11, ZZ) == [] assert gf_mul([], [1], 11, ZZ) == [] assert gf_mul([1], [], 11, ZZ) == [] assert gf_mul([1], [1], 11, ZZ) == [1] assert gf_mul([5], [7], 11, ZZ) == [2] assert gf_mul([3,0,0,6,1,2], [4,0,1,0], 11, ZZ) == [1,0,3,2,4,3,1,2,0] assert gf_mul([4,0,1,0], [3,0,0,6,1,2], 11, ZZ) == [1,0,3,2,4,3,1,2,0] assert gf_mul([2,0,0,1,7], [2,0,0,1,7], 11, ZZ) == [4,0,0,4,6,0,1,3,5] assert gf_sqr([], 11, ZZ) == [] assert gf_sqr([2], 11, ZZ) == [4] assert gf_sqr([1,2], 11, ZZ) == [1,4,4] assert gf_sqr([2,0,0,1,7], 11, ZZ) == [4,0,0,4,6,0,1,3,5]
def mul(self, x: list, y: list) -> list: return gf_rem(gf_mul(x, y, self.p, ZZ), self.reducing, self.p, ZZ)