def rho(self):
        r"""
        Return the vertex ``rho`` of the basic hyperbolic
        triangle which describes ``self``. ``rho`` has
        absolute value 1 and angle ``pi/n``.

        EXAMPLES::

            sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
            sage: HeckeTriangleGroup(3).rho() == 1/2 + sqrt(3)/2*i
            True
            sage: HeckeTriangleGroup(4).rho() == sqrt(2)/2*(1 + i)
            True
            sage: HeckeTriangleGroup(6).rho() == sqrt(3)/2 + 1/2*i
            True
            sage: HeckeTriangleGroup(10).rho()
            0.95105651629515...? + 0.30901699437494...?*I
            sage: HeckeTriangleGroup(infinity).rho()
            1
        """

        # TODO: maybe rho should be replaced by -rhobar
        # Also we could use NumberFields...
        if (self._n == infinity):
            return coerce_AA(1)
        else:
            rho = AlgebraicField()(exp(pi/self._n*i))
            rho.simplify()

            return rho
Exemple #2
0
    def rho(self):
        r"""
        Return the vertex ``rho`` of the basic hyperbolic
        triangle which describes ``self``. ``rho`` has
        absolute value 1 and angle ``pi/n``.

        EXAMPLES::

            sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
            sage: HeckeTriangleGroup(3).rho() == QQbar(1/2 + sqrt(3)/2*i)
            True
            sage: HeckeTriangleGroup(4).rho() == QQbar(sqrt(2)/2*(1 + i))
            True
            sage: HeckeTriangleGroup(6).rho() == QQbar(sqrt(3)/2 + 1/2*i)
            True
            sage: HeckeTriangleGroup(10).rho()
            0.95105651629515...? + 0.30901699437494...?*I
            sage: HeckeTriangleGroup(infinity).rho()
            1
        """

        # TODO: maybe rho should be replaced by -rhobar
        # Also we could use NumberFields...
        if (self._n == infinity):
            return coerce_AA(1)
        else:
            rho = AlgebraicField()(exp(pi / self._n * i))
            rho.simplify()

            return rho
