Example #1
0
class TestMultiplier(MultiplierSystem):
    r"""
    Test of multiplier for f(q). As in e.g. the paper of Bringmann and Ono.
    """
    def __init__(self,group,dchar=(0,0),dual=False,weight=QQ(1)/QQ(2),dimension=1,version=1,**kwargs):
        self._weight=QQ(weight)
        MultiplierSystem.__init__(self,group,dchar=dchar,dual=dual,dimension=dimension,**kwargs)
        self._k_den=self._weight.denominator()
        self._k_num=self._weight.numerator()
        self._K = CyclotomicField(12*self._k_den)
        self._z = self._K.gen()**self._k_num
        self._sqrti = CyclotomicField(8).gen()
        self._i = CyclotomicField(4).gen()
        self._fak = CyclotomicField(2*self._k_den).gen()**-self._k_num
        self._fak_arg=QQ(self._weight)/QQ(2)
        self._version = version
        self.is_consistent(weight) # test consistency


    def order(self):
        return 12*self._k_den

    def z(self):
        return self._z

    def __repr__(self):
        s="Test multiplier"
        if self._character<>None and not self._character.is_trivial():
            s+="and character "+str(self._character)
        return s


        
    def _action(self,A):
        [a,b,c,d]=A
        fak=0
        if c<0:
            a=-a; b=-b; c=-c;  d=-d; fak=self._fak_arg
        if c==0:
            if a>0:
                res = self._z**-b
            else:
                res = self._fak*self._z**-b
        else:
            arg=-QQ(1)/QQ(8)+QQ(c+a*d+1)/QQ(4)-QQ(a+d)/QQ(24*c)-QQ(a)/QQ(4)+QQ(3*d*c)/QQ(8)
            # print "arg=",arg
            arg = arg-dedekind_sum(-d,c)/QQ(2)+fak #self._fak_arg
            den=arg.denominator()
            num=arg.numerator()
            # print "den=",den
            # print  "num=",num
            res = self._K(CyclotomicField(den).gen())**num
            #res = res*fak
        if self._is_dual:
            return res**-1
        return res
Example #2
0
 def _latex_using_dpd_depth1(self, dpd_dct):
     names = [dpd_dct[c] for c in self._consts]
     _gcd = QQ(gcd(self._coeffs))
     coeffs = [c / _gcd for c in self._coeffs]
     coeffs_names = [(c, n) for c, n in zip(coeffs, names) if c != 0]
     tail_terms = ["%s %s %s" % ("+" if c > 0 else "", c, n) for c, n in coeffs_names[1:]]
     c0, n0 = coeffs_names[0]
     head_term = str(c0) + " " + str(n0)
     return r"\frac{{{pol_num}}}{{{pol_dnm}}} \left({terms}\right)".format(
         pol_dnm=latex(_gcd.denominator() * self._scalar_const._polynomial_expr()),
         pol_num=latex(_gcd.numerator()),
         terms=" ".join([head_term] + tail_terms),
     )
Example #3
0
def get_cusp_expansions_of_newform(k, N=1, fi=0, prec=10):
    r"""
    Get and return Fourier coefficients of all cusps where there exist Atkin-Lehner involutions for these cusps.

    INPUT:

     - ''k'' -- positive integer : the weight
     - ''N'' -- positive integer (default 1) : level
     - ''fi'' -- non-neg. integer (default 0) We want to use the element nr. fi f=Newforms(N,k)[fi]
     - ''prec'' -- integer (the number of coefficients to get)

     OUTPUT:

     - ''s'' string giving the Atkin-Lehner eigenvalues corresponding to the Cusps (where possible)
    """
    res = dict()
    (t, f) = _get_newform(k, N, 0, fi)
    if(not t):
        return s
    res[Infinity] = 1
    for c in f.group().cusps():
        if(c == Cusp(Infinity)):
            continue
        res[c] = list()
        cusp = QQ(c)
        q = cusp.denominator()
        p = cusp.numerator()
        d = ZZ(cusp * N)
        if(d == 0):
            ep = f.atkin_lehner_eigenvalue()
        if(d.divides(N) and gcd(ZZ(N / d), ZZ(d)) == 1):
            ep = f.atkin_lehner_eigenvalue(ZZ(d))
        else:
            # this case is not known...
            res[c] = None
            continue
        res[c] = ep
    s = html.table([res.keys(), res.values()])
    return s
Example #4
0
def make_abt_label(A,B,t):
    AB_str = ab_label(A,B)
    t = QQ(t)
    t_str = "_t%s.%s" % (t.numerator(), t.denominator())
    return AB_str + t_str
