def create_key_and_extra_args(self, order, name=None, modulus=None, names=None, impl=None, proof=None, **kwds): """ EXAMPLES:: sage: GF.create_key_and_extra_args(9, 'a') ((9, ('a',), 'conway', None, '{}', 3, 2, True), {}) sage: GF.create_key_and_extra_args(9, 'a', foo='value') ((9, ('a',), 'conway', None, "{'foo': 'value'}", 3, 2, True), {'foo': 'value'}) """ from sage.structure.proof.all import WithProof, arithmetic if proof is None: proof = arithmetic() with WithProof('arithmetic', proof): order = int(order) if order <= 1: raise ValueError("the order of a finite field must be > 1.") if arith.is_prime(order): name = None modulus = None p = integer.Integer(order) n = integer.Integer(1) elif arith.is_prime_power(order): if not names is None: name = names name = normalize_names(1, name) p, n = arith.factor(order)[0] if modulus is None or modulus == "default": if exists_conway_polynomial(p, n): modulus = "conway" else: if p == 2: modulus = "minimal_weight" else: modulus = "random" elif modulus == "random": modulus += str(random.randint(0, 1 << 128)) if isinstance(modulus, (list, tuple)): modulus = FiniteField(p)['x'](modulus) # some classes use 'random' as the modulus to # generate a random modulus, but we don't want # to cache it elif sage.rings.polynomial.polynomial_element.is_Polynomial( modulus): modulus = modulus.change_variable_name('x') elif not isinstance(modulus, str): raise ValueError("Modulus parameter not understood.") else: # Neither a prime, nor a prime power raise ValueError( "the order of a finite field must be a prime power.") return (order, name, modulus, impl, str(kwds), p, n, proof), kwds
def _unit_gens_primepowercase(p, r): r""" Return a list of generators for `(\ZZ/p^r\ZZ)^*` and their orders. EXAMPLES:: sage: from sage.rings.finite_rings.integer_mod_ring import _unit_gens_primepowercase sage: _unit_gens_primepowercase(2, 3) [(7, 2), (5, 2)] sage: _unit_gens_primepowercase(17, 1) [(3, 16)] sage: _unit_gens_primepowercase(3, 3) [(2, 18)] """ pr = p**r if p == 2: if r == 1: return [] if r == 2: return [(integer_mod.Mod(3, 4), integer.Integer(2))] return [(integer_mod.Mod(-1, pr), integer.Integer(2)), (integer_mod.Mod(5, pr), integer.Integer(2**(r - 2)))] # odd prime return [(integer_mod.Mod(primitive_root(pr, check=False), pr), integer.Integer(p**(r - 1) * (p - 1)))]
def __init__(self, p, name=None, check=True): """ Return a new finite field of order `p` where `p` is prime. INPUT: - ``p`` -- an integer at least 2 - ``name`` -- ignored - ``check`` -- bool (default: ``True``); if ``False``, do not check ``p`` for primality EXAMPLES:: sage: F = FiniteField(3); F Finite Field of size 3 """ p = integer.Integer(p) if check and not arith.is_prime(p): raise ArithmeticError, "p must be prime" self.__char = p self._IntegerModRing_generic__factored_order = factorization.Factorization( [(p, 1)], integer.Integer(1)) self._kwargs = {} # FiniteField_generic does nothing more than IntegerModRing_generic, and # it saves a non trivial overhead integer_mod_ring.IntegerModRing_generic.__init__( self, p, category=_FiniteFields)
def create_key_and_extra_args(self, order, name=None, modulus=None, names=None, impl=None, proof=None, **kwds): """ EXAMPLES:: sage: GF.create_key_and_extra_args(9, 'a') ((9, ('a',), x^2 + 2*x + 2, None, '{}', 3, 2, True), {}) sage: GF.create_key_and_extra_args(9, 'a', foo='value') ((9, ('a',), x^2 + 2*x + 2, None, "{'foo': 'value'}", 3, 2, True), {'foo': 'value'}) """ from sage.structure.proof.all import WithProof, arithmetic if proof is None: proof = arithmetic() with WithProof('arithmetic', proof): order = int(order) if order <= 1: raise ValueError("the order of a finite field must be > 1.") if arith.is_prime(order): name = None modulus = None p = integer.Integer(order) n = integer.Integer(1) elif arith.is_prime_power(order): if not names is None: name = names name = normalize_names(1, name) p, n = arith.factor(order)[0] if modulus is None or isinstance(modulus, str): # A string specifies an algorithm to find a suitable modulus. if modulus == "default": # for backward compatibility modulus = None modulus = GF(p)['x'].irreducible_element(n, algorithm=modulus) elif isinstance(modulus, (list, tuple)): modulus = GF(p)['x'](modulus) elif sage.rings.polynomial.polynomial_element.is_Polynomial( modulus): modulus = modulus.change_variable_name('x') else: raise TypeError("wrong type for modulus parameter") else: raise ValueError( "the order of a finite field must be a prime power.") return (order, name, modulus, impl, str(kwds), p, n, proof), kwds
def cardinality(self): """ Implements :meth:`EnumeratedSets.ParentMethods.cardinality`. EXAMPLES:: sage: G = Sp(4,GF(3)) sage: G.cardinality() 51840 sage: G = SL(4,GF(3)) sage: G.cardinality() 12130560 sage: F = GF(5); MS = MatrixSpace(F,2,2) sage: gens = [MS([[1,2],[-1,1]]),MS([[1,1],[0,1]])] sage: G = MatrixGroup(gens) sage: G.cardinality() 480 sage: G = MatrixGroup([matrix(ZZ,2,[1,1,0,1])]) sage: G.cardinality() +Infinity """ g = self._gap_() if g.IsFinite().bool(): return integer.Integer(gap(self).Size()) return infinity
def __unit_gens_primecase(self, p): """ Assuming the modulus is prime, returns the smallest generator of the group of units. EXAMPLES:: sage: Zmod(17)._IntegerModRing_generic__unit_gens_primecase(17) 3 """ if p == 2: return integer_mod.Mod(1, p) P = prime_divisors(p - 1) ord = integer.Integer(p - 1) one = integer_mod.Mod(1, p) x = 2 while x < p: generator = True z = integer_mod.Mod(x, p) for q in P: if z**(ord // q) == one: generator = False break if generator: return z x += 1 #end for assert False, "didn't find primitive root for p=%s" % p
def __init__(self, n, R, var='a', category=None): """ INPUT: - ``n`` - the degree - ``R`` - the base ring - ``var`` - variable used to define field of definition of actual matrices in this group. """ if not is_Ring(R): raise TypeError, "R (=%s) must be a ring" % R self._var = var self.__n = integer.Integer(n) if self.__n <= 0: raise ValueError, "The degree must be at least 1" self.__R = R if self.base_ring().is_finite(): default_category = FiniteGroups() else: # Should we ask GAP whether the group is finite? default_category = Groups() if category is None: category = default_category else: assert category.is_subcategory(default_category), \ "%s is not a subcategory of %s"%(category, default_category) Parent.__init__(self, category=category)
def krull_dimension(self): """ EXAMPLES:: sage: Integers(18).krull_dimension() 0 """ return integer.Integer(0)
def krull_dimension(self): """ Return the Krull dimension of ``self``. EXAMPLES:: sage: Integers(18).krull_dimension() 0 """ return integer.Integer(0)
def degree(self): """ Returns the degree of the finite field, which is a positive integer. EXAMPLES:: sage: FiniteField(3).degree() 1 """ return integer.Integer(1)
def degree(self): """ Return 1. EXAMPLE:: sage: R = Integers(12345678900) sage: R.degree() 1 """ return integer.Integer(1)
def factor(self, absprec=None): if self == 0: raise ValueError, "Factorization of 0 not defined" if absprec is None: absprec = min([x.precision_absolute() for x in self.list()]) else: absprec = integer.Integer(absprec) if absprec <= 0: raise ValueError, "absprec must be positive" G = self._pari_().factorpadic(self.base_ring().prime(), absprec) pols = G[0] exps = G[1] F = [] R = self.parent() for i in xrange(len(pols)): f = R(pols[i], absprec=absprec) e = int(exps[i]) F.append((f, e)) if R.base_ring().is_field(): # When the base ring is a field we normalize # the irreducible factors so they have leading # coefficient 1. for i in range(len(F)): cur = F[i][0].leading_coefficient() if cur != 1: F[i] = (F[i][0].monic(), F[i][1]) return Factorization(F, self.leading_coefficient()) else: # When the base ring is not a field, we normalize # the irreducible factors so that the leading term # is a power of p. We also ensure that the gcd of # the coefficients of each term is 1. c = self.leading_coefficient().valuation() u = self.base_ring()(1) for i in range(len(F)): upart = F[i][0].leading_coefficient().unit_part() lval = F[i][0].leading_coefficient().valuation() if upart != 1: F[i] = (F[i][0] // upart, F[i][1]) u *= upart**F[i][1] c -= lval if c != 0: F.append((self.parent()(self.base_ring().prime_pow(c)), 1)) return Factorization(F, u)
def __unit_gens_primecase(self, p): if p == 2: return integer_mod.Mod(1, p) P = prime_divisors(p - 1) ord = integer.Integer(p - 1) one = integer_mod.Mod(1, p) x = 2 while x < p: generator = True z = integer_mod.Mod(x, p) for q in P: if z**(ord // q) == one: generator = False break if generator: return z x += 1 #end for assert False, "didn't find primitive root for p=%s" % p
def cardinality(self): """ EXAMPLES:: sage: G = Sp(4,GF(3)) sage: G.cardinality() 51840 sage: G = SL(4,GF(3)) sage: G.cardinality() 12130560 sage: F = GF(5); MS = MatrixSpace(F,2,2) sage: gens = [MS([[1,2],[-1,1]]),MS([[1,1],[0,1]])] sage: G = MatrixGroup(gens) sage: G.cardinality() 480 sage: G = MatrixGroup([matrix(ZZ,2,[1,1,0,1])]) sage: G.cardinality() +Infinity """ return integer.Integer(gap(self).Size())
def create_key_and_extra_args(self, order, name=None, modulus=None, names=None, impl=None, proof=None, **kwds): """ EXAMPLES:: sage: GF.create_key_and_extra_args(9, 'a') ((9, ('a',), x^2 + 2*x + 2, None, '{}', 3, 2, True), {}) sage: GF.create_key_and_extra_args(9, 'a', foo='value') ((9, ('a',), x^2 + 2*x + 2, None, "{'foo': 'value'}", 3, 2, True), {'foo': 'value'}) """ from sage.structure.proof.all import WithProof, arithmetic if proof is None: proof = arithmetic() with WithProof('arithmetic', proof): order = int(order) if order <= 1: raise ValueError("the order of a finite field must be > 1.") if arith.is_prime(order): name = None modulus = None p = integer.Integer(order) n = integer.Integer(1) elif arith.is_prime_power(order): if not names is None: name = names name = normalize_names(1, name) p, n = arith.factor(order)[0] # The following is a temporary solution that allows us # to construct compatible systems of finite fields # until algebraic closures of finite fields are # implemented in Sage. It requires the user to # specify two parameters: # # - `conway` -- boolean; if True, this field is # constructed to fit in a compatible system using # a Conway polynomial. # - `prefix` -- a string used to generate names for # automatically constructed finite fields # # See the docstring of FiniteFieldFactory for examples. # # Once algebraic closures of finite fields are # implemented, this syntax should be superseded by # something like the following: # # sage: Fpbar = GF(5).algebraic_closure('z') # sage: F, e = Fpbar.subfield(3) # e is the embedding into Fpbar # sage: F # Finite field in z3 of size 5^3 # # This temporary solution only uses actual Conway # polynomials (no pseudo-Conway polynomials), since # pseudo-Conway polynomials are not unique, and until # we have algebraic closures of finite fields, there # is no good place to store a specific choice of # pseudo-Conway polynomials. if name is None: if not (kwds.has_key('conway') and kwds['conway']): raise ValueError( "parameter 'conway' is required if no name given") if not kwds.has_key('prefix'): raise ValueError( "parameter 'prefix' is required if no name given") name = kwds['prefix'] + str(n) if kwds.has_key('conway') and kwds['conway']: from conway_polynomials import conway_polynomial if not kwds.has_key('prefix'): raise ValueError( "a prefix must be specified if conway=True") if modulus is not None: raise ValueError( "no modulus may be specified if conway=True") # The following raises a RuntimeError if no polynomial is found. modulus = conway_polynomial(p, n) if modulus is None or isinstance(modulus, str): # A string specifies an algorithm to find a suitable modulus. if modulus == "default": # for backward compatibility modulus = None modulus = GF(p)['x'].irreducible_element(n, algorithm=modulus) elif isinstance(modulus, (list, tuple)): modulus = GF(p)['x'](modulus) elif sage.rings.polynomial.polynomial_element.is_Polynomial( modulus): modulus = modulus.change_variable_name('x') else: raise TypeError("wrong type for modulus parameter") else: raise ValueError( "the order of a finite field must be a prime power.") return (order, name, modulus, impl, str(kwds), p, n, proof), kwds
def __init__(self, q, name, modulus=None): """ Create finite field of order q with variable printed as name. INPUT: - ``q`` -- integer, size of the finite field, not prime - ``name`` -- variable used for printing element of the finite field. Also, two finite fields are considered equal if they have the same variable name, and not otherwise. - ``modulus`` -- you may provide a polynomial to use for reduction or a string: 'conway': force the use of a Conway polynomial, will raise a RuntimeError if none is found in the database; 'random': use a random irreducible polynomial. 'default': a Conway polynomial is used if found. Otherwise a random polynomial is used. OUTPUT: - FiniteField_ext_pari -- a finite field of order q with given variable name. EXAMPLES:: sage: FiniteField(65537) Finite Field of size 65537 sage: FiniteField(2^20, 'c') Finite Field in c of size 2^20 sage: FiniteField(3^11, "b") Finite Field in b of size 3^11 sage: FiniteField(3^11, "b").gen() b You can also create a finite field using GF, which is a synonym for FiniteField. :: sage: GF(19^5, 'a') Finite Field in a of size 19^5 """ if element_ext_pari.dynamic_FiniteField_ext_pariElement is None: element_ext_pari._late_import() from constructor import FiniteField as GF q = integer.Integer(q) if q < 2: raise ArithmeticError, "q must be a prime power" from sage.structure.proof.all import arithmetic proof = arithmetic() if proof: F = q.factor() else: from sage.rings.arith import is_pseudoprime_small_power F = is_pseudoprime_small_power(q, get_data=True) if len(F) != 1: raise ArithmeticError, "q must be a prime power" if F[0][1] > 1: base_ring = GF(F[0][0]) else: raise ValueError, "The size of the finite field must not be prime." #base_ring = self FiniteField_generic.__init__(self, base_ring, name, normalize=True) self._kwargs = {} self.__char = F[0][0] self.__pari_one = pari.pari(1).Mod(self.__char) self.__degree = integer.Integer(F[0][1]) self.__order = q self.__is_field = True if modulus is None or modulus == "default": from constructor import exists_conway_polynomial if exists_conway_polynomial(self.__char, self.__degree): modulus = "conway" else: modulus = "random" if isinstance(modulus, str): if modulus == "conway": from constructor import conway_polynomial modulus = conway_polynomial(self.__char, self.__degree) elif modulus == "random": # The following is fast/deterministic, but has serious problems since # it crashes on 64-bit machines, and I can't figure out why: # self.__pari_modulus = pari.pari.finitefield_init(self.__char, self.__degree, self.variable_name()) # So instead we iterate through random polys until we find an irreducible one. R = GF(self.__char)['x'] while True: modulus = R.random_element(self.__degree) modulus = modulus.monic() if modulus.degree( ) == self.__degree and modulus.is_irreducible(): break else: raise ValueError("Modulus parameter not understood") elif isinstance(modulus, (list, tuple)): modulus = GF(self.__char)['x'](modulus) elif sage.rings.polynomial.polynomial_element.is_Polynomial(modulus): if modulus.parent() is not base_ring: modulus = modulus.change_ring(base_ring) else: raise ValueError("Modulus parameter not understood") self.__modulus = modulus f = pari.pari(str(modulus)) self.__pari_modulus = f.subst(modulus.parent().variable_name(), 'a') * self.__pari_one self.__gen = element_ext_pari.FiniteField_ext_pariElement( self, pari.pari('a')) self._zero_element = self._element_constructor_(0) self._one_element = self._element_constructor_(1)
def __init__(self, q, name, modulus=None): """ Create finite field of order `q` with variable printed as name. EXAMPLES:: sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari sage: k = FiniteField_ext_pari(9, 'a'); k Finite Field in a of size 3^2 """ if element_ext_pari.dynamic_FiniteField_ext_pariElement is None: element_ext_pari._late_import() from constructor import FiniteField as GF q = integer.Integer(q) if q < 2: raise ArithmeticError, "q must be a prime power" from sage.structure.proof.all import arithmetic proof = arithmetic() if proof: F = q.factor() else: from sage.rings.arith import is_pseudoprime_small_power F = is_pseudoprime_small_power(q, get_data=True) if len(F) != 1: raise ArithmeticError, "q must be a prime power" if F[0][1] > 1: base_ring = GF(F[0][0]) else: raise ValueError, "The size of the finite field must not be prime." #base_ring = self FiniteField_generic.__init__(self, base_ring, name, normalize=True) self._kwargs = {} self.__char = F[0][0] self.__pari_one = pari.pari(1).Mod(self.__char) self.__degree = integer.Integer(F[0][1]) self.__order = q self.__is_field = True if modulus is None or modulus == "default": from conway_polynomials import exists_conway_polynomial if exists_conway_polynomial(self.__char, self.__degree): modulus = "conway" else: modulus = "random" if isinstance(modulus,str): if modulus == "conway": from conway_polynomials import conway_polynomial modulus = conway_polynomial(self.__char, self.__degree) elif modulus == "random": # The following is fast/deterministic, but has serious problems since # it crashes on 64-bit machines, and I can't figure out why: # self.__pari_modulus = pari.pari.finitefield_init(self.__char, self.__degree, self.variable_name()) # So instead we iterate through random polys until we find an irreducible one. R = GF(self.__char)['x'] while True: modulus = R.random_element(self.__degree) modulus = modulus.monic() if modulus.degree() == self.__degree and modulus.is_irreducible(): break else: raise ValueError("Modulus parameter not understood") elif isinstance(modulus, (list, tuple)): modulus = GF(self.__char)['x'](modulus) elif sage.rings.polynomial.polynomial_element.is_Polynomial(modulus): if modulus.parent() is not base_ring: modulus = modulus.change_ring(base_ring) else: raise ValueError("Modulus parameter not understood") self.__modulus = modulus f = pari.pari(str(modulus)) self.__pari_modulus = f.subst(modulus.parent().variable_name(), 'a') * self.__pari_one self.__gen = element_ext_pari.FiniteField_ext_pariElement(self, pari.pari('a')) self._zero_element = self._element_constructor_(0) self._one_element = self._element_constructor_(1)
def unit_group(self, algorithm='sage'): r""" Return the unit group of ``self``. INPUT: - ``self`` -- the ring `\ZZ/n\ZZ` for a positive integer `n` - ``algorithm`` -- either ``'sage'`` (default) or ``'pari'`` OUTPUT: The unit group of ``self``. This is a finite Abelian group equipped with a distinguished set of generators, which is computed using a deterministic algorithm depending on the ``algorithm`` parameter. - If ``algorithm == 'sage'``, the generators correspond to the prime factors `p \mid n` (one generator for each odd `p`; the number of generators for `p = 2` is 0, 1 or 2 depending on the order to which 2 divides `n`). - If ``algorithm == 'pari'``, the generators are chosen such that their orders form a decreasing sequence with respect to divisibility. EXAMPLES: The output of the algorithms ``'sage'`` and ``'pari'`` can differ in various ways. In the following example, the same cyclic factors are computed, but in a different order:: sage: A = Zmod(15) sage: G = A.unit_group(); G Multiplicative Abelian group isomorphic to C2 x C4 sage: G.gens_values() (11, 7) sage: H = A.unit_group(algorithm='pari'); H Multiplicative Abelian group isomorphic to C4 x C2 sage: H.gens_values() (7, 11) Here are two examples where the cyclic factors are isomorphic, but are ordered differently and have different generators:: sage: A = Zmod(40) sage: G = A.unit_group(); G Multiplicative Abelian group isomorphic to C2 x C2 x C4 sage: G.gens_values() (31, 21, 17) sage: H = A.unit_group(algorithm='pari'); H Multiplicative Abelian group isomorphic to C4 x C2 x C2 sage: H.gens_values() (17, 31, 21) sage: A = Zmod(192) sage: G = A.unit_group(); G Multiplicative Abelian group isomorphic to C2 x C16 x C2 sage: G.gens_values() (127, 133, 65) sage: H = A.unit_group(algorithm='pari'); H Multiplicative Abelian group isomorphic to C16 x C2 x C2 sage: H.gens_values() (133, 127, 65) In the following examples, the cyclic factors are not even isomorphic:: sage: A = Zmod(319) sage: A.unit_group() Multiplicative Abelian group isomorphic to C10 x C28 sage: A.unit_group(algorithm='pari') Multiplicative Abelian group isomorphic to C140 x C2 sage: A = Zmod(30.factorial()) sage: A.unit_group() Multiplicative Abelian group isomorphic to C2 x C16777216 x C3188646 x C62500 x C2058 x C110 x C156 x C16 x C18 x C22 x C28 sage: A.unit_group(algorithm='pari') Multiplicative Abelian group isomorphic to C20499647385305088000000 x C55440 x C12 x C12 x C4 x C2 x C2 x C2 x C2 x C2 x C2 TESTS: We test the cases where the unit group is trivial:: sage: A = Zmod(1) sage: A.unit_group() Trivial Abelian group sage: A.unit_group(algorithm='pari') Trivial Abelian group sage: A = Zmod(2) sage: A.unit_group() Trivial Abelian group sage: A.unit_group(algorithm='pari') Trivial Abelian group sage: Zmod(3).unit_group(algorithm='bogus') Traceback (most recent call last): ... ValueError: unknown algorithm 'bogus' for computing the unit group """ from sage.groups.abelian_gps.values import AbelianGroupWithValues if algorithm == 'sage': n = self.order() gens = [] orders = [] for p, r in self.factored_order(): m = n / (p**r) for g, o in _unit_gens_primepowercase(p, r): x = g.crt(integer_mod.Mod(1, m)) gens.append(x) orders.append(o) elif algorithm == 'pari': _, orders, gens = self.order().__pari__().znstar() gens = [self(g) for g in gens] orders = [integer.Integer(o) for o in orders] else: raise ValueError( 'unknown algorithm %r for computing the unit group' % algorithm) return AbelianGroupWithValues(gens, orders, values_group=self)
def __init__(self, q, name, modulus=None): """ Create finite field of order `q` with variable printed as name. EXAMPLES:: sage: k = FiniteField(9, 'a', impl='pari_mod'); k Finite Field in a of size 3^2 """ from sage.misc.superseded import deprecation deprecation(17297, 'The "pari_mod" finite field implementation is deprecated') if element_ext_pari.dynamic_FiniteField_ext_pariElement is None: element_ext_pari._late_import() from .finite_field_constructor import FiniteField as GF q = integer.Integer(q) if q < 2: raise ArithmeticError("q must be a prime power") # note: the following call takes care of the fact that # proof.arithmetic() is True or False. p, n = q.is_prime_power(get_data=True) if n > 1: base_ring = GF(p) elif n == 0: raise ArithmeticError("q must be a prime power") else: raise ValueError("The size of the finite field must not be prime.") FiniteField_generic.__init__(self, base_ring, name, normalize=True) self._kwargs = {} self.__char = p self.__pari_one = pari.pari(1).Mod(self.__char) self.__degree = n self.__order = q self.__is_field = True if not sage.rings.polynomial.polynomial_element.is_Polynomial(modulus): from sage.misc.superseded import deprecation deprecation(16930, "constructing a FiniteField_ext_pari without giving a polynomial as modulus is deprecated, use the more general FiniteField constructor instead") if modulus is None or modulus == "default": from .conway_polynomials import exists_conway_polynomial if exists_conway_polynomial(self.__char, self.__degree): modulus = "conway" else: modulus = "random" if isinstance(modulus,str): if modulus == "conway": from .conway_polynomials import conway_polynomial modulus = conway_polynomial(self.__char, self.__degree) elif modulus == "random": # The following is fast/deterministic, but has serious problems since # it crashes on 64-bit machines, and I can't figure out why: # self.__pari_modulus = pari.pari.finitefield_init(self.__char, self.__degree, self.variable_name()) # So instead we iterate through random polys until we find an irreducible one. R = GF(self.__char)['x'] while True: modulus = R.random_element(self.__degree) modulus = modulus.monic() if modulus.degree() == self.__degree and modulus.is_irreducible(): break else: raise ValueError("Modulus parameter not understood") elif isinstance(modulus, (list, tuple)): modulus = GF(self.__char)['x'](modulus) elif sage.rings.polynomial.polynomial_element.is_Polynomial(modulus): if modulus.base_ring() is not base_ring: modulus = modulus.change_ring(base_ring) else: raise ValueError("Modulus parameter not understood") self._modulus = modulus f = pari.pari(str(modulus)) self.__pari_modulus = f.subst(modulus.parent().variable_name(), 'a') * self.__pari_one self.__gen = element_ext_pari.FiniteField_ext_pariElement(self, pari.pari('a')) self._zero_element = self._element_constructor_(0) self._one_element = self._element_constructor_(1)
def _element_constructor_(self, x): r""" Coerce ``x`` into the finite field. INPUT: - ``x`` -- object OUTPUT: If possible, makes a finite field element from ``x``. EXAMPLES:: sage: k = FiniteField(3^4, 'a', impl='pari_mod') sage: b = k(5) # indirect doctest sage: b.parent() Finite Field in a of size 3^4 sage: a = k.gen() sage: k(a + 2) a + 2 Univariate polynomials coerce into finite fields by evaluating the polynomial at the field's generator:: sage: R.<x> = QQ[] sage: k.<a> = FiniteField(5^2, impl='pari_mod') sage: k(R(2/3)) 4 sage: k(x^2) a + 3 sage: R.<x> = GF(5)[] sage: k(x^3-2*x+1) 2*a + 4 sage: x = polygen(QQ) sage: k(x^25) a sage: Q.<q> = FiniteField(5^7, impl='pari_mod') sage: L = GF(5) sage: LL.<xx> = L[] sage: Q(xx^2 + 2*xx + 4) q^2 + 2*q + 4 Multivariate polynomials only coerce if constant:: sage: R = k['x,y,z']; R Multivariate Polynomial Ring in x, y, z over Finite Field in a of size 5^2 sage: k(R(2)) 2 sage: R = QQ['x,y,z'] sage: k(R(1/5)) Traceback (most recent call last): ... TypeError: unable to coerce Gap elements can also be coerced into finite fields:: sage: F = FiniteField(8, 'a', impl='pari_mod') sage: a = F.multiplicative_generator(); a a sage: b = gap(a^3); b Z(2^3)^3 sage: F(b) a + 1 sage: a^3 a + 1 sage: a = GF(13)(gap('0*Z(13)')); a 0 sage: a.parent() Finite Field of size 13 sage: F = GF(16, 'a', impl='pari_mod') sage: F(gap('Z(16)^3')) a^3 sage: F(gap('Z(16)^2')) a^2 You can also call a finite extension field with a string to produce an element of that field, like this:: sage: k = GF(2^8, 'a', impl='pari_mod') sage: k('a^200') a^4 + a^3 + a^2 This is especially useful for fast conversions from Singular etc. to ``FiniteField_ext_pariElements``. AUTHORS: - David Joyner (2005-11) - Martin Albrecht (2006-01-23) - Martin Albrecht (2006-03-06): added coercion from string """ if isinstance(x, element_ext_pari.FiniteField_ext_pariElement): if x.parent() is self: return x elif x.parent() == self: # canonically isomorphic finite fields return element_ext_pari.FiniteField_ext_pariElement(self, x) else: raise TypeError("no coercion defined") elif sage.interfaces.gap.is_GapElement(x): from sage.interfaces.gap import gfq_gap_to_sage try: return gfq_gap_to_sage(x, self) except (ValueError, IndexError, TypeError): raise TypeError("no coercion defined") if isinstance(x, (int, long, integer.Integer, rational.Rational, pari.pari_gen, list)): return element_ext_pari.FiniteField_ext_pariElement(self, x) elif isinstance(x, multi_polynomial_element.MPolynomial): if x.is_constant(): return self(x.constant_coefficient()) else: raise TypeError("no coercion defined") elif isinstance(x, polynomial_element.Polynomial): if x.is_constant(): return self(x.constant_coefficient()) else: return x.change_ring(self)(self.gen()) elif isinstance(x, str): x = x.replace(self.variable_name(),'a') x = pari.pari(x) t = x.type() if t == 't_POL': if (x.variable() == 'a' \ and x.polcoeff(0).type()[2] == 'I'): #t_INT and t_INTMOD return self(x) if t[2] == 'I': #t_INT and t_INTMOD return self(x) raise TypeError("string element does not match this finite field") try: if x.parent() == self.vector_space(): x = pari.pari('+'.join(['%s*a^%s'%(x[i], i) for i in range(self.degree())])) return element_ext_pari.FiniteField_ext_pariElement(self, x) except AttributeError: pass try: return element_ext_pari.FiniteField_ext_pariElement(self, integer.Integer(x)) except TypeError as msg: raise TypeError("%s\nno coercion defined"%msg)