Exemple #3
0
    def root_extension_embedding(self, D, K=None):
        r"""
        Return the correct embedding from the root extension field
        of the given discriminant ``D``  to the field ``K``.

        Also see the method ``root_extension_embedding(K)`` of
        ``HeckeTriangleGroupElement`` for more examples.

        INPUT:

        - ``D`` -- An element of the base ring of ``self``
                   corresponding to a discriminant.

        - ``K`` -- A field to which we want the (correct) embeddding.
                   If ``K=None`` (default) then ``AlgebraicField()`` is
                   used for positive ``D`` and ``AlgebraicRealField()``
                   otherwise.

        OUTPUT:

        The corresponding embedding if it was found.
        Otherwise a ValueError is raised.

        EXAMPLES::

            sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
            sage: G = HeckeTriangleGroup(n=infinity)
            sage: G.root_extension_embedding(32)
            Ring morphism:
              From: Number Field in e with defining polynomial x^2 - 32
              To:   Algebraic Real Field
              Defn: e |--> 5.656854249492...?
            sage: G.root_extension_embedding(-4)
            Ring morphism:
              From: Number Field in e with defining polynomial x^2 + 4
              To:   Algebraic Field
              Defn: e |--> 2*I
            sage: G.root_extension_embedding(4)
            Coercion map:
              From: Rational Field
              To:   Algebraic Real Field

            sage: G = HeckeTriangleGroup(n=7)
            sage: lam = G.lam()
            sage: D = 4*lam^2 + 4*lam - 4
            sage: G.root_extension_embedding(D, CC)
            Relative number field morphism:
              From: Number Field in e with defining polynomial x^2 - 4*lam^2 - 4*lam + 4 over its base field
              To:   Complex Field with 53 bits of precision
              Defn: e |--> 4.02438434522...
                    lam |--> 1.80193773580...
            sage: D = lam^2 - 4
            sage: G.root_extension_embedding(D)
            Relative number field morphism:
              From: Number Field in e with defining polynomial x^2 - lam^2 + 4 over its base field
              To:   Algebraic Field
              Defn: e |--> 0.?... + 0.867767478235...?*I
                    lam |--> 1.801937735804...?
        """

        D = self.base_ring()(D)
        F = self.root_extension_field(D)
        if K is None:
            if coerce_AA(D) > 0:
                K = AA
            else:
                K = AlgebraicField()

        L = [emb for emb in F.embeddings(K)]

        # Three possibilities up to numerical artefacts:
        # (1) emb = e, purely imaginary
        # (2) emb = e or lam (can't distinguish), purely real
        # (3) emb = (e,lam), e purely imaginary, lam purely real
        # (4) emb = (e,lam), e purely real, lam purely real
        # There always exists one emb with "e" positive resp. positive imaginary
        # and if there is a lam there exists a positive one...
        #
        # Criteria to pick the correct "maximum":
        # 1. First figure out if e resp. lam is purely real or imaginary
        #    (using "abs(e.imag()) > abs(e.real())")
        # 2. In the purely imaginary case we don't want anything negative imaginary
        #    and we know the positive case is unique after sorting lam
        # 3. For the remaining cases we want the biggest real part
        #    (and lam should get comparison priority)
        def emb_key(emb):
            L = []
            gens_len = len(emb.im_gens())
            for k in range(gens_len):
                a = emb.im_gens()[k]
                try:
                    a.simplify()
                    a.exactify()
                except AttributeError:
                    pass
                # If a is purely imaginary:
                if abs(a.imag()) > abs(a.real()):
                    if a.imag() < 0:
                        a = -infinity
                    else:
                        a = ZZ(0)
                else:
                    a = a.real()

                L.append(a)

            L.reverse()
            return L

        if len(L) > 1:
            L.sort(key=emb_key)
        return L[-1]
    def root_extension_embedding(self, K=AlgebraicField()):
        r"""
        Return the correct embedding from the root extension field to ``K`` (default: ``AlgebraicField()``).

        EXAMPLES::

            sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
            sage: G = HeckeTriangleGroup(n=infinity)

            sage: fp = (-G.S()).fixed_points()[0]
            sage: alg_fp = (-G.S()).root_extension_embedding()(fp)
            sage: alg_fp
            1*I
            sage: alg_fp == (-G.S()).fixed_points(embedded=True)[0]
            True

            sage: fp = (-G.V(2)).fixed_points()[1]
            sage: alg_fp = (-G.V(2)).root_extension_embedding(AA)(fp)
            sage: alg_fp
            -1.732050807568...?
            sage: alg_fp == (-G.V(2)).fixed_points(embedded=True)[1]
            True

            sage: fp = (-G.V(2)).fixed_points()[0]
            sage: alg_fp = (-G.V(2)).root_extension_embedding(AA)(fp)
            sage: alg_fp
            1.732050807568...?
            sage: alg_fp == (-G.V(2)).fixed_points(embedded=True)[0]
            True

            sage: G = HeckeTriangleGroup(n=7)

            sage: fp = (-G.S()).fixed_points()[1]
            sage: alg_fp = (-G.S()).root_extension_embedding()(fp)
            sage: alg_fp
            0.?... - 1.000000000000...?*I
            sage: alg_fp == (-G.S()).fixed_points(embedded=True)[1]
            True

            sage: fp = (-G.U()^4).fixed_points()[0]
            sage: alg_fp = (-G.U()^4).root_extension_embedding()(fp)
            sage: alg_fp
            0.9009688679024...? + 0.4338837391175...?*I
            sage: alg_fp == (-G.U()^4).fixed_points(embedded=True)[0]
            True

            sage: (-G.U()^4).root_extension_embedding(CC)(fp)
            0.900968867902... + 0.433883739117...*I
            sage: (-G.U()^4).root_extension_embedding(CC)(fp).parent()
            Complex Field with 53 bits of precision

            sage: fp = (-G.V(5)).fixed_points()[1]
            sage: alg_fp = (-G.V(5)).root_extension_embedding(AA)(fp)
            sage: alg_fp
            -0.6671145837954...?
            sage: alg_fp == (-G.V(5)).fixed_points(embedded=True)[1]
            True
        """

        G = self.parent()
        D = self.discriminant()
        F = self.root_extension_field()
        n = G.n()

        if D.is_square():
            e = D.sqrt()
            lam = G.lam()
        elif n in [3, infinity]:
            e = F.gen(0)
            lam = G.lam()
        else:
            (e, lam) = F.gens()

        emb_lam = K(G.lam())
        if self.is_elliptic():
            emb_e = K(AlgebraicField()(D).sqrt())
        else:
            emb_e = K(AA(D).sqrt())

        guess = ZZ(0)
        min_value = infinity
        index = ZZ(0)

        for (index,
             emb) in enumerate(self.root_extension_field().embeddings(K)):
            if K.is_exact():
                if emb(lam) == emb_lam and emb(e) == emb_e:
                    return emb
            else:
                value = (emb(lam) - emb_lam).n(
                    K.prec()).abs() + (emb(e) - emb_e).n(K.prec()).abs()
                if (value < min_value):
                    guess = index
                    min_value = value

        if K.is_exact() or min_value == infinity:
            raise ValueError(
                "No suitable embedding is available for K = {}!".format(K))
        else:
            return self.root_extension_field().embeddings(K)[guess]