def __init__(self, p, prec, print_mode, names, element_class):
        """
        Initialization

        TESTS::

            sage: R = Zp(5) #indirect doctest
        """
        if self.is_relaxed():
            from sage.rings.padics.pow_computer_flint import PowComputer_flint
            self.prime_pow = PowComputer_flint(p, 1, 1, 1, self.is_field())
        else:
            self.prime_pow = PowComputer(p, max(min(prec - 1, 30), 1), prec,
                                         self.is_field(), self._prec_type())
        pAdicGeneric.__init__(self, self, p, prec, print_mode, names,
                              element_class)
        if self.is_field():
            if self.is_capped_relative():
                coerce_list = [
                    pAdicCoercion_ZZ_CR(self),
                    pAdicCoercion_QQ_CR(self)
                ]
                convert_list = []
            elif self.is_floating_point():
                coerce_list = [
                    pAdicCoercion_ZZ_FP(self),
                    pAdicCoercion_QQ_FP(self)
                ]
                convert_list = []
            elif self.is_lattice_prec():
                coerce_list = [QQ]
                convert_list = []
            elif self.is_relaxed():
                coerce_list = [QQ]
                convert_list = []
            else:
                raise RuntimeError
        elif self.is_capped_relative():
            coerce_list = [pAdicCoercion_ZZ_CR(self)]
            convert_list = [pAdicConvert_QQ_CR(self)]
        elif self.is_capped_absolute():
            coerce_list = [pAdicCoercion_ZZ_CA(self)]
            convert_list = [pAdicConvert_QQ_CA(self)]
        elif self.is_fixed_mod():
            coerce_list = [pAdicCoercion_ZZ_FM(self)]
            convert_list = [pAdicConvert_QQ_FM(self)]
        elif self.is_floating_point():
            coerce_list = [pAdicCoercion_ZZ_FP(self)]
            convert_list = [pAdicConvert_QQ_FP(self)]
        elif self.is_lattice_prec():
            coerce_list = [ZZ]
            convert_list = [QQ]
        elif self.is_relaxed():
            coerce_list = [ZZ]
            convert_list = [QQ]
        else:
            raise RuntimeError
        self.Element = element_class
        self._populate_coercion_lists_(coerce_list=coerce_list,
                                       convert_list=convert_list)
Example #2
0
    def __init__(self, p, prec, print_mode, names, element_class):
        """
        Initialization

        TESTS::

            sage: R = Zp(5) #indirect doctest
        """
        self.prime_pow = PowComputer(p, max(min(prec - 1, 30), 1), prec,
                                     self.is_field(), self._prec_type())
        pAdicGeneric.__init__(self, self, p, prec, print_mode, names,
                              element_class)
        if self.is_field():
            coerce_list = [
                pAdicCoercion_ZZ_CR(self),
                pAdicCoercion_QQ_CR(self)
            ]
            convert_list = []
        elif self.is_capped_relative():
            coerce_list = [pAdicCoercion_ZZ_CR(self)]
            convert_list = [pAdicConvert_QQ_CR(self)]
        elif self.is_capped_absolute():
            coerce_list = [pAdicCoercion_ZZ_CA(self)]
            convert_list = [pAdicConvert_QQ_CA(self)]
        elif self.is_fixed_mod():
            coerce_list = [pAdicCoercion_ZZ_FM(self)]
            convert_list = [pAdicConvert_QQ_FM(self)]
        else:
            raise RuntimeError
        self._populate_coercion_lists_(coerce_list=coerce_list,
                                       convert_list=convert_list,
                                       element_constructor=element_class)
Example #3
0
    def __init__(self, p, prec, print_mode, names, element_class):
        """
        Initialization

        TESTS::

            sage: R = Zp(5) #indirect doctest
        """
        self.prime_pow = PowComputer(p, max(min(prec - 1, 30), 1), prec, self.is_field(), self._prec_type())
        pAdicGeneric.__init__(self, self, p, prec, print_mode, names, element_class)
        if self.is_field():
            if self.is_capped_relative():
                coerce_list = [pAdicCoercion_ZZ_CR(self), pAdicCoercion_QQ_CR(self)]
                convert_list = []
            else:
                coerce_list = [pAdicCoercion_ZZ_FP(self), pAdicCoercion_QQ_FP(self)]
                convert_list = []
        elif self.is_capped_relative():
            coerce_list = [pAdicCoercion_ZZ_CR(self)]
            convert_list = [pAdicConvert_QQ_CR(self)]
        elif self.is_capped_absolute():
            coerce_list = [pAdicCoercion_ZZ_CA(self)]
            convert_list = [pAdicConvert_QQ_CA(self)]
        elif self.is_fixed_mod():
            coerce_list = [pAdicCoercion_ZZ_FM(self)]
            convert_list = [pAdicConvert_QQ_FM(self)]
        elif self.is_floating_point():
            coerce_list = [pAdicCoercion_ZZ_FP(self)]
            convert_list = [pAdicConvert_QQ_FP(self)]
        else:
            raise RuntimeError
        self._populate_coercion_lists_(coerce_list=coerce_list, convert_list=convert_list, element_constructor=element_class)
