Beispiel #1
0
def zeta__exact(n):
    r"""
    Returns the exact value of the Riemann Zeta function

    The argument must be a critical value, namely either positive even
    or negative odd.

    See for example [Iwasawa]_, p13, Special value of `\zeta(2k)`

    EXAMPLES:

    Let us test the accuracy for negative special values::

        sage: RR = RealField(100)
        sage: for i in range(1,10):
        ...       print "zeta(" + str(1-2*i) + "): ", RR(zeta__exact(1-2*i)) - zeta(RR(1-2*i))
        zeta(-1):  0.00000000000000000000000000000
        zeta(-3):  0.00000000000000000000000000000
        zeta(-5):  0.00000000000000000000000000000
        zeta(-7):  0.00000000000000000000000000000
        zeta(-9):  0.00000000000000000000000000000
        zeta(-11):  0.00000000000000000000000000000
        zeta(-13):  0.00000000000000000000000000000
        zeta(-15):  0.00000000000000000000000000000
        zeta(-17):  0.00000000000000000000000000000

    Let us test the accuracy for positive special values::

        sage: all(abs(RR(zeta__exact(2*i))-zeta(RR(2*i))) < 10**(-28) for i in range(1,10))
        True

    TESTS::

        sage: zeta__exact(5)
        Traceback (most recent call last):
        ...
        TypeError: n must be a critical value (i.e. even > 0 or odd < 0)

    REFERENCES:

    .. [Iwasawa] Iwasawa, *Lectures on p-adic L-functions*
    .. [IreRos] Ireland and Rosen, *A Classical Introduction to Modern Number Theory*
    .. [WashCyc] Washington, *Cyclotomic Fields*
    """
    if n < 0:
        return bernoulli(1 - n) / (n - 1)
    elif n > 1:
        if (n % 2 == 0):
            return ZZ(-1)**(n / 2 + 1) * ZZ(2)**(
                n - 1) * pi**n * bernoulli(n) / factorial(n)
        else:
            raise TypeError(
                "n must be a critical value (i.e. even > 0 or odd < 0)")
    elif n == 1:
        return infinity
    elif n == 0:
        return -1 / 2
Beispiel #2
0
def zeta__exact(n):
    r"""
    Returns the exact value of the Riemann Zeta function

    The argument must be a critical value, namely either positive even
    or negative odd.

    See for example [Iwasawa]_, p13, Special value of `\zeta(2k)`

    EXAMPLES:

    Let us test the accuracy for negative special values::

        sage: RR = RealField(100)
        sage: for i in range(1,10):
        ...       print "zeta(" + str(1-2*i) + "): ", RR(zeta__exact(1-2*i)) - zeta(RR(1-2*i))
        zeta(-1):  0.00000000000000000000000000000
        zeta(-3):  0.00000000000000000000000000000
        zeta(-5):  0.00000000000000000000000000000
        zeta(-7):  0.00000000000000000000000000000
        zeta(-9):  0.00000000000000000000000000000
        zeta(-11):  0.00000000000000000000000000000
        zeta(-13):  0.00000000000000000000000000000
        zeta(-15):  0.00000000000000000000000000000
        zeta(-17):  0.00000000000000000000000000000

    Let us test the accuracy for positive special values::

        sage: all(abs(RR(zeta__exact(2*i))-zeta(RR(2*i))) < 10**(-28) for i in range(1,10))
        True

    TESTS::

        sage: zeta__exact(5)
        Traceback (most recent call last):
        ...
        TypeError: n must be a critical value (i.e. even > 0 or odd < 0)

    REFERENCES:

    .. [Iwasawa] Iwasawa, *Lectures on p-adic L-functions*
    .. [IreRos] Ireland and Rosen, *A Classical Introduction to Modern Number Theory*
    .. [WashCyc] Washington, *Cyclotomic Fields*
    """
    if n < 0:
        return bernoulli(1-n)/(n-1)
    elif n > 1:
        if (n % 2 == 0):
            return ZZ(-1)**(n/2 + 1) * ZZ(2)**(n-1) * pi**n * bernoulli(n) / factorial(n)
        else:
            raise TypeError("n must be a critical value (i.e. even > 0 or odd < 0)")
    elif n==1:
        return infinity
    elif n==0:
        return -1/2
Beispiel #3
0
def zeta__exact(n):
    r"""
    Returns the exact value of the Riemann Zeta function

    References:

    - Iwasawa's "Lectures on p-adic L-functions", p13, "Special value of `\zeta(2k)`"
    - Ireland and Rosen's "A Classical Introduction to Modern Number Theory"
    - Washington's "Cyclotomic Fields"

    EXAMPLES::

        sage: ## Testing the accuracy of the negative special values
        sage: RR = RealField(100)
        sage: for i in range(1,10):
        ...       print "zeta(" + str(1-2*i) + "): ", RR(zeta__exact(1-2*i)) - zeta(RR(1-2*i))
        zeta(-1):  0.00000000000000000000000000000
        zeta(-3):  0.00000000000000000000000000000
        zeta(-5):  0.00000000000000000000000000000
        zeta(-7):  0.00000000000000000000000000000
        zeta(-9):  0.00000000000000000000000000000
        zeta(-11):  0.00000000000000000000000000000
        zeta(-13):  0.00000000000000000000000000000
        zeta(-15):  0.00000000000000000000000000000
        zeta(-17):  0.00000000000000000000000000000

        sage: RR = RealField(100)
        sage: for i in range(1,10):
        ...       print "zeta(" + str(1-2*i) + "): ", RR(zeta__exact(1-2*i)) - zeta(RR(1-2*i))
        zeta(-1):  0.00000000000000000000000000000
        zeta(-3):  0.00000000000000000000000000000
        zeta(-5):  0.00000000000000000000000000000
        zeta(-7):  0.00000000000000000000000000000
        zeta(-9):  0.00000000000000000000000000000
        zeta(-11):  0.00000000000000000000000000000
        zeta(-13):  0.00000000000000000000000000000
        zeta(-15):  0.00000000000000000000000000000
        zeta(-17):  0.00000000000000000000000000000

    """
    if n < 0:
        k = 1 - n
        return -bernoulli(k) / k
    elif n > 1:
        if (n % 2 == 0):
            return ZZ(-1)**(n / 2 + 1) * ZZ(2)**(
                n - 1) * pi**n * bernoulli(n) / factorial(n)
        else:
            raise TypeError, "n must be a critical value! (I.e. even > 0 or odd < 0.)"
    elif n == 1:
        return infinity
    elif n == 0:
        return -1 / 2
Beispiel #4
0
def zeta__exact(n):
    r"""
    Returns the exact value of the Riemann Zeta function

    References:

    - Iwasawa's "Lectures on p-adic L-functions", p13, "Special value of `\zeta(2k)`"
    - Ireland and Rosen's "A Classical Introduction to Modern Number Theory"
    - Washington's "Cyclotomic Fields"

    EXAMPLES::

        sage: ## Testing the accuracy of the negative special values
        sage: RR = RealField(100)
        sage: for i in range(1,10):
        ...       print "zeta(" + str(1-2*i) + "): ", RR(zeta__exact(1-2*i)) - zeta(RR(1-2*i))
        zeta(-1):  0.00000000000000000000000000000
        zeta(-3):  0.00000000000000000000000000000
        zeta(-5):  0.00000000000000000000000000000
        zeta(-7):  0.00000000000000000000000000000
        zeta(-9):  0.00000000000000000000000000000
        zeta(-11):  0.00000000000000000000000000000
        zeta(-13):  0.00000000000000000000000000000
        zeta(-15):  0.00000000000000000000000000000
        zeta(-17):  0.00000000000000000000000000000

        sage: RR = RealField(100)
        sage: for i in range(1,10):
        ...       print "zeta(" + str(1-2*i) + "): ", RR(zeta__exact(1-2*i)) - zeta(RR(1-2*i))
        zeta(-1):  0.00000000000000000000000000000
        zeta(-3):  0.00000000000000000000000000000
        zeta(-5):  0.00000000000000000000000000000
        zeta(-7):  0.00000000000000000000000000000
        zeta(-9):  0.00000000000000000000000000000
        zeta(-11):  0.00000000000000000000000000000
        zeta(-13):  0.00000000000000000000000000000
        zeta(-15):  0.00000000000000000000000000000
        zeta(-17):  0.00000000000000000000000000000

    """
    if n<0:
        k = 1-n
        return -bernoulli(k)/k
    elif n>1:
        if (n % 2 == 0):
            return ZZ(-1)**(n/2 + 1) * ZZ(2)**(n-1) * pi**n * bernoulli(n) / factorial(n)
        else:
            raise TypeError, "n must be a critical value! (I.e. even > 0 or odd < 0.)"
    elif n==1:
        return infinity
    elif n==0:
        return -1/2
