Exemple #1
0
    def multiplicative_subgroups(self):
        r"""
        Return generators for each subgroup of
        `(\ZZ/N\ZZ)^*`.

        EXAMPLES::

            sage: Integers(5).multiplicative_subgroups()
            ((2,), (4,), ())
            sage: Integers(15).multiplicative_subgroups()
            ((11, 7), (4, 11), (8,), (11,), (14,), (7,), (4,), ())
            sage: Integers(2).multiplicative_subgroups()
            ((),)
            sage: len(Integers(341).multiplicative_subgroups())
            80

        TESTS::

            sage: IntegerModRing(1).multiplicative_subgroups()
            ((0,),)
            sage: IntegerModRing(2).multiplicative_subgroups()
            ((),)
            sage: IntegerModRing(3).multiplicative_subgroups()
            ((2,), ())
        """
        from sage.groups.abelian_gps.values import AbelianGroupWithValues
        U = self.unit_gens()
        G = AbelianGroupWithValues(U, [x.multiplicative_order() for x in U], values_group=self)
        mysubs = []
        for Gsub in G.subgroups():
            mysubs.append(tuple( g.value() for g in Gsub.gens() ))
        return tuple(mysubs)
Exemple #2
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 = map(self, gens)
            orders = map(integer.Integer, orders)
        else:
            raise ValueError(
                'unknown algorithm %r for computing the unit group' %
                algorithm)
        return AbelianGroupWithValues(gens, orders, values_group=self)