Example #4
0
class pAdicBaseGeneric(pAdicGeneric):
    _implementation = 'GMP'
    def __init__(self, p, prec, print_mode, names, element_class):
        """
        Initialization

        TESTS::

            sage: R = Zp(5) #indirect doctest
        """
        self.prime_pow = PowComputer(p, max(min(prec - 1, 30), 1), prec, self.is_field(), self._prec_type())
        pAdicGeneric.__init__(self, self, p, prec, print_mode, names, element_class)
        if self.is_field():
            if self.is_capped_relative():
                coerce_list = [pAdicCoercion_ZZ_CR(self), pAdicCoercion_QQ_CR(self)]
                convert_list = []
            else:
                coerce_list = [pAdicCoercion_ZZ_FP(self), pAdicCoercion_QQ_FP(self)]
                convert_list = []
        elif self.is_capped_relative():
            coerce_list = [pAdicCoercion_ZZ_CR(self)]
            convert_list = [pAdicConvert_QQ_CR(self)]
        elif self.is_capped_absolute():
            coerce_list = [pAdicCoercion_ZZ_CA(self)]
            convert_list = [pAdicConvert_QQ_CA(self)]
        elif self.is_fixed_mod():
            coerce_list = [pAdicCoercion_ZZ_FM(self)]
            convert_list = [pAdicConvert_QQ_FM(self)]
        elif self.is_floating_point():
            coerce_list = [pAdicCoercion_ZZ_FP(self)]
            convert_list = [pAdicConvert_QQ_FP(self)]
        else:
            raise RuntimeError
        self._populate_coercion_lists_(coerce_list=coerce_list, convert_list=convert_list, element_constructor=element_class)

    def fraction_field(self, print_mode=None):
        r"""
        Returns the fraction field of ``self``.

        INPUT:

        - ``print_mode`` - a dictionary containing print options.
          Defaults to the same options as this ring.

        OUTPUT:

        - the fraction field of ``self``.

        EXAMPLES::

            sage: R = Zp(5, print_mode='digits')
            sage: K = R.fraction_field(); repr(K(1/3))[3:]
            '31313131313131313132'
            sage: L = R.fraction_field({'max_ram_terms':4}); repr(L(1/3))[3:]
            '3132'
        """
        if self.is_field() and print_mode is None:
            return self
        from sage.rings.padics.factory import Qp
        if self.is_floating_point():
            mode = 'floating-point'
        else:
            mode = 'capped-rel'
        return Qp(self.prime(), self.precision_cap(), mode, print_mode=self._modified_print_mode(print_mode), names=self._uniformizer_print())

    def integer_ring(self, print_mode=None):
        r"""
        Returns the integer ring of ``self``, possibly with
        ``print_mode`` changed.

        INPUT:

        - ``print_mode`` - a dictionary containing print options.
          Defaults to the same options as this ring.

        OUTPUT:

        - The ring of integral elements in ``self``.

        EXAMPLES::

            sage: K = Qp(5, print_mode='digits')
            sage: R = K.integer_ring(); repr(R(1/3))[3:]
            '31313131313131313132'
            sage: S = K.integer_ring({'max_ram_terms':4}); repr(S(1/3))[3:]
            '3132'
        """
        if not self.is_field() and print_mode is None:
            return self
        from sage.rings.padics.factory import Zp
        return Zp(self.prime(), self.precision_cap(), self._prec_type(), print_mode=self._modified_print_mode(print_mode), names=self._uniformizer_print())

    def is_isomorphic(self, ring):
        r"""
        Returns whether ``self`` and ``ring`` are isomorphic, i.e. whether ``ring`` is an implementation of `\mathbb{Z}_p` for the same prime as ``self``.

        INPUT:

        - ``self`` -- a `p`-adic ring

        - ``ring`` -- a ring

        OUTPUT:

        - ``boolean`` -- whether ``ring`` is an implementation of \mathbb{Z}_p` for the same prime as ``self``.

        EXAMPLES::

            sage: R = Zp(5, 15, print_mode='digits'); S = Zp(5, 44, print_max_terms=4); R.is_isomorphic(S)
            True
        """
        return isinstance(ring, pAdicBaseGeneric) and self.prime() == ring.prime() and self.is_field() == ring.is_field()

    def gen(self, n=0):
        """
        Returns the ``nth`` generator of this extension.  For base
        rings/fields, we consider the generator to be the prime.

        EXAMPLES::

            sage: R = Zp(5); R.gen()
            5 + O(5^21)
        """
        if n != 0:
            raise IndexError("only one generator")
        return self(self.prime())

    def absolute_discriminant(self):
        """
        Returns the absolute discriminant of this `p`-adic ring

        EXAMPLES::

            sage: Zp(5).absolute_discriminant()
            1
        """
        return 1

    def discriminant(self, K=None):
        """
        Returns the discriminant of this `p`-adic ring over ``K``

        INPUT:

        - ``self`` -- a `p`-adic ring

        - ``K`` -- a sub-ring of ``self`` or ``None`` (default: ``None``)

        OUTPUT:

        - integer -- the discriminant of this ring over ``K`` (or the
          absolute discriminant if ``K`` is ``None``)

        EXAMPLES::

            sage: Zp(5).discriminant()
            1
        """
        if (K is None or K is self):
            return 1
        else:
            raise ValueError("Ground Ring must be a subring of self")

    def is_abelian(self):
        """
        Returns whether the Galois group is abelian, i.e. ``True``.
        #should this be automorphism group?

        EXAMPLES::

            sage: R = Zp(3, 10,'fixed-mod'); R.is_abelian()
            True
        """
        return True

    def is_normal(self):
        """
        Returns whether or not this is a normal extension, i.e. ``True``.

        EXAMPLES::

            sage: R = Zp(3, 10,'fixed-mod'); R.is_normal()
            True
        """
        return True

    def uniformizer(self):
        """
        Returns a uniformizer for this ring.

        EXAMPLES::

            sage: R = Zp(3,5,'fixed-mod', 'series')
            sage: R.uniformizer()
            3 + O(3^5)
        """
        return self(self.prime_pow._prime())

    def uniformizer_pow(self, n):
        """
        Returns the ``nth`` power of the uniformizer of ``self`` (as
        an element of ``self``).

        EXAMPLES::

            sage: R = Zp(5)
            sage: R.uniformizer_pow(5)
            5^5 + O(5^25)
            sage: R.uniformizer_pow(infinity)
            0
        """
        return self(self.prime_pow(n))

    def _uniformizer_print(self):
        """
        Returns how the uniformizer is supposed to print.

        EXAMPLES::

            sage: R = Zp(5, names='pi'); R._uniformizer_print()
            'pi'
        """
        return self.variable_name()

    def has_pth_root(self):
        r"""
        Returns whether or not `\mathbb{Z}_p` has a primitive `p^{th}`
        root of unity.

        EXAMPLES::

            sage: Zp(2).has_pth_root()
            True
            sage: Zp(17).has_pth_root()
            False
        """
        return (self.prime() == 2)

    def has_root_of_unity(self, n):
        r"""
        Returns whether or not `\mathbb{Z}_p` has a primitive `n^{th}`
        root of unity.

        INPUT:

        - ``self`` -- a `p`-adic ring

        - ``n`` -- an integer

        OUTPUT:

        - ``boolean`` -- whether ``self`` has primitive `n^{th}` root
          of unity

        EXAMPLES::

            sage: R=Zp(37)
            sage: R.has_root_of_unity(12)
            True
            sage: R.has_root_of_unity(11)
            False
        """
        if (self.prime() == 2):
            return n.divides(2)
        else:
            return n.divides(self.prime() - 1)

    def zeta(self, n=None):
        r"""
        Returns a generator of the group of roots of unity.

        INPUT:

        - ``self`` -- a `p`-adic ring

        - ``n`` -- an integer or ``None`` (default: ``None``)

        OUTPUT:

        - ``element`` -- a generator of the `n^{th}` roots of unity,
          or a generator of the full group of roots of unity if ``n``
          is ``None``

        EXAMPLES::

            sage: R = Zp(37,5)
            sage: R.zeta(12)
            8 + 24*37 + 37^2 + 29*37^3 + 23*37^4 + O(37^5)
        """
        if (self.prime() == 2):
            if (n is None) or (n == 2):
                return self(-1)
            if n == 1:
                return self(1)
            else:
                raise ValueError("No, %sth root of unity in self"%n)
        else:
            from sage.rings.finite_rings.finite_field_constructor import GF
            return self.teichmuller(GF(self.prime()).zeta(n).lift())

    def zeta_order(self):
        """
        Returns the order of the group of roots of unity.

        EXAMPLES::

            sage: R = Zp(37); R.zeta_order()
            36
            sage: Zp(2).zeta_order()
            2
        """
        if (self.prime() == 2):
            return 2
        else:
            return self.prime() - 1

    def plot(self, max_points=2500, **args):
        r"""
        Create a visualization of this `p`-adic ring as a fractal
        similar to a generalization of the Sierpi\'nski
        triangle.

        The resulting image attempts to capture the
        algebraic and topological characteristics of `\mathbb{Z}_p`.

        INPUT:

        - ``max_points`` -- the maximum number or points to plot,
          which controls the depth of recursion (default 2500)

        - ``**args`` -- color, size, etc. that are passed to the
          underlying point graphics objects

        REFERENCES:

        - Cuoco, A. ''Visualizing the `p`-adic Integers'', The
          American Mathematical Monthly, Vol. 98, No. 4 (Apr., 1991),
          pp. 355-364

        EXAMPLES::

            sage: Zp(3).plot()
            Graphics object consisting of 1 graphics primitive
            sage: Zp(5).plot(max_points=625)
            Graphics object consisting of 1 graphics primitive
            sage: Zp(23).plot(rgbcolor=(1,0,0))
            Graphics object consisting of 1 graphics primitive
        """
        if 'pointsize' not in args:
            args['pointsize'] = 1
        from sage.misc.mrange import cartesian_product_iterator
        from sage.rings.real_double import RDF
        from sage.plot.all import points, circle, Graphics
        p = self.prime()
        phi = 2*RDF.pi()/p
        V = RDF**2
        vs = [V([(phi*t).sin(), (phi*t).cos()]) for t in range(p)]
        all = []
        depth = max(RDF(max_points).log(p).floor(), 1)
        scale = min(RDF(1.5/p), 1/RDF(3))
        pts = [vs]*depth
        if depth == 1 and 23 < p < max_points:
            extras = int(max_points/p)
            if p/extras > 5:
                pts = [vs]*depth + [vs[::extras]]
        for digits in cartesian_product_iterator(pts):
            p = sum([v * scale**n for n, v in enumerate(digits)])
            all.append(tuple(p))
        g = points(all, **args)
        # Set default plotting options
        g.axes(False)
        g.set_aspect_ratio(1)
        return g
