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
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
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]