예제 #1
0
    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
예제 #2
0
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)))]
예제 #3
0
    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)
예제 #4
0
    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
예제 #5
0
    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
예제 #6
0
    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
예제 #7
0
    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)
예제 #8
0
 def krull_dimension(self):
     """
     EXAMPLES::
     
         sage: Integers(18).krull_dimension()
         0
     """
     return integer.Integer(0)
예제 #9
0
    def krull_dimension(self):
        """
        Return the Krull dimension of ``self``.

        EXAMPLES::

            sage: Integers(18).krull_dimension()
            0
        """
        return integer.Integer(0)
예제 #10
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)
예제 #11
0
    def degree(self):
        """
        Return 1.

        EXAMPLE::

            sage: R = Integers(12345678900)
            sage: R.degree()
            1
        """
        return integer.Integer(1)
예제 #12
0
    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)
예제 #13
0
 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
예제 #14
0
    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())
예제 #15
0
    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
예제 #16
0
    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)
예제 #17
0
    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)
예제 #18
0
    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)
예제 #19
0
    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)
예제 #20
0
    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)