def _coerce_map_from_(self, P):
        r"""Return a coercion map from `P` to `self`, or `True`, or `None`.

        The following rings admit a coercion map to the Puiseux series ring
        `A((x-a)^(1/e))`:

        - any ring that admits a coercion map to `A`

        - any Laurent series ring, power series ring, or polynomial ring in the
          variable `(x-a)` over a ring admitting a coercion map to `A`

        - any Puiseux series ring with the same center `a` and ramification
          index equal to a multiple of `self`'s ramification index. For
          example, Puiseux series in (x-a)^(1/2) can be interpreted as Puiseux
          series in (x-a)^(1/4).

        """
        # any ring that has a coercion map to A
        A = self.base_ring()
        if A is P:
            return True
        f = A.coerce_map_from(P)
        if f is not None:
            return self.coerce_map_from(A) * f

        # Laurent series rings, power series rings, and polynomial rings with
        # the same variable name and the base rings are coercible
        if ((is_PuiseuxSeriesRing(P) or is_LaurentSeriesRing(P) or
             is_PowerSeriesRing(P))
            and P.variable_name() == self.variable_name()
            and A.has_coerce_map_from(P.base_ring())):
            return True
    def _coerce_map_from_(self, P):
        r"""Return a coercion map from `P` to `self`, or `True`, or `None`.

        The following rings admit a coercion map to the Puiseux series ring
        `A((x-a)^(1/e))`:

        - any ring that admits a coercion map to `A`

        - any Laurent series ring, power series ring, or polynomial ring in the
          variable `(x-a)` over a ring admitting a coercion map to `A`

        - any Puiseux series ring with the same center `a` and ramification
          index equal to a multiple of `self`'s ramification index. For
          example, Puiseux series in (x-a)^(1/2) can be interpreted as Puiseux
          series in (x-a)^(1/4).

        """
        # any ring that has a coercion map to A
        A = self.base_ring()
        if A is P:
            return True
        f = A.coerce_map_from(P)
        if f is not None:
            return self.coerce_map_from(A) * f

        # Laurent series rings, power series rings, and polynomial rings with
        # the same variable name and the base rings are coercible
        if ((is_PuiseuxSeriesRing(P) or is_LaurentSeriesRing(P) or
             is_PowerSeriesRing(P))
            and P.variable_name() == self.variable_name()
            and A.has_coerce_map_from(P.base_ring())):
            return True
Example #3
0
    def _element_constructor_(self, x):
        r"""
        Return ``x`` coerced into this forms space.

        EXAMPLES::

            sage: from graded_ring import MModularFormsRing
            sage: from space import ModularForms
            sage: MF = ModularForms(k=12, ep=1)
            sage: (x,y,z,d) = MF.pol_ring().gens()

            sage: Delta = MModularFormsRing().Delta()
            sage: Delta.parent()
            MeromorphicModularFormsRing(n=3) over Integer Ring
            sage: MF(Delta)
            q - 24*q^2 + 252*q^3 - 1472*q^4 + O(q^5)
            sage: MF(Delta).parent() == MF
            True

            sage: MF(x^3)
            1 + 720*q + 179280*q^2 + 16954560*q^3 + 396974160*q^4 + O(q^5)
            sage: MF(x^3).parent() == MF
            True

            sage: qexp = Delta.q_expansion(prec=2)
            sage: qexp
            q + O(q^2)
            sage: qexp.parent()
            Power Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring
            sage: MF(qexp)
            q - 24*q^2 + 252*q^3 - 1472*q^4 + O(q^5)
            sage: MF(qexp) == MF(Delta)
            True

            sage: MF([0,1]) == MF(Delta)
            True
            sage: MF([1,0]) == MF(x^3) - 720*MF(Delta) # todo: this should give True, the result is False because d!=1/1728 but a formal parameter
            False

            sage: vec = MF(Delta).coordinate_vector()
            sage: vec
            (0, 1)
            sage: vec.parent()
            Vector space of dimension 2 over Fraction Field of Univariate Polynomial Ring in d over Integer Ring
            sage: vec in MF.module()
            True
            sage: MF(vec) == MF(Delta)
            True

            sage: subspace = MF.subspace([MF(Delta)])
            sage: subspace
            Subspace of dimension 1 of ModularForms(n=3, k=12, ep=1) over Integer Ring
            sage: subspace(MF(Delta)) == subspace(d*(x^3-y^2)) == subspace(qexp) == subspace([0,1]) == subspace(vec) == subspace.gen()
            True
            sage: subspace(MF(Delta)).parent() == subspace(d*(x^3-y^2)).parent() == subspace(qexp).parent() == subspace([0,1]).parent() == subspace(vec).parent()
            True
            sage: subspace([1]) == subspace.gen()
            True
            sage: ssvec = subspace(vec).coordinate_vector()
            sage: ssvec
            (1)
            sage: ssvec.parent()
            Vector space of dimension 1 over Fraction Field of Univariate Polynomial Ring in d over Integer Ring
            sage: ambvec = subspace(vec).ambient_coordinate_vector()
            sage: ambvec
            (0, 1)
            sage: ambvec.parent()
            Vector space of degree 2 and dimension 1 over Fraction Field of Univariate Polynomial Ring in d over Integer Ring
            Basis matrix:
            [0 1]
            sage: subspace(ambvec) == subspace(vec) and subspace(ambvec).parent() == subspace(vec).parent()
            True
        """

        from graded_ring_element import FormsRingElement
        if isinstance(x, FormsRingElement):
            return self.element_class(self, x._rat)
        if hasattr(x, 'parent') and (is_LaurentSeriesRing(x.parent()) or is_PowerSeriesRing(x.parent())):
            # This assumes that the series corresponds to a weakly holomorphic modular form!
            # But the construction method (with the assumption) may also be used for more general form spaces...
            return self.construct_form(x)
        if is_FreeModuleElement(x) and (self.module() == x.parent() or self.ambient_module() == x.parent()):
            return self.element_from_ambient_coordinates(x)
        if (not self.is_ambient()) and (isinstance(x, list) or isinstance(x, tuple) or is_FreeModuleElement(x)) and len(x) == self.rank():
            try:
                return self.element_from_coordinates(x)
            except ArithmeticError, TypeError:
                pass