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
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), )
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
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
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
def make_t_label(t): tsage = QQ(t) return "t%s.%s" % (tsage.numerator(), tsage.denominator())
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
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
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()))
def make_t_label(t): tsage = QQ("%d/%d" % (t[0], t[1])) return "t%s.%s" % (tsage.numerator(), tsage.denominator())
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)
def fix_t(t): tsage = QQ("%d/%d" % (t[0], t[1])) return [int(tsage.numerator()), int(tsage.denominator())]
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
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
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())
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
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
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
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
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)