Exemplo n.º 1
0
    def J_inv_ZZ(self):
        r"""
        Return the rational Fourier expansion of ``J_inv``,
        where the parameter ``d`` is replaced by ``1``.

        This is the main function used to determine all Fourier expansions!

        .. NOTE:

        The Fourier expansion of ``J_inv`` for ``d!=1``
        is given by ``J_inv_ZZ(q/d)``.

        .. TODO:

          The functions that are used in this implementation are
          products of hypergeometric series with other, elementary,
          functions.  Implement them and clean up this representation.

        EXAMPLES::

            sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor
            sage: MFSeriesConstructor(prec=3).J_inv_ZZ()
            q^-1 + 31/72 + 1823/27648*q + O(q^2)
            sage: MFSeriesConstructor(group=5, prec=3).J_inv_ZZ()
            q^-1 + 79/200 + 42877/640000*q + O(q^2)
            sage: MFSeriesConstructor(group=5, prec=3).J_inv_ZZ().parent()
            Laurent Series Ring in q over Rational Field

            sage: MFSeriesConstructor(group=infinity, prec=3).J_inv_ZZ()
            q^-1 + 3/8 + 69/1024*q + O(q^2)
        """

        F1 = lambda a, b: self._series_ring([ZZ(0)] + [
            rising_factorial(a, k) * rising_factorial(b, k) /
            (ZZ(k).factorial())**2 * sum(
                ZZ(1) / (a + j) + ZZ(1) / (b + j) - ZZ(2) / ZZ(1 + j)
                for j in range(ZZ(0), ZZ(k)))
            for k in range(ZZ(1), ZZ(self._prec + 1))
        ], ZZ(self._prec + 1))

        F = lambda a, b, c: self._series_ring([
            rising_factorial(a, k) * rising_factorial(b, k) / rising_factorial(
                c, k) / ZZ(k).factorial()
            for k in range(ZZ(0), ZZ(self._prec + 1))
        ], ZZ(self._prec + 1))
        a = self._group.alpha()
        b = self._group.beta()
        Phi = F1(a, b) / F(a, b, ZZ(1))
        q = self._series_ring.gen()

        # the current implementation of power series reversion is slow
        # J_inv_ZZ = ZZ(1) / ((q*Phi.exp()).reverse())

        temp_f = (q * Phi.exp()).polynomial()
        new_f = temp_f.revert_series(temp_f.degree() + 1)
        J_inv_ZZ = ZZ(1) / (new_f + O(q**(temp_f.degree() + 1)))

        return J_inv_ZZ
Exemplo n.º 2
0
        def _deflated(self, a, b, z):
            """
            Private helper to return list of deflated terms.
            
            EXAMPLES::

                sage: x = hypergeometric([5], [4], 3)
                sage: y = x.deflated()
                sage: y
                7/4*hypergeometric((), (), 3)
                sage: x.n(); y.n()
                35.1496896155784
                35.1496896155784
            """
            new = self.eliminate_parameters()
            aa = new.operands()[0].operands()
            bb = new.operands()[1].operands()
            for i, aaa in enumerate(aa):
                for j, bbb in enumerate(bb):
                    m = aaa - bbb
                    if m in ZZ and m > 0:
                        aaaa = aa[:i] + aa[i + 1:]
                        bbbb = bb[:j] + bb[j + 1:]
                        terms = []
                        for k in range(m + 1):
                            # TODO: could rewrite prefactors as recurrence
                            term = binomial(m, k)
                            for c in aaaa:
                                term *= rising_factorial(c, k)
                            for c in bbbb:
                                term /= rising_factorial(c, k)
                            term *= z**k
                            term /= rising_factorial(aaa - m, k)
                            F = hypergeometric([c + k for c in aaaa],
                                               [c + k for c in bbbb], z)
                            unique = []
                            counts = []
                            for c, f in F._deflated():
                                if f in unique:
                                    counts[unique.index(f)] += c
                                else:
                                    unique.append(f)
                                    counts.append(c)
                            Fterms = zip(counts, unique)
                            terms += [(term * termG, G)
                                      for (termG, G) in Fterms]
                        return terms
            return ((1, new), )