Example #5
0
class pAdicBaseGeneric(pAdicGeneric):
    _implementation = 'GMP'

    def __init__(self, p, prec, print_mode, names, element_class):
        """
        Initialization

        TESTS::

            sage: R = Zp(5) #indirect doctest
        """
        self.prime_pow = PowComputer(p, max(min(prec - 1, 30), 1), prec,
                                     self.is_field(), self._prec_type())
        pAdicGeneric.__init__(self, self, p, prec, print_mode, names,
                              element_class)
        if self.is_field():
            if self.is_capped_relative():
                coerce_list = [
                    pAdicCoercion_ZZ_CR(self),
                    pAdicCoercion_QQ_CR(self)
                ]
                convert_list = []
            else:
                coerce_list = [
                    pAdicCoercion_ZZ_FP(self),
                    pAdicCoercion_QQ_FP(self)
                ]
                convert_list = []
        elif self.is_capped_relative():
            coerce_list = [pAdicCoercion_ZZ_CR(self)]
            convert_list = [pAdicConvert_QQ_CR(self)]
        elif self.is_capped_absolute():
            coerce_list = [pAdicCoercion_ZZ_CA(self)]
            convert_list = [pAdicConvert_QQ_CA(self)]
        elif self.is_fixed_mod():
            coerce_list = [pAdicCoercion_ZZ_FM(self)]
            convert_list = [pAdicConvert_QQ_FM(self)]
        elif self.is_floating_point():
            coerce_list = [pAdicCoercion_ZZ_FP(self)]
            convert_list = [pAdicConvert_QQ_FP(self)]
        else:
            raise RuntimeError
        self._populate_coercion_lists_(coerce_list=coerce_list,
                                       convert_list=convert_list,
                                       element_constructor=element_class)

    def fraction_field(self, print_mode=None):
        r"""
        Returns the fraction field of ``self``.

        INPUT:

        - ``print_mode`` - a dictionary containing print options.
          Defaults to the same options as this ring.

        OUTPUT:

        - the fraction field of ``self``.

        EXAMPLES::

            sage: R = Zp(5, print_mode='digits')
            sage: K = R.fraction_field(); repr(K(1/3))[3:]
            '31313131313131313132'
            sage: L = R.fraction_field({'max_ram_terms':4}); repr(L(1/3))[3:]
            '3132'
        """
        if self.is_field() and print_mode is None:
            return self
        from sage.rings.padics.factory import Qp
        if self.is_floating_point():
            mode = 'floating-point'
        else:
            mode = 'capped-rel'
        return Qp(self.prime(),
                  self.precision_cap(),
                  mode,
                  print_mode=self._modified_print_mode(print_mode),
                  names=self._uniformizer_print())

    def integer_ring(self, print_mode=None):
        r"""
        Returns the integer ring of ``self``, possibly with
        ``print_mode`` changed.

        INPUT:

        - ``print_mode`` - a dictionary containing print options.
          Defaults to the same options as this ring.

        OUTPUT:

        - The ring of integral elements in ``self``.

        EXAMPLES::

            sage: K = Qp(5, print_mode='digits')
            sage: R = K.integer_ring(); repr(R(1/3))[3:]
            '31313131313131313132'
            sage: S = K.integer_ring({'max_ram_terms':4}); repr(S(1/3))[3:]
            '3132'
        """
        if not self.is_field() and print_mode is None:
            return self
        from sage.rings.padics.factory import Zp
        return Zp(self.prime(),
                  self.precision_cap(),
                  self._prec_type(),
                  print_mode=self._modified_print_mode(print_mode),
                  names=self._uniformizer_print())

    def is_isomorphic(self, ring):
        r"""
        Returns whether ``self`` and ``ring`` are isomorphic, i.e. whether ``ring`` is an implementation of `\mathbb{Z}_p` for the same prime as ``self``.

        INPUT:

        - ``self`` -- a `p`-adic ring

        - ``ring`` -- a ring

        OUTPUT:

        - ``boolean`` -- whether ``ring`` is an implementation of \mathbb{Z}_p` for the same prime as ``self``.

        EXAMPLES::

            sage: R = Zp(5, 15, print_mode='digits'); S = Zp(5, 44, print_max_terms=4); R.is_isomorphic(S)
            True
        """
        return isinstance(ring, pAdicBaseGeneric) and self.prime(
        ) == ring.prime() and self.is_field() == ring.is_field()

    def gen(self, n=0):
        """
        Returns the ``nth`` generator of this extension.  For base
        rings/fields, we consider the generator to be the prime.

        EXAMPLES::

            sage: R = Zp(5); R.gen()
            5 + O(5^21)
        """
        if n != 0:
            raise IndexError("only one generator")
        return self(self.prime())

    def absolute_discriminant(self):
        """
        Returns the absolute discriminant of this `p`-adic ring

        EXAMPLES::

            sage: Zp(5).absolute_discriminant()
            1
        """
        return 1

    def discriminant(self, K=None):
        """
        Returns the discriminant of this `p`-adic ring over ``K``

        INPUT:

        - ``self`` -- a `p`-adic ring

        - ``K`` -- a sub-ring of ``self`` or ``None`` (default: ``None``)

        OUTPUT:

        - integer -- the discriminant of this ring over ``K`` (or the
          absolute discriminant if ``K`` is ``None``)

        EXAMPLES::

            sage: Zp(5).discriminant()
            1
        """
        if (K is None or K is self):
            return 1
        else:
            raise ValueError("Ground Ring must be a subring of self")

    def is_abelian(self):
        """
        Returns whether the Galois group is abelian, i.e. ``True``.
        #should this be automorphism group?

        EXAMPLES::

            sage: R = Zp(3, 10,'fixed-mod'); R.is_abelian()
            True
        """
        return True

    def is_normal(self):
        """
        Returns whether or not this is a normal extension, i.e. ``True``.

        EXAMPLES::

            sage: R = Zp(3, 10,'fixed-mod'); R.is_normal()
            True
        """
        return True

    def uniformizer(self):
        """
        Returns a uniformizer for this ring.

        EXAMPLES::

            sage: R = Zp(3,5,'fixed-mod', 'series')
            sage: R.uniformizer()
            3 + O(3^5)
        """
        return self(self.prime_pow._prime())

    def uniformizer_pow(self, n):
        """
        Returns the ``nth`` power of the uniformizer of ``self`` (as
        an element of ``self``).

        EXAMPLES::

            sage: R = Zp(5)
            sage: R.uniformizer_pow(5)
            5^5 + O(5^25)
            sage: R.uniformizer_pow(infinity)
            0
        """
        return self(self.prime_pow(n))

    def _uniformizer_print(self):
        """
        Returns how the uniformizer is supposed to print.

        EXAMPLES::

            sage: R = Zp(5, names='pi'); R._uniformizer_print()
            'pi'
        """
        return self.variable_name()

    def has_pth_root(self):
        r"""
        Returns whether or not `\mathbb{Z}_p` has a primitive `p^{th}`
        root of unity.

        EXAMPLES::

            sage: Zp(2).has_pth_root()
            True
            sage: Zp(17).has_pth_root()
            False
        """
        return (self.prime() == 2)

    def has_root_of_unity(self, n):
        r"""
        Returns whether or not `\mathbb{Z}_p` has a primitive `n^{th}`
        root of unity.

        INPUT:

        - ``self`` -- a `p`-adic ring

        - ``n`` -- an integer

        OUTPUT:

        - ``boolean`` -- whether ``self`` has primitive `n^{th}` root
          of unity

        EXAMPLES::

            sage: R=Zp(37)
            sage: R.has_root_of_unity(12)
            True
            sage: R.has_root_of_unity(11)
            False
        """
        if (self.prime() == 2):
            return n.divides(2)
        else:
            return n.divides(self.prime() - 1)

    def zeta(self, n=None):
        r"""
        Returns a generator of the group of roots of unity.

        INPUT:

        - ``self`` -- a `p`-adic ring

        - ``n`` -- an integer or ``None`` (default: ``None``)

        OUTPUT:

        - ``element`` -- a generator of the `n^{th}` roots of unity,
          or a generator of the full group of roots of unity if ``n``
          is ``None``

        EXAMPLES::

            sage: R = Zp(37,5)
            sage: R.zeta(12)
            8 + 24*37 + 37^2 + 29*37^3 + 23*37^4 + O(37^5)
        """
        if (self.prime() == 2):
            if (n is None) or (n == 2):
                return self(-1)
            if n == 1:
                return self(1)
            else:
                raise ValueError("No, %sth root of unity in self" % n)
        else:
            from sage.rings.finite_rings.finite_field_constructor import GF
            return self.teichmuller(GF(self.prime()).zeta(n).lift())

    def zeta_order(self):
        """
        Returns the order of the group of roots of unity.

        EXAMPLES::

            sage: R = Zp(37); R.zeta_order()
            36
            sage: Zp(2).zeta_order()
            2
        """
        if (self.prime() == 2):
            return 2
        else:
            return self.prime() - 1

    def plot(self, max_points=2500, **args):
        r"""
        Create a visualization of this `p`-adic ring as a fractal
        similar to a generalization of the Sierpi\'nski
        triangle.

        The resulting image attempts to capture the
        algebraic and topological characteristics of `\mathbb{Z}_p`.

        INPUT:

        - ``max_points`` -- the maximum number or points to plot,
          which controls the depth of recursion (default 2500)

        - ``**args`` -- color, size, etc. that are passed to the
          underlying point graphics objects

        REFERENCES:

        - Cuoco, A. ''Visualizing the `p`-adic Integers'', The
          American Mathematical Monthly, Vol. 98, No. 4 (Apr., 1991),
          pp. 355-364

        EXAMPLES::

            sage: Zp(3).plot()
            Graphics object consisting of 1 graphics primitive
            sage: Zp(5).plot(max_points=625)
            Graphics object consisting of 1 graphics primitive
            sage: Zp(23).plot(rgbcolor=(1,0,0))
            Graphics object consisting of 1 graphics primitive
        """
        if 'pointsize' not in args:
            args['pointsize'] = 1
        from sage.misc.mrange import cartesian_product_iterator
        from sage.rings.real_double import RDF
        from sage.plot.all import points, circle, Graphics
        p = self.prime()
        phi = 2 * RDF.pi() / p
        V = RDF**2
        vs = [V([(phi * t).sin(), (phi * t).cos()]) for t in range(p)]
        all = []
        depth = max(RDF(max_points).log(p).floor(), 1)
        scale = min(RDF(1.5 / p), 1 / RDF(3))
        pts = [vs] * depth
        if depth == 1 and 23 < p < max_points:
            extras = int(max_points / p)
            if p / extras > 5:
                pts = [vs] * depth + [vs[::extras]]
        for digits in cartesian_product_iterator(pts):
            p = sum([v * scale**n for n, v in enumerate(digits)])
            all.append(tuple(p))
        g = points(all, **args)
        # Set default plotting options
        g.axes(False)
        g.set_aspect_ratio(1)
        return g