Example #5
0
def set_info_for_web_newform(level=None,
                             weight=None,
                             character=None,
                             label=None,
                             **kwds):
    r"""
    Set the info for on modular form.

    """
    info = to_dict(kwds)
    info['level'] = level
    info['weight'] = weight
    info['character'] = character
    info['label'] = label
    if level is None or weight is None or character is None or label is None:
        s = "In set info for one form but do not have enough args!"
        s += "level={0},weight={1},character={2},label={3}".format(
            level, weight, character, label)
        emf_logger.critical(s)
    emf_logger.debug("In set_info_for_one_mf: info={0}".format(info))
    prec = my_get(info, 'prec', default_prec, int)
    bprec = my_get(info, 'bprec', default_display_bprec, int)
    emf_logger.debug("PREC: {0}".format(prec))
    emf_logger.debug("BITPREC: {0}".format(bprec))
    try:
        WNF = WebNewForm_cached(level=level,
                                weight=weight,
                                character=character,
                                label=label)
        if not WNF.has_updated():
            raise IndexError(
                "Unfortunately, we do not have this newform in the database.")
        info['character_order'] = WNF.character.order
        info['code'] = WNF.code
        emf_logger.debug("defined webnewform for rendering!")
    except IndexError as e:
        info['error'] = e.message
    url1 = url_for("emf.render_elliptic_modular_forms")
    url2 = url_for("emf.render_elliptic_modular_forms", level=level)
    url3 = url_for("emf.render_elliptic_modular_forms",
                   level=level,
                   weight=weight)
    url4 = url_for("emf.render_elliptic_modular_forms",
                   level=level,
                   weight=weight,
                   character=character)
    bread = [(EMF_TOP, url1)]
    bread.append(("Level %s" % level, url2))
    bread.append(("Weight %s" % weight, url3))
    bread.append(("Character \( %s \)" % (WNF.character.latex_name), url4))
    bread.append(
        ("Newform %d.%d.%d.%s" % (level, weight, int(character), label), ''))
    info['bread'] = bread

    properties2 = list()
    friends = list()
    space_url = url_for('emf.render_elliptic_modular_forms',
                        level=level,
                        weight=weight,
                        character=character)
    friends.append(
        ('\( S_{%s}(%s, %s)\)' %
         (WNF.weight, WNF.level, WNF.character.latex_name), space_url))
    if hasattr(WNF.base_ring, "lmfdb_url") and WNF.base_ring.lmfdb_url:
        friends.append(('Number field ' + WNF.base_ring.lmfdb_pretty,
                        WNF.base_ring.lmfdb_url))
    if hasattr(WNF.coefficient_field,
               "lmfdb_url") and WNF.coefficient_field.lmfdb_label:
        friends.append(('Number field ' + WNF.coefficient_field.lmfdb_pretty,
                        WNF.coefficient_field.lmfdb_url))
    friends = uniq(friends)
    friends.append(("Dirichlet character \(" + WNF.character.latex_name + "\)",
                    WNF.character.url()))

    if WNF.dimension == 0 and not info.has_key('error'):
        info['error'] = "This space is empty!"
    info['title'] = 'Newform ' + WNF.hecke_orbit_label
    info['learnmore'] = [('History of Modular forms',
                          url_for('holomorphic_mf_history'))]
    if 'error' in info:
        return info
    ## Until we have figured out how to do the embeddings correctly we don't display the Satake
    ## parameters for non-trivial characters....

    ## Example to illustrate the different cases
    ## base              = CyclotomicField(n) -- of degree phi(n)
    ## coefficient_field = NumberField( p(x)) for some p in base['x'] of degree m
    ##   we would then have cdeg = m*phi(n) and bdeg = phi(n)
    ##   and rdeg = m
    ## Unfortunately, for e.g. base = coefficient_field = CyclotomicField(6)
    ## we get coefficient_field.relative_degree() == 2 although it should be 1
    cdeg = WNF.coefficient_field.absolute_degree()
    bdeg = WNF.base_ring.absolute_degree()
    if cdeg == 1:
        rdeg = 1
    else:
        ## just setting rdeg = WNF.coefficient_field.relative_degree() does not give correct result...
        ##
        rdeg = QQ(cdeg) / QQ(bdeg)
    cf_is_QQ = (cdeg == 1)
    br_is_QQ = (bdeg == 1)
    if cf_is_QQ:
        info['satake'] = WNF.satake
    if WNF.complexity_of_first_nonvanishing_coefficients(
    ) > default_max_height:
        info['qexp'] = ""
        info['qexp_display'] = ''
        info['hide_qexp'] = True
        n, c = WNF.first_nonvanishing_coefficient()
        info['trace_nv'] = latex(WNF.first_nonvanishing_coefficient_trace())
        info['norm_nv'] = '\\approx ' + latex(
            WNF.first_nonvanishing_coefficient_norm().n())
        info['index_nv'] = n
    else:
        if WNF.prec < prec:
            #get WNF record at larger prec
            WNF.prec = prec
            WNF.update_from_db()
        info['qexp'] = WNF.q_expansion_latex(prec=10, name='\\alpha ')
        info['qexp_display'] = url_for(".get_qexp_latex",
                                       level=level,
                                       weight=weight,
                                       character=character,
                                       label=label)
        info["hide_qexp"] = False
    info['max_cn_qexp'] = WNF.q_expansion.prec()
    ## All combinations should be tested...
    ## 13/4/4/a -> base ring = coefficient_field = QQ(zeta_6)
    ## 13/3/8/a ->  base_ring = QQ(zeta_4), coefficient_field has poly x^2+(2\zeta_4+2x-3\zeta_$ over base_ring
    ## 13/4/3/a ->  base_ring = coefficient_field = QQ(zeta_3)
    ## 13/4/1/a -> all rational
    ## 13/6/1/a/ -> base_ring = QQ, coefficient_field = Q(sqrt(17))
    ## These are variables which needs to be set properly below
    info['polvars'] = {'base_ring': 'x', 'coefficient_field': '\\alpha'}
    if not cf_is_QQ:
        if rdeg > 1:  # not WNF.coefficient_field == WNF.base_ring:
            ## Here WNF.base_ring should be some cyclotomic field and we have an extension over this.
            p1 = WNF.coefficient_field.relative_polynomial()
            c_pol_ltx = web_latex_poly(p1,
                                       '\\alpha')  # make the variable \alpha
            c_pol_ltx_x = web_latex_poly(p1, 'x')
            zeta = p1.base_ring().gens()[0]
            #           p2 = zeta.minpoly() #this is not used anymore
            #           b_pol_ltx = web_latex_poly(p2, latex(zeta)) #this is not used anymore
            z1 = zeta.multiplicative_order()
            info['coeff_field'] = [
                WNF.coefficient_field.absolute_polynomial_latex('x'),
                c_pol_ltx_x, z1
            ]
            if hasattr(WNF.coefficient_field,
                       "lmfdb_url") and WNF.coefficient_field.lmfdb_url:
                info['coeff_field_pretty'] = [
                    WNF.coefficient_field.lmfdb_url,
                    WNF.coefficient_field.lmfdb_pretty,
                    WNF.coefficient_field.lmfdb_label
                ]
            if z1 == 4:
                info[
                    'polynomial_st'] = '<div class="where">where</div> {0}\(\mathstrut=0\) and \(\zeta_4=i\).</div><br/>'.format(
                        c_pol_ltx)
                info['polvars']['base_ring'] = 'i'
            elif z1 <= 2:
                info[
                    'polynomial_st'] = '<div class="where">where</div> {0}\(\mathstrut=0\).</div><br/>'.format(
                        c_pol_ltx)
            else:
                info[
                    'polynomial_st'] = '<div class="where">where</div> %s\(\mathstrut=0\) and \(\zeta_{%s}=e^{\\frac{2\\pi i}{%s}}\) ' % (
                        c_pol_ltx, z1, z1)
                info['polvars']['base_ring'] = '\zeta_{{ {0} }}'.format(z1)
                if z1 == 3:
                    info[
                        'polynomial_st'] += 'is a primitive cube root of unity.'
                else:
                    info[
                        'polynomial_st'] += 'is a primitive {0}-th root of unity.'.format(
                            z1)
        elif not br_is_QQ:
            ## Now we have base and coefficient field being equal, meaning that since the coefficient field is not QQ it is some cyclotomic field
            ## generated by some \zeta_n
            p1 = WNF.coefficient_field.absolute_polynomial()
            z1 = WNF.coefficient_field.gens()[0].multiplicative_order()
            c_pol_ltx = web_latex_poly(p1, '\\zeta_{{{0}}}'.format(z1))
            c_pol_ltx_x = web_latex_poly(p1, 'x')
            info['coeff_field'] = [
                WNF.coefficient_field.absolute_polynomial_latex('x'),
                c_pol_ltx_x
            ]
            if hasattr(WNF.coefficient_field,
                       "lmfdb_url") and WNF.coefficient_field.lmfdb_url:
                info['coeff_field_pretty'] = [
                    WNF.coefficient_field.lmfdb_url,
                    WNF.coefficient_field.lmfdb_pretty,
                    WNF.coefficient_field.lmfdb_label
                ]
            if z1 == 4:
                info[
                    'polynomial_st'] = '<div class="where">where \(\zeta_4=e^{{\\frac{{\\pi i}}{{ 2 }} }}=i \).</div>'.format(
                        c_pol_ltx)
                info['polvars']['coefficient_field'] = 'i'
            elif z1 <= 2:
                info['polynomial_st'] = ''
            else:
                info[
                    'polynomial_st'] = '<div class="where">where \(\zeta_{{{0}}}=e^{{\\frac{{2\\pi i}}{{ {0} }} }}\) '.format(
                        z1)
                info['polvars']['coefficient_field'] = '\zeta_{{{0}}}'.format(
                    z1)
                if z1 == 3:
                    info[
                        'polynomial_st'] += 'is a primitive cube root of unity.</div>'
                else:
                    info[
                        'polynomial_st'] += 'is a primitive {0}-th root of unity.</div>'.format(
                            z1)
    else:
        info['polynomial_st'] = ''
    if info["hide_qexp"]:
        info['polynomial_st'] = ''
    info['degree'] = int(cdeg)
    if cdeg == 1:
        info['is_rational'] = 1
        info['coeff_field_pretty'] = [
            WNF.coefficient_field.lmfdb_url, WNF.coefficient_field.lmfdb_pretty
        ]
    else:
        info['is_rational'] = 0
    emf_logger.debug("PREC2: {0}".format(prec))
    info['embeddings'] = WNF._embeddings[
        'values']  #q_expansion_embeddings(prec, bprec,format='latex')
    info['embeddings_len'] = len(info['embeddings'])
    properties2 = [('Level', str(level)), ('Weight', str(weight)),
                   ('Character', '$' + WNF.character.latex_name + '$'),
                   ('Label', WNF.hecke_orbit_label),
                   ('Dimension of Galois orbit', str(WNF.dimension))]
    if (ZZ(level)).is_squarefree():
        info['twist_info'] = WNF.twist_info
        if isinstance(info['twist_info'],
                      list) and len(info['twist_info']) > 0:
            info['is_minimal'] = info['twist_info'][0]
            if (info['twist_info'][0]):
                s = 'Is minimal<br>'
            else:
                s = 'Is a twist of lower level<br>'
            properties2 += [('Twist info', s)]
    else:
        info['twist_info'] = 'Twist info currently not available.'
        properties2 += [('Twist info', 'not available')]
    args = list()
    for x in range(5, 200, 10):
        args.append({'digits': x})
    alev = None
    CM = WNF._cm_values
    if CM is not None:
        if CM.has_key('tau') and len(CM['tau']) != 0:
            info['CM_values'] = CM
    info['is_cm'] = WNF.is_cm
    if WNF.is_cm == 1:
        info['cm_field'] = "2.0.{0}.1".format(-WNF.cm_disc)
        info['cm_disc'] = WNF.cm_disc
        info['cm_field_knowl'] = nf_display_knowl(
            info['cm_field'], getDBConnection(),
            field_pretty(info['cm_field']))
        info['cm_field_url'] = url_for("number_fields.by_label",
                                       label=info["cm_field"])
    if WNF.is_cm is None or WNF.is_cm == -1:
        s = '- Unknown (insufficient data)<br>'
    elif WNF.is_cm == 1:
        s = 'Yes<br>'
    else:
        s = 'No<br>'
    properties2.append(('CM', s))
    alev = WNF.atkin_lehner_eigenvalues()
    info['atkinlehner'] = None
    if isinstance(alev, dict) and len(alev.keys()) > 0 and level != 1:
        s1 = " Atkin-Lehner eigenvalues "
        s2 = ""
        for Q in alev.keys():
            s2 += "\( \omega_{ %s } \) : %s <br>" % (Q, alev[Q])
        properties2.append((s1, s2))
        emf_logger.debug("properties={0}".format(properties2))
        # alev = WNF.atkin_lehner_eigenvalues_for_all_cusps()
        # if isinstance(alev,dict) and len(alev.keys())>0:
        #     emf_logger.debug("alev={0}".format(alev))
        #     info['atkinlehner'] = list()
        #     for Q in alev.keys():
        #         s = "\(" + latex(c) + "\)"
        #         Q = alev[c][0]
        #         ev = alev[c][1]
        #         info['atkinlehner'].append([Q, c, ev])
    if (level == 1):
        poly = WNF.explicit_formulas.get('as_polynomial_in_E4_and_E6', '')
        if poly != '':
            d, monom, coeffs = poly
            emf_logger.critical("poly={0}".format(poly))
            info['explicit_formulas'] = '\('
            for i in range(len(coeffs)):
                c = QQ(coeffs[i])
                s = ""
                if d > 1 and i > 0 and c > 0:
                    s = "+"
                if c < 0:
                    s = "-"
                if c.denominator() > 1:
                    cc = "\\frac{{ {0} }}{{ {1} }}".format(
                        abs(c.numerator()), c.denominator())
                else:
                    cc = str(abs(c))
                s += "{0} \cdot ".format(cc)
                a = monom[i][0]
                b = monom[i][1]
                if a == 0 and b != 0:
                    s += "E_6^{{ {0} }}".format(b)
                elif b == 0 and a != 0:
                    s += "E_4^{{ {0} }}".format(a)
                else:
                    s += "E_4^{{ {0} }}E_6^{{ {1} }}".format(a, b)
                info['explicit_formulas'] += s
            info['explicit_formulas'] += " \)"
    cur_url = '?&level=' + str(level) + '&weight=' + str(weight) + '&character=' + str(character) + \
        '&label=' + str(label)
    if len(WNF.parent.hecke_orbits) > 1:
        for label_other in WNF.parent.hecke_orbits.keys():
            if (label_other != label):
                s = 'Modular form '
                if character:
                    s += newform_label(level, weight, character, label_other)
                else:
                    s += newform_label(level, weight, 1, label_other)

                url = url_for('emf.render_elliptic_modular_forms',
                              level=level,
                              weight=weight,
                              character=character,
                              label=label_other)
                friends.append((s, url))

    s = 'L-Function '
    if character:
        s += newform_label(level, weight, character, label)
    else:
        s += newform_label(level, weight, 1, label)
    # url =
    # "/L/ModularForm/GL2/Q/holomorphic?level=%s&weight=%s&character=%s&label=%s&number=%s"
    # %(level,weight,character,label,0)
    url = '/L' + url_for('emf.render_elliptic_modular_forms',
                         level=level,
                         weight=weight,
                         character=character,
                         label=label)
    if WNF.coefficient_field_degree > 1:
        for h in range(WNF.coefficient_field_degree):
            s0 = s + ".{0}".format(h)
            url0 = url + "{0}/".format(h)
            friends.append((s0, url0))
    else:
        friends.append((s, url))
    # if there is an elliptic curve over Q associated to self we also list that
    if WNF.weight == 2 and WNF.coefficient_field_degree == 1:
        llabel = str(level) + '.' + label
        s = 'Elliptic curve isogeny class ' + llabel
        url = '/EllipticCurve/Q/' + llabel
        friends.append((s, url))
    info['properties2'] = properties2
    info['friends'] = friends
    info['max_cn'] = WNF.max_available_prec()
    return info
Example #6
0
def make_t_label(t):
    tsage = QQ(t)
    return "t%s.%s" % (tsage.numerator(), tsage.denominator())
Example #7
0
def make_abt_label(A, B, t):
    AB_str = ab_label(A, B)
    t = QQ(t)
    t_str = "_t%s.%s" % (t.numerator(), t.denominator())
    return AB_str + t_str
class EtaQuotientMultiplier_2(MultiplierSystem):
    r"""
    Eta multiplier given by eta(Az)^{r}/eta(Bz)^s
    The weight should be r/2-s/2 mod 2.
    The group is Gamma0(lcm(A,B))
    """
    def __init__(self,A,B,r,s,k=None,number=0,ch=None,dual=False,version=1,**kwargs):
        r"""
        Initialize the Eta multiplier system: $\nu_{\eta}^{2(k+r)}$.
        INPUT:

        - G -- Group
        - ch -- character
        - dual -- if we have the dual (in this case conjugate)
        - weight -- Weight (recall that eta has weight 1/2 and eta**2k has weight k. If weight<>k we adjust the power accordingly.
        - number -- we consider eta^power (here power should be an integer so as not to change the weight...)

        EXAMPLE:
        
                
        """
        self._level=lcm(A,B)
        G = Gamma0(self._level)
        if k==None:
            k = (QQ(r)-QQ(s))/QQ(2)
        self._weight=QQ(k)
        if floor(self._weight-QQ(1)/QQ(2))==ceil(self._weight-QQ(1)/QQ(2)):
            self._half_integral_weight=1
        else:
            self._half_integral_weight=0
        MultiplierSystem.__init__(self,G,dimension=1,character=ch,dual=dual)
        number = number % 12
        if not is_even(number):
            raise ValueError,"Need to have v_eta^(2(k+r)) with r even!"
        self._arg_num = A
        self._arg_den = B
        self._exp_num = r
        self._exp_den = s
        self._pow=QQ((self._weight+number)) ## k+r
        self._k_den=self._pow.denominator()
        self._k_num=self._pow.numerator()
        self._K = CyclotomicField(12*self._k_den)
        self._z = self._K.gen()**self._k_num
        self._i = CyclotomicField(4).gen()
        self._fak = CyclotomicField(2*self._k_den).gen()**-self._k_num
        self._version = version
        self.is_consistent(k) # test consistency

    def __repr__(self):
        s="Quotient of Eta multipliers :  "
        s+="eta({0})^{1}/eta({2})^{3}".format(self._arg_num,self._exp_num,self._arg_den,self._exp_den)
        if self._character<>None and not self._character.is_trivial():
            s+=" and character "+str(self._character)
        s+=" with weight="+str(self._weight)
        return s

    def level(self):
        return self._level
        
    def order(self):
        return 12*self._k_den

    def z(self):
        return self._z

    def q_shift(self):
        r"""
        Gives the 'shift' at the cusp at infinity of the q-series.
        The 'true' q-expansion of the eta quotient is then q^shift*q_expansion
        """
        num =  self._arg_num*self._exp_num-self._arg_den*self._exp_den
        return QQ(num)/QQ(24)
    
    def q_expansion(self,n=20):
        r"""
        Give the q-expansion of the quotient.
        """
        var('q')
        et = qexp_eta(ZZ[['q']],n)
        etA= et.subs(q=q**self._arg_num).power_series(ZZ[['q']])
        etB= et.subs(q=q**self._arg_den).power_series(ZZ[['q']])
        res = etA**(self._exp_num)/etB**(self._exp_den)
        return res
    #def _action(self,A):
    #    return self._action(A)
        
    def _action(self,A):
        [a,b,c,d]=A
        if not c % self._level == 0 :
            raise ValueError,"Need A in {0}! Got: {1}".format(self.group,A)
        fak=1
        if c<0:
            a=-a; b=-b; c=-c;  d=-d; fak=-self._fak
            #fak = fak*(-1)**(self._exp_num-self._exp_den)
        arg1,v1 = eta_conjugated(a,b,c,d,self._arg_num)
        arg2,v2 = eta_conjugated(a,b,c,d,self._arg_den)
        res=self._z**(arg1*self._exp_num-arg2*self._exp_den)
        if v1<>1:
            res=res*v1**self._exp_num
        if v2<>1:
            res=res/v2**self._exp_den
        if fak<>1:
            res=res*fak**(self._exp_num-self._exp_den)
        return res