Exemplo n.º 3
0
        def _deflated(cls, self, a, b, z):
            """
            Private helper to return list of deflated terms.
            
            EXAMPLES::

                sage: x = hypergeometric([5], [4], 3)
                sage: y = x.deflated()
                sage: y
                7/4*hypergeometric((), (), 3)
                sage: x.n(); y.n()
                35.1496896155784
                35.1496896155784
            """
            new = self.eliminate_parameters()
            aa = new.operands()[0].operands()
            bb = new.operands()[1].operands()
            for i, aaa in enumerate(aa):
                for j, bbb in enumerate(bb):
                    m = aaa - bbb
                    if m in ZZ and m > 0:
                        aaaa = aa[:i] + aa[i + 1:]
                        bbbb = bb[:j] + bb[j + 1:]
                        terms = []
                        for k in xrange(m + 1):
                            # TODO: could rewrite prefactors as recurrence
                            term = binomial(m, k)
                            for c in aaaa:
                                term *= rising_factorial(c, k)
                            for c in bbbb:
                                term /= rising_factorial(c, k)
                            term *= z ** k
                            term /= rising_factorial(aaa - m, k)
                            F = hypergeometric([c + k for c in aaaa],
                                               [c + k for c in bbbb], z)
                            unique = []
                            counts = []
                            for c, f in F._deflated():
                                if f in unique:
                                    counts[unique.index(f)] += c
                                else:
                                    unique.append(f)
                                    counts.append(c)
                            Fterms = zip(counts, unique)
                            terms += [(term * termG, G) for (termG, G) in
                                      Fterms]
                        return terms
            return ((1, new),)
Exemplo n.º 4
0
def _sympysage_rf(self):
    """
    EXAMPLES::

        sage: from sympy import Symbol, rf
        sage: _ = var('x, y')
        sage: rfxy = rf(Symbol('x'), Symbol('y'))
        sage: assert rising_factorial(x,y)._sympy_() == rfxy.rewrite('gamma')
        sage: assert rising_factorial(x,y) == rfxy._sage_()
    """
    from sage.arith.all import rising_factorial
    return rising_factorial(self.args[0]._sage_(), self.args[1]._sage_())
Exemplo n.º 5
0
def _sympysage_rf(self):
    """
    EXAMPLES::

        sage: from sympy import Symbol, rf
        sage: _ = var('x, y')
        sage: rfxy = rf(Symbol('x'), Symbol('y'))
        sage: assert rising_factorial(x,y)._sympy_() == rfxy.rewrite('gamma')
        sage: assert rising_factorial(x,y) == rfxy._sage_()
    """
    from sage.arith.all import rising_factorial
    return rising_factorial(self.args[0]._sage_(), self.args[1]._sage_())
Exemplo n.º 6
0
    def J_inv_ZZ(self):
        r"""
        Return the rational Fourier expansion of ``J_inv``,
        where the parameter ``d`` is replaced by ``1``.

        This is the main function used to determine all Fourier expansions!

        .. NOTE::

            The Fourier expansion of ``J_inv`` for ``d!=1``
            is given by ``J_inv_ZZ(q/d)``.

        .. TODO::

          The functions that are used in this implementation are
          products of hypergeometric series with other, elementary,
          functions.  Implement them and clean up this representation.

        EXAMPLES::

            sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor
            sage: MFSeriesConstructor(prec=3).J_inv_ZZ()
            q^-1 + 31/72 + 1823/27648*q + O(q^2)
            sage: MFSeriesConstructor(group=5, prec=3).J_inv_ZZ()
            q^-1 + 79/200 + 42877/640000*q + O(q^2)
            sage: MFSeriesConstructor(group=5, prec=3).J_inv_ZZ().parent()
            Laurent Series Ring in q over Rational Field

            sage: MFSeriesConstructor(group=infinity, prec=3).J_inv_ZZ()
            q^-1 + 3/8 + 69/1024*q + O(q^2)
        """

        F1       = lambda a,b:   self._series_ring(
                       [ ZZ(0) ]
                       + [
                           rising_factorial(a,k) * rising_factorial(b,k) / (ZZ(k).factorial())**2
                           * sum(ZZ(1)/(a+j) + ZZ(1)/(b+j) - ZZ(2)/ZZ(1+j)
                                  for j in range(ZZ(0),ZZ(k))
                             )
                           for k in range(ZZ(1), ZZ(self._prec+1))
                       ],
                       ZZ(self._prec+1)
                   )

        F        = lambda a,b,c: self._series_ring(
                       [
                         rising_factorial(a,k) * rising_factorial(b,k) / rising_factorial(c,k) / ZZ(k).factorial()
                         for k in range(ZZ(0), ZZ(self._prec+1))
                       ],
                       ZZ(self._prec+1)
                   )
        a        = self._group.alpha()
        b        = self._group.beta()
        Phi      = F1(a,b) / F(a,b,ZZ(1))
        q        = self._series_ring.gen()

        # the current implementation of power series reversion is slow
        # J_inv_ZZ = ZZ(1) / ((q*Phi.exp()).reverse())

        temp_f   = (q*Phi.exp()).polynomial()
        new_f    = temp_f.revert_series(temp_f.degree()+1)
        J_inv_ZZ = ZZ(1) / (new_f + O(q**(temp_f.degree()+1)))

        return J_inv_ZZ