class pAdicBaseGeneric(pAdicGeneric):
    _implementation = 'GMP'

    def __init__(self, p, prec, print_mode, names, element_class):
        """
        Initialization

        TESTS::

            sage: R = Zp(5) #indirect doctest
        """
        if self.is_relaxed():
            from sage.rings.padics.pow_computer_flint import PowComputer_flint
            self.prime_pow = PowComputer_flint(p, 1, 1, 1, self.is_field())
        else:
            self.prime_pow = PowComputer(p, max(min(prec - 1, 30), 1), prec,
                                         self.is_field(), self._prec_type())
        pAdicGeneric.__init__(self, self, p, prec, print_mode, names,
                              element_class)
        if self.is_field():
            if self.is_capped_relative():
                coerce_list = [
                    pAdicCoercion_ZZ_CR(self),
                    pAdicCoercion_QQ_CR(self)
                ]
                convert_list = []
            elif self.is_floating_point():
                coerce_list = [
                    pAdicCoercion_ZZ_FP(self),
                    pAdicCoercion_QQ_FP(self)
                ]
                convert_list = []
            elif self.is_lattice_prec():
                coerce_list = [QQ]
                convert_list = []
            elif self.is_relaxed():
                coerce_list = [QQ]
                convert_list = []
            else:
                raise RuntimeError
        elif self.is_capped_relative():
            coerce_list = [pAdicCoercion_ZZ_CR(self)]
            convert_list = [pAdicConvert_QQ_CR(self)]
        elif self.is_capped_absolute():
            coerce_list = [pAdicCoercion_ZZ_CA(self)]
            convert_list = [pAdicConvert_QQ_CA(self)]
        elif self.is_fixed_mod():
            coerce_list = [pAdicCoercion_ZZ_FM(self)]
            convert_list = [pAdicConvert_QQ_FM(self)]
        elif self.is_floating_point():
            coerce_list = [pAdicCoercion_ZZ_FP(self)]
            convert_list = [pAdicConvert_QQ_FP(self)]
        elif self.is_lattice_prec():
            coerce_list = [ZZ]
            convert_list = [QQ]
        elif self.is_relaxed():
            coerce_list = [ZZ]
            convert_list = [QQ]
        else:
            raise RuntimeError
        self.Element = element_class
        self._populate_coercion_lists_(coerce_list=coerce_list,
                                       convert_list=convert_list)

    def _repr_(self, do_latex=False):
        r"""
        Returns a print representation of this p-adic ring or field.

        EXAMPLES::

            sage: K = Zp(17); K #indirect doctest
            17-adic Ring with capped relative precision 20
            sage: latex(K)
            \Bold{Z}_{17}
            sage: K = ZpCA(17); K #indirect doctest
            17-adic Ring with capped absolute precision 20
            sage: latex(K)
            \Bold{Z}_{17}
            sage: K = ZpFP(17); K #indirect doctest
            17-adic Ring with floating precision 20
            sage: latex(K)
            \Bold{Z}_{17}
            sage: K = ZpFM(7); K
            7-adic Ring of fixed modulus 7^20
            sage: latex(K) #indirect doctest
            \Bold{Z}_{7}
            sage: K = ZpLF(2); K   # indirect doctest
            doctest:...: FutureWarning: This class/method/function is marked as experimental. It, its functionality or its interface might change without a formal deprecation.
            See http://trac.sagemath.org/23505 for details.
            2-adic Ring with lattice-float precision
            sage: latex(K)
            \Bold{Z}_{2}
            sage: K = Qp(17); K #indirect doctest
            17-adic Field with capped relative precision 20
            sage: latex(K)
            \Bold{Q}_{17}
            sage: K = QpFP(17); K #indirect doctest
            17-adic Field with floating precision 20
            sage: latex(K)
            \Bold{Q}_{17}
            sage: K = QpLC(2); K   # indirect doctest
            2-adic Field with lattice-cap precision
            sage: latex(K)
            \Bold{Q}_{2}
        """
        if do_latex:
            if self.is_field():
                s = r"\Bold{Q}_{%s}" % self.prime()
            else:
                s = r"\Bold{Z}_{%s}" % self.prime()
            if hasattr(self, '_label') and self._label:
                s = r"\verb'%s' (\simeq %s)" % (self._label, s)
        else:
            s = "Field " if self.is_field() else "Ring "
            s = "%s-adic " % self.prime() + s + precprint(
                self._prec_type(), self.precision_cap(), self.prime())
            if hasattr(self, '_label') and self._label:
                s += " (label: %s)" % self._label
        return s

    def exact_field(self):
        """
        Returns the rational field.

        For compatibility with extensions of p-adics.

        EXAMPLES::

            sage: Zp(5).exact_field()
            Rational Field
        """
        from sage.rings.rational_field import QQ
        return QQ

    def exact_ring(self):
        """
        Returns the integer ring.

        EXAMPLES::

            sage: Zp(5).exact_ring()
            Integer Ring
        """
        from sage.rings.integer_ring import ZZ
        return ZZ

    def is_isomorphic(self, ring):
        r"""
        Returns whether ``self`` and ``ring`` are isomorphic, i.e. whether ``ring`` is an implementation of `\ZZ_p` for the same prime as ``self``.

        INPUT:

        - ``self`` -- a `p`-adic ring

        - ``ring`` -- a ring

        OUTPUT:

        - ``boolean`` -- whether ``ring`` is an implementation of \ZZ_p` for the same prime as ``self``.

        EXAMPLES::

            sage: R = Zp(5, 15, print_mode='digits'); S = Zp(5, 44, print_max_terms=4); R.is_isomorphic(S)
            True
        """
        return isinstance(ring, pAdicBaseGeneric) and self.prime(
        ) == ring.prime() and self.is_field() == ring.is_field()

    def gen(self, n=0):
        """
        Returns the ``nth`` generator of this extension.  For base
        rings/fields, we consider the generator to be the prime.

        EXAMPLES::

            sage: R = Zp(5); R.gen()
            5 + O(5^21)
        """
        if n != 0:
            raise IndexError("only one generator")
        return self(self.prime())

    def modulus(self, exact=False):
        r"""
        Returns the polynomial defining this extension.

        For compatibility with extension fields; we define the modulus to be x-1.

        INPUT:

        - ``exact`` -- boolean (default ``False``), whether to return a polynomial with integer entries.

        EXAMPLES::

            sage: Zp(5).modulus(exact=True)
            x
        """
        return self.defining_polynomial(exact=exact)

    def absolute_discriminant(self):
        """
        Returns the absolute discriminant of this `p`-adic ring

        EXAMPLES::

            sage: Zp(5).absolute_discriminant()
            1
        """
        return 1

    def discriminant(self, K=None):
        """
        Returns the discriminant of this `p`-adic ring over ``K``

        INPUT:

        - ``self`` -- a `p`-adic ring

        - ``K`` -- a sub-ring of ``self`` or ``None`` (default: ``None``)

        OUTPUT:

        - integer -- the discriminant of this ring over ``K`` (or the
          absolute discriminant if ``K`` is ``None``)

        EXAMPLES::

            sage: Zp(5).discriminant()
            1
        """
        if (K is None or K is self):
            return 1
        else:
            raise ValueError("Ground Ring must be a subring of self")

    def is_abelian(self):
        """
        Returns whether the Galois group is abelian, i.e. ``True``.
        #should this be automorphism group?

        EXAMPLES::

            sage: R = Zp(3, 10,'fixed-mod'); R.is_abelian()
            True
        """
        return True

    def is_normal(self):
        """
        Returns whether or not this is a normal extension, i.e. ``True``.

        EXAMPLES::

            sage: R = Zp(3, 10,'fixed-mod'); R.is_normal()
            True
        """
        return True

    def uniformizer(self):
        """
        Returns a uniformizer for this ring.

        EXAMPLES::

            sage: R = Zp(3,5,'fixed-mod', 'series')
            sage: R.uniformizer()
            3
        """
        return self(self.prime_pow._prime())

    def uniformizer_pow(self, n):
        """
        Returns the ``nth`` power of the uniformizer of ``self`` (as
        an element of ``self``).

        EXAMPLES::

            sage: R = Zp(5)
            sage: R.uniformizer_pow(5)
            5^5 + O(5^25)
            sage: R.uniformizer_pow(infinity)
            0
        """
        return self(self.prime_pow(n))

    def _uniformizer_print(self):
        """
        Returns how the uniformizer is supposed to print.

        EXAMPLES::

            sage: R = Zp(5, names='pi'); R._uniformizer_print()
            'pi'
        """
        return self.variable_name()

    def has_pth_root(self):
        r"""
        Returns whether or not `\ZZ_p` has a primitive `p^{th}`
        root of unity.

        EXAMPLES::

            sage: Zp(2).has_pth_root()
            True
            sage: Zp(17).has_pth_root()
            False
        """
        return (self.prime() == 2)

    def has_root_of_unity(self, n):
        r"""
        Returns whether or not `\ZZ_p` has a primitive `n^{th}`
        root of unity.

        INPUT:

        - ``self`` -- a `p`-adic ring

        - ``n`` -- an integer

        OUTPUT:

        - ``boolean`` -- whether ``self`` has primitive `n^{th}` root
          of unity

        EXAMPLES::

            sage: R=Zp(37)
            sage: R.has_root_of_unity(12)
            True
            sage: R.has_root_of_unity(11)
            False
        """
        if (self.prime() == 2):
            return n.divides(2)
        else:
            return n.divides(self.prime() - 1)

    def zeta(self, n=None):
        r"""
        Returns a generator of the group of roots of unity.

        INPUT:

        - ``self`` -- a `p`-adic ring

        - ``n`` -- an integer or ``None`` (default: ``None``)

        OUTPUT:

        - ``element`` -- a generator of the `n^{th}` roots of unity,
          or a generator of the full group of roots of unity if ``n``
          is ``None``

        EXAMPLES::

            sage: R = Zp(37,5)
            sage: R.zeta(12)
            8 + 24*37 + 37^2 + 29*37^3 + 23*37^4 + O(37^5)
        """
        if (self.prime() == 2):
            if (n is None) or (n == 2):
                return self(-1)
            if n == 1:
                return self(1)
            else:
                raise ValueError("No, %sth root of unity in self" % n)
        else:
            from sage.rings.finite_rings.finite_field_constructor import GF
            return self.teichmuller(GF(self.prime()).zeta(n).lift())

    def zeta_order(self):
        """
        Returns the order of the group of roots of unity.

        EXAMPLES::

            sage: R = Zp(37); R.zeta_order()
            36
            sage: Zp(2).zeta_order()
            2
        """
        if (self.prime() == 2):
            return 2
        else:
            return self.prime() - 1

    def plot(self, max_points=2500, **args):
        r"""
        Create a visualization of this `p`-adic ring as a fractal
        similar to a generalization of the Sierpi\'nski
        triangle.

        The resulting image attempts to capture the
        algebraic and topological characteristics of `\ZZ_p`.

        INPUT:

        - ``max_points`` -- the maximum number or points to plot,
          which controls the depth of recursion (default 2500)

        - ``**args`` -- color, size, etc. that are passed to the
          underlying point graphics objects

        REFERENCES:

        - Cuoco, A. ''Visualizing the `p`-adic Integers'', The
          American Mathematical Monthly, Vol. 98, No. 4 (Apr., 1991),
          pp. 355-364

        EXAMPLES::

            sage: Zp(3).plot()
            Graphics object consisting of 1 graphics primitive
            sage: Zp(5).plot(max_points=625)
            Graphics object consisting of 1 graphics primitive
            sage: Zp(23).plot(rgbcolor=(1,0,0))
            Graphics object consisting of 1 graphics primitive
        """
        if 'pointsize' not in args:
            args['pointsize'] = 1
        from sage.misc.mrange import cartesian_product_iterator
        from sage.rings.real_double import RDF
        from sage.plot.all import points
        p = self.prime()
        phi = 2 * RDF.pi() / p
        V = RDF**2
        vs = [V([(phi * t).sin(), (phi * t).cos()]) for t in range(p)]
        all = []
        depth = max(RDF(max_points).log(p).floor(), 1)
        scale = min(RDF(1.5 / p), 1 / RDF(3))
        pts = [vs] * depth
        if depth == 1 and 23 < p < max_points:
            extras = int(max_points / p)
            if p / extras > 5:
                pts = [vs] * depth + [vs[::extras]]
        for digits in cartesian_product_iterator(pts):
            p = sum([v * scale**n for n, v in enumerate(digits)])
            all.append(tuple(p))
        g = points(all, **args)
        # Set default plotting options
        g.axes(False)
        g.set_aspect_ratio(1)
        return g