Example #9
0
class EtaMultiplier(MultiplierSystem):
    r"""
    Eta multiplier. Valid for any (real) weight.
    """
    def __init__(self,G,k=QQ(1)/QQ(2),number=0,ch=None,dual=False,version=1,dimension=1,**kwargs):
        r"""
        Initialize the Eta multiplier system: $\nu_{\eta}^{2(k+r)}$.
        INPUT:

        - G -- Group
        - ch -- character
        - dual -- if we have the dual (in this case conjugate)
        - weight -- Weight (recall that eta has weight 1/2 and eta**2k has weight k. If weight<>k we adjust the power accordingly.
        - number -- we consider eta^power (here power should be an integer so as not to change the weight...)
                
        """
        self._weight=QQ(k)
        if floor(self._weight-QQ(1)/QQ(2))==ceil(self._weight-QQ(1)/QQ(2)):
            self._half_integral_weight=1
        else:
            self._half_integral_weight=0
        MultiplierSystem.__init__(self,G,character=ch,dual=dual,dimension=dimension)
        number = number % 12
        if not is_even(number):
            raise ValueError,"Need to have v_eta^(2(k+r)) with r even!"
        self._pow=QQ((self._weight+number)) ## k+r
        self._k_den=self._pow.denominator()
        self._k_num=self._pow.numerator()
        self._K = CyclotomicField(12*self._k_den)
        self._z = self._K.gen()**self._k_num
        self._i = CyclotomicField(4).gen()
        self._fak = CyclotomicField(2*self._k_den).gen()**-self._k_num
        self._version = version
        
        self.is_consistent(k) # test consistency

    def __repr__(self):
        s="Eta multiplier "
        if self._pow<>1:
            s+="to power 2*"+str(self._pow)+" "
        if self._character<>None and not self._character.is_trivial():
            s+=" and character "+str(self._character)
        s+="with weight="+str(self._weight)
        return s
        
    def order(self):
        return 12*self._k_den

    def z(self):
        return self._z
    
     
    def _action(self,A):
        if self._version==1:
            return self._action1(A)
        elif self._version==2:
            return self._action2(A)
        else:
            raise ValueError

    def _action1(self,A):
        [a,b,c,d]=A
        return self._action0(a,b,c,d)
    def _action0(self,a,b,c,d):
        r"""
        Recall that the formula is valid only for c>0. Otherwise we have to use:
        v(A)=v((-I)(-A))=sigma(-I,-A)v(-I)v(-A).
        Then note that by the formula for sigma we have:
        sigma(-I,SL2Z[a, b, c, d])=-1 if (c=0 and d<0) or c>0 and other wise it is =1.
        """

        fak=1
        if c<0:
            a=-a; b=-b; c=-c;  d=-d; fak=-self._fak
        if c==0:
            if a>0:
                res = self._z**b
            else:
                res = self._fak*self._z**b
        else:
            if is_even(c):
                arg = (a+d)*c-b*d*(c*c-1)+3*d-3-3*c*d
                v=kronecker(c,d)
            else:
                arg = (a+d)*c-b*d*(c*c-1)-3*c
                v=kronecker(d,c)
            if not self._half_integral_weight:
                # recall that we can use eta for any real weight
                v=v**(2*self._weight)
            arg=arg*(self._k_num)
            res = v*fak*self._z**arg
            if self._character:
                res = res * self._character(d)
        if self._is_dual:
            res=res**-1
        return res


    def _action2(self,A):
        [a,b,c,d]=A
        fak=1
        if c<0:
            a=-a; b=-b; c=-c;  d=-d; fak=-self._fak
        if c==0:
            if a>0:
                res = self._z**b
            else:
                res = self._fak*self._z**b
        else:
            arg = dedekind_sum(-d,c)
            arg = arg+QQ(a+d)/QQ(12*c)-QQ(1)/QQ(4)
            # print "arg=",arg
            arg=arg*QQ(2)
            den = arg.denominator()*self._k_den
            num = arg.numerator()*self._k_num
            K = CyclotomicField(2*den)
            z=K.gen()
            if z.multiplicative_order()>4:
                fak=K(fak)
                # z = CyclotomicField(2*arg.denominator()).gen()
            res = z**num #rg.numerator()
            if self._character:
                ch = self._character(d)
                res=res*ch
            res = res*fak
        if self._is_dual:
            return res**-1
        return res
Example #10
0
def display_t(tn, td):
    t = QQ("%d/%d" % (tn, td))
    if t.denominator() == 1:
        return str(t.numerator())
    return "%s/%s" % (str(t.numerator()), str(t.denominator()))
Example #11
0
def make_t_label(t):
    tsage = QQ("%d/%d" % (t[0], t[1]))
    return "t%s.%s" % (tsage.numerator(), tsage.denominator())
Example #12
0
def hgm_search(**args):
    info = to_dict(args)
    bread = get_bread([("Search results", url_for('.search'))])
    C = base.getDBConnection()
    query = {}
    if 'jump_to' in info:
        return render_hgm_webpage({'label': info['jump_to']})

    family_search = False
    if info.get('Submit Family') or info.get('family'):
        family_search = True

    # generic, irreducible not in DB yet
    for param in [
            'A', 'B', 'hodge', 'a2', 'b2', 'a3', 'b3', 'a5', 'b5', 'a7', 'b7'
    ]:
        if info.get(param):
            info[param] = clean_input(info[param])
            if IF_RE.match(info[param]):
                query[param] = parse_list(info[param])
                query[param].sort()
            else:
                name = param
                if field == 'hodge':
                    name = 'Hodge vector'
                info[
                    'err'] = 'Error parsing input for %s.  It needs to be a list of integers in square brackets, such as [2,3] or [1,1,1]' % name
                return search_input_error(info, bread)

    if info.get('t') and not family_search:
        info['t'] = clean_input(info['t'])
        try:
            tsage = QQ(str(info['t']))
            tlist = [int(tsage.numerator()), int(tsage.denominator())]
            query['t'] = tlist
        except:
            info[
                'err'] = 'Error parsing input for t.  It needs to be a rational number, such as 2/3 or -3'

    # sign can only be 1, -1, +1
    if info.get('sign') and not family_search:
        sign = info['sign']
        sign = re.sub(r'\s', '', sign)
        sign = clean_input(sign)
        if sign == '+1':
            sign = '1'
        if not (sign == '1' or sign == '-1'):
            info[
                'err'] = 'Error parsing input %s for sign.  It needs to be 1 or -1' % sign
            return search_input_error(info, bread)
        query['sign'] = int(sign)

    for param in ['degree', 'weight', 'conductor']:
        # We don't look at conductor in family searches
        if info.get(param) and not (param == 'conductor' and family_search):
            if param == 'conductor':
                cond = info['conductor']
                try:
                    cond = re.sub(r'(\d)\s+(\d)', r'\1 * \2',
                                  cond)  # implicit multiplication of numbers
                    cond = cond.replace(r'..', r'-')  # all ranges use -
                    cond = re.sub(r'[a..zA..Z]', '', cond)
                    cond = clean_input(cond)
                    tmp = parse_range2(cond, 'cond', myZZ)
                except:
                    info[
                        'err'] = 'Error parsing input for conductor.  It needs to be an integer (e.g., 8), a range of integers (e.g. 10-100), or a list of such (e.g., 5,7,8,10-100).  Integers may be given in factored form (e.g. 2^5 3^2) %s' % cond
                    return search_input_error(info, bread)
            else:  # not conductor
                info[param] = clean_input(info[param])
                ran = info[param]
                ran = ran.replace(r'..', r'-')
                if LIST_RE.match(ran):
                    tmp = parse_range2(ran, param)
                else:
                    names = {'weight': 'weight', 'degree': 'degree'}
                    info[
                        'err'] = 'Error parsing input for the %s.  It needs to be an integer (such as 5), a range of integers (such as 2-10 or 2..10), or a comma-separated list of these (such as 2,3,8 or 3-5, 7, 8-11).' % names[
                            param]
                    return search_input_error(info, bread)
            # work around syntax for $or
            # we have to foil out multiple or conditions
            if tmp[0] == '$or' and '$or' in query:
                newors = []
                for y in tmp[1]:
                    oldors = [dict.copy(x) for x in query['$or']]
                    for x in oldors:
                        x.update(y)
                    newors.extend(oldors)
                tmp[1] = newors
            query[tmp[0]] = tmp[1]

    #print query
    count_default = 20
    if info.get('count'):
        try:
            count = int(info['count'])
        except:
            count = count_default
    else:
        count = count_default
    info['count'] = count

    start_default = 0
    if info.get('start'):
        try:
            start = int(info['start'])
            if (start < 0):
                start += (1 - (start + 1) / count) * count
        except:
            start = start_default
    else:
        start = start_default
    if info.get('paging'):
        try:
            paging = int(info['paging'])
            if paging == 0:
                start = 0
        except:
            pass

    # logger.debug(query)
    if family_search:
        res = C.hgm.families.find(query).sort([('label', pymongo.ASCENDING)])
    else:
        res = C.hgm.motives.find(query).sort([('cond', pymongo.ASCENDING),
                                              ('label', pymongo.ASCENDING)])
    nres = res.count()
    res = res.skip(start).limit(count)

    if (start >= nres):
        start -= (1 + (start - nres) / count) * count
    if (start < 0):
        start = 0

    info['motives'] = res
    info['number'] = nres
    info['start'] = start
    if nres == 1:
        info['report'] = 'unique match'
    else:
        if nres > count or start != 0:
            info['report'] = 'displaying matches %s-%s of %s' % (
                start + 1, min(nres, start + count), nres)
        else:
            info['report'] = 'displaying all %s matches' % nres
    info['make_label'] = make_abt_label
    info['make_t_label'] = make_t_label
    info['ab_label'] = ab_label
    info['display_t'] = display_t
    info['family'] = family_search
    info['factorint'] = factorint

    if family_search:
        return render_template(
            "hgm-search.html",
            info=info,
            title="Hypergeometric Family over $\Q$ Search Result",
            bread=bread,
            credit=HGM_credit)
    else:
        return render_template(
            "hgm-search.html",
            info=info,
            title="Hypergeometric Motive over $\Q$ Search Result",
            bread=bread,
            credit=HGM_credit)
Example #13
0
def fix_t(t):
    tsage = QQ("%d/%d" % (t[0], t[1]))
    return [int(tsage.numerator()), int(tsage.denominator())]
Example #14
0
def make_t_label(t):
    tsage = QQ("%d/%d" % (t[0], t[1]))
    return "t%s.%s" % (tsage.numerator(), tsage.denominator())