def gritsenko_lift_subspace(N, weight, precision):
    """
    Return a list of data, which can be used by the Fourier expansion
    generator, for the space of Gritsenko lifts.
    
    INPUT:
        - `N`           -- the level of the paramodular group 
        - ``weight``    -- the weight of the space, that we consider
        - ``precision`` -- A precision class 
        
    NOTE:
        The lifts returned have to have integral Fourier coefficients.
    """
    jf = JacobiFormsD1NN(QQ, JacobiFormD1NN_Gamma(
        N,
        weight), (4 * N**2 + precision._enveloping_discriminant_bound() - 1) //
                         (4 * N) + 1)

    return Sequence([
        gritsenko_lift_fourier_expansion(
            g if i != 0 else (bernoulli(weight) /
                              (2 * weight)).denominator() * g, precision, True)
        for (i, g) in enumerate(jf.gens())
    ],
                    universe=ParamodularFormD2FourierExpansionRing(ZZ, N),
                    immutable=True,
                    check=False)
    def gritsenko_lift(self, f, k, is_integral=False):
        """
        INPUT:
            - `f` -- the Fourier expansion of a Jacobi form as a dictionary
        """
        N = self.level()
        frN = 4 * N
        p1list = self.precision()._p1list()

        divisor_dict = self._divisor_dict()

        ##TODO: Precalculate disc_coeffs or at least use a recursive definition
        disc_coeffs = dict()
        coeffs = dict()
        f_index = lambda d, b: ((d + b**2) // frN, b)

        for (
            ((a, b, c), l), eps, disc
        ) in self.__precision._iter_positive_forms_with_content_and_discriminant(
        ):
            (_, bp, _) = apply_GL_to_form(p1list[l], (a, b, c))
            try:
                coeffs[((a, b, c), l)] = disc_coeffs[(disc, bp, eps)]
            except KeyError:
                disc_coeffs[(disc, bp, eps)] = \
                    sum(   t**(k-1) * f[ f_index(disc//t**2, (bp // t) % (2 * N)) ]
                           for t in divisor_dict[eps] )

                if disc_coeffs[(disc, bp, eps)] != 0:
                    coeffs[((a, b, c), l)] = disc_coeffs[(disc, bp, eps)]

        for ((a, b, c), l) in self.__precision.iter_indefinite_forms():
            if l == 0:
                coeffs[((a, b, c), l)] = (
                    sigma(c, k - 1) * f[(0, 0)] if c != 0 else
                    (Integer(-bernoulli(k) / Integer(2 * k) *
                             f[(0, 0)]) if is_integral else -bernoulli(k) /
                     Integer(2 * k) * f[(0, 0)]))
            else:
                coeffs[((a, b, c), l)] = (
                    sigma(c // self.level(), k - 1) * f[(0, 0)] if c != 0 else
                    (Integer(-bernoulli(k) / Integer(2 * k) *
                             f[(0, 0)]) if is_integral else -bernoulli(k) /
                     Integer(2 * k) * f[(0, 0)]))

        return coeffs
    def gritsenko_lift(self, f, k, is_integral = False) :
        """
        INPUT:
            - `f` -- the Fourier expansion of a Jacobi form as a dictionary
        """
        N = self.level()
        frN = 4 * N
        p1list = self.precision()._p1list()

        divisor_dict = self._divisor_dict()
        
        ##TODO: Precalculate disc_coeffs or at least use a recursive definition
        disc_coeffs = dict()
        coeffs = dict()
        f_index = lambda d,b : ((d + b**2)//frN, b)
        
        for (((a,b,c),l), eps, disc) in self.__precision._iter_positive_forms_with_content_and_discriminant() :
            (_,bp,_) = apply_GL_to_form(p1list[l], (a,b,c))
            try :
                coeffs[((a,b,c),l)] = disc_coeffs[(disc, bp, eps)]
            except KeyError :
                disc_coeffs[(disc, bp, eps)] = \
                    sum(   t**(k-1) * f[ f_index(disc//t**2, (bp // t) % (2 * N)) ]
                           for t in divisor_dict[eps] )
 
                if disc_coeffs[(disc, bp, eps)]  != 0 :
                    coeffs[((a,b,c),l)] = disc_coeffs[(disc, bp, eps)]

        for ((a,b,c), l) in self.__precision.iter_indefinite_forms() :
            if l == 0 :
                coeffs[((a,b,c),l)] = ( sigma(c, k-1) * f[(0,0)]
                                        if c != 0 else 
                                         ( Integer(-bernoulli(k) / Integer(2 * k) * f[(0,0)])
                                           if is_integral else
                                           -bernoulli(k) / Integer(2 * k) * f[(0,0)] ) )
            else :
                coeffs[((a,b,c),l)] = ( sigma(c//self.level(), k-1) * f[(0,0)]
                                        if c != 0 else 
                                         ( Integer(-bernoulli(k) / Integer(2 * k) * f[(0,0)])
                                           if is_integral else
                                           -bernoulli(k) / Integer(2 * k) * f[(0,0)] ) )
        
        return coeffs
def gritsenko_lift_subspace(N, weight, precision) :
    """
    Return a list of data, which can be used by the Fourier expansion
    generator, for the space of Gritsenko lifts.
    
    INPUT:
        - `N`           -- the level of the paramodular group 
        - ``weight``    -- the weight of the space, that we consider
        - ``precision`` -- A precision class 
        
    NOTE:
        The lifts returned have to have integral Fourier coefficients.
    """
    jf = JacobiFormsD1NN( QQ, JacobiFormD1NN_Gamma(N, weight),
                          (4 * N**2 + precision._enveloping_discriminant_bound() - 1)//(4 * N) + 1)

    return Sequence( [ gritsenko_lift_fourier_expansion( g if i != 0 else (bernoulli(weight) / (2 * weight)).denominator() * g,
                                                         precision, True )
                       for (i,g) in enumerate(jf.gens()) ],
                       universe = ParamodularFormD2FourierExpansionRing(ZZ, N), immutable = True,
                       check = False )
    def __maass_lifts(self, k, precision, return_value) :
        r"""
        Return the Fourier expansion of all Maass forms of weight `k`.
        """
        result = []
        
        if k < 4 or k % 2 != 0 :
            return []
                
        mf = ModularForms(1,k).echelon_basis()
        cf = ModularForms(1,k + 2).echelon_basis()[1:]
        integrality_factor = 2*k * bernoulli(k).denominator()

        for c in [(integrality_factor * mf[0],0)] \
                     + [ (f,0) for f in mf[1:] ] + [ (0,g) for g in cf ] :
            if return_value == "lifts" :
                result.append(SiegelModularFormG2MaassLift(c[0],c[1], precision, True))
            else :
                result.append(c)
        
        return result
Beispiel #10
0
    def __maass_lifts(self, k, precision, return_value):
        r"""
        Return the Fourier expansion of all Maass forms of weight `k`.
        """
        result = []

        if k < 4 or k % 2 != 0:
            return []

        mf = ModularForms(1, k).echelon_basis()
        cf = ModularForms(1, k + 2).echelon_basis()[1:]
        integrality_factor = 2 * k * bernoulli(k).denominator()

        for c in [(integrality_factor * mf[0],0)] \
                     + [ (f,0) for f in mf[1:] ] + [ (0,g) for g in cf ] :
            if return_value == "lifts":
                result.append(
                    SiegelModularFormG2MaassLift(c[0], c[1], precision, True))
            else:
                result.append(c)

        return result
Beispiel #11
0
        def coeff(m):
            m = ZZ(m)
            if m < 0:
                return ZZ(0)
            elif m == 0:
                return ZZ(1)

            factor = -2 * k / QQ(bernoulli(k)) / lamk
            sum1 = sigma(m, k - 1)
            if M.divides(m):
                sum2 = (lamk - 1) * sigma(ZZ(m / M), k - 1)
            else:
                sum2 = ZZ(0)
            if (M == 1):
                sum3 = ZZ(0)
            else:
                if (m == 1):
                    N = ZZ(1)
                else:
                    N = ZZ(m / M**ZZ(m.valuation(M)))
                sum3 = -sigma(ZZ(N), k - 1) * ZZ(m / N)**(k - 1) / (lamk + 1)

            return factor * (sum1 + sum2 + sum3) * dval**m
        def coeff(m):
            m = ZZ(m)
            if m < 0:
                return ZZ(0)
            elif m == 0:
                return ZZ(1)

            factor = -2*k / QQ(bernoulli(k)) / lamk
            sum1   = sigma(m, k-1)
            if M.divides(m):
                sum2 = (lamk-1) * sigma(ZZ(m/M), k-1)
            else:
                sum2 = ZZ(0)
            if (M == 1):
                sum3 = ZZ(0)
            else:
                if (m == 1):
                    N = ZZ(1)
                else:
                    N = ZZ(m / M**ZZ(m.valuation(M)))
                sum3 = -sigma(ZZ(N), k-1) * ZZ(m/N)**(k-1) / (lamk + 1)

            return factor * (sum1 + sum2 + sum3) * dval**m
Beispiel #13
0
    def maass_form(self, f, g, k=None, is_integral=False):
        r"""
        Return the Siegel modular form `I(f,g)` (Notation as in [Sko]).
    
        INPUT:
        - `f`              -- modular form of level `1`
        - `g`              -- cusp form of level `1` and weight = ``weight of f + 2``
        - ``is_integral``  -- ``True`` if the result is garanteed to have integer
                              coefficients
        """

        ## we introduce an abbreviations
        if is_integral:
            PS = self.integral_power_series_ring()
        else:
            PS = self.power_series_ring()

        fismodular = isinstance(f, ModularFormElement)
        gismodular = isinstance(g, ModularFormElement)

        ## We only check the arguments if f and g are ModularFormElements.
        ## Otherwise we trust in the user
        if fismodular and gismodular:
            assert( f.weight() + 2 == g.weight() | (f==0) | (g==0)), \
                    "incorrect weights!"
            assert (
                g.q_expansion(1) == 0), "second argument is not a cusp form"

        qexp_prec = self._get_maass_form_qexp_prec()
        if qexp_prec is None:  # there are no forms below prec
            return dict()

        if fismodular:
            k = f.weight()
            if f == f.parent()(0):
                f = PS(0, qexp_prec)
            else:
                f = PS(f.qexp(qexp_prec), qexp_prec)
        elif f == 0:
            f = PS(0, qexp_prec)
        else:
            f = PS(f(qexp_prec), qexp_prec)

        if gismodular:
            k = g.weight() - 2
            if g == g.parent()(0):
                g = PS(0, qexp_prec)
            else:
                g = PS(g.qexp(qexp_prec), qexp_prec)
        elif g == 0:
            g = PS(0, qexp_prec)
        else:
            g = PS(g(qexp_prec), qexp_prec)

        if k is None:
            raise ValueError, "if neither f nor g are not ModularFormElements " + \
                              "you must pass k"

        fderiv = f.derivative().shift(1)
        f *= Integer(k / 2)
        gfderiv = g - fderiv

        ## Form A and B - the Jacobi forms used in [Sko]'s I map.
        ## This is not necessary if we multiply Ifg0 and Ifg1 by etapow
        # (A0,A1,B0,B1) = (a0*etapow, a1*etapow, b0*etapow, b1*etapow)

        ## Calculate the image of the pair of modular forms (f,g) under
        ## [Sko]'s isomorphism I : M_{k} \oplus S_{k+2} -> J_{k,1}.

        # Multiplication of big polynomials may take > 60 GB, so wie have
        # to do it in small parts; This is only implemented for integral
        # coefficients.
        """
        Create the Jacobi form I(f,g) as in [Sko].
    
        It suffices to construct for all Jacobi forms phi only the part
        sum_{r=0,1;n} c_phi(r^2-4n) q^n zeta^r.
        When, in this code part, we speak of Jacobi form we only mean this part.
        
        We need to compute Ifg = \sum_{r=0,1; n} c(r^2-4n) q^n zeta^r up to
        4n-r^2 <= Dtop, i.e. n < precision
        """

        ## Create the Jacobi forms A=a*etapow and B=b*etapow in stages.
        ## Recall a = sum_{s != r mod 2} s^2*(-1)^r*q^((s^2+r^2-1)/4)*zeta^r
        ##        b = sum_{s != r mod 2}     (-1)^r*q^((s^2+r^2-1)/4)*zeta^r
        ## r, s run over ZZ but with opposite parities.
        ## For r=0, we need s odd, (s^2-1)/4 < precision, with s=2t+1 hence t^2+t < precision.
        ## For r=1, we need s even, s^2/4 < precision, with s=2t hence t^2 < precision.

        ## we use a slightly overestimated ab_prec

        ab_prec = isqrt(qexp_prec + 1)
        a1dict = dict()
        a0dict = dict()
        b1dict = dict()
        b0dict = dict()

        for t in xrange(1, ab_prec + 1):
            tmp = t**2
            a1dict[tmp] = -8 * tmp
            b1dict[tmp] = -2

            tmp += t
            a0dict[tmp] = 8 * tmp + 2
            b0dict[tmp] = 2
        b1dict[0] = -1
        a0dict[0] = 2
        b0dict[0] = 2

        a1 = PS(a1dict)
        b1 = PS(b1dict)
        a0 = PS(a0dict)
        b0 = PS(b0dict)

        ## Finally: I(f,g) is given by the formula below:
        ## We multiply by etapow explecitely and save two multiplications
        # Ifg0 = k/2*f*A0 - fderiv*B0 + g*B0 + O(q^precision)
        # Ifg1 = k/2*f*A1 - fderiv*B1 + g*B1 + O(q^precision)
        Ifg0 = (self._eta_power() * (f * a0 + gfderiv * b0)).list()
        Ifg1 = (self._eta_power() * (f * a1 + gfderiv * b1)).list()

        if len(Ifg0) < qexp_prec:
            Ifg0 += [0] * (qexp_prec - len(Ifg0))
        if len(Ifg1) < qexp_prec:
            Ifg1 += [0] * (qexp_prec - len(Ifg1))

        ## For applying the Maass' lifting to genus 2 modular forms.
        ## we put the coefficients of Ifg into a dictionary Chi
        ## so that we can access the coefficient corresponding to
        ## discriminant D by going Chi[D].

        Cphi = dict([(0, 0)])
        for i in xrange(qexp_prec):
            Cphi[-4 * i] = Ifg0[i]
            Cphi[1 - 4 * i] = Ifg1[i]

        del Ifg0[:], Ifg1[:]
        """
        Create the Maas lift F := VI(f,g) as in [Sko].
        """

        ## The constant term is given by -Cphi[0]*B_{2k}/(4*k)
        ## (note in [Sko] this coeff has typos).
        ## For nonconstant terms,
        ## The Siegel coefficient of q^n * zeta^r * qdash^m is given
        ## by the formula  \sum_{ a | gcd(n,r,m) } Cphi[D/a^2] where
        ## D = r^2-4*n*m is the discriminant.
        ## Hence in either case the coefficient
        ## is fully deterimined by the pair (D,gcd(n,r,m)).
        ## Put (D,t) -> \sum_{ a | t } Cphi[D/a^2]
        ## in a dictionary (hash table) maassc.

        maass_coeffs = dict()
        divisor_dict = self._divisor_dict()

        ## First calculate maass coefficients corresponding to strictly positive definite matrices:
        for disc in self._negative_fundamental_discriminants():
            for s in xrange(
                    1,
                    isqrt((-self.__precision.discriminant()) // disc) + 1):
                ## add (disc*s^2,t) as a hash key, for each t that divides s
                for t in divisor_dict[s]:
                    maass_coeffs[(disc * s**2,t)] = \
                       sum( a**(k-1) * Cphi[disc * s**2 / a**2]
                            for a in divisor_dict[t] )

        ## Compute the coefficients of the Siegel form $F$:
        siegel_coeffs = dict()
        for (n, r,
             m), g in self.__precision.iter_positive_forms_with_content():
            siegel_coeffs[(n, r, m)] = maass_coeffs[(r**2 - 4 * m * n, g)]

        ## Secondly, deal with the singular part.
        ## Include the coeff corresponding to (0,0,0):
        ## maass_coeffs = {(0,0): -bernoulli(k)/(2*k)*Cphi[0]}
        siegel_coeffs[(0, 0, 0)] = -bernoulli(k) / (2 * k) * Cphi[0]
        if is_integral:
            siegel_coeffs[(0, 0, 0)] = Integer(siegel_coeffs[(0, 0, 0)])

        ## Calculate the other discriminant-zero maass coefficients.
        ## Since sigma is quite cheap it is faster to estimate the bound and
        ## save the time for repeated calculation
        for i in xrange(1, self.__precision._indefinite_content_bound()):
            ## maass_coeffs[(0,i)] = sigma(i, k-1) * Cphi[0]
            siegel_coeffs[(0, 0, i)] = sigma(i, k - 1) * Cphi[0]

        return siegel_coeffs
Beispiel #14
0
def eta_char(i,p,k,j,M):
	v=[0 for j in range(0,i)]+[binomial(j,i)*bernoulli(j-i) for j in range(i,M)]
	return dist_char(p,k,j,v)
    def additive_lift(self, forms, weight, with_character = False, is_integral = False) :
        """
        Borcherds additive lift to hermitian modular forms of
        degree `2`. This coinsides with Gritsenko's arithmetic lift after
        using the theta decomposition.
        
        INPUT:
            - ``forms``          -- A list of functions accepting an integer and
                                    returning a q-expansion.
            - ``weight``         -- A positive integer; The weight of the lift.
            - ``with_character`` -- A boolean (default: ``False``); Whether the
                                    lift has nontrivial character.
            - ``is_integral``    -- A boolean (default: ``False``); If ``True``
                                    use rings of integral q-expansions over `\Z`.
        
        ALGORITHME:
            We use the explicite formulas in [D].

        TESTS::
            sage: from hermitianmodularforms.hermitianmodularformd2_fegenerators import HermitianModularFormD2AdditiveLift
            sage: HermitianModularFormD2AdditiveLift(4, [1,0,0], -3, 4).coefficients()
            {(2, 3, 2, 2): 720, (1, 1, 1, 1): 27, (1, 0, 0, 2): 270, (3, 3, 3, 3): 2943, (2, 1, 1, 3): 2592, (0, 0, 0, 2): 9, (2, 2, 2, 2): 675, (2, 3, 2, 3): 2160, (1, 1, 1, 2): 216, (3, 0, 0, 3): 8496, (2, 0, 0, 3): 2214, (1, 0, 0, 3): 720, (2, 1, 1, 2): 1080, (0, 0, 0, 1): 1, (3, 3, 2, 3): 4590, (3, 1, 1, 3): 4590, (1, 1, 1, 3): 459, (2, 0, 0, 2): 1512, (1, 0, 0, 1): 72, (0, 0, 0, 0): 1/240, (3, 4, 3, 3): 2808, (0, 0, 0, 3): 28, (3, 2, 2, 3): 4752, (2, 2, 2, 3): 1350}
            sage: HermitianModularFormD2AdditiveLift(4, [0,1,0], -3, 6).coefficients()
            {(2, 3, 2, 2): -19680, (1, 1, 1, 1): -45, (1, 0, 0, 2): -3690, (3, 3, 3, 3): -306225, (2, 1, 1, 3): -250560, (0, 0, 0, 2): 33, (2, 2, 2, 2): -13005, (2, 3, 2, 3): -153504, (1, 1, 1, 2): -1872, (3, 0, 0, 3): -1652640, (2, 0, 0, 3): -295290, (1, 0, 0, 3): -19680, (2, 1, 1, 2): -43920, (0, 0, 0, 1): 1, (3, 3, 2, 3): -948330, (3, 1, 1, 3): -1285290, (1, 1, 1, 3): -11565, (2, 0, 0, 2): -65520, (1, 0, 0, 1): -240, (0, 0, 0, 0): -1/504, (3, 4, 3, 3): -451152, (0, 0, 0, 3): 244, (3, 2, 2, 3): -839520, (2, 2, 2, 3): -108090}
        """
        if with_character and self.__D % 4 != 0 :
            raise ValueError( "Characters are only possible for even discriminants." )

        ## This will be needed if characters are implemented
        if with_character :
            if (Integer(self.__D / 4) % 4) in [-2,2] :
                alpha = (-self.__D / 4, 1/2)
            else :
                alpha = (-self.__D / 8, 1/2)
        
        #minv = 1/2 if with_character else 1
        
        R = self.power_series_ring()
        q = R.gen(0)
            
        (vv_expfactor, vv_basis) = self._additive_lift_vector_valued_basis()
        
        vvform = dict((self._reduce_vector_valued_index(k), R(0)) for (k,_) in self._semireduced_vector_valued_indices_with_discriminant_offset(1))

        for (f,b) in zip(forms, vv_basis) :
            ## We have to apply the scaling of exponents to the form
            f = R( f(self._qexp_precision()) ).add_bigoh(self._qexp_precision()) \
                 .subs({q : q**vv_expfactor})
            
            if not f.is_zero() :
                for (k,e) in b.iteritems() :
                    vvform[k] = vvform[k] + e * f
        
        ## the T = matrix(2,[*, t / 2, \bar t / 2, *] th fourier coefficients of the lift
        ## only depends on (- 4 * D * det(T), eps = gcd(T), \theta \cong t / eps)
        ## if m != 1 we consider 2*T
        maass_coeffs = dict()

        ## TODO: use divisor dictionaries
        if not with_character :
            ## The factor for the exponent of the basis of vector valued forms
            ## and the factor D in the formula for the discriminant are combined
            ## here 
            vv_expfactor = vv_expfactor // (- self.__D)
            for eps in self._iterator_content() : 
                for (theta, offset) in self._semireduced_vector_valued_indices_with_discriminant_offset(eps) :
                    for disc in self._iterator_discriminant(eps, offset) :
                        maass_coeffs[(disc, eps, theta)] = \
                             sum( a**(weight-1) *
                                  vvform[self._reduce_vector_valued_index((theta[0]//a, theta[1]//a))][vv_expfactor * disc // a**2]
                                  for a in divisors(eps))
        else :
            ## The factor for the exponent of the basis of vector valued forms
            ## and the factor D in the formula for the discriminant are combined
            ## here 
            vv_expfactor = (2 * vv_expfactor) // (- self.__D) 

            if self.__D // 4 % 2 == 0 :
                for eps in self._iterator_content() : 
                    for (theta, offset) in self._semireduced_vector_valued_indices_with_discriminant_offset(eps) :
                        for disc in self._iter_discriminant(eps, offset) :
                            maass_coeffs[(disc, eps, theta)] = \
                                 sum( a**(weight-1) * (1 if (theta[0] + theta[1] - 1) % 4 == 0 else -1) *
                                      vvform[self._reduce_vector_valued_index((theta[0]//a, theta[1]//a))][vv_expfactor * disc // a**2]
                                      for a in divisors(eps))
            else :
                for eps in self._iterator_content() : 
                    for (theta, offset) in self._semireduced_vector_valued_indices_with_discriminant_offset(eps) :
                        for disc in self._iter_discriminant(eps, offset) :
                            maass_coeffs[(disc, eps, theta)] = \
                                 sum( a**(weight-1) * (1 if (theta[1] - 1) % 4 == 0 else -1) *
                                      vvform[self._reduce_vector_valued_index((theta[0]//a, theta[1]//a))][vv_expfactor * disc // a**2]
                                      for a in divisors(eps) )
        lift_coeffs = dict()
        ## TODO: Check whether this is correct. Add the character as an argument.
        for ((a,b1,b2,c), eps, disc) in self.precision().iter_positive_forms_for_character_with_content_and_discriminant(for_character = with_character) :
            (theta1, theta2) = self._reduce_vector_valued_index((b1/eps, b2/eps))
            theta = (eps * theta1, eps * theta2)
            try:
                lift_coeffs[(a,b1,b2,c)] = maass_coeffs[(disc, eps, theta)]
            except :
                raise RuntimeError(str((a,b1,b2,c)) + " ; " + str((disc, eps, theta)))

        # Eisenstein component
        for (_,_,_,c) in self.precision().iter_semidefinite_forms_for_character(for_character = with_character) :
            if c != 0 :
                lift_coeffs[(0,0,0,c)] = vvform[(0,0)][0] * sigma(c, weight - 1)
            
        lift_coeffs[(0,0,0,0)] = - vvform[(0,0)][0] * bernoulli(weight) / Integer(2 * weight)
        if is_integral :
            lift_coeffs[(0,0,0,0)] = ZZ(lift_coeffs[(0,0,0,0)])
        
        return lift_coeffs
Beispiel #16
0
def eta(i,p,k,M):
	"""helper function in solving the difference equation -- see Lemma 4.4 of [PS]"""
	v=[0 for j in range(0,i)]+[binomial(j,i)*bernoulli(j-i) for j in range(i,M)]
	return dist(p,k,vector(v))
def siegel_product(self, u):
    """
    Computes the infinite product of local densities of the quadratic
    form for the number `u`.

    EXAMPLES::
    
        sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1])
        sage: Q.theta_series(11)
        1 + 8*q + 24*q^2 + 32*q^3 + 24*q^4 + 48*q^5 + 96*q^6 + 64*q^7 + 24*q^8 + 104*q^9 + 144*q^10 + O(q^11)

        sage: Q.siegel_product(1)
        8
        sage: Q.siegel_product(2)      ## This one is wrong -- expect 24, and the higher powers of 2 don't work... =(
        24
        sage: Q.siegel_product(3)
        32
        sage: Q.siegel_product(5)
        48
        sage: Q.siegel_product(6)
        96
        sage: Q.siegel_product(7)
        64
        sage: Q.siegel_product(9)
        104

        sage: Q.local_density(2,1)
        1
        sage: M = 4; len([v  for v in mrange([M,M,M,M])  if Q(v) % M == 1]) / M^3
        1
        sage: M = 16; len([v  for v in mrange([M,M,M,M])  if Q(v) % M == 1]) / M^3  # long time (41s on sage.math, 2011)
        1

        sage: Q.local_density(2,2)
        3/2
        sage: M = 4; len([v  for v in mrange([M,M,M,M])  if Q(v) % M == 2]) / M^3
        3/2
        sage: M = 16; len([v  for v in mrange([M,M,M,M])  if Q(v) % M == 2]) / M^3  # long time (41s on sage.math, 2011)
        3/2

    TESTS::

        sage: [1] + [Q.siegel_product(ZZ(a))  for a in range(1,11)] == Q.theta_series(11).list()
        True
    """
    ## Protect u (since it fails often if it's an just an int!)
    u = ZZ(u)

    n = self.dim()
    d = self.det()       ## ??? Warning: This is a factor of 2^n larger than it should be!

    ## DIAGNOSTIC
    verbose("n = " + str(n))
    verbose("d = " + str(d))
    verbose("In siegel_product:  d = ", d, "\n");


    ## Product of "bad" places to omit
    S = 2 * d * u

    ## DIAGNOSTIC
    verbose("siegel_product Break 1. \n")
    verbose(" u = ", u, "\n")


    ## Make the odd generic factors
    if ((n % 2) == 1):
        m = (n-1) / 2
        d1 = fundamental_discriminant(((-1)**m) * 2*d * u)     ## Replaced d by 2d here to compensate for the determinant 
        f = abs(d1)                                            ## gaining an odd power of 2 by using the matrix of 2Q instead 
                                                               ## of the matrix of Q.
                                                               ##  --> Old d1 = CoreDiscriminant((mpz_class(-1)^m) * d * u);      

        ## Make the ratio of factorials factor: [(2m)! / m!] * prod_{i=1}^m (2*i-1)
        factor1 = 1
        for i in range(1, m+1):
            factor1 *= 2*i - 1
        for i in range(m+1, 2*m + 1):
            factor1 *= i
    
        genericfactor = factor1 * ((u / f) ** m) \
            * QQ(sqrt((2 ** n) *  f) / (u * d)) \
            * abs(QuadraticBernoulliNumber(m, d1) / bernoulli(2*m))



    ## DIAGNOSTIC
    verbose("siegel_product Break 2. \n")


    ## Make the even generic factor
    if ((n % 2) == 0):
        m = n / 2
        d1 = fundamental_discriminant(((-1)**m) * d)  
        f = abs(d1)                                

        ## DIAGNOSTIC
        #cout << " mpz_class(-1)^m = " << (mpz_class(-1)^m) << " and d = " << d << endl;
        #cout << " f = " << f << " and d1 = " << d1 << endl;


        genericfactor = m / QQ(sqrt(f*d)) \
            * ((u/2) ** (m-1)) * (f ** m) \
            / abs(QuadraticBernoulliNumber(m, d1)) \
            * (2 ** m)                                               ## This last factor compensates for using the matrix of 2*Q


    ##return genericfactor
  
  
    ## Omit the generic factors in S and compute them separately
    omit = 1
    include = 1
  
    S_divisors = prime_divisors(S)

    ## DIAGNOSTIC
    #cout << "\n S is " << S << endl;
    #cout << " The Prime divisors of S are :";
    #PrintV(S_divisors);


    for p in S_divisors:    
        Q_normal = self.local_normal_form(p)
    

        ## DIAGNOSTIC
        verbose(" p = " + str(p) + " and its Kronecker symbol (d1/p) = (" + str(d1) + "/" + str(p) + ") is " + str(kronecker_symbol(d1, p)) + "\n")

        omit *= 1 / (1 - (kronecker_symbol(d1, p) / (p**m))) 


        ## DIAGNOSTIC
        verbose(" omit = " + str(omit) + "\n")
        verbose(" Q_normal is \n" + str(Q_normal) + "\n")
        verbose(" Q_normal = \n" + str(Q_normal))
        verbose(" p = " + str(p) + "\n")
        verbose(" u = " +str(u) + "\n")
        verbose(" include = " + str(include) + "\n")


        include *= Q_normal.local_density(p, u)


        ## DIAGNOSTIC
        #cout << " Including the p = " << p << " factor: " << local_density(Q_normal, p, u) << endl; 

        ## DIAGNSOTIC
        verbose("    ---  Exiting loop \n")




    #// ****************  Important *******************
    #// Additional fix (only included for n=4) to deal 
    #// with the power of 2 introduced at the real place 
    #// by working with Q instead of 2*Q.  This needs to 
    #// be done for all other n as well... 
    #/*
    #if (n==4) 
    #  genericfactor = 4 * genericfactor;
    #*/


    ## DIAGNSOTIC
    #cout << endl;
    #cout << " generic factor = " << genericfactor << endl;
    #cout << " omit = " << omit << endl;
    #cout << " include = " << include << endl;
    #cout << endl;


    ## DIAGNSOTIC
    #//  cout << "siegel_product Break 3. " << endl;


    ## Return the final factor (and divide by 2 if n=2)
    if (n == 2): 
        return (genericfactor * omit * include / 2)
    else:
        return (genericfactor * omit * include)
def siegel_product(self, u):
    """
    Computes the infinite product of local densities of the quadratic
    form for the number `u`.

    EXAMPLES::
    
        sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1])
        sage: Q.theta_series(11)
        1 + 8*q + 24*q^2 + 32*q^3 + 24*q^4 + 48*q^5 + 96*q^6 + 64*q^7 + 24*q^8 + 104*q^9 + 144*q^10 + O(q^11)

        sage: Q.siegel_product(1)
        8
        sage: Q.siegel_product(2)      ## This one is wrong -- expect 24, and the higher powers of 2 don't work... =(
        24
        sage: Q.siegel_product(3)
        32
        sage: Q.siegel_product(5)
        48
        sage: Q.siegel_product(6)
        96
        sage: Q.siegel_product(7)
        64
        sage: Q.siegel_product(9)
        104

        sage: Q.local_density(2,1)
        1
        sage: M = 4; len([v  for v in mrange([M,M,M,M])  if Q(v) % M == 1]) / M^3
        1
        sage: M = 16; len([v  for v in mrange([M,M,M,M])  if Q(v) % M == 1]) / M^3  # long time (41s on sage.math, 2011)
        1

        sage: Q.local_density(2,2)
        3/2
        sage: M = 4; len([v  for v in mrange([M,M,M,M])  if Q(v) % M == 2]) / M^3
        3/2
        sage: M = 16; len([v  for v in mrange([M,M,M,M])  if Q(v) % M == 2]) / M^3  # long time (41s on sage.math, 2011)
        3/2

    TESTS::

        sage: [1] + [Q.siegel_product(ZZ(a))  for a in range(1,11)] == Q.theta_series(11).list()
        True
    """
    ## Protect u (since it fails often if it's an just an int!)
    u = ZZ(u)

    n = self.dim()
    d = self.det(
    )  ## ??? Warning: This is a factor of 2^n larger than it should be!

    ## DIAGNOSTIC
    verbose("n = " + str(n))
    verbose("d = " + str(d))
    verbose("In siegel_product:  d = ", d, "\n")

    ## Product of "bad" places to omit
    S = 2 * d * u

    ## DIAGNOSTIC
    verbose("siegel_product Break 1. \n")
    verbose(" u = ", u, "\n")

    ## Make the odd generic factors
    if ((n % 2) == 1):
        m = (n - 1) / 2
        d1 = fundamental_discriminant(
            ((-1)**m) * 2 * d *
            u)  ## Replaced d by 2d here to compensate for the determinant
        f = abs(
            d1)  ## gaining an odd power of 2 by using the matrix of 2Q instead
        ## of the matrix of Q.
        ##  --> Old d1 = CoreDiscriminant((mpz_class(-1)^m) * d * u);

        ## Make the ratio of factorials factor: [(2m)! / m!] * prod_{i=1}^m (2*i-1)
        factor1 = 1
        for i in range(1, m + 1):
            factor1 *= 2 * i - 1
        for i in range(m + 1, 2 * m + 1):
            factor1 *= i

        genericfactor = factor1 * ((u / f) ** m) \
            * QQ(sqrt((2 ** n) *  f) / (u * d)) \
            * abs(QuadraticBernoulliNumber(m, d1) / bernoulli(2*m))

    ## DIAGNOSTIC
    verbose("siegel_product Break 2. \n")

    ## Make the even generic factor
    if ((n % 2) == 0):
        m = n / 2
        d1 = fundamental_discriminant(((-1)**m) * d)
        f = abs(d1)

        ## DIAGNOSTIC
        #cout << " mpz_class(-1)^m = " << (mpz_class(-1)^m) << " and d = " << d << endl;
        #cout << " f = " << f << " and d1 = " << d1 << endl;


        genericfactor = m / QQ(sqrt(f*d)) \
            * ((u/2) ** (m-1)) * (f ** m) \
            / abs(QuadraticBernoulliNumber(m, d1)) \
            * (2 ** m)                                               ## This last factor compensates for using the matrix of 2*Q

    ##return genericfactor

    ## Omit the generic factors in S and compute them separately
    omit = 1
    include = 1

    S_divisors = prime_divisors(S)

    ## DIAGNOSTIC
    #cout << "\n S is " << S << endl;
    #cout << " The Prime divisors of S are :";
    #PrintV(S_divisors);

    for p in S_divisors:
        Q_normal = self.local_normal_form(p)

        ## DIAGNOSTIC
        verbose(" p = " + str(p) + " and its Kronecker symbol (d1/p) = (" +
                str(d1) + "/" + str(p) + ") is " +
                str(kronecker_symbol(d1, p)) + "\n")

        omit *= 1 / (1 - (kronecker_symbol(d1, p) / (p**m)))

        ## DIAGNOSTIC
        verbose(" omit = " + str(omit) + "\n")
        verbose(" Q_normal is \n" + str(Q_normal) + "\n")
        verbose(" Q_normal = \n" + str(Q_normal))
        verbose(" p = " + str(p) + "\n")
        verbose(" u = " + str(u) + "\n")
        verbose(" include = " + str(include) + "\n")

        include *= Q_normal.local_density(p, u)

        ## DIAGNOSTIC
        #cout << " Including the p = " << p << " factor: " << local_density(Q_normal, p, u) << endl;

        ## DIAGNSOTIC
        verbose("    ---  Exiting loop \n")

    #// ****************  Important *******************
    #// Additional fix (only included for n=4) to deal
    #// with the power of 2 introduced at the real place
    #// by working with Q instead of 2*Q.  This needs to
    #// be done for all other n as well...
    #/*
    #if (n==4)
    #  genericfactor = 4 * genericfactor;
    #*/

    ## DIAGNSOTIC
    #cout << endl;
    #cout << " generic factor = " << genericfactor << endl;
    #cout << " omit = " << omit << endl;
    #cout << " include = " << include << endl;
    #cout << endl;

    ## DIAGNSOTIC
    #//  cout << "siegel_product Break 3. " << endl;

    ## Return the final factor (and divide by 2 if n=2)
    if (n == 2):
        return (genericfactor * omit * include / 2)
    else:
        return (genericfactor * omit * include)
 def solve_diff_eqn(self):
     r"""
     Solves the difference equation.
     
     See Theorem 4.5 and Lemma 4.4 of [PS].
     
     INPUT:
     
     - ``self`` - an overconvergent distribution `\mu` of absolute
         precision `M`
     
     OUTPUT:
     
     - an overconvergent distribution `\nu` of absolute precision
         `M - \lfloor\log_p(M)\rfloor - 1` such that
     
     .. math::
     
         \nu|\Delta = \mu,\text{ where }\Delta=\begin{pmatrix}1&1\\0&1
         \end{pmatrix} - 1.
     
     EXAMPLES::
     
         sage: D = OverconvergentDistributions(0,7,base=ZpCA(7,5))
         sage: D10 = D.change_precision(10)
         sage: mu10 = D10((O(7^10), 4 + 6*7 + 5*7^3 + 2*7^4 + 5*7^5 + O(7^9), 5 + 7^3 + 5*7^4 + 6*7^5 + 7^6 + 6*7^7 + O(7^8), 2 + 7 + 6*7^2 + 6*7^4 + 7^5 + 7^6 + O(7^7), 3*7 + 4*7^2 + 4*7^3 + 3*7^4 + 3*7^5 + O(7^6), 5 + 3*7 + 2*7^2 + 7^3 + 3*7^4 + O(7^5), 1 + 7^2 + 7^3 + O(7^4), 6*7 + 6*7^2 + O(7^3), 2 + 3*7 + O(7^2), 1 + O(7)))
         sage: nu10 = mu10.solve_diff_eqn()
         sage: MS = OverconvergentModularSymbols(14, coefficients=D)
         sage: MR = MS.source()
         sage: Id = MR.gens()[0]
         sage: nu10 * MR.gammas[Id] - nu10 - mu10
         7^8 * ()
         sage: D = OverconvergentDistributions(0,7,base=Qp(7,5))
         sage: D10 = D.change_precision(10)
         sage: mu10 = D10((O(7^10), 4 + 6*7 + 5*7^3 + 2*7^4 + 5*7^5 + O(7^9), 5 + 7^3 + 5*7^4 + 6*7^5 + 7^6 + 6*7^7 + O(7^8), 2 + 7 + 6*7^2 + 6*7^4 + 7^5 + 7^6 + O(7^7), 3*7 + 4*7^2 + 4*7^3 + 3*7^4 + 3*7^5 + O(7^6), 5 + 3*7 + 2*7^2 + 7^3 + 3*7^4 + O(7^5), 1 + 7^2 + 7^3 + O(7^4), 6*7 + 6*7^2 + O(7^3), 2 + 3*7 + O(7^2), 1 + O(7)))
         sage: nu10 = mu10.solve_diff_eqn()
         sage: MS = OverconvergentModularSymbols(14, coefficients=D);
         sage: MR = MS.source();
         sage: Id = MR.gens()[0]
         sage: nu10 * MR.gammas[Id] - nu10 - mu10
         7^8 * ()
         sage: R = ZpCA(5, 5); D = OverconvergentDistributions(0,base=R);
         sage: nu = D((R(O(5^5)), R(5 + 3*5^2 + 4*5^3 + O(5^4)), R(5 + O(5^3)), R(2*5 + O(5^2), 2 + O(5))));
         sage: nu.solve_diff_eqn()
         5 * (1 + 3*5 + O(5^2), O(5))
         
     Check input of relative precision 2::
     
         sage: from sage.modular.pollack_stevens.coeffmod_OMS_element import CoeffMod_OMS_element
         sage: R = ZpCA(3, 9)
         sage: D = OverconvergentDistributions(0, base=R, prec_cap=4)
         sage: V = D.approx_module(2)
         sage: nu = CoeffMod_OMS_element(V([R(0, 9), R(2*3^2 + 2*3^4 + 2*3^7 + 3^8 + O(3^9))]), D, ordp=0, check=False)
         sage: mu = nu.solve_diff_eqn()
         sage: mu
         3 * ()
     """
     #RH: see tests.sage for randomized verification that this function works correctly
     p = self.parent().prime()
     abs_prec = ZZ(self.precision_absolute())
     if self.is_zero():
         mu = self.parent()(0)
         mu.ordp = abs_prec - abs_prec.exact_log(p) - 1
         return mu
     if self._unscaled_moment(0) != 0:
         raise ValueError("Distribution must have total measure 0 to be in image of difference operator.")
     M = ZZ(len(self._moments))
     ## RP: This should never happen -- the distribution must be 0 at this point if M==1
     if M == 1:
         return self.parent()(0)
     if M == 2:
         if p == 2:
             raise ValueError("Not enough accuracy to return anything")
         else:
             out_prec = abs_prec - abs_prec.exact_log(p) - 1
             if self.ordp >= out_prec:
                 mu = self.parent()(0)
                 mu.ordp = out_prec
                 return mu
             mu = self.parent()(self._unscaled_moment(1))
             mu.ordp = self.ordp
             return mu
     R = self.parent().base_ring()
     K = R.fraction_field()
     bern = [bernoulli(i) for i in range(0,M-1,2)]
     minhalf = ~K(-2)    #bernoulli(1)
     # bernoulli(1) = -1/2; the only nonzero odd bernoulli number
     v = [minhalf * self.moment(m) for m in range(M-1)] #(m choose m-1) * B_1 * mu[m]/m            
     for m in range(1,M):
         scalar = K(self.moment(m)) * (~K(m))
         for j in range(m-1,M-1,2):
             v[j] += binomial(j,m-1) * bern[(j-m+1)//2] * scalar
     ordp = min(a.valuation() for a in v)
     #Is this correct in ramified extensions of QQp?
     verbose("abs_prec: %s, ordp: %s"%(abs_prec, ordp), level=2)
     if ordp != 0:
         new_M = abs_prec - 1 - (abs_prec).exact_log(p) - ordp
         verbose("new_M: %s"%(new_M), level=2)
         V = self.parent().approx_module(new_M)
         v = V([R(v[i] >> ordp) for i in range(new_M)])
     else:
         new_M = abs_prec - abs_prec.exact_log(p) - 1
         verbose("new_M: %s"%(new_M), level=2)
         V = self.parent().approx_module(new_M)
         v = V([R(v[i]) for i in range(new_M)])
     v[new_M-1] = v[new_M-1].add_bigoh(1)  #To force normalize to deal with this properly. May not be necessary any more.
     mu = CoeffMod_OMS_element(v, self.parent(), ordp=ordp, check=False)
     verbose("mu.ordp: %s, mu._moments: %s"%(mu.ordp, mu._moments), level=2)
     return mu.normalize()
    def maass_form( self, f, g, k = None, is_integral = False) :
        r"""
        Return the Siegel modular form `I(f,g)` (Notation as in [Sko]).
    
        INPUT:
        - `f`              -- modular form of level `1`
        - `g`              -- cusp form of level `1` and weight = ``weight of f + 2``
        - ``is_integral``  -- ``True`` if the result is garanteed to have integer
                              coefficients
        """
        
        ## we introduce an abbreviations
        if is_integral :
            PS = self.integral_power_series_ring()
        else :
            PS = self.power_series_ring()
        
        fismodular = isinstance(f, ModularFormElement)
        gismodular = isinstance(g, ModularFormElement)
    
        ## We only check the arguments if f and g are ModularFormElements.
        ## Otherwise we trust in the user 
        if fismodular and gismodular :
            assert( f.weight() + 2 == g.weight() | (f==0) | (g==0)), \
                    "incorrect weights!"
            assert( g.q_expansion(1) == 0), "second argument is not a cusp form"

        qexp_prec = self._get_maass_form_qexp_prec()
        if qexp_prec is None : # there are no forms below prec
            return dict()

        if fismodular :
            k = f.weight()
            if f == f.parent()(0) :
                f = PS(0, qexp_prec)
            else :
                f = PS(f.qexp(qexp_prec), qexp_prec)
        elif f == 0 :
            f = PS(0, qexp_prec)
        else :
            f = PS(f(qexp_prec), qexp_prec)
        
        if gismodular :
            k = g.weight() - 2
            if g == g.parent()(0) :
                g = PS(0, qexp_prec)
            else :
                g = PS(g.qexp(qexp_prec), qexp_prec)
        elif g == 0 :
            g = PS(0, qexp_prec)
        else :
            g = PS(g(qexp_prec), qexp_prec)
                
        if k is None :
            raise ValueError, "if neither f nor g are not ModularFormElements " + \
                              "you must pass k"
            
        fderiv = f.derivative().shift(1)
        f *= Integer(k/2)
        gfderiv = g - fderiv

        ## Form A and B - the Jacobi forms used in [Sko]'s I map.
        ## This is not necessary if we multiply Ifg0 and Ifg1 by etapow
        # (A0,A1,B0,B1) = (a0*etapow, a1*etapow, b0*etapow, b1*etapow)
    
        ## Calculate the image of the pair of modular forms (f,g) under
        ## [Sko]'s isomorphism I : M_{k} \oplus S_{k+2} -> J_{k,1}.
        
        # Multiplication of big polynomials may take > 60 GB, so wie have
        # to do it in small parts; This is only implemented for integral
        # coefficients.

        """
        Create the Jacobi form I(f,g) as in [Sko].
    
        It suffices to construct for all Jacobi forms phi only the part
        sum_{r=0,1;n} c_phi(r^2-4n) q^n zeta^r.
        When, in this code part, we speak of Jacobi form we only mean this part.
        
        We need to compute Ifg = \sum_{r=0,1; n} c(r^2-4n) q^n zeta^r up to
        4n-r^2 <= Dtop, i.e. n < precision
        """

        ## Create the Jacobi forms A=a*etapow and B=b*etapow in stages.
        ## Recall a = sum_{s != r mod 2} s^2*(-1)^r*q^((s^2+r^2-1)/4)*zeta^r
        ##        b = sum_{s != r mod 2}     (-1)^r*q^((s^2+r^2-1)/4)*zeta^r
        ## r, s run over ZZ but with opposite parities.
        ## For r=0, we need s odd, (s^2-1)/4 < precision, with s=2t+1 hence t^2+t < precision.
        ## For r=1, we need s even, s^2/4 < precision, with s=2t hence t^2 < precision.
    
        ## we use a slightly overestimated ab_prec 
        
        ab_prec = isqrt(qexp_prec + 1)
        a1dict = dict(); a0dict = dict()
        b1dict = dict(); b0dict = dict()
    
        for t in xrange(1, ab_prec + 1) :
            tmp = t**2
            a1dict[tmp] = -8*tmp
            b1dict[tmp] = -2
        
            tmp += t
            a0dict[tmp] = 8*tmp + 2
            b0dict[tmp] = 2
        b1dict[0] = -1
        a0dict[0] = 2; b0dict[0] = 2 
        
        a1 = PS(a1dict); b1 = PS(b1dict)
        a0 = PS(a0dict); b0 = PS(b0dict)

        ## Finally: I(f,g) is given by the formula below:
        ## We multiply by etapow explecitely and save two multiplications
        # Ifg0 = k/2*f*A0 - fderiv*B0 + g*B0 + O(q^precision)
        # Ifg1 = k/2*f*A1 - fderiv*B1 + g*B1 + O(q^precision)
        Ifg0 = (self._eta_power() * (f*a0 + gfderiv*b0)).list()
        Ifg1 = (self._eta_power() * (f*a1 + gfderiv*b1)).list()

        if len(Ifg0) < qexp_prec :
            Ifg0 += [0]*(qexp_prec - len(Ifg0))
        if len(Ifg1) < qexp_prec :
            Ifg1 += [0]*(qexp_prec - len(Ifg1))
        
        ## For applying the Maass' lifting to genus 2 modular forms.
        ## we put the coefficients of Ifg into a dictionary Chi
        ## so that we can access the coefficient corresponding to 
        ## discriminant D by going Chi[D].
        
        Cphi = dict([(0,0)])
        for i in xrange(qexp_prec) :
            Cphi[-4*i] = Ifg0[i]
            Cphi[1-4*i] = Ifg1[i]

        del Ifg0[:], Ifg1[:]

        """
        Create the Maas lift F := VI(f,g) as in [Sko].
        """
        
        ## The constant term is given by -Cphi[0]*B_{2k}/(4*k)
        ## (note in [Sko] this coeff has typos).
        ## For nonconstant terms,
        ## The Siegel coefficient of q^n * zeta^r * qdash^m is given 
        ## by the formula  \sum_{ a | gcd(n,r,m) } Cphi[D/a^2] where 
        ## D = r^2-4*n*m is the discriminant.  
        ## Hence in either case the coefficient 
        ## is fully deterimined by the pair (D,gcd(n,r,m)).
        ## Put (D,t) -> \sum_{ a | t } Cphi[D/a^2]
        ## in a dictionary (hash table) maassc.

        maass_coeffs = dict()
        divisor_dict = self._divisor_dict()

        ## First calculate maass coefficients corresponding to strictly positive definite matrices:        
        for disc in self._negative_fundamental_discriminants() :
            for s in xrange(1, isqrt((-self.__precision.discriminant()) // disc) + 1) :
                ## add (disc*s^2,t) as a hash key, for each t that divides s
                for t in divisor_dict[s] :
                    maass_coeffs[(disc * s**2,t)] = \
                       sum( a**(k-1) * Cphi[disc * s**2 / a**2] 
                            for a in divisor_dict[t] )

        ## Compute the coefficients of the Siegel form $F$:
        siegel_coeffs = dict()
        for (n,r,m), g in self.__precision.iter_positive_forms_with_content() :
            siegel_coeffs[(n,r,m)] = maass_coeffs[(r**2 - 4*m*n, g)]

        ## Secondly, deal with the singular part.
        ## Include the coeff corresponding to (0,0,0):
        ## maass_coeffs = {(0,0): -bernoulli(k)/(2*k)*Cphi[0]}
        siegel_coeffs[(0,0,0)] = -bernoulli(k)/(2*k)*Cphi[0]
        if is_integral :
            siegel_coeffs[(0,0,0)] = Integer(siegel_coeffs[(0,0,0)])
        
        ## Calculate the other discriminant-zero maass coefficients.
        ## Since sigma is quite cheap it is faster to estimate the bound and
        ## save the time for repeated calculation
        for i in xrange(1, self.__precision._indefinite_content_bound()) :
            ## maass_coeffs[(0,i)] = sigma(i, k-1) * Cphi[0]
            siegel_coeffs[(0,0,i)] = sigma(i, k-1) * Cphi[0]

        return siegel_coeffs
    def additive_lift(self,
                      forms,
                      weight,
                      with_character=False,
                      is_integral=False):
        """
        Borcherds additive lift to hermitian modular forms of
        degree `2`. This coinsides with Gritsenko's arithmetic lift after
        using the theta decomposition.
        
        INPUT:
            - ``forms``          -- A list of functions accepting an integer and
                                    returning a q-expansion.
            - ``weight``         -- A positive integer; The weight of the lift.
            - ``with_character`` -- A boolean (default: ``False``); Whether the
                                    lift has nontrivial character.
            - ``is_integral``    -- A boolean (default: ``False``); If ``True``
                                    use rings of integral q-expansions over `\Z`.
        
        ALGORITHME:
            We use the explicite formulas in [D].

        TESTS::
            sage: from hermitianmodularforms.hermitianmodularformd2_fegenerators import HermitianModularFormD2AdditiveLift
            sage: HermitianModularFormD2AdditiveLift(4, [1,0,0], -3, 4).coefficients()
            {(2, 3, 2, 2): 720, (1, 1, 1, 1): 27, (1, 0, 0, 2): 270, (3, 3, 3, 3): 2943, (2, 1, 1, 3): 2592, (0, 0, 0, 2): 9, (2, 2, 2, 2): 675, (2, 3, 2, 3): 2160, (1, 1, 1, 2): 216, (3, 0, 0, 3): 8496, (2, 0, 0, 3): 2214, (1, 0, 0, 3): 720, (2, 1, 1, 2): 1080, (0, 0, 0, 1): 1, (3, 3, 2, 3): 4590, (3, 1, 1, 3): 4590, (1, 1, 1, 3): 459, (2, 0, 0, 2): 1512, (1, 0, 0, 1): 72, (0, 0, 0, 0): 1/240, (3, 4, 3, 3): 2808, (0, 0, 0, 3): 28, (3, 2, 2, 3): 4752, (2, 2, 2, 3): 1350}
            sage: HermitianModularFormD2AdditiveLift(4, [0,1,0], -3, 6).coefficients()
            {(2, 3, 2, 2): -19680, (1, 1, 1, 1): -45, (1, 0, 0, 2): -3690, (3, 3, 3, 3): -306225, (2, 1, 1, 3): -250560, (0, 0, 0, 2): 33, (2, 2, 2, 2): -13005, (2, 3, 2, 3): -153504, (1, 1, 1, 2): -1872, (3, 0, 0, 3): -1652640, (2, 0, 0, 3): -295290, (1, 0, 0, 3): -19680, (2, 1, 1, 2): -43920, (0, 0, 0, 1): 1, (3, 3, 2, 3): -948330, (3, 1, 1, 3): -1285290, (1, 1, 1, 3): -11565, (2, 0, 0, 2): -65520, (1, 0, 0, 1): -240, (0, 0, 0, 0): -1/504, (3, 4, 3, 3): -451152, (0, 0, 0, 3): 244, (3, 2, 2, 3): -839520, (2, 2, 2, 3): -108090}
        """
        if with_character and self.__D % 4 != 0:
            raise ValueError(
                "Characters are only possible for even discriminants.")

        ## This will be needed if characters are implemented
        if with_character:
            if (Integer(self.__D / 4) % 4) in [-2, 2]:
                alpha = (-self.__D / 4, 1 / 2)
            else:
                alpha = (-self.__D / 8, 1 / 2)

        #minv = 1/2 if with_character else 1

        R = self.power_series_ring()
        q = R.gen(0)

        (vv_expfactor, vv_basis) = self._additive_lift_vector_valued_basis()

        vvform = dict(
            (self._reduce_vector_valued_index(k), R(0)) for (k, _) in self.
            _semireduced_vector_valued_indices_with_discriminant_offset(1))

        for (f, b) in zip(forms, vv_basis):
            ## We have to apply the scaling of exponents to the form
            f = R( f(self._qexp_precision()) ).add_bigoh(self._qexp_precision()) \
                 .subs({q : q**vv_expfactor})

            if not f.is_zero():
                for (k, e) in b.iteritems():
                    vvform[k] = vvform[k] + e * f

        ## the T = matrix(2,[*, t / 2, \bar t / 2, *] th fourier coefficients of the lift
        ## only depends on (- 4 * D * det(T), eps = gcd(T), \theta \cong t / eps)
        ## if m != 1 we consider 2*T
        maass_coeffs = dict()

        ## TODO: use divisor dictionaries
        if not with_character:
            ## The factor for the exponent of the basis of vector valued forms
            ## and the factor D in the formula for the discriminant are combined
            ## here
            vv_expfactor = vv_expfactor // (-self.__D)
            for eps in self._iterator_content():
                for (
                        theta, offset
                ) in self._semireduced_vector_valued_indices_with_discriminant_offset(
                        eps):
                    for disc in self._iterator_discriminant(eps, offset):
                        maass_coeffs[(disc, eps, theta)] = \
                             sum( a**(weight-1) *
                                  vvform[self._reduce_vector_valued_index((theta[0]//a, theta[1]//a))][vv_expfactor * disc // a**2]
                                  for a in divisors(eps))
        else:
            ## The factor for the exponent of the basis of vector valued forms
            ## and the factor D in the formula for the discriminant are combined
            ## here
            vv_expfactor = (2 * vv_expfactor) // (-self.__D)

            if self.__D // 4 % 2 == 0:
                for eps in self._iterator_content():
                    for (
                            theta, offset
                    ) in self._semireduced_vector_valued_indices_with_discriminant_offset(
                            eps):
                        for disc in self._iter_discriminant(eps, offset):
                            maass_coeffs[(disc, eps, theta)] = \
                                 sum( a**(weight-1) * (1 if (theta[0] + theta[1] - 1) % 4 == 0 else -1) *
                                      vvform[self._reduce_vector_valued_index((theta[0]//a, theta[1]//a))][vv_expfactor * disc // a**2]
                                      for a in divisors(eps))
            else:
                for eps in self._iterator_content():
                    for (
                            theta, offset
                    ) in self._semireduced_vector_valued_indices_with_discriminant_offset(
                            eps):
                        for disc in self._iter_discriminant(eps, offset):
                            maass_coeffs[(disc, eps, theta)] = \
                                 sum( a**(weight-1) * (1 if (theta[1] - 1) % 4 == 0 else -1) *
                                      vvform[self._reduce_vector_valued_index((theta[0]//a, theta[1]//a))][vv_expfactor * disc // a**2]
                                      for a in divisors(eps) )
        lift_coeffs = dict()
        ## TODO: Check whether this is correct. Add the character as an argument.
        for ((a, b1, b2, c), eps, disc) in self.precision(
        ).iter_positive_forms_for_character_with_content_and_discriminant(
                for_character=with_character):
            (theta1, theta2) = self._reduce_vector_valued_index(
                (b1 / eps, b2 / eps))
            theta = (eps * theta1, eps * theta2)
            try:
                lift_coeffs[(a, b1, b2, c)] = maass_coeffs[(disc, eps, theta)]
            except:
                raise RuntimeError(
                    str((a, b1, b2, c)) + " ; " + str((disc, eps, theta)))

        # Eisenstein component
        for (_, _, _,
             c) in self.precision().iter_semidefinite_forms_for_character(
                 for_character=with_character):
            if c != 0:
                lift_coeffs[(0, 0, 0,
                             c)] = vvform[(0, 0)][0] * sigma(c, weight - 1)

        lift_coeffs[(
            0, 0, 0,
            0)] = -vvform[(0, 0)][0] * bernoulli(weight) / Integer(2 * weight)
        if is_integral:
            lift_coeffs[(0, 0, 0, 0)] = ZZ(lift_coeffs[(0, 0, 0, 0)])

        return lift_coeffs