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
Example #2
0
def _sz_s( k, m, l, n):
    r"""
    OUTPUT
        The function  $s_{k,m}(l,n)$, i.e.~the trace
        of $T(l) \circ W_n$ on the "certain" space
        $\mathcal{M}_{2k-2}^{\text{cusp}}(m)$ of modular forms
        as defined in [S-Z].

    INPUT
        l -- index of the Hecke operator, rel. prime to the level $m$
        n -- index of the Atkin-Lehner involution (exact divisor of $m$)
        k -- integer ($2k-2$ is the weight)
        m -- level
    """
    k = Integer(k)
    m = Integer(m)
    l = Integer(l)
    n = Integer(n)
    if k < 2:
        return 0
    if 1 != m.gcd(l):
        raise ValueError, \
              "gcd(%s,%s) != 1: not yet implemented" % (m,l)

    ellT = 0
    for np in n.divisors():
        ellT -= sum( l**(k-2) \
                     * _gegenbauer_pol( k-2, s*s*np/l) \
                     * hurwitz_kronecker_class_no_x( m/n, s*s*np*np - 4*l*np) \
                     for s in range( -(Integer(4*l*np).isqrt()//np), \
                                     1+(Integer(4*l*np).isqrt()//np)) \
                     if (n//np).gcd(s*s).is_squarefree())/2

    parT = -sum( min( lp, l//lp)**(2*k-3) \
                 * _ab(n)[0].gcd( lp+l//lp) \
                 * _ab(m/n)[0].gcd( lp-l//lp) \
                 for lp in l.divisors())/2
    
    if 2 == k and (m//n).is_square():
        corT = sigma(n,0)*sigma(l,1)
    else:
        corT = 0
        
    return Integer( ellT + parT + corT)
    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 _cWP(self, d, r):
     #\wp(z) & = \frac{1}{12} + \frac{p}{(1-p)^2} + \sum_{k,r \geq 1} k (p^k - 2 + p^{-k}) q^{kr}
     if d < 0: return 0
     if d == 0:
         if r < 0: return 0
         elif r == 0: return QQ(1/12)
         else: return r
     if d > 0:
         if r == 0: return -2*sigma(d,1)
         elif d % r == 0:
           return abs(r)
         else:
           return 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
Example #6
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
Example #7
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
    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
    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