Example #15
0
def hgm_search(**args):
    info = to_dict(args)
    bread = get_bread([("Search results", url_for('.search'))])
    C = base.getDBConnection()
    query = {}
    if 'jump_to' in info:
        return render_hgm_webpage({'label': info['jump_to']})

    family_search = False
    if info.get('Submit Family') or info.get('family'):
        family_search = True

    # generic, irreducible not in DB yet
    for param in ['A', 'B', 'hodge', 'a2', 'b2', 'a3', 'b3', 'a5', 'b5', 'a7', 'b7']:
        if info.get(param):
            info[param] = clean_input(info[param])
            if IF_RE.match(info[param]):
                query[param] = split_list(info[param])
                query[param].sort()
            else:
                name = param
                if field == 'hodge':
                    name = 'Hodge vector'
                info['err'] = 'Error parsing input for %s.  It needs to be a list of integers in square brackets, such as [2,3] or [1,1,1]' % name
                return search_input_error(info, bread)

    if info.get('t') and not family_search:
        info['t'] = clean_input(info['t'])
        try:
            tsage = QQ(str(info['t']))
            tlist = [int(tsage.numerator()), int(tsage.denominator())]
            query['t'] = tlist
        except:
            info['err'] = 'Error parsing input for t.  It needs to be a rational number, such as 2/3 or -3'

    # sign can only be 1, -1, +1
    if info.get('sign') and not family_search:
        sign = info['sign']
        sign = re.sub(r'\s','',sign)
        sign = clean_input(sign)
        if sign == '+1':
            sign = '1'
        if not (sign == '1' or sign == '-1'):
            info['err'] = 'Error parsing input %s for sign.  It needs to be 1 or -1' % sign
            return search_input_error(info, bread)
        query['sign'] = int(sign)


    for param in ['degree','weight','conductor']:
        # We don't look at conductor in family searches
        if info.get(param) and not (param=='conductor' and family_search):
            if param=='conductor':
                cond = info['conductor']
                try:
                    cond = re.sub(r'(\d)\s+(\d)', r'\1 * \2', cond) # implicit multiplication of numbers
                    cond = cond.replace(r'..', r'-') # all ranges use -
                    cond = re.sub(r'[a..zA..Z]', '', cond)
                    cond = clean_input(cond)
                    tmp = parse_range2(cond, 'cond', myZZ)
                except:
                    info['err'] = 'Error parsing input for conductor.  It needs to be an integer (e.g., 8), a range of integers (e.g. 10-100), or a list of such (e.g., 5,7,8,10-100).  Integers may be given in factored form (e.g. 2^5 3^2) %s' % cond
                    return search_input_error(info, bread)
            else: # not conductor
                info[param] = clean_input(info[param])
                ran = info[param]
                ran = ran.replace(r'..', r'-')
                if LIST_RE.match(ran):
                    tmp = parse_range2(ran, param)
                else:
                    names = {'weight': 'weight', 'degree': 'degree'}
                    info['err'] = 'Error parsing input for the %s.  It needs to be an integer (such as 5), a range of integers (such as 2-10 or 2..10), or a comma-separated list of these (such as 2,3,8 or 3-5, 7, 8-11).' % names[param]
                    return search_input_error(info, bread)
            # work around syntax for $or
            # we have to foil out multiple or conditions
            if tmp[0] == '$or' and '$or' in query:
                newors = []
                for y in tmp[1]:
                    oldors = [dict.copy(x) for x in query['$or']]
                    for x in oldors:
                        x.update(y)
                    newors.extend(oldors)
                tmp[1] = newors
            query[tmp[0]] = tmp[1]

    #print query
    count_default = 20
    if info.get('count'):
        try:
            count = int(info['count'])
        except:
            count = count_default
    else:
        count = count_default
    info['count'] = count

    start_default = 0
    if info.get('start'):
        try:
            start = int(info['start'])
            if(start < 0):
                start += (1 - (start + 1) / count) * count
        except:
            start = start_default
    else:
        start = start_default
    if info.get('paging'):
        try:
            paging = int(info['paging'])
            if paging == 0:
                start = 0
        except:
            pass

    # logger.debug(query)
    if family_search:
        res = C.hgm.families.find(query).sort([('label', pymongo.ASCENDING)])
    else:
        res = C.hgm.motives.find(query).sort([('cond', pymongo.ASCENDING), ('label', pymongo.ASCENDING)])
    nres = res.count()
    res = res.skip(start).limit(count)

    if(start >= nres):
        start -= (1 + (start - nres) / count) * count
    if(start < 0):
        start = 0

    info['motives'] = res
    info['number'] = nres
    info['start'] = start
    if nres == 1:
        info['report'] = 'unique match'
    else:
        if nres > count or start != 0:
            info['report'] = 'displaying matches %s-%s of %s' % (start + 1, min(nres, start + count), nres)
        else:
            info['report'] = 'displaying all %s matches' % nres
    info['make_label'] = make_abt_label
    info['make_t_label'] = make_t_label
    info['ab_label'] = ab_label
    info['display_t'] = display_t
    info['family'] = family_search
    info['factorint'] = factorint

    if family_search:
        return render_template("hgm-search.html", info=info, title="Hypergeometric Family over $\Q$ Search Result", bread=bread, credit=HGM_credit)
    else:
        return render_template("hgm-search.html", info=info, title="Hypergeometric Motive over $\Q$ Search Result", bread=bread, credit=HGM_credit)
class EtaQuotientMultiplier(MultiplierSystem):
    r"""
    Eta multiplier given by eta(Az)^{r}/eta(Bz)^s
    The weight should be r/2-s/2 mod 2.
    The group is Gamma0(lcm(A,B))
    """
    def __init__(self,args=[1],exponents=[1],ch=None,dual=False,version=1,**kwargs):
        r"""
        Initialize the Eta multiplier system: $\nu_{\eta}^{2(k+r)}$.
        INPUT:

        - G -- Group
        - ch -- character
        - dual -- if we have the dual (in this case conjugate)
        - weight -- Weight (recall that eta has weight 1/2 and eta**2k has weight k. If weight<>k we adjust the power accordingly.
        - number -- we consider eta^power (here power should be an integer so as not to change the weight...)

        EXAMPLE:
        
                
        """
        assert len(args) == len(exponents)
        self._level=lcm(args)
        G = Gamma0(self._level)
        k = sum([QQ(x)*QQ(1)/QQ(2) for x in exponents])
        self._weight=QQ(k)
        if floor(self._weight-QQ(1)/QQ(2))==ceil(self._weight-QQ(1)/QQ(2)):
            self._half_integral_weight=1
        else:
            self._half_integral_weight=0
        MultiplierSystem.__init__(self,G,dimension=1,character=ch,dual=dual)
        self._arguments = args
        self._exponents =exponents
        self._pow=QQ((self._weight)) ## k+r
        self._k_den = self._weight.denominator()
        self._k_num = self._weight.numerator()
        self._K = CyclotomicField(12*self._k_den)
        self._z = self._K.gen()**self._k_num
        self._i = CyclotomicField(4).gen()
        self._fak = CyclotomicField(2*self._k_den).gen()**-self._k_num
        self._version = version
        self.is_consistent(k) # test consistency

    def __repr__(self):
        s="Quotient of Eta multipliers :  "
        for i in range(len(self._arguments)):
            n = self._arguments[i]
            e = self._exponents[i]
            s+="eta({0}z)^{1}".format(n,e)
            if i < len(self._arguments)-1:
                s+="*"
        if self._character<>None and not self._character.is_trivial():
            s+=" and character "+str(self._character)
        s+=" with weight="+str(self._weight)
        return s

    def level(self):
        return self._level
        
    def order(self):
        return 12*self._k_den

    def z(self):
        return self._z

    def q_shift(self):
        r"""
        Gives the 'shift' at the cusp at infinity of the q-series.
        The 'true' q-expansion of the eta quotient is then q^shift*q_expansion
        """
        num =  sum([self._argument[i]*self._exponent[i] for i in range(len(self._arguments))])

        return QQ(num)/QQ(24)
    
    def q_expansion(self,n=20):
        r"""
        Give the q-expansion of the quotient.
        """
        eta = qexp_eta(ZZ[['q']],n)
        R = eta.parent()
        q = R.gens()[0]
        res = R(1)
        prefak = 0
        for i in range(len(self._arguments)):        
            res = res*eta.subs({q:q**self._arguments[i]})**self._exponents[i]
            prefak = prefak+self._arguments[i]*self._exponents[i]
        if prefak % 24 == 0:
            return res*q**(prefak/24)
        else:
            return res,prefak/24
        #etA= et.subs(q=q**self._arg_num).power_series(ZZ[['q']])
        #etB= et.subs(q=q**self._arg_den).power_series(ZZ[['q']])
        #res = etA**(self._exp_num)/etB**(self._exp_den)
        #return res
    #def _action(self,A):
    #    return self._action(A)
        
    def _action(self,A):
        [a,b,c,d]=A
        if not c % self._level == 0 :
            raise ValueError,"Need A in {0}! Got: {1}".format(self.group,A)
        fak=1
        if c<0:
            a=-a; b=-b; c=-c;  d=-d; fak=-self._fak
            #fak = fak*(-1)**(self._exp_num-self._exp_den)
        res = 1
        exp = 0
        for i in range(len(self._exponents)):
            z = CyclotomicField(lcm(12,self._exponents[i].denominator())).gen()
            arg,v = eta_conjugated(a,b,c,d,self._arguments[i])
            #arg2,v2 = eta_conjugated(a,b,c,d,self._arg_den)
            #res=self._z**(arg1*self._exp_num-arg2*self._exp_den)
#            exp += arg*self._exponents[i]
            if v<>1:
                res=res*v**self._exponents[i]
            #if v2<>1:
            #res=res/v2**self._exp_den
            res = res*z**(arg*self._exponents[i].numerator())
#        res = res*self._z**exp
        if fak<>1:
            res=res*fak**exp
        return res
class EtaMultiplier(MultiplierSystem):
    r"""
    Eta multiplier. Valid for any (real) weight.
    """
    def __init__(self,G,k=QQ(1)/QQ(2),number=0,ch=None,dual=False,version=1,dimension=1,**kwargs):
        r"""
        Initialize the Eta multiplier system: $\nu_{\eta}^{2(k+r)}$.
        INPUT:

        - G -- Group
        - ch -- character
        - dual -- if we have the dual (in this case conjugate)
        - weight -- Weight (recall that eta has weight 1/2 and eta**2k has weight k. If weight<>k we adjust the power accordingly.
        - number -- we consider eta^power (here power should be an integer so as not to change the weight...)
                
        """
        self._weight=QQ(k)
        if floor(self._weight-QQ(1)/QQ(2))==ceil(self._weight-QQ(1)/QQ(2)):
            self._half_integral_weight=1
        else:
            self._half_integral_weight=0
        MultiplierSystem.__init__(self,G,character=ch,dual=dual,dimension=dimension)
        number = number % 12
        if not is_even(number):
            raise ValueError,"Need to have v_eta^(2(k+r)) with r even!"
        self._pow=QQ((self._weight+number)) ## k+r
        self._k_den=self._pow.denominator()
        self._k_num=self._pow.numerator()
        self._K = CyclotomicField(12*self._k_den)
        self._z = self._K.gen()**self._k_num
        self._i = CyclotomicField(4).gen()
        self._fak = CyclotomicField(2*self._k_den).gen()**-self._k_num
        self._version = version
        
        self.is_consistent(k) # test consistency

    def __repr__(self):
        s="Eta multiplier "
        if self._pow<>1:
            s+="to power 2*"+str(self._pow)+" "
        if self._character<>None and not self._character.is_trivial():
            s+=" and character "+str(self._character)
        s+="with weight="+str(self._weight)
        return s
        
    def order(self):
        return 12*self._k_den

    def z(self):
        return self._z
    
     
    def _action(self,A):
        if self._version==1:
            return self._action1(A)
        elif self._version==2:
            return self._action2(A)
        else:
            raise ValueError

    def _action1(self,A):
        [a,b,c,d]=A
        return self._action0(a,b,c,d)
    def _action0(self,a,b,c,d):
        r"""
        Recall that the formula is valid only for c>0. Otherwise we have to use:
        v(A)=v((-I)(-A))=sigma(-I,-A)v(-I)v(-A).
        Then note that by the formula for sigma we have:
        sigma(-I,SL2Z[a, b, c, d])=-1 if (c=0 and d<0) or c>0 and other wise it is =1.
        """

        fak=1
        if c<0:
            a=-a; b=-b; c=-c;  d=-d; fak=-self._fak
        if c==0:
            if a>0:
                res = self._z**b
            else:
                res = self._fak*self._z**b
        else:
            if is_even(c):
                arg = (a+d)*c-b*d*(c*c-1)+3*d-3-3*c*d
                v=kronecker(c,d)
            else:
                arg = (a+d)*c-b*d*(c*c-1)-3*c
                v=kronecker(d,c)
            if not self._half_integral_weight:
                # recall that we can use eta for any real weight
                v=v**(2*self._weight)
            arg=arg*(self._k_num)
            res = v*fak*self._z**arg
            if self._character:
                res = res * self._character(d)
        if self._is_dual:
            res=res**-1
        return res


    def _action2(self,A):
        [a,b,c,d]=A
        fak=1
        if c<0:
            a=-a; b=-b; c=-c;  d=-d; fak=-self._fak
        if c==0:
            if a>0:
                res = self._z**b
            else:
                res = self._fak*self._z**b
        else:
            arg = dedekind_sum(-d,c)
            arg = arg+QQ(a+d)/QQ(12*c)-QQ(1)/QQ(4)
            # print "arg=",arg
            arg=arg*QQ(2)
            den = arg.denominator()*self._k_den
            num = arg.numerator()*self._k_num
            K = CyclotomicField(2*den)
            z=K.gen()
            if z.multiplicative_order()>4:
                fak=K(fak)
                # z = CyclotomicField(2*arg.denominator()).gen()
            res = z**num #rg.numerator()
            if self._character:
                ch = self._character(d)
                res=res*ch
            res = res*fak
        if self._is_dual:
            return res**-1
        return res
