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 _random_irriducible(char, degree): """ Return randomly chosen irreducible polynomial of self.degree. """ cardinality = char ** degree basefield = FinitePrimeField.getInstance(char) seed = bigrandom.randrange(1, char) + cardinality cand = uniutil.FiniteFieldPolynomial(enumerate(arith1.expand(seed, cardinality)), coeffring=basefield) while cand.degree() < degree or not cand.isirreducible(): seed = bigrandom.randrange(1, cardinality) + cardinality cand = uniutil.FiniteFieldPolynomial(enumerate(arith1.expand(seed, cardinality)), coeffring=basefield) _log.debug(cand.order.format(cand)) return cand
def mul(Q, x, C, n): """ Return x*Q on the curve C mod n. m*Q and (m+1)*Q are being tracked in the main loop. """ if x == 0: return POINT_AT_INFINITY if x == 1: return Q if x == 2: return double(Q, C, n) minor = Q major = double(Q, C, n) binary = _arith1.expand(x, 2) lastbit, binary = binary[0], binary[1:] while binary: if binary.pop() == 1: minor = add(major, minor, Q, n) major = double(major, C, n) else: major = add(minor, major, Q, n) minor = double(minor, C, n) if lastbit: return add(minor, major, Q, n) return double(minor, C, n)
def createElement(self, seed): """ Create an element of the field. """ if isinstance(seed, int): expansion = arith1.expand(seed, self.char) return FiniteExtendedFieldElement( FinitePrimeFieldPolynomial(enumerate(expansion), self.basefield), self) elif isinstance(seed, FinitePrimeFieldPolynomial): return FiniteExtendedFieldElement(seed, self) elif isinstance(seed, FinitePrimeFieldElement ) and seed.m == self.getCharacteristic(): return FiniteExtendedFieldElement( FinitePrimeFieldPolynomial([(0, seed)], self.basefield), self) elif seed in self: # seed is in self, return only embedding return self.zero + seed else: try: # lastly check sequence return FiniteExtendedFieldElement( FinitePrimeFieldPolynomial(enumerate(seed), self.basefield), self) except TypeError: raise TypeError("seed %s is not an appropriate object." % str(seed))
def createElement(self, seed): """ Create an element of the field. """ if isinstance(seed, int): expansion = arith1.expand(seed, card(self.basefield)) return ExtendedFieldElement( uniutil.FiniteFieldPolynomial(enumerate(expansion), self.basefield), self) elif seed in self.basefield: return ExtendedFieldElement( uniutil.FiniteFieldPolynomial([(0, seed)], self.basefield), self) elif seed in self: # seed is in self, return only embedding return self.zero + seed elif (isinstance(seed, uniutil.FiniteFieldPolynomial) and seed.getCoefficientRing() is self.basefield): return ExtendedFieldElement(seed, self) else: try: # lastly check sequence return ExtendedFieldElement( uniutil.FiniteFieldPolynomial(enumerate(seed), self.basefield), self) except TypeError: raise TypeError("seed %s is not an appropriate object." % str(seed))
def createElement(self, seed): """ Create an element of the field. """ if isinstance(seed, (int, long)): expansion = arith1.expand(seed, card(self.basefield)) return ExtendedFieldElement( uniutil.FiniteFieldPolynomial(enumerate(expansion), self.basefield), self) elif seed in self.basefield: return ExtendedFieldElement( uniutil.FiniteFieldPolynomial([(0, seed)], self.basefield), self) elif seed in self: # seed is in self, return only embedding return self.zero + seed elif (isinstance(seed, uniutil.FiniteFieldPolynomial) and seed.getCoefficientRing() is self.basefield): return ExtendedFieldElement(seed, self) else: try: # lastly check sequence return ExtendedFieldElement( uniutil.FiniteFieldPolynomial(enumerate(seed), self.basefield), self) except TypeError: raise TypeError("seed %s is not an appropriate object." % str(seed))
def _random_irriducible(char, degree): """ Return randomly chosen irreducible polynomial of self.degree. """ cardinality = char**degree basefield = FinitePrimeField.getInstance(char) seed = bigrandom.randrange(1, char) + cardinality cand = uniutil.FiniteFieldPolynomial(enumerate( arith1.expand(seed, cardinality)), coeffring=basefield) while cand.degree() < degree or not cand.isirreducible(): seed = bigrandom.randrange(1, cardinality) + cardinality cand = uniutil.FiniteFieldPolynomial(enumerate( arith1.expand(seed, cardinality)), coeffring=basefield) _log.debug(cand.order.format(cand)) return cand
def __init__(self, characteristic, n_or_modulus): """ FiniteExtendedField(p, n_or_modulus) creates a finite field. characteristic must be prime. n_or_modulus can be: 1) an integer greater than 1, or 2) a polynomial in a polynomial ring of F_p with degree greater than 1. """ FiniteField.__init__(self, characteristic) self.basefield = FinitePrimeField.getInstance(self.char) if isinstance(n_or_modulus, int): if n_or_modulus <= 1: raise ValueError("degree of extension must be > 1.") self.degree = n_or_modulus # randomly chosen irreducible polynomial top = FinitePrimeFieldPolynomial({self.degree: 1}, coeffring=self.basefield) seed = bigrandom.randrange(1, self.char) cand = FinitePrimeFieldPolynomial(enumerate( arith1.expand(seed, self.char)), coeffring=self.basefield) + top while cand.degree() < self.degree or not cand.isirreducible(): seed = bigrandom.randrange(1, self.char**self.degree) cand = FinitePrimeFieldPolynomial( enumerate(arith1.expand(seed, self.char)), coeffring=self.basefield) + top self.modulus = cand elif isinstance(n_or_modulus, FinitePrimeFieldPolynomial): if isinstance(n_or_modulus.getCoefficientRing(), FinitePrimeField): if n_or_modulus.degree() > 1 and n_or_modulus.isirreducible(): self.degree = n_or_modulus.degree() self.modulus = n_or_modulus else: raise ValueError( "modulus must be of degree greater than 1.") else: raise TypeError("modulus must be F_p polynomial.") else: raise TypeError("degree or modulus must be supplied.") self.registerModuleAction(rational.theIntegerRing, self._int_mul) self.registerModuleAction(FinitePrimeField.getInstance(self.char), self._fp_mul)
def mul(self, k, P): """ this returns [k]*P """ if k >= 0: l = arith1.expand(k, 2) Q = [0] for j in range(len(l) - 1, -1, -1): Q = self.add(Q, Q) if l[j] == 1: Q = self.add(Q, P) return Q else: return self.sub([0], self.mul(-k, P))
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 _lucas_chain(n, f, g, x_0, x_1): """ Given an integer n, two functions f and g, and initial value (x_0, x_1), compute (x_n, x_{n+1}), where the sequence {x_i} is defined as: x_{2i} = f(x_i) x_{2i+1} = g(x_i, x_{i+1}) """ binary = arith1.expand(n, 2) u = x_0 v = x_1 while binary: if 1 == binary.pop(): u, v = g(u, v), f(v) else: u, v = f(u), g(u, v) return u, v
def Lucas_chain(n, f, g, x_0, x_1): """ Given an integer n, two functions f and g, and initial value (x_0, x_1), compute (x_n, x_{n+1}), where the sequence {x_i} is defined as: x_{2i} = f(x_i) x_{2i+1} = g(x_i, x_{i+1}) """ binary = arith1.expand(n, 2) u = x_0 v = x_1 while binary: if 1 == binary.pop(): u, v = g(u, v), f(v) else: u, v = f(u), g(u, v) return u, v
def __init__(self, p, initial, power): """ PadicInteger(p, initial, power) The second argument initial can be either integer or iterable. If initial is an integer, it will be expanded p-adically. In iterable case, it will be treated as a p-adic expansion. The third argument power is a power index of modulus, by which the representation is finite. """ if isinstance(initial, int): cutoff = p**power # taking modulo cutoff is useful for nagative integers. self.expansion = tuple(arith1.expand(initial % cutoff, p)) else: # take only first 'power' elements of initial. self.expansion = tuple([e for i, e in zip(range(power), initial)]) self.p = p
def _three_pow(self, element, index): """ powering by using left-right base 3 method. """ digits = arith1.expand(index, 3) e = len(digits) - 1 f = e # Precomputation pre_table = [element, self.square(element)] # Main Loop while f >= 0: tit = digits[f] if f == e: sol = pre_table[tit - 1] else: sol = self.mul(self.square(sol), sol) if tit: sol = self.mul(sol, pre_table[tit - 1]) f -= 1 return sol
def createElement(self, seed): """ Create an element of the field. """ # FIXME: Undefined variable 'FinitFieldExtensionElement' if isinstance(seed, int): expansion = arith1.expand(seed, card(self.basefield)) return FinitFieldExtensionElement( polynomial.OneVariableDensePolynomial(expansion, "#1", self.basefield), self) elif isinstance(seed, polynomial.OneVariablePolynomial): return FiniteFieldExtensionElement(seed("#1"), self) else: try: # lastly check sequence return FiniteFieldExtensionElement( polynomial.OneVariableDensePolynomial( list(seed), "#1", self.basefield), self) except TypeError: raise TypeError("seed %s is not an appropriate object." % str(seed))
def testExpand(self): self.assertEqual( [0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1], arith1.expand(10**6, 2)) self.assertEqual([1, 1, 3, 3, 3, 3, 1, 1], arith1.expand(10**6, 7))