def is_consistent(self, k): r""" Return True if the Weil representation is a multiplier of weight k. """ if self._verbose > 0: print("is_consistent at wr! k={0}".format(k)) twok = QQ(2) * QQ(k) if not twok.is_integral(): return False if self._sym_type != 0: if self.is_dual(): sig_mod_4 = -self._weil_module.signature() % 4 else: sig_mod_4 = self._weil_module.signature() % 4 if is_odd(self._weil_module.signature()): return (twok % 4 == (self._sym_type * sig_mod_4 % 4)) else: if sig_mod_4 == (1 - self._sym_type) % 4: return twok % 4 == 0 else: return twok % 4 == 2 if is_even(twok) and is_even(self._weil_module.signature()): return True if is_odd(twok) and is_odd(self._weil_module.signature()): return True return False
def _recover_increment_and_states(outputs, state_bitsize, output_bitsize, modulus, multiplier): B = 2**(state_bitsize - output_bitsize) mult1 = multiplier mult2 = 1 # Adapted from the code to solve the Hidden Number Problem using a lattice attack. m = len(outputs) M = matrix(QQ, m + 3, m + 3) for i in range(m): M[i, i] = modulus M[m, i] = mult1 M[m + 1, i] = mult2 # Adding B // 2 improves the quality of the results. M[m + 2, i] = (-(B * outputs[i] + B // 2)) % modulus mult1 = (multiplier * mult1) % modulus mult2 = (multiplier * mult2 + 1) % modulus M[m, m] = B / QQ(modulus) M[m + 1, m + 1] = B / QQ(modulus) M[m + 2, m] = 0 M[m + 2, m + 1] = 0 M[m + 2, m + 2] = B L = M.LLL() for row in L.rows(): seed = (int(row[m] * modulus) // B) % modulus increment = (int(row[m + 1] * modulus) // B) % modulus if seed != 0 and increment != 0 and row[m + 2] == B: states = [] for i in range(len(outputs)): states.append((B * outputs[i] + B // 2 + int(row[i]))) yield modulus, multiplier, increment, states break
def _D_lower_c(self,c,as_int=False): r""" Return the set D_c={x in D| cx = 0} INPUT: -''c'' -- integer -''s_int'' -- logical, if true then we return the set D^c as a list of integers """ Dc=list() if(as_int): setD=self._D_as_integers else: setD=self._D for x in setD: if(as_int): z=(c*x) % len(self._D) else: y=c*x p=y.numer(); q=y.denom(); z=QQ(p % q)/QQ(q) #print "c*",x,"=",z if(z==0): Dc.append(x) Dc.sort() # make unique for x in Dc: i=Dc.count(x) if(i>1): for j in range(i-1): Dc.remove(x) return Dc
def dedekind_sum(d, c): res = 0 for i in range(c): tmp = saw_tooth_fn(QQ(i) / QQ(c)) tmp *= saw_tooth_fn(QQ(d * i) / QQ(c)) res = res + tmp return res
def B(self,x,y): r""" Bilinear form B(x,y) mod 1, givenby the quadratic form Q INPUT: -''x'' -- rational -''y'' -- rational OUTPUT: -''B(x,y)'' -- rational EXAMPLES:: sage: WR=WeilRepDiscriminantForm(3,dual=True) sage: WR.B(1/6,1/2) 1/2 sage: WR.B(1/6,1/6) 1/6 sage: WR.B(1/6,-1+1/6) 1/6 """ #print "N=",self._N,x,y r=Integer(2)*self._N*x*y p=r.numerator() q=r.denominator() res=QQ(p % q)/QQ(q) return res
def to_polredabs(K): """ INPUT: * "K" - a number field OUTPUT: * "phi" - an isomorphism K -> L, where L = QQ['x']/f and f a polynomial such that f = polredabs(f) """ R = PolynomialRing(QQ,'x') x = R.gen(0) if K == QQ: L = QQ.extension(x,'w') return QQ.hom(L) L = K.absolute_field('a') m1 = L.structure()[1] f = L.absolute_polynomial() g = pari(f).polredabs(1) g,h = g[0].sage(locals={'x':x}),g[1].lift().sage(locals={'x':x}) if debug: print 'f',f print 'g',g print 'h',h M = QQ.extension(g,'w') m2 = L.hom([h(M.gen(0))]) return m2*m1
def test_back_and_forth_rat(): p = iet.Permutation("a b c", "c b a") T = iet.IntervalExchangeTransformation( p, [QQ((12, 5)), QQ((2, 7)), QQ((1, 21))]) T2 = iet_to_pyintervalxt(T) T3 = iet_from_pyintervalxt(T2) assert T == T3
def is_consistent(self,k): r""" Return True if the Weil representation is a multiplier of weight k. """ if self._verbose>0: print "is_consistent at wr! k={0}".format(k) twok =QQ(2)*QQ(k) if not twok.is_integral(): return False if self._sym_type <>0: if self.is_dual(): sig_mod_4 = -self._weil_module.signature() % 4 else: sig_mod_4 = self._weil_module.signature() % 4 if is_odd(self._weil_module.signature()): return (twok % 4 == (self._sym_type*sig_mod_4 %4)) else: if sig_mod_4 == (1 - self._sym_type) % 4: return twok % 4 == 0 else: return twok % 4 == 2 if is_even(twok) and is_even(self._weil_module.signature()): return True if is_odd(twok) and is_odd(self._weil_module.signature()): return True return False
def _D_times_c_star(self,c,as_int=False): r""" Return the set D^c*=x_c+{c*x | x in D}, where x_c=0 or 1/2 INPUT: -''c'' -- integer -''as_int'' -- logical, if true then we return the set D^c as a list of integers """ Dc=self._D_times_c(c,as_int) Dcs=list() x_c=self._xc(c,as_int) for x in Dc: if(as_int): z=(x + x_c) % len(self._D) else: y=QQ(c*x)+x_c p=y.numer(); q=y.denom(); z=QQ(p % q)/QQ(q) #print "c*",x,"=",z Dcs.append(z) Dcs.sort() # make unique for x in Dcs: i=Dcs.count(x) if(i>1): for j in range(i-1): Dcs.remove(x) return Dcs
def symmetric_transformation_matrix(Pa, Pb, S, H, Q, tol=1e-4): r"""Returns the symplectic matrix `\Gamma` mapping the period matrices `Pa,Pb` to a symmetric period matrices. A helper function to :func:`symmetrize_periods`. Parameters ---------- Pa : complex matrix A `g x g` a-period matrix. Pb : complex matrix A `g x g` b-period matrix. S : integer matrix Integer kernel basis matrix. H : integer matrix Topological type classification matrix. Q : integer matrix The transformation matrix from `symmetric_block_diagonalize`. tol : double (Default: 1e-4) Tolerance used to verify integrality of intermediate matrices. Dependent on precision of period matrices. Returns ------- Gamma : integer matrix A `2g x 2g` symplectic matrix. """ # compute A and B g,g = Pa.dimensions() rhs = S*Q.change_ring(ZZ) A = rhs[:g,:g].T B = rhs[g:,:g].T H = H.change_ring(ZZ) # compute C and D half = QQ(1)/QQ(2) temp = (A*Re(Pa) + B*Re(Pb)).inverse() CT = half*A.T*H - Re(Pb)*temp CT_ZZ = CT.round().change_ring(ZZ) C = CT_ZZ.T DT = half*B.T*H + Re(Pa)*temp DT_ZZ = DT.round().change_ring(ZZ) D = DT_ZZ.T # sanity checks: make sure C and D are integral C_error = (CT.round() - CT).norm() D_error = (DT.round() - DT).norm() if (C_error > tol) or (D_error > tol): raise ValueError("The symmetric transformation matrix is not integral. " "Try increasing the precision of the input period " "matrices.") # construct Gamma Gamma = zero_matrix(ZZ, 2*g, 2*g) Gamma[:g,:g] = A Gamma[:g,g:] = B Gamma[g:,:g] = C Gamma[g:,g:] = D return Gamma
def class_nr_pos_def_qf(D): r""" Compute the class number of positive definite quadratic forms. For fundamental discriminants this is the class number of Q(sqrt(D)), otherwise it is computed using: Cohen 'A course in Computational Algebraic Number Theory', p. 233 """ if D>0: return 0 D4 = D % 4 if D4 == 3 or D4==2: return 0 K = QuadraticField(D) if is_fundamental_discriminant(D): return K.class_number() else: D0 = K.discriminant() Df = ZZ(D).divide_knowing_divisible_by(D0) if not is_square(Df): raise ArithmeticError("Did not get a discrimimant * square! D={0} disc(D)={1}".format(D,D0)) D2 = sqrt(Df) h0 = QuadraticField(D0).class_number() w0 = _get_w(D0) w = _get_w(D) #print "w,w0=",w,w0 #print "h0=",h0 h = 1 for p in prime_divisors(D2): h = QQ(h)*(1-kronecker(D0,p)/QQ(p)) #print "h=",h #print "fak=", h=QQ(h*h0*D2*w)/QQ(w0) return h
def saw_tooth_fn(x): if floor(x) == ceil(x): return 0 elif x in QQ: return QQ(x) - QQ(floor(x)) - QQ(1) / QQ(2) else: return x - floor(x) - 0.5
def __init__(self, group, dchar=(0, 0), dual=False, is_trivial=False, dimension=1, **kwargs): if not ZZ(4).divides(group.level()): raise ValueError(" Need level divisible by 4. Got: {0} ".format( self._group.level())) MultiplierSystem.__init__(self, group, dchar=dchar, dual=dual, is_trivial=is_trivial, dimension=dimension, **kwargs) self._i = CyclotomicField(4).gen() self._one = self._i**4 self._weight = QQ(kwargs.get("weight", QQ(1) / QQ(2))) ## We have to make sure that we have the correct multiplier & character ## for the desired weight if self._weight != None: if floor(2 * self._weight) != ceil(2 * self._weight): raise ValueError( " Use ThetaMultiplier for half integral or integral weight only!" ) t = self.is_consistent(self._weight) if not t: self.set_dual() t1 = self.is_consistent(self._weight) if not t1: raise ArithmeticError( "Could not find consistent theta multiplier! Try to add a character." )
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 to_polredabs(K): """ INPUT: * "K" - a number field OUTPUT: * "phi" - an isomorphism K -> L, where L = QQ['x']/f and f a polynomial such that f = polredabs(f) """ R = PolynomialRing(QQ, 'x') x = R.gen(0) if K == QQ: L = QQ.extension(x, 'w') return QQ.hom(L) L = K.absolute_field('a') m1 = L.structure()[1] f = L.absolute_polynomial() g = pari(f).polredabs(1) g, h = g[0].sage(locals={'x': x}), g[1].lift().sage(locals={'x': x}) if debug: print('f', f) print('g', g) print('h', h) M = QQ.extension(g, 'w') m2 = L.hom([h(M.gen(0))]) return m2 * m1
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 test_vv(N=11): return WR = WeilRepDiscriminantForm(11, dual=True) M = VVHarmonicWeakMaassForms(WR, 0.5, 15) PP = {(QQ(7) / QQ(22), 0): 1} F = M.get_element(PP, 12) print(F)
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 dual_multiplier(self): r""" Returns the dual multiplier of self. """ weight = QQ(2) - QQ(self._weight) dual = int(not self._is_dual) m = WeilRepMultiplier(self._weil_module,weight,use_symmetry,self._group,dual=dual,**self._kwargs) return m
def table_euler_factors_t(self, t, plist=None): if plist is None: plist = sorted(self.euler_factors) t = QQ(t) tmodp = [(p, t.mod_ui(p)) for p in plist if t.denominator() % p != 0] # filter return [[p] + self.process_euler(self.euler_factors[p][tp - 2], p) for p, tp in tmodp if tp > 1]
def _test(self): from sage.all import QQ, PolynomialRing, GaussValuation R = PolynomialRing(QQ, 'x') x = R.gen() v = QQ.valuation(2) v = GaussValuation(R, v).augmentation(x + 1, QQ(1) / 2) f = x**4 - 30 * x**2 - 75 v.mac_lane_step(f)
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 __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 _hecke_pol_klingen(k, j): '''k: even. F: Kligen-Eisenstein series of determinant weight k whose Hecke field is the rational filed. Return the Hecke polynomial of F at 2. ''' f = CuspForms(1, k + j).basis()[0] R = PolynomialRing(QQ, names="x") x = R.gens()[0] pl = QQ(1) - f[2] * x + QQ(2) ** (k + j - 1) * x ** 2 return pl * pl.subs({x: x * QQ(2) ** (k - 2)})
def dual_multiplier(self): r""" Returns the dual multiplier of self. """ m = copy(self) m._is_dual = int(not self._is_dual) o = self._character.order() m._character = self._character**(o - 1) m._weight = QQ(2) - QQ(self.weight()) return m
def do_addrec(A, B, F): global newrecs degree, weight, A1, B1, t, famhodge, hodge, conductor, sign, sig, locinfo, lcms, hardness, coeffs = F 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), '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 = 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]) 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)
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 xi(self, A): r""" The eight-root of unity in front of the Weil representation. INPUT: -''N'' -- integer -''A'' -- element of PSL(2,Z) EXAMPLES:: sage: A=SL2Z([41,77,33,62]) sage: WR.xi(A) -zeta8^3] sage: S,T=SL2Z.gens() sage: WR.xi(S) -zeta8^3 sage: WR.xi(T) 1 sage: A=SL2Z([-1,1,-4,3]) sage: WR.xi(A) -zeta8^2 sage: A=SL2Z([0,1,-1,0]) sage: WR.xi(A) -zeta8 """ a = Integer(A[0, 0]) b = Integer(A[0, 1]) c = Integer(A[1, 0]) d = Integer(A[1, 1]) if (c == 0): return 1 z = CyclotomicField(8).gen() N = self._N N2 = odd_part(N) Neven = ZZ(2 * N).divide_knowing_divisible_by(N2) c2 = odd_part(c) Nc = gcd(Integer(2 * N), Integer(c)) cNc = ZZ(c).divide_knowing_divisible_by(Nc) f1 = kronecker(-a, cNc) f2 = kronecker(cNc, ZZ(2 * N).divide_knowing_divisible_by(Nc)) if (is_odd(c)): s = c * N2 elif (c % Neven == 0): s = (c2 + 1 - N2) * (a + 1) else: s = (c2 + 1 - N2) * (a + 1) - N2 * a * c2 r = -1 - QQ(N2) / QQ(gcd(c, N2)) + s xi = f1 * f2 * z**r return xi
def mittag_leffler_e(alpha, beta=1): alpha = QQ.coerce(alpha) if alpha <= QQ.zero(): raise ValueError num, den = alpha.numerator(), alpha.denominator() dop0 = prod(alpha * x * Dx + beta - num + t for t in range(num)) - x**den expo = dop0.indicial_polynomial(x).roots(QQ, multiplicities=False) pre = prod((x * Dx - k) for k in range(den) if QQ(k) not in expo) dop = pre * dop0 # homogenize dop = dop.numerator().primitive_part() expo = sorted(dop.indicial_polynomial(x).roots(QQ, multiplicities=False)) assert len(expo) == dop.order() ini = [(1 / funs.gamma(alpha * k + beta) if k in ZZ else 0) for k in expo] return IVP(0, dop, ini)
def from_discriminant(self,D): r""" Return the (r,n) s.t. D=n+-q(r). """ ZI=IntegerModRing(self._level) if(self.is_dual()): x=ZI(-D) else: x=ZI(D) for j in self._D: x=self.Qv[j] n=QQ(D)/QQ(self._level)-QQ(x) if(n % self._level == 0): print("D/4N-q(v)={0}".format(n)) return (self._D[j],ZZ(QQ(n)/QQ(self._level)))
def parse_newton_polygon(inp, query, qfield): polygons = [] for polygon in BRACKETING_RE.finditer(inp): polygon = polygon.groups()[0][1:-1] if '[' in polygon or ']' in polygon: raise ValueError("Mismatched brackets") slopes = [] lastslope = None for slope in polygon.split(','): if not QQ_RE.match(slope): raise ValueError("%s is not a rational slope" % slope) qslope = QQ(slope) if lastslope is not None and qslope < lastslope: raise ValueError("Slopes must be increasing: %s, %s" % (lastslope, slope)) lastslope = qslope slopes.append(slope) polygons.append(slopes) replaced = BRACKETING_RE.sub('#', inp) if '[' in replaced or ']' in replaced: raise ValueError("Mismatched brackets") for slope in replaced.split(','): if slope == '#': continue if not QQ_RE.match(slope): raise ValueError("%s is not a rational slope" % slope) raise ValueError("You cannot specify slopes on their own") polygons = [_multiset_encode(poly) for poly in polygons] if len(polygons) == 1: query[qfield] = {'$contains': polygons[0]} else: query[qfield] = {'$or': [{'$contains': poly} for poly in polygons]}
def _rational_(self): r""" Convert this element to a rational number, if possible. EXAMPLES:: sage: from pyeantic import RealEmbeddedNumberField sage: K = NumberField(x**2 - 2, 'a', embedding=sqrt(AA(2))) sage: K = RealEmbeddedNumberField(K) sage: QQ(K.one()) 1 sage: QQ(K.gen()) Traceback (most recent call last): ... TypeError: not a rational number TESTS:: sage: K.one() in QQ True sage: K.gen() not in QQ True """ if not self.renf_elem.is_rational(): raise TypeError("not a rational number") return QQ(str(cppyy.gbl.eantic.cppyy.rational(self.renf_elem)))
def _integer_(self, *args): r""" Convert this element to an integer, if possible. EXAMPLES:: sage: from pyeantic import RealEmbeddedNumberField sage: K = NumberField(x**2 - 2, 'a', embedding=sqrt(AA(2))) sage: K = RealEmbeddedNumberField(K) sage: ZZ(K.one()) 1 sage: ZZ(K.gen()) Traceback (most recent call last): ... TypeError: not an integer TESTS:: sage: K.one() in ZZ True sage: K.gen() not in ZZ True """ if not self.renf_elem.is_integer(): raise TypeError("not an integer") return QQ(self).numerator()
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 _call_(self, x): r""" Convert ``x`` to the codomain. EXAMPLES:: sage: from pyeantic import RealEmbeddedNumberField sage: K = NumberField(x**2 - 2, 'a', embedding=sqrt(AA(2))) sage: KK = RealEmbeddedNumberField(K) sage: a = KK.an_element() sage: K(a) a sage: K = NumberField(x**2 - 2, 'b', embedding=sqrt(AA(2))) sage: KK = RealEmbeddedNumberField(K) sage: b = KK.an_element() sage: K(b) b """ rational_coefficients = [ ZZ(c.get_str()) / ZZ(x.renf_elem.den().get_str()) for c in x.renf_elem.num_vector() ] while len(rational_coefficients) < self.domain().number_field.degree(): rational_coefficients.append(QQ.zero()) return self.codomain()(rational_coefficients)
def EllipticCurve_from_hoeij_data(line): """Given a line of the file "http://www.math.fsu.edu/~hoeij/files/X1N/LowDegreePlaces" that is actually corresponding to an elliptic curve, this function returns the elliptic curve corresponding to this """ Rx=PolynomialRing(QQ,'x') x = Rx.gen(0) Rxy = PolynomialRing(Rx,'y') y = Rxy.gen(0) N=ZZ(line.split(",")[0].split()[-1]) x_rel=Rx(line.split(',')[-2][2:-4]) assert x_rel.leading_coefficient()==1 y_rel=line.split(',')[-1][1:-5] K = QQ.extension(x_rel,'x') x = K.gen(0) y_rel=Rxy(y_rel).change_ring(K) y_rel=y_rel/y_rel.leading_coefficient() if y_rel.degree()==1: y = - y_rel[0] else: #print "needing an extension!!!!" L = K.extension(y_rel,'y') y = L.gen(0) K = L #B=L.absolute_field('s') #f1,f2 = B.structure() #x,y=f2(x),f2(y) r = (x**2*y-x*y+y-1)/x/(x*y-1) s = (x*y-y+1)/x/y b = r*s*(r-1) c = s*(r-1) E=EllipticCurve([1-c,-b,-b,0,0]) return N,E,K
def tink12(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, k): if ((k % _sage_const_12) == _sage_const_0): S = a0 if ((k % _sage_const_12) == _sage_const_1): S = a1 if ((k % _sage_const_12) == _sage_const_2): S = a2 if ((k % _sage_const_12) == _sage_const_3): S = a3 if ((k % _sage_const_12) == _sage_const_4): S = a4 if ((k % _sage_const_12) == _sage_const_5): S = a5 if ((k % _sage_const_12) == _sage_const_6): S = a6 if ((k % _sage_const_12) == _sage_const_7): S = a7 if ((k % _sage_const_12) == _sage_const_8): S = a8 if ((k % _sage_const_12) == _sage_const_9): S = a9 if ((k % _sage_const_12) == _sage_const_10): S = a10 if ((k % _sage_const_12) == _sage_const_11): S = a11 return QQ(S)
def x10_with_prec_inner(prec): prec = PrecisionDeg2(prec) load_cached_gens_from_file(prec) k = 10 key = "x" + str(k) f = load_deg2_cached_gens(key, prec, k, cuspidal=True) if f: return f es4 = eisenstein_series_degree2(4, prec) es6 = eisenstein_series_degree2(6, prec) es10 = eisenstein_series_degree2(10, prec) res = QQ(43867) * QQ(2 ** 10 * 3 ** 5 * 5 ** 2 * 7 * 53) ** (-1) * \ (- es10 + es4 * es6) res._is_cuspidal = True res._is_gen = key Deg2global_gens_dict[key] = res return res.change_ring(ZZ)
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 __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 __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 __init__(self,WR,weight=QQ(1)/QQ(2),use_symmetry=True,group=SL2Z,dual=False,**kwargs): r""" WR should be a Weil representation. INPUT: - weight -- weight (should be consistent with the signature of self) - use_symmetry -- if False we do not symmetrize the functions with respect to Z -- if True we need a compatible weight - 'group' -- Group to act on. """ if isinstance(WR,(Integer,int)): #self.WR=WeilRepDiscriminantForm(WR) #self.WR=WeilModule(WR) self._weil_module = WeilModule(WR) elif hasattr(WR,"signature"): self._weil_module=WR else: raise ValueError,"{0} is not a Weil module!".format(WR) self._sym_type = 0 if group.level() <>1: raise NotImplementedError,"Only Weil representations of SL2Z implemented!" self._group = MySubgroup(Gamma0(1)) self._dual = int(dual) self._sgn = (-1)**self._dual self.Qv=[] self._weight = weight self._use_symmetry = use_symmetry self._kwargs = kwargs self._sgn = (-1)**int(dual) half = QQ(1)/QQ(2) threehalf = QQ(3)/QQ(2) if use_symmetry: ## First find weight mod 2: twok= QQ(2)*QQ(weight) if not twok.is_integral(): raise ValueError,"Only integral or half-integral weights implemented!" kmod2 = QQ(twok % 4)/QQ(2) if dual: sig_mod_4 = -self._weil_module.signature() % 4 else: sig_mod_4 = self._weil_module.signature() % 4 sym_type = 0 if (kmod2,sig_mod_4) in [(half,1),(threehalf,3),(0,0),(1,2)]: sym_type = 1 elif (kmod2,sig_mod_4) in [(half,3),(threehalf,1),(0,2),(1,0)]: sym_type = -1 else: raise ValueError,"The Weil module with signature {0} is incompatible with the weight {1}!".format( self._weil_module.signature(),weight) ## Deven and Dodd contains the indices for the even and odd basis Deven=[]; Dodd=[] if sym_type==1: self._D = self._weil_module.even_submodule(indices=1) else: #sym_type==-1: self._D = self._weil_module.odd_submodule(indices=1) self._sym_type=sym_type dim = len(self._D) #Dfinish-Dstart+1 else: dim = len(self._weil_module.finite_quadratic_module().list()) self._D = range(dim) self._sym_type=0 if hasattr(self._weil_module,"finite_quadratic_module"): # for x in list(self._weil_module.finite_quadratic_module()): for x in self._weil_module.finite_quadratic_module(): self.Qv.append(self._weil_module.finite_quadratic_module().Q(x)) else: self.Qv=self._weil_module.Qv ambient_rank = self._weil_module.rank() MultiplierSystem.__init__(self,self._group,dual=dual,dimension=dim,ambient_rank=ambient_rank)
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)
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 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 fix_t(t): tsage = QQ("%d/%d" % (t[0], t[1])) return [int(tsage.numerator()), int(tsage.denominator())]
def compute_satake_parameters_numeric(self, prec=10, bits=53,insert_in_db=True): r""" Compute the Satake parameters and return an html-table. We only do satake parameters for primes p primitive to the level. By defintion the S. parameters are given as the roots of X^2 - c(p)X + chi(p)*p^(k-1) if (p,N)=1 INPUT: -''prec'' -- compute parameters for p <=prec -''bits'' -- do real embedings intoi field of bits precision """ if self.character().order()>2: ## We only implement this for trival or quadratic characters. ## Otherwise there is difficulty to figure out what the embeddings mean... return K = self.coefficient_field() degree = self.degree() RF = RealField(bits) CF = ComplexField(bits) ps = prime_range(prec) self._satake['ps'] = [] alphas = dict() thetas = dict() aps = list() tps = list() k = self.weight() for j in range(degree): alphas[j] = dict() thetas[j] = dict() for j in xrange(len(ps)): p = ps[j] try: ap = self.coefficient(p) except IndexError: break # Remove bad primes if p.divides(self.level()): continue self._satake['ps'].append(p) chip = self.character().value(p) wmf_logger.debug("p={0}".format(p)) wmf_logger.debug("chip={0} of type={1}".format(chip,type(chip))) if hasattr(chip,'complex_embeddings'): wmf_logger.debug("embeddings(chip)={0}".format(chip.complex_embeddings())) wmf_logger.debug("ap={0}".format(ap)) wmf_logger.debug("K={0}".format(K)) # ap=self._f.coefficients(ZZ(prec))[p] if K.absolute_degree()==1: f1 = QQ(4 * chip * p ** (k - 1) - ap ** 2) alpha_p = (QQ(ap) + I * f1.sqrt()) / QQ(2) ab = RF(p ** ((k - 1) / 2)) norm_alpha = alpha_p / ab t_p = CF(norm_alpha).argument() thetas[0][p] = t_p alphas[0][p] = (alpha_p / ab).n(bits) else: for jj in range(degree): app = ap.complex_embeddings(bits)[jj] wmf_logger.debug("chip={0}".format(chip)) wmf_logger.debug("app={0}".format(app)) wmf_logger.debug("jj={0}".format(jj)) if not hasattr(chip,'complex_embeddings'): f1 = (4 * CF(chip) * p ** (k - 1) - app ** 2) else: f1 = (4 * chip.complex_embeddings(bits)[jj] * p ** (k - 1) - app ** 2) alpha_p = (app + I * abs(f1).sqrt()) # ab=RF(/RF(2))) # alpha_p=alpha_p/RealField(bits)(2) wmf_logger.debug("f1={0}".format(f1)) alpha_p = alpha_p / RF(2) wmf_logger.debug("alpha_p={0}".format(alpha_p)) t_p = CF(alpha_p).argument() # tps.append(t_p) # aps.append(alpha_p) alphas[jj][p] = alpha_p thetas[jj][p] = t_p self._satake['alphas'] = alphas self._satake['thetas'] = thetas self._satake['alphas_latex'] = dict() self._satake['thetas_latex'] = dict() for j in self._satake['alphas'].keys(): self._satake['alphas_latex'][j] = dict() for p in self._satake['alphas'][j].keys(): s = latex(self._satake['alphas'][j][p]) self._satake['alphas_latex'][j][p] = s for j in self._satake['thetas'].keys(): self._satake['thetas_latex'][j] = dict() for p in self._satake['thetas'][j].keys(): s = latex(self._satake['thetas'][j][p]) self._satake['thetas_latex'][j][p] = s wmf_logger.debug("satake=".format(self._satake)) return self._satake
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 render_curve_webpage_by_label(label): C = lmfdb.base.getDBConnection() data = C.elliptic_curves.curves.find_one({'lmfdb_label': label}) if data is None: return elliptic_curve_jump_error(label, {}) info = {} ainvs = [int(a) for a in data['ainvs']] E = EllipticCurve(ainvs) cremona_label = data['label'] lmfdb_label = data['lmfdb_label'] N = ZZ(data['conductor']) cremona_iso_class = data['iso'] # eg '37a' lmfdb_iso_class = data['lmfdb_iso'] # eg '37.a' rank = data['rank'] try: j_invariant = QQ(str(data['jinv'])) except KeyError: j_invariant = E.j_invariant() if j_invariant == 0: j_inv_factored = latex(0) else: j_inv_factored = latex(j_invariant.factor()) jinv = unicode(str(j_invariant)) CMD = 0 CM = "no" EndE = "\(\Z\)" if E.has_cm(): CMD = E.cm_discriminant() CM = "yes (\(%s\))"%CMD if CMD%4==0: d4 = ZZ(CMD)//4 # r = d4.squarefree_part() # f = (d4//r).isqrt() # f="" if f==1 else str(f) # EndE = "\(\Z[%s\sqrt{%s}]\)"%(f,r) EndE = "\(\Z[\sqrt{%s}]\)"%(d4) else: EndE = "\(\Z[(1+\sqrt{%s})/2]\)"%CMD # plot=E.plot() discriminant = E.discriminant() xintpoints_projective = [E.lift_x(x) for x in xintegral_point(data['x-coordinates_of_integral_points'])] xintpoints = proj_to_aff(xintpoints_projective) if 'degree' in data: modular_degree = data['degree'] else: try: modular_degree = E.modular_degree() except RuntimeError: modular_degree = 0 # invalid, will be displayed nicely G = E.torsion_subgroup().gens() minq = E.minimal_quadratic_twist()[0] if E == minq: minq_label = lmfdb_label else: minq_ainvs = [str(c) for c in minq.ainvs()] minq_label = C.elliptic_curves.curves.find_one({'ainvs': minq_ainvs})['lmfdb_label'] # We do not just do the following, as Sage's installed database # might not have all the curves in the LMFDB database. # minq_label = E.minimal_quadratic_twist()[0].label() if 'gens' in data: generator = parse_gens(data['gens']) if len(G) == 0: tor_struct = '\mathrm{Trivial}' tor_group = '\mathrm{Trivial}' else: tor_group = ' \\times '.join(['\Z/{%s}\Z' % a.order() for a in G]) if 'torsion_structure' in data: info['tor_structure'] = ' \\times '.join(['\Z/{%s}\Z' % int(a) for a in data['torsion_structure']]) else: info['tor_structure'] = tor_group info.update(data) if rank >= 2: lder_tex = "L%s(E,1)" % ("^{(" + str(rank) + ")}") elif rank == 1: lder_tex = "L%s(E,1)" % ("'" * rank) else: assert rank == 0 lder_tex = "L(E,1)" info['Gamma0optimal'] = ( cremona_label[-1] == '1' if cremona_iso_class != '990h' else cremona_label[-1] == '3') info['modular_degree'] = modular_degree p_adic_data_exists = (C.elliptic_curves.padic_db.find( {'lmfdb_iso': lmfdb_iso_class}).count()) > 0 and info['Gamma0optimal'] # Local data local_data = [] for p in N.prime_factors(): local_info = E.local_data(p) local_data.append({'p': p, 'tamagawa_number': local_info.tamagawa_number(), 'kodaira_symbol': web_latex(local_info.kodaira_symbol()).replace('$', ''), 'reduction_type': local_info.bad_reduction_type() }) mod_form_iso = lmfdb_label_regex.match(lmfdb_iso_class).groups()[1] info.update({ 'conductor': N, 'disc_factor': latex(discriminant.factor()), 'j_invar_factor': j_inv_factored, 'label': lmfdb_label, 'cremona_label': cremona_label, 'iso_class': lmfdb_iso_class, 'cremona_iso_class': cremona_iso_class, 'equation': web_latex(E), #'f': ajax_more(E.q_eigenform, 10, 20, 50, 100, 250), 'f': web_latex(E.q_eigenform(10)), 'generators': ', '.join(web_latex(g) for g in generator) if 'gens' in data else ' ', 'lder': lder_tex, 'p_adic_primes': [p for p in sage.all.prime_range(5, 100) if E.is_ordinary(p) and not p.divides(N)], 'p_adic_data_exists': p_adic_data_exists, 'ainvs': format_ainvs(data['ainvs']), 'CM': CM, 'CMD': CMD, 'EndE': EndE, 'tamagawa_numbers': r' \cdot '.join(str(sage.all.factor(c)) for c in E.tamagawa_numbers()), 'local_data': local_data, 'cond_factor': latex(N.factor()), 'xintegral_points': ', '.join(web_latex(P) for P in xintpoints), 'tor_gens': ', '.join(web_latex(eval(g)) for g in data['torsion_generators']) if False else ', '.join(web_latex(P.element().xy()) for P in list(G)) }) info['friends'] = [ ('Isogeny class ' + lmfdb_iso_class, "/EllipticCurve/Q/%s" % lmfdb_iso_class), ('Minimal quadratic twist ' + minq_label, "/EllipticCurve/Q/%s" % minq_label), ('All twists ', url_for("rational_elliptic_curves", jinv=jinv)), ('L-function', url_for("l_functions.l_function_ec_page", label=lmfdb_label)), ('Symmetric square L-function', url_for("l_functions.l_function_ec_sym_page", power='2', label=lmfdb_iso_class)), ('Symmetric 4th power L-function', url_for("l_functions.l_function_ec_sym_page", power='4', label=lmfdb_iso_class))] info['friends'].append(('Modular form ' + lmfdb_iso_class.replace('.', '.2'), url_for( "emf.render_elliptic_modular_forms", level=int(N), weight=2, character=0, label=mod_form_iso))) info['downloads'] = [('Download coeffients of q-expansion', url_for("download_EC_qexp", label=lmfdb_label, limit=100)), ('Download all stored data', url_for("download_EC_all", label=lmfdb_label))] # info['learnmore'] = [('Elliptic Curves', url_for("not_yet_implemented"))] # info['plot'] = image_src(plot) info['plot'] = url_for('plot_ec', label=lmfdb_label) properties2 = [('Label', '%s' % lmfdb_label), (None, '<img src="%s" width="200" height="150"/>' % url_for( 'plot_ec', label=lmfdb_label)), ('Conductor', '\(%s\)' % N), ('Discriminant', '\(%s\)' % discriminant), ('j-invariant', '%s' % web_latex(j_invariant)), ('CM', '%s' % CM), ('Rank', '\(%s\)' % rank), ('Torsion Structure', '\(%s\)' % tor_group) ] # properties.extend([ "prop %s = %s<br/>" % (_,_*1923) for _ in range(12) ]) credit = 'John Cremona' if info['label'] == info['cremona_label']: t = "Elliptic Curve %s" % info['label'] else: t = "Elliptic Curve %s (Cremona label %s)" % (info['label'], info['cremona_label']) bread = [('Elliptic Curves ', url_for("rational_elliptic_curves")), ('Elliptic curves %s' % lmfdb_label, ' ')] return render_template("elliptic_curve/elliptic_curve.html", properties2=properties2, credit=credit, bread=bread, title=t, info=info, friends=info['friends'], downloads=info['downloads'])
def make_t_label(t): tsage = QQ(t) return "t%s.%s" % (tsage.numerator(), tsage.denominator())
def make_t_label(t): tsage = QQ("%d/%d" % (t[0], t[1])) return "t%s.%s" % (tsage.numerator(), tsage.denominator())
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 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,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) 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 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 get_satake_parameters(k, N=1, chi=0, fi=0, prec=10, bits=53, angles=False): r""" Compute the Satake parameters and return an html-table. INPUT: - ''k'' -- positive integer : the weight - ''N'' -- positive integer (default 1) : level - ''chi'' -- non-neg. integer (default 0) use character nr. chi - ''fi'' -- non-neg. integer (default 0) We want to use the element nr. fi f=Newforms(N,k)[fi] -''prec'' -- compute parameters for p <=prec -''bits'' -- do real embedings intoi field of bits precision -''angles''-- return the angles t_p instead of the alpha_p here alpha_p=p^((k-1)/2)exp(i*t_p) """ (t, f) = _get_newform(k, N, chi, fi) if(not t): return f K = f.base_ring() RF = RealField(bits) CF = ComplexField(bits) if(K != QQ): M = len(K.complex_embeddings()) ems = dict() for j in range(M): ems[j] = list() ps = prime_range(prec) alphas = list() for p in ps: ap = f.coefficients(ZZ(prec))[p] if(K == QQ): f1 = QQ(4 * p ** (k - 1) - ap ** 2) alpha_p = (QQ(ap) + I * f1.sqrt()) / QQ(2) # beta_p=(QQ(ap)-I*f1.sqrt())/QQ(2) # satake[p]=(alpha_p,beta_p) ab = RF(p ** ((k - 1) / 2)) norm_alpha = alpha_p / ab t_p = CF(norm_alpha).argument() if(angles): alphas.append(t_p) else: alphas.append(alpha_p) else: for j in range(M): app = ap.complex_embeddings(bits)[j] f1 = (4 * p ** (k - 1) - app ** 2) alpha_p = (app + I * f1.sqrt()) / RealField(bits)(2) ab = RF(p ** ((k - 1) / 2)) norm_alpha = alpha_p / ab t_p = CF(norm_alpha).argument() if(angles): ems[j].append(t_p) else: ems[j].append(alpha_p) tbl = dict() tbl['headersh'] = ps if(K == QQ): tbl['headersv'] = [""] tbl['data'] = [alphas] tbl['corner_label'] = "$p$" else: tbl['data'] = list() tbl['headersv'] = list() tbl['corner_label'] = "Embedding \ $p$" for j in ems.keys(): tbl['headersv'].append(j) tbl['data'].append(ems[j]) # logger.debug(tbl) s = html_table(tbl) return s
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_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