Example #18
0
def make_t_label(t):
    tsage = QQ(t)
    return "t%s.%s" % (tsage.numerator(), tsage.denominator())
Example #19
0
def make_label(A,B,tn,td):
    AB_str = ab_label(A,B)
    t = QQ( "%d/%d" % (tn, td))
    t_str = "/t%s.%s" % (str(t.numerator()), str(t.denominator()))
    return AB_str + t_str
Example #20
0
def display_t(tn, td):
    t = QQ("%d/%d" % (tn, td))
    if t.denominator() == 1:
        return str(t.numerator())
    return "%s/%s" % (t.numerator(), t.denominator())
Example #21
0
class EtaQuotientMultiplier(MultiplierSystem):
    r"""
    Eta multiplier given by eta(Az)^{r}/eta(Bz)^s
    The weight should be r/2-s/2 mod 2.
    The group is Gamma0(lcm(A,B))
    """
    def __init__(self,A,B,r,s,k=None,number=0,ch=None,dual=False,version=1,**kwargs):
        r"""
        Initialize the Eta multiplier system: $\nu_{\eta}^{2(k+r)}$.
        INPUT:

        - G -- Group
        - ch -- character
        - dual -- if we have the dual (in this case conjugate)
        - weight -- Weight (recall that eta has weight 1/2 and eta**2k has weight k. If weight<>k we adjust the power accordingly.
        - number -- we consider eta^power (here power should be an integer so as not to change the weight...)

        EXAMPLE:
        
                
        """
        self._level=lcm(A,B)
        G = Gamma0(self._level)
        if k==None:
            k = (QQ(r)-QQ(s))/QQ(2)
        self._weight=QQ(k)
        if floor(self._weight-QQ(1)/QQ(2))==ceil(self._weight-QQ(1)/QQ(2)):
            self._half_integral_weight=1
        else:
            self._half_integral_weight=0
        MultiplierSystem.__init__(self,G,dimension=1,character=ch,dual=dual)
        number = number % 12
        if not is_even(number):
            raise ValueError,"Need to have v_eta^(2(k+r)) with r even!"
        self._arg_num = A
        self._arg_den = B
        self._exp_num = r
        self._exp_den = s
        self._pow=QQ((self._weight+number)) ## k+r
        self._k_den=self._pow.denominator()
        self._k_num=self._pow.numerator()
        self._K = CyclotomicField(12*self._k_den)
        self._z = self._K.gen()**self._k_num
        self._i = CyclotomicField(4).gen()
        self._fak = CyclotomicField(2*self._k_den).gen()**-self._k_num
        self._version = version
        self.is_consistent(k) # test consistency

    def __repr__(self):
        s="Quotient of Eta multipliers :  "
        s+="eta({0})^{1}/eta({2})^{3}".format(self._arg_num,self._exp_num,self._arg_den,self._exp_den)
        if self._character<>None and not self._character.is_trivial():
            s+=" and character "+str(self._character)
        s+=" with weight="+str(self._weight)
        return s

    def level(self):
        return self._level
        
    def order(self):
        return 12*self._k_den

    def z(self):
        return self._z

    def q_shift(self):
        r"""
        Gives the 'shift' at the cusp at infinity of the q-series.
        The 'true' q-expansion of the eta quotient is then q^shift*q_expansion
        """
        num =  self._arg_num*self._exp_num-self._arg_den*self._exp_den
        return QQ(num)/QQ(24)
    
    def q_expansion(self,n=20):
        r"""
        Give the q-expansion of the quotient.
        """
        var('q')
        et = qexp_eta(ZZ[['q']],n)
        etA= et.subs(q=q**self._arg_num).power_series(ZZ[['q']])
        etB= et.subs(q=q**self._arg_den).power_series(ZZ[['q']])
        res = etA**(self._exp_num)/etB**(self._exp_den)
        return res
    #def _action(self,A):
    #    return self._action(A)
        
    def _action(self,A):
        [a,b,c,d]=A
        if not c % self._level == 0 :
            raise ValueError,"Need A in {0}! Got: {1}".format(self.group,A)
        fak=1
        if c<0:
            a=-a; b=-b; c=-c;  d=-d; fak=-self._fak
            #fak = fak*(-1)**(self._exp_num-self._exp_den)
        arg1,v1 = eta_conjugated(a,b,c,d,self._arg_num)
        arg2,v2 = eta_conjugated(a,b,c,d,self._arg_den)
        res=self._z**(arg1*self._exp_num-arg2*self._exp_den)
        if v1<>1:
            res=res*v1**self._exp_num
        if v2<>1:
            res=res/v2**self._exp_den
        if fak<>1:
            res=res*fak**(self._exp_num-self._exp_den)
        return res
Example #22
0
def set_info_for_web_newform(level=None, weight=None, character=None, label=None, **kwds):
    r"""
    Set the info for on modular form.

    """
    info = to_dict(kwds)
    info["level"] = level
    info["weight"] = weight
    info["character"] = character
    info["label"] = label
    if level is None or weight is None or character is None or label is None:
        s = "In set info for one form but do not have enough args!"
        s += "level={0},weight={1},character={2},label={3}".format(level, weight, character, label)
        emf_logger.critical(s)
    emf_logger.debug("In set_info_for_one_mf: info={0}".format(info))
    prec = my_get(info, "prec", default_prec, int)
    bprec = my_get(info, "bprec", default_display_bprec, int)
    emf_logger.debug("PREC: {0}".format(prec))
    emf_logger.debug("BITPREC: {0}".format(bprec))
    try:
        WNF = WebNewForm_cached(level=level, weight=weight, character=character, label=label)
        emf_logger.critical("defined webnewform for rendering!")
        # if info.has_key('download') and info.has_key('tempfile'):
        #     WNF._save_to_file(info['tempfile'])
        #     info['filename']=str(weight)+'-'+str(level)+'-'+str(character)+'-'+label+'.sobj'
        #     return info
    except IndexError as e:
        WNF = None
        info["error"] = e.message
    url1 = url_for("emf.render_elliptic_modular_forms")
    url2 = url_for("emf.render_elliptic_modular_forms", level=level)
    url3 = url_for("emf.render_elliptic_modular_forms", level=level, weight=weight)
    url4 = url_for("emf.render_elliptic_modular_forms", level=level, weight=weight, character=character)
    bread = [(EMF_TOP, url1)]
    bread.append(("of level %s" % level, url2))
    bread.append(("weight %s" % weight, url3))
    if int(character) == 0:
        bread.append(("trivial character", url4))
    else:
        bread.append(("\( %s \)" % (WNF.character.latex_name), url4))
    info["bread"] = bread

    properties2 = list()
    friends = list()
    space_url = url_for("emf.render_elliptic_modular_forms", level=level, weight=weight, character=character)
    friends.append(("\( S_{%s}(%s, %s)\)" % (WNF.weight, WNF.level, WNF.character.latex_name), space_url))
    if WNF.coefficient_field_label(check=True):
        friends.append(("Number field " + WNF.coefficient_field_label(), WNF.coefficient_field_url()))
    friends.append(("Number field " + WNF.base_field_label(), WNF.base_field_url()))
    friends = uniq(friends)
    friends.append(("Dirichlet character \(" + WNF.character.latex_name + "\)", WNF.character.url()))

    if WNF.dimension == 0:
        info["error"] = "This space is empty!"

    #    emf_logger.debug("WNF={0}".format(WNF))

    # info['name'] = name
    info["title"] = "Modular Form " + WNF.hecke_orbit_label

    if "error" in info:
        return info
    # info['name']=WNF._name
    ## Until we have figured out how to do the embeddings correctly we don't display the Satake
    ## parameters for non-trivial characters....

    cdeg = WNF.coefficient_field.absolute_degree()
    bdeg = WNF.base_ring.absolute_degree()
    if WNF.coefficient_field.absolute_degree() == 1:
        rdeg = 1
    else:
        rdeg = WNF.coefficient_field.relative_degree()
    if cdeg == 1:
        info["satake"] = WNF.satake
    info["qexp"] = WNF.q_expansion_latex(prec=10, name="a")
    info["qexp_display"] = url_for(".get_qexp_latex", level=level, weight=weight, character=character, label=label)

    # info['qexp'] = WNF.q_expansion_latex(prec=prec)
    # c_pol_st = str(WNF.absolute_polynomial)
    # b_pol_st = str(WNF.polynomial(type='base_ring',format='str'))
    # b_pol_ltx = str(WNF.polynomial(type='base_ring',format='latex'))
    # print "c=",c_pol_ltx
    # print "b=",b_pol_ltx
    if cdeg > 1:  ## Field is QQ
        if bdeg > 1 and rdeg > 1:
            p1 = WNF.coefficient_field.relative_polynomial()
            c_pol_ltx = latex(p1)
            lgc = p1.variables()[0]
            c_pol_ltx = c_pol_ltx.replace(lgc, "a")
            z = p1.base_ring().gens()[0]
            p2 = z.minpoly()
            b_pol_ltx = latex(p2)
            b_pol_ltx = b_pol_ltx.replace(latex(p2.variables()[0]), latex(z))
            info["polynomial_st"] = "where \({0}=0\) and \({1}=0\).".format(c_pol_ltx, b_pol_ltx)
        else:
            c_pol_ltx = latex(WNF.coefficient_field.relative_polynomial())
            lgc = str(latex(WNF.coefficient_field.relative_polynomial().variables()[0]))
            c_pol_ltx = c_pol_ltx.replace(lgc, "a")
            info["polynomial_st"] = "where \({0}=0\)".format(c_pol_ltx)
    else:
        info["polynomial_st"] = ""
    info["degree"] = int(cdeg)
    if cdeg == 1:
        info["is_rational"] = 1
    else:
        info["is_rational"] = 0
    # info['q_exp_embeddings'] = WNF.print_q_expansion_embeddings()
    # if(int(info['degree'])>1 and WNF.dimension()>1):
    #    s = 'One can embed it into \( \mathbb{C} \) as:'
    # bprec = 26
    # print s
    #    info['embeddings'] =  ajax_more2(WNF.print_q_expansion_embeddings,{'prec':[5,10,25,50],'bprec':[26,53,106]},text=['more coeffs.','higher precision'])
    # elif(int(info['degree'])>1):
    #    s = 'There are '+str(info['degree'])+' embeddings into \( \mathbb{C} \):'
    # bprec = 26
    # print s
    #    info['embeddings'] =  ajax_more2(WNF.print_q_expansion_embeddings,{'prec':[5,10,25,50],'bprec':[26,53,106]},text=['more coeffs.','higher precision'])
    # else:
    #    info['embeddings'] = ''
    emf_logger.debug("PREC2: {0}".format(prec))
    info["embeddings"] = WNF._embeddings["values"]  # q_expansion_embeddings(prec, bprec,format='latex')
    info["embeddings_len"] = len(info["embeddings"])
    properties2 = []
    if (ZZ(level)).is_squarefree():
        info["twist_info"] = WNF.twist_info
        if isinstance(info["twist_info"], list) and len(info["twist_info"]) > 0:
            info["is_minimal"] = info["twist_info"][0]
            if info["twist_info"][0]:
                s = "- Is minimal<br>"
            else:
                s = "- Is a twist of lower level<br>"
            properties2 = [("Twist info", s)]
    else:
        info["twist_info"] = "Twist info currently not available."
        properties2 = [("Twist info", "not available")]
    args = list()
    for x in range(5, 200, 10):
        args.append({"digits": x})
    alev = None
    CM = WNF._cm_values
    if CM is not None:
        if CM.has_key("tau") and len(CM["tau"]) != 0:
            info["CM_values"] = CM
    info["is_cm"] = WNF.is_cm
    if WNF.is_cm is None:
        s = "- Unknown (insufficient data)<br>"
    elif WNF.is_cm is True:
        s = "- Is a CM-form<br>"
    else:
        s = "- Is not a CM-form<br>"
    properties2.append(("CM info", s))
    alev = WNF.atkin_lehner_eigenvalues()
    info["atkinlehner"] = None
    if isinstance(alev, dict) and len(alev.keys()) > 0 and level != 1:
        s1 = " Atkin-Lehner eigenvalues "
        s2 = ""
        for Q in alev.keys():
            s2 += "\( \omega_{ %s } \) : %s <br>" % (Q, alev[Q])
        properties2.append((s1, s2))
        emf_logger.debug("properties={0}".format(properties2))
        # alev = WNF.atkin_lehner_eigenvalues_for_all_cusps()
        # if isinstance(alev,dict) and len(alev.keys())>0:
        #     emf_logger.debug("alev={0}".format(alev))
        #     info['atkinlehner'] = list()
        #     for Q in alev.keys():
        #         s = "\(" + latex(c) + "\)"
        #         Q = alev[c][0]
        #         ev = alev[c][1]
        #         info['atkinlehner'].append([Q, c, ev])
    if level == 1:
        poly = WNF.explicit_formulas.get("as_polynomial_in_E4_and_E6", "")
        if poly != "":
            d, monom, coeffs = poly
            emf_logger.critical("poly={0}".format(poly))

            info["explicit_formulas"] = "\("
            for i in range(d):
                c = QQ(coeffs[i])
                s = ""
                if d > 1 and i > 0 and c > 0:
                    s = "+"
                if c < 0:
                    s = "-"
                if c.denominator() > 1:
                    cc = "\\frac{{ {0} }}{{ {1} }}".format(abs(c.numerator()), c.denominator())
                else:
                    cc = str(abs(c))
                s += "{0} \cdot ".format(cc)
                a = monom[i][0]
                b = monom[i][1]
                if a == 0 and b != 0:
                    s += "E_6^{{ {0} }}".format(b)
                elif b == 0 and a != 0:
                    s += "E_4^{{ {0} }}".format(a)
                else:
                    s += "E_4^{{ {0} }}E_6^{{ {1} }}".format(a, b)
                info["explicit_formulas"] += s
            info["explicit_formulas"] += " \)"
    cur_url = (
        "?&level=" + str(level) + "&weight=" + str(weight) + "&character=" + str(character) + "&label=" + str(label)
    )
    if len(WNF.parent.hecke_orbits) > 1:
        for label_other in WNF.parent.hecke_orbits.keys():
            if label_other != label:
                s = "Modular form "
                if character:
                    s = s + str(level) + "." + str(weight) + "." + str(character) + str(label_other)
                else:
                    s = s + str(level) + "." + str(weight) + str(label_other)
                url = url_for(
                    "emf.render_elliptic_modular_forms",
                    level=level,
                    weight=weight,
                    character=character,
                    label=label_other,
                )
                friends.append((s, url))

    s = "L-Function "
    if character:
        s = s + str(level) + "." + str(weight) + "." + str(character) + str(label)
    else:
        s = s + str(level) + "." + str(weight) + str(label)
    # url =
    # "/L/ModularForm/GL2/Q/holomorphic?level=%s&weight=%s&character=%s&label=%s&number=%s"
    # %(level,weight,character,label,0)
    url = "/L" + url_for(
        "emf.render_elliptic_modular_forms", level=level, weight=weight, character=character, label=label
    )
    if WNF.coefficient_field_degree > 1:
        for h in range(WNF.coefficient_field_degree):
            s0 = s + ".{0}".format(h)
            url0 = url + "{0}/".format(h)
            friends.append((s0, url0))
    else:
        friends.append((s, url))
    # if there is an elliptic curve over Q associated to self we also list that
    if WNF.weight == 2 and WNF.coefficient_field_degree == 1:
        llabel = str(level) + "." + label
        s = "Elliptic curve isogeny class " + llabel
        url = "/EllipticCurve/Q/" + llabel
        friends.append((s, url))
    info["properties2"] = properties2
    info["friends"] = friends
    info["max_cn"] = WNF.max_cn()
    return info