class pAdicBaseGeneric(pAdicGeneric):
    _implementation = 'GMP'
    def __init__(self, p, prec, print_mode, names, element_class):
        """
        Initialization

        TESTS::

            sage: R = Zp(5) #indirect doctest
        """
        self.prime_pow = PowComputer(p, max(min(prec - 1, 30), 1), prec, self.is_field(), self._prec_type())
        pAdicGeneric.__init__(self, self, p, prec, print_mode, names, element_class)
        if self.is_field():
            if self.is_capped_relative():
                coerce_list = [pAdicCoercion_ZZ_CR(self), pAdicCoercion_QQ_CR(self)]
                convert_list = []
            elif self.is_floating_point():
                coerce_list = [pAdicCoercion_ZZ_FP(self), pAdicCoercion_QQ_FP(self)]
                convert_list = []
            elif self.is_lattice_prec():
                coerce_list = [QQ]
                convert_list = []
            else:
                raise RuntimeError
        elif self.is_capped_relative():
            coerce_list = [pAdicCoercion_ZZ_CR(self)]
            convert_list = [pAdicConvert_QQ_CR(self)]
        elif self.is_capped_absolute():
            coerce_list = [pAdicCoercion_ZZ_CA(self)]
            convert_list = [pAdicConvert_QQ_CA(self)]
        elif self.is_fixed_mod():
            coerce_list = [pAdicCoercion_ZZ_FM(self)]
            convert_list = [pAdicConvert_QQ_FM(self)]
        elif self.is_floating_point():
            coerce_list = [pAdicCoercion_ZZ_FP(self)]
            convert_list = [pAdicConvert_QQ_FP(self)]
        elif self.is_lattice_prec():
            coerce_list = [ZZ]
            convert_list = [QQ]
        else:
            raise RuntimeError
        self.Element = element_class
        self._populate_coercion_lists_(coerce_list=coerce_list, convert_list=convert_list)

    def _repr_(self, do_latex=False):
        r"""
        Returns a print representation of this p-adic ring or field.

        EXAMPLES::

            sage: K = Zp(17); K #indirect doctest
            17-adic Ring with capped relative precision 20
            sage: latex(K)
            \ZZ_{17}
            sage: K = ZpCA(17); K #indirect doctest
            17-adic Ring with capped absolute precision 20
            sage: latex(K)
            \ZZ_{17}
            sage: K = ZpFP(17); K #indirect doctest
            17-adic Ring with floating precision 20
            sage: latex(K)
            \ZZ_{17}
            sage: K = ZpFM(7); K
            7-adic Ring of fixed modulus 7^20
            sage: latex(K) #indirect doctest
            \ZZ_{7}
            sage: K = ZpLF(2); K   # indirect doctest
            doctest:...: FutureWarning: This class/method/function is marked as experimental. It, its functionality or its interface might change without a formal deprecation.
            See http://trac.sagemath.org/23505 for details.
            2-adic Ring with lattice-float precision
            sage: latex(K)
            \ZZ_{2}
            sage: K = Qp(17); K #indirect doctest
            17-adic Field with capped relative precision 20
            sage: latex(K)
            \QQ_{17}
            sage: K = QpFP(17); K #indirect doctest
            17-adic Field with floating precision 20
            sage: latex(K)
            \QQ_{17}
            sage: K = QpLC(2); K   # indirect doctest
            2-adic Field with lattice-cap precision
            sage: latex(K)
            \QQ_{2}
        """
        if do_latex:
            if self.is_field():
                s = r"\QQ_{%s}" % self.prime()
            else:
                s = r"\ZZ_{%s}" % self.prime()
            if hasattr(self, '_label') and self._label:
                s = r"\verb'%s' (\simeq %s)"%(self._label, s)
        else:
            s = "Field " if self.is_field() else "Ring "
            s = "%s-adic "%self.prime() + s + precprint(self._prec_type(), self.precision_cap(), self.prime())
            if hasattr(self, '_label') and self._label:
                s+= " (label: %s)"%self._label
        return s

    def exact_field(self):
        """
        Returns the rational field.

        For compatibility with extensions of p-adics.

        EXAMPLES::

            sage: Zp(5).exact_field()
            Rational Field
        """
        from sage.rings.rational_field import QQ
        return QQ

    def exact_ring(self):
        """
        Returns the integer ring.

        EXAMPLES::

            sage: Zp(5).exact_ring()
            Integer Ring
        """
        from sage.rings.integer_ring import ZZ
        return ZZ

    def is_isomorphic(self, ring):
        r"""
        Returns whether ``self`` and ``ring`` are isomorphic, i.e. whether ``ring`` is an implementation of `\mathbb{Z}_p` for the same prime as ``self``.

        INPUT:

        - ``self`` -- a `p`-adic ring

        - ``ring`` -- a ring

        OUTPUT:

        - ``boolean`` -- whether ``ring`` is an implementation of \mathbb{Z}_p` for the same prime as ``self``.

        EXAMPLES::

            sage: R = Zp(5, 15, print_mode='digits'); S = Zp(5, 44, print_max_terms=4); R.is_isomorphic(S)
            True
        """
        return isinstance(ring, pAdicBaseGeneric) and self.prime() == ring.prime() and self.is_field() == ring.is_field()

    def gen(self, n=0):
        """
        Returns the ``nth`` generator of this extension.  For base
        rings/fields, we consider the generator to be the prime.

        EXAMPLES::

            sage: R = Zp(5); R.gen()
            5 + O(5^21)
        """
        if n != 0:
            raise IndexError("only one generator")
        return self(self.prime())

    def absolute_discriminant(self):
        """
        Returns the absolute discriminant of this `p`-adic ring

        EXAMPLES::

            sage: Zp(5).absolute_discriminant()
            1
        """
        return 1

    def discriminant(self, K=None):
        """
        Returns the discriminant of this `p`-adic ring over ``K``

        INPUT:

        - ``self`` -- a `p`-adic ring

        - ``K`` -- a sub-ring of ``self`` or ``None`` (default: ``None``)

        OUTPUT:

        - integer -- the discriminant of this ring over ``K`` (or the
          absolute discriminant if ``K`` is ``None``)

        EXAMPLES::

            sage: Zp(5).discriminant()
            1
        """
        if (K is None or K is self):
            return 1
        else:
            raise ValueError("Ground Ring must be a subring of self")

    def is_abelian(self):
        """
        Returns whether the Galois group is abelian, i.e. ``True``.
        #should this be automorphism group?

        EXAMPLES::

            sage: R = Zp(3, 10,'fixed-mod'); R.is_abelian()
            True
        """
        return True

    def is_normal(self):
        """
        Returns whether or not this is a normal extension, i.e. ``True``.

        EXAMPLES::

            sage: R = Zp(3, 10,'fixed-mod'); R.is_normal()
            True
        """
        return True

    def uniformizer(self):
        """
        Returns a uniformizer for this ring.

        EXAMPLES::

            sage: R = Zp(3,5,'fixed-mod', 'series')
            sage: R.uniformizer()
            3 + O(3^5)
        """
        return self(self.prime_pow._prime())

    def uniformizer_pow(self, n):
        """
        Returns the ``nth`` power of the uniformizer of ``self`` (as
        an element of ``self``).

        EXAMPLES::

            sage: R = Zp(5)
            sage: R.uniformizer_pow(5)
            5^5 + O(5^25)
            sage: R.uniformizer_pow(infinity)
            0
        """
        return self(self.prime_pow(n))

    def _uniformizer_print(self):
        """
        Returns how the uniformizer is supposed to print.

        EXAMPLES::

            sage: R = Zp(5, names='pi'); R._uniformizer_print()
            'pi'
        """
        return self.variable_name()

    def has_pth_root(self):
        r"""
        Returns whether or not `\mathbb{Z}_p` has a primitive `p^{th}`
        root of unity.

        EXAMPLES::

            sage: Zp(2).has_pth_root()
            True
            sage: Zp(17).has_pth_root()
            False
        """
        return (self.prime() == 2)

    def has_root_of_unity(self, n):
        r"""
        Returns whether or not `\mathbb{Z}_p` has a primitive `n^{th}`
        root of unity.

        INPUT:

        - ``self`` -- a `p`-adic ring

        - ``n`` -- an integer

        OUTPUT:

        - ``boolean`` -- whether ``self`` has primitive `n^{th}` root
          of unity

        EXAMPLES::

            sage: R=Zp(37)
            sage: R.has_root_of_unity(12)
            True
            sage: R.has_root_of_unity(11)
            False
        """
        if (self.prime() == 2):
            return n.divides(2)
        else:
            return n.divides(self.prime() - 1)

    def zeta(self, n=None):
        r"""
        Returns a generator of the group of roots of unity.

        INPUT:

        - ``self`` -- a `p`-adic ring

        - ``n`` -- an integer or ``None`` (default: ``None``)

        OUTPUT:

        - ``element`` -- a generator of the `n^{th}` roots of unity,
          or a generator of the full group of roots of unity if ``n``
          is ``None``

        EXAMPLES::

            sage: R = Zp(37,5)
            sage: R.zeta(12)
            8 + 24*37 + 37^2 + 29*37^3 + 23*37^4 + O(37^5)
        """
        if (self.prime() == 2):
            if (n is None) or (n == 2):
                return self(-1)
            if n == 1:
                return self(1)
            else:
                raise ValueError("No, %sth root of unity in self"%n)
        else:
            from sage.rings.finite_rings.finite_field_constructor import GF
            return self.teichmuller(GF(self.prime()).zeta(n).lift())

    def zeta_order(self):
        """
        Returns the order of the group of roots of unity.

        EXAMPLES::

            sage: R = Zp(37); R.zeta_order()
            36
            sage: Zp(2).zeta_order()
            2
        """
        if (self.prime() == 2):
            return 2
        else:
            return self.prime() - 1

    def plot(self, max_points=2500, **args):
        r"""
        Create a visualization of this `p`-adic ring as a fractal
        similar to a generalization of the Sierpi\'nski
        triangle.

        The resulting image attempts to capture the
        algebraic and topological characteristics of `\mathbb{Z}_p`.

        INPUT:

        - ``max_points`` -- the maximum number or points to plot,
          which controls the depth of recursion (default 2500)

        - ``**args`` -- color, size, etc. that are passed to the
          underlying point graphics objects

        REFERENCES:

        - Cuoco, A. ''Visualizing the `p`-adic Integers'', The
          American Mathematical Monthly, Vol. 98, No. 4 (Apr., 1991),
          pp. 355-364

        EXAMPLES::

            sage: Zp(3).plot()
            Graphics object consisting of 1 graphics primitive
            sage: Zp(5).plot(max_points=625)
            Graphics object consisting of 1 graphics primitive
            sage: Zp(23).plot(rgbcolor=(1,0,0))
            Graphics object consisting of 1 graphics primitive
        """
        if 'pointsize' not in args:
            args['pointsize'] = 1
        from sage.misc.mrange import cartesian_product_iterator
        from sage.rings.real_double import RDF
        from sage.plot.all import points, circle, Graphics
        p = self.prime()
        phi = 2*RDF.pi()/p
        V = RDF**2
        vs = [V([(phi*t).sin(), (phi*t).cos()]) for t in range(p)]
        all = []
        depth = max(RDF(max_points).log(p).floor(), 1)
        scale = min(RDF(1.5/p), 1/RDF(3))
        pts = [vs]*depth
        if depth == 1 and 23 < p < max_points:
            extras = int(max_points/p)
            if p/extras > 5:
                pts = [vs]*depth + [vs[::extras]]
        for digits in cartesian_product_iterator(pts):
            p = sum([v * scale**n for n, v in enumerate(digits)])
            all.append(tuple(p))
        g = points(all, **args)
        # Set default plotting options
        g.axes(False)
        g.set_aspect_ratio(1)
        return g