def testSubtraction(self): Z = self.Z f = uniutil.polynomial(enumerate(range(1, 6)), Z) # sf bug # 1937925 f2 = uniutil.polynomial([(1, 2), (2, 3), (3, 4), (4, 5)], Z) self.assertEqual(f2, f - 1) self.assertEqual(-f2, 1 - f)
def _small_irriducible(char, degree): """ Return an irreducible polynomial of self.degree with a small number of non-zero coefficients. """ cardinality = char**degree basefield = FinitePrimeField.getInstance(char) top = uniutil.polynomial({degree: 1}, coeffring=basefield) for seed in range(degree - 1): for const in range(1, char): coeffs = [const] + arith1.expand(seed, 2) cand = uniutil.polynomial(enumerate(coeffs), coeffring=basefield) + top if cand.isirreducible(): _log.debug(cand.order.format(cand)) return cand for subdeg in range(degree): subseedbound = char**subdeg for subseed in range(subseedbound + 1, char * subseedbound): if not subseed % char: continue seed = subseed + cardinality cand = uniutil.polynomial(enumerate( arith1.expand(seed, cardinality)), coeffring=basefield) if cand.isirreducible(): return cand
def testDivPoly(self): E = elliptic.EC([3, 4], 101) F101 = finitefield.FinitePrimeField.getInstance(E.ch) D = ({-1:uniutil.polynomial({0:-1}, F101), 0:uniutil.polynomial({}, F101), 1:uniutil.polynomial({0:1}, F101), 2:uniutil.polynomial({0:2}, F101), 3:uniutil.polynomial({0:92, 1:48, 2:18, 4:3}, F101), 4:uniutil.polynomial({0:188, 1:10, 2:22, 3:118, 4:60, 6:4}, F101), 5:uniutil.polynomial({0:48, 1:58, 2:53, 3:60, 4:28, 5:93, 6:79, 7:52, 8:65, 9:5, 10:85, 12:5}, F101), 6:uniutil.polynomial({0:18, 1:24, 2:88, 3:32, 4:128, 5:44, 6:152, 7:56, 8:84, 9:192, 10:174, 12:114, 13:124, 14:28, 16:6}, F101), 7:uniutil.polynomial({0:94, 1:77, 2:87, 3:65, 4:97, 5:45, 6:80, 7:22, 8:44, 9:76, 10:5, 11:49, 12:49, 13:74, 14:76, 15:53, 16:69, 17:47, 18:63, 19:70, 20:78, 21:20, 22:15, 24:7}, F101), 8:uniutil.polynomial({0:32, 1:100, 2:58, 3:20, 4:124, 5:160, 6:82, 7:132, 8:158, 9:96, 10:154, 11:106, 12:134, 13:140, 14:10, 15:36, 16:72, 17:56, 18:116, 19:190, 20:134, 21:182, 22:74, 23:186, 24:50, 25:186, 26:122, 27:68, 28:136, 30:8}, F101)}, [2, 3, 5, 7]) self.assertEqual(D, E.divPoly([]))
def _primitive_polynomial(char, degree): """ Return a primitive polynomial of self.degree. REF: Lidl & Niederreiter, Introduction to finite fields and their applications. """ cardinality = char**degree basefield = FinitePrimeField.getInstance(char) const = basefield.primitive_element() if degree & 1: const = -const cand = uniutil.polynomial({0: const, degree: basefield.one}, basefield) maxorder = factor_misc.FactoredInteger((cardinality - 1) // (char - 1)) var = uniutil.polynomial({1: basefield.one}, basefield) while not (cand.isirreducible() and all( pow(var, int(maxorder) // p, cand).degree() > 0 for p in maxorder.prime_divisors())): # randomly modify the polynomial deg = bigrandom.randrange(1, degree) coeff = basefield.random_element(1, char) cand += uniutil.polynomial({deg: coeff}, basefield) _log.debug(cand.order.format(cand)) return cand
def setUp(self): """ define a class using DivisionProvider """ R = rational.Rational Q = rational.theRationalField self.up1 = up1 = uniutil.polynomial([(1, R(1))], coeffring=Q) self.u = uniutil.polynomial([(0, up1), (3, up1)], up1.getRing()) self.v = uniutil.polynomial([(0, -up1)], up1.getRing())
def testShortSeq(self): """ sequence has less dimension """ F5 = finitefield.FinitePrimeField.getInstance(5) f5 = F5.createElement ann = uniutil.polynomial({1: 1}, F5) self.assertEqual(ann, linrec.minpoly(map(f5, [3, 0, 0, 0, 0, 0]))) ann = uniutil.polynomial({2: 1}, F5) self.assertEqual(ann, linrec.minpoly(map(f5, [3, 1, 0, 0, 0, 0])))
def testAddition(self): Z = self.Z f = uniutil.polynomial(enumerate(range(1, 6)), Z) g = uniutil.polynomial(enumerate(range(7, 10)), Z) h = uniutil.polynomial(enumerate([8, 10, 12, 4, 5]), Z) self.assertEqual(h, f + g) self.assertTrue(isinstance(f + g, uniutil.IntegerPolynomial)) # sf bug # 1937925 f2 = uniutil.polynomial(enumerate([2, 2, 3, 4, 5]), Z) self.assertEqual(f2, f + 1) self.assertEqual(f2, 1 + f)
def testResultant(self): Z = rational.theIntegerRing I = rational.Integer f = uniutil.polynomial(enumerate(map(I, range(5))), coeffring=Z) g = uniutil.polynomial(enumerate(map(I, range(7, 10))), coeffring=Z) self.assertEqual(0, f.resultant(f * g)) h1 = uniutil.polynomial(enumerate(map(I, [-2, 0, 0, 1])), coeffring=Z) h2 = uniutil.polynomial(enumerate([Z.zero, Z.one]), coeffring=Z) self.assertEqual(2, h1.resultant(h2)) t = uniutil.polynomial(enumerate(map(I, range(7, 0, -1))), coeffring=Z) self.assertEqual(2**16 * 7**4, t.resultant(t.differentiate()))
def setUp(self): """ set up some polynomials """ self.f1 = uniutil.polynomial(enumerate([3, 6, 81, 1]), Z) self.f2 = uniutil.polynomial(enumerate([1, 81, 6, 3]), Z) self.f3 = uniutil.polynomial(enumerate([37, 6, 18, 1]), Z) self.f4 = uniutil.polynomial(enumerate([91, 7, 14, 1]), Z) # f5 = (x - 6)(x - 5)...x(x + 1)(x + 2) - 1 self.f5 = uniutil.polynomial( enumerate([1439, -1368, -1324, 1638, -231, -252, 114, -18, 1]), Z)
def testNonPrimitive(self): f1 = uniutil.polynomial(enumerate([3, 6]), Z) f2 = uniutil.polynomial(enumerate([5, 4, 1]), Z) f3 = uniutil.polynomial(enumerate([-1, 3]), Z) f = f1**3 * f2**2 * f3 r = zassenhaus.integerpolynomialfactorization(f) self.assertTrue(isinstance(r, list)) self.assertEqual(4, len(r), r) self.assertTrue(isinstance(r[0][0], uniutil.IntegerPolynomial)) self.assertTrue(isinstance(r[1][0], uniutil.IntegerPolynomial)) self.assertTrue(isinstance(r[2][0], uniutil.IntegerPolynomial)) self.assertTrue(isinstance(r[3][0], uniutil.IntegerPolynomial)) self.assertEqual(f, r[0][0]**r[0][1] * r[1][0]**r[1][1] * r[2][0]**r[2][1] * r[3][0]**r[3][1])
def setUp(self): """ define a class using DivisionProvider """ Polynomial = multiutil.UniqueFactorizationDomainPolynomial R = rational.Rational Q = rational.theRationalField self.f1 = f1 = Polynomial([((3, 1), R(1)), ((0, 1), R(1))], coeffring=Q) f2 = Polynomial([((0, 1), R(-1))], coeffring=Q) self.fn = uniutil.polynomial([(0, f1), (3, f2)], coeffring=f1.getRing()) self.fz = Polynomial([((0, 3, 1), R(1)), ((3, 0, 1), R(-1)), ((0, 0, 1), R(1))], coeffring=Q) u1 = uniutil.polynomial([(1, R(1))], coeffring=Q) u2 = uniutil.polynomial([(1, R(1))], coeffring=Q) self.u = uniutil.polynomial([(0, u1), (3, u2)], u1.getRing())
def testWeilPairing(self): # this example was refered to Washington. e = elliptic.EC([0, 2], 7) P = [5, 1] Q = [0, 3] R = e.WeilPairing(3, P, Q) self.assertEqual(finitefield.FinitePrimeFieldElement(2, 7), R) # test case of extension field, characteristic 7 p = 7 r = 11 F = finitefield.FinitePrimeField(p) PX = uniutil.polynomial({0:3,1:3,2:2,3:1,4:4,5:1,6:1,10:1},F) Fx = finitefield.FiniteExtendedField(p,PX) E = elliptic.EC([F.one,-F.one],F) Ex = elliptic.EC([Fx.one,-Fx.one],Fx) P = [3,6] assert E.whetherOn(P) assert Ex.whetherOn(P) assert E.mul(11,P) == E.infpoint Qxcoord = Fx.createElement(6*7**9+7**8+7**6+6*7**3+6*7**2+7+6) Qycoord = Fx.createElement(3*7**9+6*7**8+4*7**7+2*7**6+5*7**4+5*7**3+7**2+7+3) Q = [Qxcoord,Qycoord] assert Ex.whetherOn(Q) assert Ex.mul(11,Q) == Ex.infpoint w = Ex.WeilPairing(11, P, Q) Wp = Fx.createElement(7**9 + 5*7**8 + 4*7**7 + 2*7**5 + 7**4 + 6*7**2) assert w == Wp
def Dedekind(minpoly_coeff, p, e): """ Return (finished or not, an order) the Dedekind criterion Arguments: - minpoly_coeff: (integer) list of the minimal polynomial of theta. - p, e: p**e divides the discriminant of the minimal polynomial. """ n = len(minpoly_coeff) - 1 # degree of the minimal polynomial m, uniq = _factor_minpoly_modp(minpoly_coeff, p) omega = _default_omega(n) if m == 0: return True, omega minpoly = uniutil.polynomial(enumerate(minpoly_coeff), Z) v = [_coeff_list(uniq, n)] shift = uniq for i in range(1, m): shift = shift.upshift_degree(1).pseudo_mod(minpoly) v.append(_coeff_list(shift, n)) updater = ModuleWithDenominator(v, p) return (m + 1 > e), updater + omega
def testDiscriminant(self): Q = rational.theRationalField rat = rational.Rational a, b, c = rat(2, 7), rat(5, 14), rat(1, 7) q1 = uniutil.polynomial(enumerate([c, b, a]), Q) d = b**2 - 4 * a * c self.assertEqual(d, q1.discriminant())
def testIrreducible(self): f = uniutil.polynomial(enumerate([12, 6, 1]), Z) r = zassenhaus.zassenhaus(f) self.assertTrue(isinstance(r, list), r) self.assertEqual(1, len(r)) self.assertTrue(isinstance(r[0], uniutil.UniqueFactorizationDomainPolynomial)) self.assertEqual(f, r[0])
def padic_factorization(f): """ padic_factorization(f) -> p, factors Return a prime p and a p-adic factorization of given integer coefficient squarefree polynomial f. The result factors have integer coefficients, injected from F_p to its minimum absolute representation. The prime is chosen to be 1) f is still squarefree mod p, 2) the number of factors is not greater than with the successive prime. """ num_factors = f.degree() stock = None for p in prime.generator(): fmodp = uniutil.polynomial(f.terms(), finitefield.FinitePrimeField.getInstance(p)) if f.degree() > fmodp.degree(): continue g = fmodp.getRing().gcd(fmodp, fmodp.differentiate()) if g.degree() == 0: fp_factors = fmodp.factor() if (not stock) or num_factors > len(fp_factors): stock = (p, fp_factors) if len(fp_factors) == 1: return stock num_factors = len(fp_factors) else: break p = stock[0] fp_factors = [] for (fp_factor, m) in stock[1]: assert m == 1 # since squarefree fp_factors.append(minimum_absolute_injection(fp_factor)) return (p, fp_factors)
def qpoly(coeffs): """ Return a rational coefficient polynomial constructed from given coeffs. The coeffs is a list of coefficients in ascending order. """ terms = [(i, rational.Rational(c)) for (i, c) in enumerate(coeffs)] return uniutil.polynomial(terms, rational.theRationalField)
def fppoly(coeffs, p): """ Return a Z_p coefficient polynomial constructed from given coeffs. The coeffs is a list of coefficients in ascending order. """ return uniutil.polynomial(enumerate(coeffs), finitefield.FinitePrimeField(p))
def _mod_p(poly, p): """ Return modulo p reduction of given integer coefficient polynomial. """ coeff = {} for d, c in poly: coeff[d] = finitefield.FinitePrimeFieldElement(c, p) return uniutil.polynomial(poly, finitefield.FinitePrimeField.getInstance(p))
def testAtti(self): """ This test case is taken from the paper of Atti et al. """ Q = rational.theRationalField rat = rational.Rational ann = uniutil.polynomial(enumerate([0, 1, 1, 1]), Q) self.assertEqual(ann, linrec.minpoly(map(rat, [1, 2, 7, -9, 2, 7])))
def testRegular(self): f = uniutil.polynomial(enumerate([12, 7, 1]), Z) r = zassenhaus.padic_factorization(f) self.assertTrue(isinstance(r, tuple)) self.assertEqual(2, len(r)) self.assertTrue(prime.primeq(r[0])) self.assertTrue(isinstance(r[1], list)) self.assertEqual(2, len(r[1]))
def setUp(self): self.f = ratfunc.RationalFunction(uniutil.polynomial({ 3: 1, 0: 1 }, Z), uniutil.polynomial({ 2: 1, 0: -2 }, Z)) self.f2 = self.f self.f3 = ratfunc.RationalFunction( uniutil.polynomial({ 4: 1, 1: 1 }, Z), uniutil.polynomial({ 3: 1, 1: -2 }, Z))
def testRegular(self): f = uniutil.polynomial(enumerate([12, 7, 1]), Z) r = zassenhaus.zassenhaus(f) self.assertTrue(isinstance(r, list)) self.assertEqual(2, len(r), r) self.assertTrue(isinstance(r[0], uniutil.UniqueFactorizationDomainPolynomial)) self.assertTrue(isinstance(r[1], uniutil.UniqueFactorizationDomainPolynomial)) self.assertEqual(f, r[0] * r[1])
def testAtti_19(self): """ testAtti on F19 """ F19 = finitefield.FinitePrimeField.getInstance(19) f19 = F19.createElement ann = uniutil.polynomial(enumerate([0, 1, 1, 1]), F19) self.assertEqual(ann, linrec.minpoly(map(f19, [1, 2, 7, -9, 2, 7])))
def _min_abs_poly(poly_p): """ Return minimal absolute mapping of given F_p coefficient polynomial. """ coeff = {} p = poly_p.getCoefficientRing().char for d, c in poly_p: coeff[d] = _pull_back(c, p) return uniutil.polynomial(coeff, Z)
def minpoly(firstterms): """ Return the minimal polynomial having at most degree n of of the linearly recurrent sequence whose first 2n terms are given. """ field = ring.getRing(firstterms[0]) r_0 = uniutil.polynomial({len(firstterms): field.one}, field) r_1 = uniutil.polynomial(enumerate(reversed(firstterms)), field) poly_ring = r_0.getRing() v_0 = poly_ring.zero v_1 = poly_ring.one n = len(firstterms) // 2 while n <= r_1.degree(): q, r = divmod(r_0, r_1) v_0, v_1 = v_1, v_0 - q * v_1 r_0, r_1 = r_1, r return v_1.scalar_mul(v_1.leading_coefficient().inverse())
def getCharPoly(self): """ Return the characteristic polynomial of self by compute products of (x-self^{(i)}). """ if not hasattr(self, "charpoly"): Conj = self.getApprox() P = uniutil.polynomial({0:-Conj[0], 1:1}, ring.getRing(Conj[0])) for i in range(1, self.degree): P *= uniutil.polynomial({0:-Conj[i], 1:1}, ring.getRing(Conj[i])) charcoeff = [] for i in range(self.degree + 1): if hasattr(P[i], "real"): charcoeff.append(int(math.floor(P[i].real + 0.5))) else: charcoeff.append(int(math.floor(P[i] + 0.5))) self.charpoly = charcoeff return self.charpoly
def _zero_polynomial(self): """ Return the zero polynomial in the polynomial ring. """ if self.number_of_variables == 1: import nzmath.poly.uniutil as uniutil return uniutil.polynomial((), self._coefficient_ring) else: import nzmath.poly.multiutil as multiutil return multiutil.polynomial((), coeffring=self._coefficient_ring, number_of_variables=self.number_of_variables)
def testReduceEuclideanPolynomial(self): whole = poly_ring.PolynomialIdeal(-1, self.zx) f = uniutil.polynomial([(0, 3), (1, 2)], self.Z) f_ideal = poly_ring.PolynomialIdeal(f, self.zx) self.assertFalse(whole.reduce(f)) self.assertTrue(f_ideal.reduce(self.Z.one)) two_generators = poly_ring.PolynomialIdeal([f, self.zx.createElement(5)], self.zx) self.assertFalse(two_generators.reduce(f)) self.assertTrue(two_generators.reduce(self.Z.one))
def _prepared_polynomial(self, preparation): """ Return a polynomial from given preparation, which is suited for the first argument of uni-/multi-variable polynomials. """ if self.number_of_variables == 1: import nzmath.poly.uniutil as uniutil return uniutil.polynomial(preparation, self._coefficient_ring) else: import nzmath.poly.multiutil as multiutil return multiutil.polynomial(preparation, self._coefficient_ring)
def testSeptic(self): """ Test an example: X^7 + 2X^6 + ... + 7X + 8 """ poly_disc = uniutil.polynomial(enumerate(self.septic), self.Z).discriminant() self.assertEqual(-2**16 * 3**12, poly_disc) result = round2.round2(self.septic) self.assertTrue(result) self.assertEqual(2, len(result)) self.assertEqual(-2**12 * 3**10, result[1], result)
def _constant_polynomial(self, seed): """ Return a constant polynomial made from a constant seed. seed should not be zero. """ if self.number_of_variables == 1: import nzmath.poly.uniutil as uniutil return uniutil.polynomial({0: seed}, self._coefficient_ring) else: import nzmath.poly.multiutil as multiutil const = (0,) * self.number_of_variables return multiutil.polynomial({const: seed}, self._coefficient_ring)
def _factor_minpoly_modp(minpoly_coeff, p): """ Factor theminpoly modulo p, and return two values in a tuple. We call gcd(square factors mod p, difference of minpoly and its modp) Z. 1) degree of Z 2) (minpoly mod p) / Z """ Fp = finitefield.FinitePrimeField.getInstance(p) theminpoly_p = uniutil.polynomial([(d, Fp.createElement(c)) for (d, c) in enumerate(minpoly_coeff)], Fp) modpfactors = theminpoly_p.factor() mini_p = arith1.product([t for (t, e) in modpfactors]) quot_p = theminpoly_p.exact_division(mini_p) mini = _min_abs_poly(mini_p) quot = _min_abs_poly(quot_p) minpoly = uniutil.polynomial(enumerate(minpoly_coeff), Z) f_p = _mod_p((mini * quot - minpoly).scalar_exact_division(p), p) gcd = f_p.getRing().gcd common_p = gcd(gcd(mini_p, quot_p), f_p) # called Z uniq_p = theminpoly_p // common_p uniq = _min_abs_poly(uniq_p) return common_p.degree(), uniq
def extgcdp(f, g, p): """ extgcdp(f,g,p) -> u,v,w Find u,v,w such that f*u + g*v = w = gcd(f,g) mod p. """ zpz = intresidue.IntegerResidueClassRing.getInstance(p) f_zpz = uniutil.polynomial(f, zpz) g_zpz = uniutil.polynomial(g, zpz) zero, one = f_zpz.getRing().zero, f_zpz.getRing().one u, v, w, x, y, z = one, zero, f_zpz, zero, one, g_zpz while z: q = w // z u, v, w, x, y, z = x, y, z, u - q*x, v - q*y, w - q*z if w.degree() == 0 and w[0] != zpz.one: u = u.scalar_exact_division(w[0]) # u / w v = v.scalar_exact_division(w[0]) # v / w w = w.getRing().one # w / w u = minimum_absolute_injection(u) v = minimum_absolute_injection(v) w = minimum_absolute_injection(w) return u, v, w
def _primitive_polynomial(char, degree): """ Return a primitive polynomial of self.degree. REF: Lidl & Niederreiter, Introduction to finite fields and their applications. """ cardinality = char ** degree basefield = FinitePrimeField.getInstance(char) const = basefield.primitive_element() if degree % 2: const = -const cand = uniutil.polynomial({0:const, degree:basefield.one}, basefield) maxorder = factor_misc.FactoredInteger((cardinality - 1) // (char - 1)) var = uniutil.polynomial({1:basefield.one}, basefield) while not (cand.isirreducible() and all(pow(var, int(maxorder) // p, cand).degree() > 0 for p in maxorder.prime_divisors())): # randomly modify the polynomial deg = bigrandom.randrange(1, degree) coeff = basefield.random_element(1, char) cand += uniutil.polynomial({deg:coeff}, basefield) _log.debug(cand.order.format(cand)) return cand
def _small_irriducible(char, degree): """ Return an irreducible polynomial of self.degree with a small number of non-zero coefficients. """ cardinality = char ** degree basefield = FinitePrimeField.getInstance(char) top = uniutil.polynomial({degree: 1}, coeffring=basefield) for seed in range(degree - 1): for const in range(1, char): coeffs = [const] + arith1.expand(seed, 2) cand = uniutil.polynomial(enumerate(coeffs), coeffring=basefield) + top if cand.isirreducible(): _log.debug(cand.order.format(cand)) return cand for subdeg in range(degree): subseedbound = char ** subdeg for subseed in range(subseedbound + 1, char * subseedbound): if not subseed % char: continue seed = subseed + cardinality cand = uniutil.polynomial(enumerate(arith1.expand(seed, cardinality)), coeffring=basefield) if cand.isirreducible(): return cand
def nest(self, outer, coeffring): """ Nest the polynomial by extracting outer variable at the given position. """ combined = {} if self.number_of_variables == 2: itercoeff = lambda coeff: [(i[0], c) for (i, c) in coeff] poly = uniutil.polynomial polyring = poly_ring.PolynomialRing.getInstance(coeffring) elif self.number_of_variables >= 3: itercoeff = lambda coeff: coeff poly = self.__class__ polyring = poly_ring.PolynomialRing.getInstance(coeffring, self.number_of_variables - 1) else: raise TypeError("number of variable is not multiple") for index, coeff in self.combine_similar_terms(outer): combined[index] = poly(itercoeff(coeff), coeffring=coeffring) return uniutil.polynomial(combined, coeffring=polyring)
def _SimMethod(g, initials=None, newtoninitial=None, repeat=250): """ Return zeros of a polynomial given as a list. - g is the list of the polynomial coefficient in ascending order. - initial (optional) is a list of initial approximations of zeros. - newtoninitial (optional) is an initial value for Newton method to obtain an initial approximations of zeros if 'initial' is not given. - repeat (optional) is the number of iteration. The default is 250. """ if initials is None: if newtoninitial: z = _initialize(g, newtoninitial) else: z = _initialize(g) else: z = initials f = uniutil.polynomial(enumerate(g), imaginary.theComplexField) deg = f.degree() df = f.differentiate() value_list = [f(z[i]) for i in range(deg)] for loop in range(repeat): sigma_list = [0] * deg for i in range(deg): if not value_list[i]: continue sigma = 0 for j in range(i): sigma += 1 / (z[i] - z[j]) for j in range(i+1, deg): sigma += 1 / (z[i] - z[j]) sigma_list[i] = sigma for i in range(deg): if not value_list[i]: continue ratio = value_list[i] / df(z[i]) z[i] -= ratio / (1 - ratio*sigma_list[i]) value_list[i] = f(z[i]) return z
def _p_maximal(p, e, minpoly_coeff): """ Return p-maximal basis with some related informations. The arguments: p: the prime e: the exponent minpoly_coeff: (intefer) list of coefficients of the minimal polynomial of theta """ # Apply the Dedekind criterion finished, omega = Dedekind(minpoly_coeff, p, e) if finished: _log.info("Dedekind(%d)" % p) return omega # main loop to construct p-maximal order minpoly = uniutil.polynomial(enumerate(minpoly_coeff), Z) theminpoly = minpoly.to_field_polynomial() n = theminpoly.degree() q = p ** (arith1.log(n, p) + 1) while True: # Ip: radical of pO # Ip = <alpha>, l = dim Ip/pO (essential part of Ip) alpha, l = _p_radical(omega, p, q, minpoly, n) # instead of step 9 big matrix, # Kida's LN section 2.2 # Up = {x in Ip | xIp \subset pIp} = <zeta> + p<omega> zeta = _p_module(alpha, l, p, theminpoly) if zeta.rank == 0: # no new basis is found break # new order # 1/p Up = 1/p<zeta> + <omega> omega2 = zeta / p + omega if all(o1 == o2 for o1, o2 in zip(omega.basis, omega2.basis)): break omega = omega2 # now <omega> is p-maximal. return omega
def round2(minpoly_coeff): """ Return integral basis of the ring of integers of a field with its discriminant. The field is given by a list of integers, which is a polynomial of generating element theta. The polynomial ought to be monic, in other word, the generating element ought to be an algebraic integer. The integral basis will be given as a list of rational vectors with respect to theta. (In other functions, bases are returned in the same fashion.) """ minpoly_int = uniutil.polynomial(enumerate(minpoly_coeff), Z) d = minpoly_int.discriminant() squarefactors = _prepare_squarefactors(d) omega = _default_omega(minpoly_int.degree()) for p, e in squarefactors: _log.debug("p = %d" % p) omega = omega + _p_maximal(p, e, minpoly_coeff) G = omega.determinant() return omega.get_rationals(), d * G**2
def _kernel_of_qpow(omega, q, p, minpoly, n): """ Return the kernel of q-th powering, which is a linear map over Fp. q is a power of p which exceeds n. (omega_j^q (mod theminpoly) = \sum a_i_j omega_i a_i_j in Fp) """ omega_poly = omega.get_polynomials() denom = omega.denominator theminpoly = minpoly.to_field_polynomial() field_p = finitefield.FinitePrimeField.getInstance(p) zero = field_p.zero qpow = matrix.zeroMatrix(n, n, field_p) # Fp matrix for j in range(n): a_j = [zero] * n omega_poly_j = uniutil.polynomial(enumerate(omega.basis[j]), Z) omega_j_qpow = pow(omega_poly_j, q, minpoly) redundancy = gcd.gcd(omega_j_qpow.content(), denom ** q) omega_j_qpow = omega_j_qpow.coefficients_map(lambda c: c // redundancy) essential = denom ** q // redundancy while omega_j_qpow: i = omega_j_qpow.degree() a_ji = int(omega_j_qpow[i] / (omega_poly[i][i] * essential)) omega_j_qpow -= a_ji * (omega_poly[i] * essential) if omega_j_qpow.degree() < i: a_j[i] = field_p.createElement(a_ji) else: _log.debug("%s / %d" % (str(omega_j_qpow), essential)) _log.debug("j = %d, a_ji = %s" % (j, a_ji)) raise ValueError("omega is not a basis") qpow.setColumn(j + 1, a_j) result = qpow.kernel() if result is None: _log.debug("(_k_q): trivial kernel") return matrix.zeroMatrix(n, 1, field_p) else: return result
def minimum_absolute_injection(f): """ minimum_absolute_injection(f) -> F Return an integer coefficient polynomial F by injection of a Z/pZ coefficient polynomial f with sending each coefficient to minimum absolute representatives. """ coefficientRing = f.getCoefficientRing() if isinstance(coefficientRing, intresidue.IntegerResidueClassRing): p = coefficientRing.m elif isinstance(coefficientRing, finitefield.FinitePrimeField): p = coefficientRing.getCharacteristic() else: raise TypeError("unknown ring (%s)" % repr(coefficientRing)) half = p // 2 g = {} for i, c in f.iterterms(): if c.n > half: g[i] = c.n - p else: g[i] = c.n return uniutil.polynomial(g, rational.theIntegerRing)
def padic_factorization(f): """ padic_factorization(f) -> p, factors Return a prime p and a p-adic factorization of given integer coefficient squarefree polynomial f. The result factors have integer coefficients, injected from F_p to its minimum absolute representation. The prime is chosen to be 1) f is still squarefree mod p, 2) the number of factors is not greater than with the successive prime. """ num_factors = f.degree() stock = None for p in prime.generator(): fmodp = uniutil.polynomial( f.terms(), finitefield.FinitePrimeField.getInstance(p)) if f.degree() > fmodp.degree(): continue g = fmodp.getRing().gcd(fmodp, fmodp.differentiate()) if g.degree() == 0: fp_factors = fmodp.factor() if not stock or num_factors > len(fp_factors): stock = (p, fp_factors) if len(fp_factors) == 1: return stock num_factors = len(fp_factors) else: break p = stock[0] fp_factors = [] for (fp_factor, m) in stock[1]: assert m == 1 # since squarefree fp_factors.append(minimum_absolute_injection(fp_factor)) return (p, fp_factors)
except ValueError, e: print e.message print m = matrix.Matrix(2, 2, [1, 0, 1, 0], f2) print m print v = matrix.Matrix(2, 1, [1, 1], f2) print v print print m.inverseImage(v) print f2 = finitefield.FinitePrimeField(2) P = polyring.PolynomialRing(f2) x = P.createElement(polynomial([(1, 1)], f2)) def T(A, j): p = A.coeff_ring.getCharacteristic() phi = lambda A: (x * A + matrix.unitMatrix(A.row, A.coeff_ring)).determinant() return phi(A)[p**j] A = matrix.Matrix(2, 2, [1, 0, 1, 0], f2) print T(A, 1) print #A = matrix.Matrix(4, 4, [2, 1, 1, 1, 2, 1, 2, 1, 3, 2, 2, 1, 0, 1, 2, 1], R) A = random_matrix(8, 3, f2) print "Rank", A.rank() try: (L, U, P) = A.LUPDecomposition()
def _rational_polynomial(coeffs): """ Return rational polynomial with given coefficients in ascending order. """ return uniutil.polynomial(enumerate(coeffs), Q)
def zpoly(coeffs): """ Return an integer coefficient polynomial constructed from given coeffs. The coeffs is a list of coefficients in ascending order. """ return uniutil.polynomial(enumerate(coeffs), rational.theIntegerRing)
def affine_multiple_method(lhs, field): """ Find and return a root of the equation lhs = 0 by brute force search in the given field. If there is no root in the field, ValueError is raised. The first argument lhs is a univariate polynomial with coefficients in a finite field. The second argument field is an extension field of the field of coefficients of lhs. Affine multiple A(X) is $\sum_{i=0}^{n} a_i X^{q^i} - a$ for some a_i's and a in the coefficient field of lhs, which is a multiple of the lhs. """ polynomial_ring = lhs.getRing() coeff_field = lhs.getCoefficientRing() q = card(coeff_field) n = lhs.degree() # residues = [x, x^q, x^{q^2}, ..., x^{q^{n-1}}] residues = [lhs.mod(polynomial_ring.one.term_mul((1, 1)))] # x for i in range(1, n): residues.append(pow(residues[-1], q, lhs)) # x^{q^i} # find a linear relation among residues and a constant coeff_matrix = matrix.createMatrix(n, n, [coeff_field.zero] * (n**2), coeff_field) for j, residue in enumerate(residues): for i in range(residue.degree() + 1): coeff_matrix[i + 1, j + 1] = residue[i] constant_components = [coeff_field.one] + [coeff_field.zero] * (n - 1) constant_vector = vector.Vector(constant_components) try: relation_vector, kernel = coeff_matrix.solve(constant_vector) for j in range(n, 0, -1): if relation_vector[j]: constant = relation_vector[j].inverse() relation = [constant * c for c in relation_vector] break except matrix.NoInverseImage: kernel_matrix = coeff_matrix.kernel() relation_vector = kernel_matrix[1] assert type(relation_vector) is vector.Vector for j in range(n, 0, -1): if relation_vector[j]: normalizer = relation_vector[j].inverse() relation = [normalizer * c for c in relation_vector] constant = coeff_field.zero break # define L(X) = A(X) + constant coeffs = {} for i, relation_i in enumerate(relation): coeffs[q**i] = relation_i linearized = uniutil.polynomial(coeffs, coeff_field) # Fq basis [1, X, ..., X^{s-1}] qbasis = [1] root = field.createElement(field.char) s = arith1.log(card(field), q) qbasis += [root**i for i in range(1, s)] # represent L as Matrix lmat = matrix.createMatrix(s, s, field.basefield) for j, base in enumerate(qbasis): imagei = linearized(base) if imagei.getRing() == field.basefield: lmat[1, j + 1] = imagei else: for i, coeff in imagei.rep.iterterms(): if coeff: lmat[i + 1, j + 1] = coeff # solve L(X) = the constant constant_components = [constant] + [coeff_field.zero] * (s - 1) constant_vector = vector.Vector(constant_components) solution, kernel = lmat.solve(constant_vector) assert lmat * solution == constant_vector solutions = [solution] for v in kernel: for i in range(card(field.basefield)): solutions.append(solution + i * v) # roots of A(X) contains the solutions of lhs = 0 for t in bigrange.multirange([(card(field.basefield),)] * len(kernel)): affine_root_vector = solution for i, ti in enumerate(t): affine_root_vector += ti * kernel[i] affine_root = field.zero for i, ai in enumerate(affine_root_vector): affine_root += ai * qbasis[i] if not lhs(affine_root): return affine_root raise ValueError("no root found")