Example #23
0
def fix_t(t):
    tsage = QQ("%d/%d" % (t[0], t[1]))
    return [int(tsage.numerator()), int(tsage.denominator())]
Example #24
0
def set_info_for_web_newform(level=None, weight=None, character=None, label=None, **kwds):
    r"""
    Set the info for on modular form.

    """
    info = to_dict(kwds)
    info['level'] = level
    info['weight'] = weight
    info['character'] = character
    info['label'] = label
    if level is None or weight is None or character is None or label is None:
        s = "In set info for one form but do not have enough args!"
        s += "level={0},weight={1},character={2},label={3}".format(level, weight, character, label)
        emf_logger.critical(s)
    emf_logger.debug("In set_info_for_one_mf: info={0}".format(info))
    prec = my_get(info, 'prec', default_prec, int)
    bprec = my_get(info, 'bprec', default_display_bprec, int)
    emf_logger.debug("PREC: {0}".format(prec))
    emf_logger.debug("BITPREC: {0}".format(bprec))    
    try:
        WNF = WebNewForm_cached(level=level, weight=weight, character=character, label=label)
        emf_logger.critical("defined webnewform for rendering!")
        # if info.has_key('download') and info.has_key('tempfile'):
        #     WNF._save_to_file(info['tempfile'])
        #     info['filename']=str(weight)+'-'+str(level)+'-'+str(character)+'-'+label+'.sobj'
        #     return info
    except IndexError as e:
        WNF = None
        info['error'] = e.message
    url1 = url_for("emf.render_elliptic_modular_forms")
    url2 = url_for("emf.render_elliptic_modular_forms", level=level)
    url3 = url_for("emf.render_elliptic_modular_forms", level=level, weight=weight)
    url4 = url_for("emf.render_elliptic_modular_forms", level=level, weight=weight, character=character)
    bread = [(EMF_TOP, url1)]
    bread.append(("of level %s" % level, url2))
    bread.append(("weight %s" % weight, url3))
    if int(character) == 0:
        bread.append(("trivial character", url4))
    else:
        bread.append(("\( %s \)" % (WNF.character.latex_name), url4))
    info['bread'] = bread
    
    properties2 = list()
    friends = list()
    space_url = url_for('emf.render_elliptic_modular_forms',level=level, weight=weight, character=character)
    friends.append(('\( S_{%s}(%s, %s)\)'%(WNF.weight, WNF.level, WNF.character.latex_name), space_url))
    if hasattr(WNF.base_ring, "lmfdb_url") and WNF.base_ring.lmfdb_url:
        friends.append(('Number field ' + WNF.base_ring.lmfdb_pretty, WNF.base_ring.lmfdb_url))
    if hasattr(WNF.coefficient_field, "lmfdb_url") and WNF.coefficient_field.lmfdb_label:
        friends.append(('Number field ' + WNF.coefficient_field.lmfdb_pretty, WNF.coefficient_field.lmfdb_url))
    friends = uniq(friends)
    friends.append(("Dirichlet character \(" + WNF.character.latex_name + "\)", WNF.character.url()))
    
    if WNF.dimension==0:
        info['error'] = "This space is empty!"

#    emf_logger.debug("WNF={0}".format(WNF))    

    #info['name'] = name
    info['title'] = 'Modular Form ' + WNF.hecke_orbit_label
    
    if 'error' in info:
        return info
    # info['name']=WNF._name
    ## Until we have figured out how to do the embeddings correctly we don't display the Satake
    ## parameters for non-trivial characters....

    cdeg = WNF.coefficient_field.absolute_degree()
    bdeg = WNF.base_ring.absolute_degree()
    if cdeg == 1:
        rdeg = 1
    else:
        rdeg = WNF.coefficient_field.relative_degree()
    cf_is_QQ = (cdeg == 1)
    br_is_QQ = (bdeg == 1)
    if cf_is_QQ:
        info['satake'] = WNF.satake
    info['qexp'] = WNF.q_expansion_latex(prec=10, name='\\alpha ')
    info['qexp_display'] = url_for(".get_qexp_latex", level=level, weight=weight, character=character, label=label)
    info['max_cn_qexp'] = WNF.q_expansion.prec()

    if not cf_is_QQ:
        if not br_is_QQ and rdeg>1: # not WNF.coefficient_field == WNF.base_ring:
            p1 = WNF.coefficient_field.relative_polynomial()
            c_pol_ltx = web_latex_poly(p1, '\\alpha')  # make the variable \alpha
            c_pol_ltx_x = web_latex_poly(p1, 'x')
            zeta = p1.base_ring().gens()[0]
#           p2 = zeta.minpoly() #this is not used anymore
#           b_pol_ltx = web_latex_poly(p2, latex(zeta)) #this is not used anymore
            z1 = zeta.multiplicative_order() 
            info['coeff_field'] = [ WNF.coefficient_field.absolute_polynomial_latex('x'),c_pol_ltx_x, z1]
            if hasattr(WNF.coefficient_field, "lmfdb_url") and WNF.coefficient_field.lmfdb_url:
                info['coeff_field_pretty'] = [ WNF.coefficient_field.lmfdb_url, WNF.coefficient_field.lmfdb_pretty, WNF.coefficient_field.lmfdb_label]
            if z1==4:
                info['polynomial_st'] = '<div class="where">where</div> {0}\(\mathstrut=0\) and \(\zeta_4=i\).</div><br/>'.format(c_pol_ltx)
            elif z1<=2:
                info['polynomial_st'] = '<div class="where">where</div> {0}\(\mathstrut=0\).</div><br/>'.format(c_pol_ltx)
            else:
                info['polynomial_st'] = '<div class="where">where</div> %s\(\mathstrut=0\) and \(\zeta_{%s}=e^{\\frac{2\\pi i}{%s}}\).'%(c_pol_ltx, z1,z1)
        else:
            p1 = WNF.coefficient_field.relative_polynomial()
            c_pol_ltx = web_latex_poly(p1, '\\alpha')
            c_pol_ltx_x = web_latex_poly(p1, 'x')
            z1 = p1.base_ring().gens()[0].multiplicative_order()
            info['coeff_field'] = [ WNF.coefficient_field.absolute_polynomial_latex('x'), c_pol_ltx_x, z1]
            if hasattr(WNF.coefficient_field, "lmfdb_url") and WNF.coefficient_field.lmfdb_url:
                info['coeff_field_pretty'] = [ WNF.coefficient_field.lmfdb_url, WNF.coefficient_field.lmfdb_pretty, WNF.coefficient_field.lmfdb_label]
            if z1==4:
                info['polynomial_st'] = '<div class="where">where</div> {0}\(\mathstrut=0\) and \(\zeta_4=i\).'.format(c_pol_ltx)
            elif z1<=2:
                info['polynomial_st'] = '<div class="where">where</div> {0}\(\mathstrut=0\).</div><br/>'.format(c_pol_ltx)
            else:
                info['polynomial_st'] = '<div class="where">where</div> %s\(\mathstrut=0\) and \(\zeta_{%s}=e^{\\frac{2\\pi i}{%s}}\).'%(c_pol_ltx, z1,z1)
    else:
        info['polynomial_st'] = ''
    info['degree'] = int(cdeg)
    if cdeg==1:
        info['is_rational'] = 1
        info['coeff_field_pretty'] = [ WNF.coefficient_field.lmfdb_url, WNF.coefficient_field.lmfdb_pretty ]
    else:
        info['is_rational'] = 0
    # info['q_exp_embeddings'] = WNF.print_q_expansion_embeddings()
    # if(int(info['degree'])>1 and WNF.dimension()>1):
    #    s = 'One can embed it into \( \mathbb{C} \) as:'
        # bprec = 26
        # print s
    #    info['embeddings'] =  ajax_more2(WNF.print_q_expansion_embeddings,{'prec':[5,10,25,50],'bprec':[26,53,106]},text=['more coeffs.','higher precision'])
    # elif(int(info['degree'])>1):
    #    s = 'There are '+str(info['degree'])+' embeddings into \( \mathbb{C} \):'
        # bprec = 26
        # print s
    #    info['embeddings'] =  ajax_more2(WNF.print_q_expansion_embeddings,{'prec':[5,10,25,50],'bprec':[26,53,106]},text=['more coeffs.','higher precision'])
    # else:
    #    info['embeddings'] = ''
    emf_logger.debug("PREC2: {0}".format(prec))
    info['embeddings'] = WNF._embeddings['values'] #q_expansion_embeddings(prec, bprec,format='latex')
    info['embeddings_len'] = len(info['embeddings'])
    properties2 = []
    if (ZZ(level)).is_squarefree():
        info['twist_info'] = WNF.twist_info
        if isinstance(info['twist_info'], list) and len(info['twist_info'])>0:
            info['is_minimal'] = info['twist_info'][0]
            if(info['twist_info'][0]):
                s = 'Is minimal<br>'
            else:
                s = 'Is a twist of lower level<br>'
            properties2 = [('Twist info', s)]
    else:
        info['twist_info'] = 'Twist info currently not available.'
        properties2 = [('Twist info', 'not available')]
    args = list()
    for x in range(5, 200, 10):
        args.append({'digits': x})
    alev = None
    CM = WNF._cm_values
    if CM is not None:
        if CM.has_key('tau') and len(CM['tau']) != 0:
            info['CM_values'] = CM
    info['is_cm'] = WNF.is_cm
    if WNF.is_cm:
        info['cm_field'] = "2.0.{0}.1".format(-WNF.cm_disc)
        info['cm_disc'] = WNF.cm_disc
        info['cm_field_knowl'] = nf_display_knowl(info['cm_field'], getDBConnection(), field_pretty(info['cm_field']))
        info['cm_field_url'] = url_for("number_fields.by_label", label=info["cm_field"])
    if WNF.is_cm is None:
        s = '- Unknown (insufficient data)<br>'
    elif WNF.is_cm:
        s = 'Is a CM-form<br>'
    else:
        s = 'Is not a CM-form<br>'
    properties2.append(('CM info', s))
    alev = WNF.atkin_lehner_eigenvalues()
    info['atkinlehner'] = None
    if isinstance(alev,dict) and len(alev.keys())>0 and level != 1:
        s1 = " Atkin-Lehner eigenvalues "
        s2 = ""
        for Q in alev.keys():
            s2 += "\( \omega_{ %s } \) : %s <br>" % (Q, alev[Q])
        properties2.append((s1, s2))
        emf_logger.debug("properties={0}".format(properties2))
        # alev = WNF.atkin_lehner_eigenvalues_for_all_cusps() 
        # if isinstance(alev,dict) and len(alev.keys())>0:
        #     emf_logger.debug("alev={0}".format(alev))
        #     info['atkinlehner'] = list()
        #     for Q in alev.keys():
        #         s = "\(" + latex(c) + "\)"
        #         Q = alev[c][0]
        #         ev = alev[c][1]
        #         info['atkinlehner'].append([Q, c, ev])
    if(level == 1):
        poly = WNF.explicit_formulas.get('as_polynomial_in_E4_and_E6','')
        if poly != '':
            d,monom,coeffs = poly
            emf_logger.critical("poly={0}".format(poly))
            info['explicit_formulas'] = '\('
            for i in range(len(coeffs)):
                c = QQ(coeffs[i])
                s = ""
                if d>1 and i >0 and c>0:
                    s="+"
                if c<0:
                    s="-"
                if c.denominator()>1:
                    cc = "\\frac{{ {0} }}{{ {1} }}".format(abs(c.numerator()),c.denominator())
                else:
                    cc = str(abs(c))
                s += "{0} \cdot ".format(cc)
                a = monom[i][0]; b = monom[i][1]
                if a == 0 and b != 0:
                    s+="E_6^{{ {0} }}".format(b)
                elif b ==0 and a != 0:
                    s+="E_4^{{ {0} }}".format(a)
                else:
                    s+="E_4^{{ {0} }}E_6^{{ {1} }}".format(a,b)
                info['explicit_formulas'] += s
            info['explicit_formulas'] += " \)"            
    cur_url = '?&level=' + str(level) + '&weight=' + str(weight) + '&character=' + str(character) + \
        '&label=' + str(label)
    if len(WNF.parent.hecke_orbits) > 1:
        for label_other in WNF.parent.hecke_orbits.keys():
            if(label_other != label):
                s = 'Modular form '
                if character:
                    s = s + str(level) + '.' + str(weight) + '.' + str(character) + str(label_other)
                else:
                    s = s + str(level) + '.' + str(weight) + str(label_other)
                url = url_for('emf.render_elliptic_modular_forms', level=level,
                              weight=weight, character=character, label=label_other)
                friends.append((s, url))

    s = 'L-Function '
    if character:
        s = s + str(level) + '.' + str(weight) + '.' + str(character) + str(label)
    else:
        s = s + str(level) + '.' + str(weight) + str(label)
    # url =
    # "/L/ModularForm/GL2/Q/holomorphic?level=%s&weight=%s&character=%s&label=%s&number=%s"
    # %(level,weight,character,label,0)
    url = '/L' + url_for(
        'emf.render_elliptic_modular_forms', level=level, weight=weight, character=character, label=label)
    if WNF.coefficient_field_degree > 1:
        for h in range(WNF.coefficient_field_degree):
            s0 = s + ".{0}".format(h)
            url0 = url + "{0}/".format(h)
            friends.append((s0, url0))
    else:
        friends.append((s, url))
    # if there is an elliptic curve over Q associated to self we also list that
    if WNF.weight == 2 and WNF.coefficient_field_degree == 1:
        llabel = str(level) + '.' + label
        s = 'Elliptic curve isogeny class ' + llabel
        url = '/EllipticCurve/Q/' + llabel
        friends.append((s, url))
    info['properties2'] = properties2
    info['friends'] = friends
    info['max_cn'] = WNF.max_cn()
    return info
Example #25
0
def set_info_for_web_newform(level=None, weight=None, character=None, label=None, **kwds):
    r"""
    Set the info for on modular form.

    """
    info = to_dict(kwds)
    info['level'] = level
    info['weight'] = weight
    info['character'] = character
    info['label'] = label
    if level is None or weight is None or character is None or label is None:
        s = "In set info for one form but do not have enough args!"
        s += "level={0},weight={1},character={2},label={3}".format(level, weight, character, label)
        emf_logger.critical(s)
    emf_logger.debug("In set_info_for_one_mf: info={0}".format(info))
    prec = my_get(info, 'prec', default_prec, int)
    bprec = my_get(info, 'bprec', default_display_bprec, int)
    emf_logger.debug("PREC: {0}".format(prec))
    emf_logger.debug("BITPREC: {0}".format(bprec))    
    try:
        WNF = WebNewForm_cached(level=level, weight=weight, character=character, label=label)
        if not WNF.has_updated():
            raise IndexError("Unfortunately, we do not have this newform in the database.")
        info['character_order'] = WNF.character.order
        info['code'] = WNF.code
        emf_logger.debug("defined webnewform for rendering!")
    except IndexError as e:
        info['error'] = e.message
    url0 = url_for("mf.modular_form_main_page")
    url1 = url_for("emf.render_elliptic_modular_forms")
    url2 = url_for("emf.render_elliptic_modular_forms", level=level)
    url3 = url_for("emf.render_elliptic_modular_forms", level=level, weight=weight)
    url4 = url_for("emf.render_elliptic_modular_forms", level=level, weight=weight, character=character)
    bread = [(MF_TOP, url0), (EMF_TOP, url1)]
    bread.append(("Level %s" % level, url2))
    bread.append(("Weight %s" % weight, url3))
    bread.append(("Character \( %s \)" % (WNF.character.latex_name), url4))
    bread.append(("Newform %d.%d.%d.%s" % (level, weight, int(character), label),''))
    info['bread'] = bread
    
    properties2 = list()
    friends = list()
    space_url = url_for('emf.render_elliptic_modular_forms',level=level, weight=weight, character=character)
    friends.append(('\( S_{%s}(%s, %s)\)'%(WNF.weight, WNF.level, WNF.character.latex_name), space_url))
    if hasattr(WNF.base_ring, "lmfdb_url") and WNF.base_ring.lmfdb_url:
        friends.append(('Number field ' + WNF.base_ring.lmfdb_pretty, WNF.base_ring.lmfdb_url))
    if hasattr(WNF.coefficient_field, "lmfdb_url") and WNF.coefficient_field.lmfdb_label:
        friends.append(('Number field ' + WNF.coefficient_field.lmfdb_pretty, WNF.coefficient_field.lmfdb_url))
    friends = uniq(friends)
    friends.append(("Dirichlet character \(" + WNF.character.latex_name + "\)", WNF.character.url()))
    
    if WNF.dimension==0 and not info.has_key('error'):
        info['error'] = "This space is empty!"
    info['title'] = 'Newform ' + WNF.hecke_orbit_label
    info['learnmore'] = [('History of modular forms', url_for('.holomorphic_mf_history'))]    
    if 'error' in info:
        return info
    ## Until we have figured out how to do the embeddings correctly we don't display the Satake
    ## parameters for non-trivial characters....

    ## Example to illustrate the different cases
    ## base              = CyclotomicField(n) -- of degree phi(n) 
    ## coefficient_field = NumberField( p(x)) for some p in base['x'] of degree m
    ##   we would then have cdeg = m*phi(n) and bdeg = phi(n)
    ##   and rdeg = m
    ## Unfortunately, for e.g. base = coefficient_field = CyclotomicField(6)
    ## we get coefficient_field.relative_degree() == 2 although it should be 1
    cdeg = WNF.coefficient_field.absolute_degree()
    bdeg = WNF.base_ring.absolute_degree()
    if cdeg == 1:
        rdeg = 1
    else:
        ## just setting rdeg = WNF.coefficient_field.relative_degree() does not give correct result...
        ## 
        rdeg = QQ(cdeg)/QQ(bdeg)
    cf_is_QQ = (cdeg == 1)
    br_is_QQ = (bdeg == 1)
    if cf_is_QQ:
        info['satake'] = WNF.satake
    if WNF.complexity_of_first_nonvanishing_coefficients() > default_max_height:
        info['qexp'] = ""
        info['qexp_display'] = ''
        info['hide_qexp'] = True
        n,c = WNF.first_nonvanishing_coefficient()
        info['trace_nv'] = latex(WNF.first_nonvanishing_coefficient_trace())
        info['norm_nv'] = '\\approx ' + latex(WNF.first_nonvanishing_coefficient_norm().n())
        info['index_nv'] = n
    else:
        if WNF.prec < prec:
            #get WNF record at larger prec
            WNF.prec = prec
            WNF.update_from_db()
        info['qexp'] = WNF.q_expansion_latex(prec=10, name='\\alpha ')
        info['qexp_display'] = url_for(".get_qexp_latex", level=level, weight=weight, character=character, label=label)
        info["hide_qexp"] = False
    info['max_cn_qexp'] = WNF.q_expansion.prec()
    ## All combinations should be tested...
    ## 13/4/4/a -> base ring = coefficient_field = QQ(zeta_6)
    ## 13/3/8/a ->  base_ring = QQ(zeta_4), coefficient_field has poly x^2+(2\zeta_4+2x-3\zeta_$ over base_ring
    ## 13/4/3/a ->  base_ring = coefficient_field = QQ(zeta_3) 
    ## 13/4/1/a -> all rational
    ## 13/6/1/a/ -> base_ring = QQ, coefficient_field = Q(sqrt(17))
    ## These are variables which needs to be set properly below
    info['polvars'] = {'base_ring':'x','coefficient_field':'\\alpha'}
    if not cf_is_QQ:
        if rdeg>1: # not WNF.coefficient_field == WNF.base_ring:
            ## Here WNF.base_ring should be some cyclotomic field and we have an extension over this.
            p1 = WNF.coefficient_field.relative_polynomial()
            c_pol_ltx = web_latex_poly(p1, '\\alpha')  # make the variable \alpha
            c_pol_ltx_x = web_latex_poly(p1, 'x')
            zeta = p1.base_ring().gens()[0]
#           p2 = zeta.minpoly() #this is not used anymore
#           b_pol_ltx = web_latex_poly(p2, latex(zeta)) #this is not used anymore
            z1 = zeta.multiplicative_order() 
            info['coeff_field'] = [ WNF.coefficient_field.absolute_polynomial_latex('x'),c_pol_ltx_x, z1]
            if hasattr(WNF.coefficient_field, "lmfdb_url") and WNF.coefficient_field.lmfdb_url:
                info['coeff_field_pretty'] = [ WNF.coefficient_field.lmfdb_url, WNF.coefficient_field.lmfdb_pretty, WNF.coefficient_field.lmfdb_label]
            if z1==4:
                info['polynomial_st'] = '<div class="where">where</div> {0}\(\mathstrut=0\) and \(\zeta_4=i\).</div><br/>'.format(c_pol_ltx)
                info['polvars']['base_ring']='i'
            elif z1<=2:
                info['polynomial_st'] = '<div class="where">where</div> {0}\(\mathstrut=0\).</div><br/>'.format(c_pol_ltx)
            else:
                info['polynomial_st'] = '<div class="where">where</div> %s\(\mathstrut=0\) and \(\zeta_{%s}=e^{\\frac{2\\pi i}{%s}}\) '%(c_pol_ltx, z1,z1)
                info['polvars']['base_ring']='\zeta_{{ {0} }}'.format(z1)
                if z1==3:
                    info['polynomial_st'] += 'is a primitive cube root of unity.'
                else:
                    info['polynomial_st'] += 'is a primitive {0}-th root of unity.'.format(z1)
        elif not br_is_QQ:
            ## Now we have base and coefficient field being equal, meaning that since the coefficient field is not QQ it is some cyclotomic field
            ## generated by some \zeta_n 
            p1 = WNF.coefficient_field.absolute_polynomial()
            z1 = WNF.coefficient_field.gens()[0].multiplicative_order()
            c_pol_ltx = web_latex_poly(p1, '\\zeta_{{{0}}}'.format(z1))
            c_pol_ltx_x = web_latex_poly(p1, 'x')
            info['coeff_field'] = [ WNF.coefficient_field.absolute_polynomial_latex('x'), c_pol_ltx_x]
            if hasattr(WNF.coefficient_field, "lmfdb_url") and WNF.coefficient_field.lmfdb_url:
                info['coeff_field_pretty'] = [ WNF.coefficient_field.lmfdb_url, WNF.coefficient_field.lmfdb_pretty, WNF.coefficient_field.lmfdb_label]
            if z1==4:
                info['polynomial_st'] = '<div class="where">where \(\zeta_4=e^{{\\frac{{\\pi i}}{{ 2 }} }}=i \).</div>'.format(c_pol_ltx)
                info['polvars']['coefficient_field']='i'
            elif z1<=2:
                info['polynomial_st'] = '' 
            else:
                info['polynomial_st'] = '<div class="where">where \(\zeta_{{{0}}}=e^{{\\frac{{2\\pi i}}{{ {0} }} }}\) '.format(z1)
                info['polvars']['coefficient_field']='\zeta_{{{0}}}'.format(z1)
                if z1==3:
                    info['polynomial_st'] += 'is a primitive cube root of unity.</div>'
                else:
                    info['polynomial_st'] += 'is a primitive {0}-th root of unity.</div>'.format(z1)
    else:
        info['polynomial_st'] = ''
    if info["hide_qexp"]:
        info['polynomial_st'] = ''
    info['degree'] = int(cdeg)
    if cdeg==1:
        info['is_rational'] = 1
        info['coeff_field_pretty'] = [ WNF.coefficient_field.lmfdb_url, WNF.coefficient_field.lmfdb_pretty ]
    else:
        info['is_rational'] = 0
    emf_logger.debug("PREC2: {0}".format(prec))
    info['embeddings'] = WNF._embeddings['values'] #q_expansion_embeddings(prec, bprec,format='latex')
    info['embeddings_len'] = len(info['embeddings'])
    properties2 = [('Level', str(level)),
                       ('Weight', str(weight)),
                       ('Character', '$' + WNF.character.latex_name + '$'),
                       ('Label', WNF.hecke_orbit_label),
                       ('Dimension of Galois orbit', str(WNF.dimension))]
    if (ZZ(level)).is_squarefree():
        info['twist_info'] = WNF.twist_info
        if isinstance(info['twist_info'], list) and len(info['twist_info'])>0:
            info['is_minimal'] = info['twist_info'][0]
            if(info['twist_info'][0]):
                s = 'Is minimal<br>'
            else:
                s = 'Is a twist of lower level<br>'
            properties2 += [('Twist info', s)]
    else:
        info['twist_info'] = 'Twist info currently not available.'
        properties2 += [('Twist info', 'not available')]
    args = list()
    for x in range(5, 200, 10):
        args.append({'digits': x})
    alev = None
    CM = WNF._cm_values
    if CM is not None:
        if CM.has_key('tau') and len(CM['tau']) != 0:
            info['CM_values'] = CM
    info['is_cm'] = WNF.is_cm
    if WNF.is_cm == 1:
        info['cm_field'] = "2.0.{0}.1".format(-WNF.cm_disc)
        info['cm_disc'] = WNF.cm_disc
        info['cm_field_knowl'] = nf_display_knowl(info['cm_field'], getDBConnection(), field_pretty(info['cm_field']))
        info['cm_field_url'] = url_for("number_fields.by_label", label=info["cm_field"])
    if WNF.is_cm is None or WNF.is_cm==-1:
        s = '- Unknown (insufficient data)<br>'
    elif WNF.is_cm == 1:
        s = 'Yes<br>'
    else:
        s = 'No<br>'
    properties2.append(('CM', s))
    alev = WNF.atkin_lehner_eigenvalues()
    info['atkinlehner'] = None
    if isinstance(alev,dict) and len(alev.keys())>0 and level != 1:
        s1 = " Atkin-Lehner eigenvalues "
        s2 = ""
        for Q in alev.keys():
            s2 += "\( \omega_{ %s } \) : %s <br>" % (Q, alev[Q])
        properties2.append((s1, s2))
        emf_logger.debug("properties={0}".format(properties2))
        # alev = WNF.atkin_lehner_eigenvalues_for_all_cusps() 
        # if isinstance(alev,dict) and len(alev.keys())>0:
        #     emf_logger.debug("alev={0}".format(alev))
        #     info['atkinlehner'] = list()
        #     for Q in alev.keys():
        #         s = "\(" + latex(c) + "\)"
        #         Q = alev[c][0]
        #         ev = alev[c][1]
        #         info['atkinlehner'].append([Q, c, ev])
    if(level == 1):
        poly = WNF.explicit_formulas.get('as_polynomial_in_E4_and_E6','')
        if poly != '':
            d,monom,coeffs = poly
            emf_logger.critical("poly={0}".format(poly))
            info['explicit_formulas'] = '\('
            for i in range(len(coeffs)):
                c = QQ(coeffs[i])
                s = ""
                if d>1 and i >0 and c>0:
                    s="+"
                if c<0:
                    s="-"
                if c.denominator()>1:
                    cc = "\\frac{{ {0} }}{{ {1} }}".format(abs(c.numerator()),c.denominator())
                else:
                    cc = str(abs(c))
                s += "{0} \cdot ".format(cc)
                a = monom[i][0]; b = monom[i][1]
                if a == 0 and b != 0:
                    s+="E_6^{{ {0} }}".format(b)
                elif b ==0 and a != 0:
                    s+="E_4^{{ {0} }}".format(a)
                else:
                    s+="E_4^{{ {0} }}E_6^{{ {1} }}".format(a,b)
                info['explicit_formulas'] += s
            info['explicit_formulas'] += " \)"            
    # cur_url = '?&level=' + str(level) + '&weight=' + str(weight) + '&character=' + str(character) + '&label=' + str(label) # never used
    if len(WNF.parent.hecke_orbits) > 1:
        for label_other in WNF.parent.hecke_orbits.keys():
            if(label_other != label):
                s = 'Modular form '
                if character:
                    s += newform_label(level,weight,character,label_other)
                else:
                    s += newform_label(level,weight,1,label_other)

                url = url_for('emf.render_elliptic_modular_forms', level=level,
                              weight=weight, character=character, label=label_other)
                friends.append((s, url))

    s = 'L-Function '
    if character:
        s += newform_label(level,weight,character,label)
    else:
        s += newform_label(level,weight,1,label)
    # url =
    # "/L/ModularForm/GL2/Q/holomorphic?level=%s&weight=%s&character=%s&label=%s&number=%s"
    # %(level,weight,character,label,0)
    url = '/L' + url_for(
        'emf.render_elliptic_modular_forms', level=level, weight=weight, character=character, label=label)
    if WNF.coefficient_field_degree > 1:
        for h in range(WNF.coefficient_field_degree):
            s0 = s + ".{0}".format(h)
            url0 = url + "{0}/".format(h)
            friends.append((s0, url0))
    else:
        friends.append((s, url))
    # if there is an elliptic curve over Q associated to self we also list that
    if WNF.weight == 2 and WNF.coefficient_field_degree == 1:
        llabel = str(level) + '.' + label
        s = 'Elliptic curve isogeny class ' + llabel
        url = '/EllipticCurve/Q/' + llabel
        friends.append((s, url))
    info['properties2'] = properties2
    info['friends'] = friends
    info['max_cn'] = WNF.max_available_prec()
    return info
Example #26
0
def do_addrec(F):
    global newrecs
    degree, weight, A, B, t, famhodge, hodge, conductor, sign, sig, locinfo, lcms, hardness, coeffs  = F
    A,B = orderAB(A,B)
    A.sort(reverse=True)
    B.sort(reverse=True)
    Astr = '.'.join([str(x) for x in A])
    Bstr = '.'.join([str(x) for x in B])
    myt = QQ(str(t[1])+'/'+str(t[0]))
    tstr = str(myt.numerator())+'.'+str(myt.denominator())
    label = "A%s_B%s_t%s" % (Astr, Bstr, tstr)

    data = {
        'label': label,
        'degree': degree,
        'weight': weight,
        't': str(myt),
        'A': list2string(A),
        'B': list2string(B),
        'Arev': list2string(B),
        'Brev': list2string(A),
        'hodge': list2string(hodge),
        'famhodge': list2string(famhodge),
        'sign': sign,
        'sig': sig,
        'req': hardness,
        'coeffs': coeffs,
        'lcms': lcms,
        'cond': conductor,
        'locinfo': locinfo,
        'centralval': 0
    }
    for p in [2,3,5,7]:
        mod = modpair(A,B,p)
        mod = killdup(mod[0],mod[1])
        data['A'+str(p)] = list2string(mod[0])
        data['B'+str(p)] = list2string(mod[1])
        data['C'+str(p)] = list2string(mod[2])
        mod = modpair(B,A,p)
        mod = killdup(mod[0],mod[1])
        data['A'+str(p)+'rev'] = list2string(mod[0])
        data['B'+str(p)+'rev'] = list2string(mod[1])
        mod = modupperpair(A,B,p)
        mod = killdup(mod[0],mod[1])
        data['Au'+str(p)] = list2string(mod[0])
        data['Bu'+str(p)] = list2string(mod[1])
        data['Cu'+str(p)] = list2string(mod[2])
        data['Bu'+str(p)+'rev'] = list2string(mod[0])
        data['Au'+str(p)+'rev'] = list2string(mod[1])

    is_new = True
    for field in hgm.find({'label': label}):
        is_new = False
        break

    for k in newrecs:
        if k['label'] == label:
            is_new = False
            break

    if is_new:
        #print "new family"
        newrecs.append(data)