def siegel_series_dim2(q, p): det_4 = q.Gram_det() * ZZ(4) c = q.content_order() fd = fundamental_discriminant(-det_4) f = (valuation(det_4, p) - valuation(fd, p)) / ZZ(2) return (_siegel_series_dim2(p, c, f + 1) - kronecker_symbol(fd, p) * p * X * _siegel_series_dim2(p, c, f))
def _fc__unramfactor(self, content, det_4): chi = kronecker_character(-det_4) pfacs = prime_factors(det_4) fd = fundamental_discriminant(-det_4) l = [(p, valuation(content, p), (valuation(det_4, p) - valuation(fd, p)) / 2) for p in pfacs] return reduce(operator.mul, [self._fc__unramfactor_at_p(p, ci, fi, chi) for (p, ci, fi) in l])
def gauss_valuation(poly, prime, prec=30): """Compute the Gauss norm of the given polynomial, with prime identifying the valuation.""" if is_Polynomial(poly): return min([valuation(c, prime) for c in poly]) if is_LaurentSeries(poly): return series_valuation(poly, prime, prec) else: # in case we just get a constant return valuation(poly, prime)
def _jordan_decomposition_2(S): ''' Input: S: half integral matrix Output: list of tuples (a, b) Here a is an integer which is an exponent. b is equal to an element of [1, 3, 5, 7] or 'h' or 'y'. ''' n = len(S.columns()) acc = [] while True: i0, j0 = find_min_ord_elet(S, 2) if (n == 1) or (n == 2 and i0 != j0): mat_lst = acc + [S] break if i0 == j0: S = _jordan_dcomp_diag(i0, n, S) acc.append(S.submatrix(nrows=1, ncols=1)) S = S.submatrix(row=1, col=1) n -= 1 else: # (0, 1) element has the minimal order. S = bracket_action(S, perm_mat2(i0, j0, n)) u = identity_matrix(QQ, n) for j in range(2, n): s00, s01, s11 = S[(0, 0)], S[(0, 1)], S[(1, 1)] d = s00 * s11 - s01 ** 2 s0j = S[(0, j)] s1j = S[(1, j)] a0 = (-s11 * s0j + s01 * s1j) / d a1 = (s01 * s0j - s00 * s1j) / d u[(0, j)] = a0 u[(1, j)] = a1 S = bracket_action(S, u) acc.append(S.submatrix(nrows=2, ncols=2)) S = S.submatrix(row=2, col=2) n -= 2 res = [] for m in mat_lst: if m.ncols() == 1: a = m[0, 0] e = valuation(a, two) u = (a / two ** e) % 8 res.append((e, u)) else: e = valuation(m[0, 1], two) + 1 m = m / two ** (e - 1) if m.det() % 8 == 3: h_or_y = 'y' else: h_or_y = 'h' res.append((e, h_or_y)) return res
def poly_reduced_degree(poly, prime): if is_Polynomial(poly): i = poly.degree() v = 1 while v > 0 and i >= 0: v = valuation(poly[i], prime) i -= 1 return i+1 elif valuation(poly, prime) > 0: return -infinity else: return 0
def _xc(self,c,as_int=False): r""" Return the element x_c of order 2 (for this Discriminant form 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 """ x_c=0 if(valuation(2*self._N,2)==valuation(c,2)): if(as_int): x_c=self._N else: x_c=QQ(1)/QQ(2) return x_c
def series_reduced_valuation(series, prime): i = series.valuation() v = 1 while v > 0: v = valuation(series[i], prime) i += 1 return i-1
def find_min_ord_elet(S, p): ''' S: ((1+delta_ij)/2 s_ij) half integral matrix Retruns (i, j) such that s_ij != 0 and ord((1+delta_ij)/2 s_ij) is min. If p = 2, then index (i, j) (i != j) is preferred. If p is odd, index (i, j) (i == j) is preferred. ''' p = Integer(p) n = len(S.columns()) elts_with_idx = [(S[(i, j)], (i, j)) if i == j else (S[(i, j)] * 2, (i, j)) for i in range(n) for j in range(n) if i <= j and S[(i, j)] != 0] val_with_idx = [(valuation(e, p), i) for e, i in elts_with_idx] min_val = min([v for v, _ in val_with_idx]) min_val_idcs = [i for v, i in val_with_idx if v == min_val] if p != 2: for i, j in min_val_idcs: if i == j: return (i, j) return min_val_idcs[0] else: for i, j in min_val_idcs: if i != j: return (i, j) return min_val_idcs[0]
def _chi_p_odd(a, p): p = ZZ(p) r = valuation(a, p) if r % 2 == 0: c = a // (p ** r) return kronecker_symbol(c, p) else: return 0
def modvecupper(A, p): Ap = [] for a in A: v = valuation(a, p) ap = p**v aprime = a / ap Ap.extend([aprime] * euler_phi(ap)) Ap.sort(reverse=True) return Ap
def Qc(self,c,x): r""" compute Q_c(x) for x in D^c* """ Dcstar=self._D_times_c_star(c) if (not x in Dcstar): raise ValueError(" Call only for x in D^c*! Got x={0} and D^c*={1}".format(x,Dcstar)) xc=0 if(valuation(c,2)==valuation(2*self._N,2)): xc=QQ(1)/QQ(2) cy=x-xc Dc=self._D_times_c(c) for y in Dc: p=numerator(y*c) q=denominator(y*c) if(QQ(p%q)/QQ(q) == QQ(cy)): Qc=c*self.Q(y)+self.B(xc,y) return Qc return ArithmeticError," Could not find y s.t. x=x_c+cy! x=%s and c=%s " %(x,c)
def small_d(q): ''' d(B) given in Thoerem 3.2. ''' two = ZZ(2) n = q.dim() p = q.p larged = two ** (2 * (n // 2)) * q.Gram_det() return valuation(larged, p)
def Qc(self,c,x): r""" compute Q_c(x) for x in D^c* """ Dcstar=self._D_times_c_star(c) if (not x in Dcstar): raise ValueError," Call only for x in D^c*! Got x=%s and D^c*=%s" %(x,Dcstar) xc=0 if(valuation(c,2)==valuation(2*self._N,2)): xc=QQ(1)/QQ(2) cy=x-xc Dc=self._D_times_c(c) for y in Dc: p=numerator(y*c) q=denominator(y*c) if( QQ(p%q)/QQ(q) == QQ(cy)): Qc=c*self.Q(y)+self.B(xc,y) return Qc return ArithmeticError," Could not find y s.t. x=x_c+cy! x=%s and c=%s " %(x,c)
def id_dirichlet(fun, N, n): N = Integer(N) if N == 1: return (1, 1) p2 = valuation(N, 2) N2 = 2**p2 Nodd = N // N2 Nfact = list(factor(Nodd)) #print "n = "+str(n) #for j in range(20): # print "chi(%d) = e(%d/%d)"%(j+2, fun(j+2,n), n) plist = [z[0] for z in Nfact] ppows = [z[0]**z[1] for z in Nfact] ppows2 = list(ppows) idems = [1 for z in Nfact] proots = [primitive_root(z) for z in ppows] # Get CRT idempotents if p2 > 0: ppows2.append(N2) for j in range(len(plist)): exps = [1 for z in idems] if p2 > 0: exps.append(1) exps[j] = proots[j] idems[j] = crt(exps, ppows2) idemvals = [fun(z, n) for z in idems] # now normalize to right root of unity base idemvals = [ idemvals[j] * euler_phi(ppows[j]) / n for j in range(len(idemvals)) ] ans = [ Integer(mod(proots[j], ppows[j])**idemvals[j]) for j in range(len(proots)) ] ans = crt(ans, ppows) # There are cases depending on 2-part of N if p2 == 0: return (N, ans) if p2 == 1: return (N, crt([1, ans], [2, Nodd])) if p2 == 2: my3 = crt([3, 1], [N2, Nodd]) if fun(my3, n) == 0: return (N, crt([1, ans], [4, Nodd])) else: return (N, crt([3, ans], [4, Nodd])) # Final case 2^3 | N my5 = crt([5, 1], [N2, Nodd]) test1 = fun(my5, n) * N2 / 4 / n test1 = Integer(mod(5, N2)**test1) minusone = crt([-1, 1], [N2, Nodd]) test2 = (fun(minusone, n) * N2 / 4 / n) % (N2 / 4) if test2 > 0: test1 = Integer(mod(-test1, N2)) return (N, crt([test1, ans], [N2, Nodd]))
def splitint(a, p): if a == 1: return ' ' j = valuation(a, p) if j == 0: return str(a) a = a / p**j if a == 1: return latex(ZZ(p**j).factor()) return str(a) + r'\cdot' + latex(ZZ(p**j).factor())
def _i_func(q): '''Return i(B) in Katsurada's paper. ''' m = ZZ(2) * (q.matrix()) ** (-1) i = valuation(gcd(m.list()), ZZ(2)) m = ZZ(2) ** (-i) * m if all(m[a, a] % 2 == 0 for a in range(m.ncols())): return - i - 1 else: return - i
def splitint(a,p): if a==1: return ' ' j = valuation(a,p) if j==0: return str(a) a = a/p**j if a==1: return latex(ZZ(p**j).factor()) return str(a)+r'\cdot'+latex(ZZ(p**j).factor())
def id_dirichlet(fun, N, n): N = Integer(N) if N == 1: return (1, 1) p2 = valuation(N, 2) N2 = 2 ** p2 Nodd = N / N2 Nfact = list(factor(Nodd)) # print "n = "+str(n) # for j in range(20): # print "chi(%d) = e(%d/%d)"%(j+2, fun(j+2,n), n) plist = [z[0] for z in Nfact] ppows = [z[0] ** z[1] for z in Nfact] ppows2 = list(ppows) idems = [1 for z in Nfact] proots = [primitive_root(z) for z in ppows] # Get CRT idempotents if p2 > 0: ppows2.append(N2) for j in range(len(plist)): exps = [1 for z in idems] if p2 > 0: exps.append(1) exps[j] = proots[j] idems[j] = crt(exps, ppows2) idemvals = [fun(z, n) for z in idems] # now normalize to right root of unity base idemvals = [idemvals[j] * euler_phi(ppows[j]) / n for j in range(len(idemvals))] ans = [Integer(mod(proots[j], ppows[j]) ** idemvals[j]) for j in range(len(proots))] ans = crt(ans, ppows) # There are cases depending on 2-part of N if p2 == 0: return (N, ans) if p2 == 1: return (N, crt([1, ans], [2, Nodd])) if p2 == 2: my3 = crt([3, 1], [N2, Nodd]) if fun(my3, n) == 0: return (N, crt([1, ans], [4, Nodd])) else: return (N, crt([3, ans], [4, Nodd])) # Final case 2^3 | N my5 = crt([5, 1], [N2, Nodd]) test1 = fun(my5, n) * N2 / 4 / n test1 = Integer(mod(5, N2) ** test1) minusone = crt([-1, 1], [N2, Nodd]) test2 = (fun(minusone, n) * N2 / 4 / n) % (N2 / 4) if test2 > 0: test1 = Integer(mod(-test1, N2)) return (N, crt([test1, ans], [N2, Nodd]))
def IsSquareInQp(x, p): if x == 0: return true # Check parity of valuation v = valuation(x, p) if v % 2: return false # Renormalise to get a unit x //= p**v # Reduce mod p and conclude if p == 2: return Mod(x, 8) == 1 else: return kronecker_symbol(x, p) == 1
def IsSquareInQp(x,p): if x==0: return true # Check parity of valuation v=valuation(x,p) if v%2: return false # Renormalise to get a unit x//=p**v # Reduce mod p and conclude if p==2: return Mod(x,8)==1 else: return kronecker_symbol(x,p)==1
def _chi_2(a): two = ZZ(2) r = valuation(a, two) if r % 2 == 1: return 0 else: c = a // (two ** r) rem = c % 8 if rem == 1: return 1 elif rem == 5: return -1 else: return 0
def series_valuation(series, prime, prec=30): """Compute the Gauss norm of the given Laurent series, with prime identifying the valuation. For practical reasons, we use a simple heuristic to determine if this valuation is bounded: We look at prec terms, and unless the minimal valuation occurs in the first two thirds of these, we say that we have unbounded valuation.""" assert is_LaurentSeries(series) deg = series.valuation() trunc = series.truncate(prec - deg) coeffs = [valuation(c, prime) for c in list(trunc)] allmin = apply(min, coeffs) end = (2 * len(coeffs)) // 3 startmin = apply(min, coeffs[:end]) if startmin > allmin: return -infinity else: return allmin
def jordan_blocks_odd(S, p): ''' p: odd prime, S: half integral matrix. Let S ~ sum p**a_i * b_i * x_i^2 be a jordan decomposition. Returns the instance of JordanBlocks attached to a list of (a_i, b_i) sorted so that a_0 >= a_1 >= ... ''' p = Integer(p) res = [] u = least_quadratic_nonresidue(p) for e, ls in groupby(_jordan_decomposition_odd_p(S, p), key=lambda x: valuation(x, p)): ls = [x // p ** e for x in ls] part_res = [(e, ZZ(1)) for _ in ls] if legendre_symbol(mul(ls), p) == -1: part_res[-1] = (e, u) res.extend(part_res) return JordanBlocks(list(reversed(res)), p)
def pnotp(a,p): pv = p**valuation(a,p) return [pv, a/pv]
def rho(self,M,silent=0,numeric=0,prec=-1): r""" The Weil representation acting on SL(2,Z). INPUT:: -``M`` -- element of SL2Z - ''numeric'' -- set to 1 to return a Matrix_complex_dense with prec=prec instead of exact - ''prec'' -- precision EXAMPLES:: sage: WR=WeilRepDiscriminantForm(1,dual=False) sage: S,T=SL2Z.gens() sage: WR.rho(S) [ [-zeta8^3 -zeta8^3] [-zeta8^3 zeta8^3], sqrt(1/2) ] sage: WR.rho(T) [ [ 1 0] [ 0 -zeta8^2], 1 ] sage: A=SL2Z([-1,1,-4,3]); WR.rho(A) [ [zeta8^2 0] [ 0 1], 1 ] sage: A=SL2Z([41,77,33,62]); WR.rho(A) [ [-zeta8^3 zeta8^3] [ zeta8 zeta8], sqrt(1/2) ] """ N=self._N; D=2*N; D2=2*D if numeric==0: K=CyclotomicField (lcm(4*self._N,8)) z=K(CyclotomicField(4*self._N).gen()) rho=matrix(K,D) else: CF = MPComplexField(prec) RF = CF.base() MS = MatrixSpace(CF,int(D),int(D)) rho = Matrix_complex_dense(MS) #arg = RF(2)*RF.pi()/RF(4*self._N) z = CF(0,RF(2)*RF.pi()/RF(4*self._N)).exp() [a,b,c,d]=M fak=1; sig=1 if c<0: # need to use the reflection # r(-A)=r(Z)r(A)sigma(Z,A) where sigma(Z,A)=-1 if c>0 sig=-1 if numeric==0: fz=CyclotomicField(4).gen() # = i else: fz=CF(0,1) # the factor is rho(Z) sigma(Z,-A) #if(c < 0 or (c==0 and d>0)): # fak=-fz #else: #sig=1 #fz=1 fak=fz a=-a; b=-b; c=-c; d=-d; A=SL2Z([a,b,c,d]) if numeric==0: chi=self.xi(A) else: chi=CF(self.xi(A).complex_embedding(prec)) if(silent>0): print "fz=",fz print "chi=",chi elif c==0: # then we use the simple formula if d<0: sig=-1 if numeric==0: fz=CyclotomicField(4).gen() else: fz=CF(0,1) fak=fz a=-a; b=-b; c=-c; d=-d; else: fak=1 for alpha in range(D): arg=(b*alpha*alpha ) % D2 if(sig==-1): malpha = (D - alpha) % D rho[malpha,alpha]=fak*z**arg else: #print "D2=",D2 #print "b=",b #print "arg=",arg rho[alpha,alpha]=z**arg return [rho,1] else: if numeric==0: chi=self.xi(M) else: chi=CF(self.xi(M).complex_embedding(prec)) Nc=gcd(Integer(D),Integer(c)) #chi=chi*sqrt(CF(Nc)/CF(D)) if( valuation(Integer(c),2)==valuation(Integer(D),2)): xc=Integer(N) else: xc=0 if(silent>0): print "c=",c print "xc=",xc print "chi=",chi for alpha in range(D): al=QQ(alpha)/QQ(D) for beta in range(D): be=QQ(beta)/QQ(D) c_div=False if(xc==0): alpha_minus_dbeta=(alpha-d*beta) % D else: alpha_minus_dbeta=(alpha-d*beta-xc) % D if(silent > 0): # and alpha==7 and beta == 7): print "alpha,beta=",alpha,',',beta print "c,d=",c,',',d print "alpha-d*beta=",alpha_minus_dbeta invers=0 for r in range(D): if((r*c - alpha_minus_dbeta) % D ==0): c_div=True invers=r break if c_div and silent > 0: print "invers=",invers print " inverse(alpha-d*beta) mod c=",invers elif(silent>0): print " no inverse!" if(c_div): y=invers if xc==0: argu=a*c*y**2+b*d*beta**2+2*b*c*y*beta else: argu=a*c*y**2+2*xc*(a*y+b*beta)+b*d*beta**2+2*b*c*y*beta argu = argu % D2 tmp1=z**argu # exp(2*pi*I*argu) if silent>0:# and alpha==7 and beta==7): print "a,b,c,d=",a,b,c,d print "xc=",xc print "argu=",argu print "exp(...)=",tmp1 print "chi=",chi print "sig=",sig if sig==-1: minus_alpha = (D - alpha) % D rho[minus_alpha,beta]=tmp1*chi else: rho[alpha,beta]=tmp1*chi #print "fak=",fak if numeric==0: return [fak*rho,sqrt(QQ(Nc)/QQ(D))] else: return [CF(fak)*rho,RF(sqrt(QQ(Nc)/QQ(D)))]
def factored_conductor(self): return [(p, valuation(Integer(self.conductor()), p)) for p in self.bad_primes()]
def factor_base_factor(n, fb): return [[p, valuation(n,p)] for p in fb]
def ordinary(f, p): return all( valuation(f[i], p) == v for i, v in self.hodge_polygon[:middle])
def rho(self,M,silent=0,numeric=0,prec=-1): r""" The Weil representation acting on SL(2,Z). INPUT:: -``M`` -- element of SL2Z - ''numeric'' -- set to 1 to return a Matrix_complex_dense with prec=prec instead of exact - ''prec'' -- precision EXAMPLES:: sage: WR=WeilRepDiscriminantForm(1,dual=False) sage: S,T=SL2Z.gens() sage: WR.rho(S) [ [-zeta8^3 -zeta8^3] [-zeta8^3 zeta8^3], sqrt(1/2) ] sage: WR.rho(T) [ [ 1 0] [ 0 -zeta8^2], 1 ] sage: A=SL2Z([-1,1,-4,3]); WR.rho(A) [ [zeta8^2 0] [ 0 1], 1 ] sage: A=SL2Z([41,77,33,62]); WR.rho(A) [ [-zeta8^3 zeta8^3] [ zeta8 zeta8], sqrt(1/2) ] """ N=self._N; D=2*N; D2=2*D if numeric==0: K=CyclotomicField (lcm(4*self._N,8)) z=K(CyclotomicField(4*self._N).gen()) rho=matrix(K,D) else: CF = MPComplexField(prec) RF = CF.base() MS = MatrixSpace(CF,int(D),int(D)) rho = Matrix_complex_dense(MS) #arg = RF(2)*RF.pi()/RF(4*self._N) z = CF(0,RF(2)*RF.pi()/RF(4*self._N)).exp() [a,b,c,d]=M fak=1; sig=1 if c<0: # need to use the reflection # r(-A)=r(Z)r(A)sigma(Z,A) where sigma(Z,A)=-1 if c>0 sig=-1 if numeric==0: fz=CyclotomicField(4).gen() # = i else: fz=CF(0,1) # the factor is rho(Z) sigma(Z,-A) #if(c < 0 or (c==0 and d>0)): # fak=-fz #else: #sig=1 #fz=1 fak=fz a=-a; b=-b; c=-c; d=-d; A=SL2Z([a,b,c,d]) if numeric==0: chi=self.xi(A) else: chi=CF(self.xi(A).complex_embedding(prec)) if(silent>0): print("fz={0}".format(fz)) print("chi={0}".format(chi)) elif c == 0: # then we use the simple formula if d < 0: sig=-1 if numeric == 0: fz=CyclotomicField(4).gen() else: fz=CF(0,1) fak=fz a=-a; b=-b; c=-c; d=-d; else: fak=1 for alpha in range(D): arg=(b*alpha*alpha ) % D2 if(sig==-1): malpha = (D - alpha) % D rho[malpha,alpha]=fak*z**arg else: #print "D2=",D2 #print "b=",b #print "arg=",arg rho[alpha,alpha]=z**arg return [rho,1] else: if numeric==0: chi=self.xi(M) else: chi=CF(self.xi(M).complex_embedding(prec)) Nc=gcd(Integer(D),Integer(c)) #chi=chi*sqrt(CF(Nc)/CF(D)) if(valuation(Integer(c),2)==valuation(Integer(D),2)): xc=Integer(N) else: xc=0 if silent>0: print("c={0}".format(c)) print("xc={0}".format(xc)) print("chi={0}".format(chi)) for alpha in range(D): al=QQ(alpha)/QQ(D) for beta in range(D): be=QQ(beta)/QQ(D) c_div=False if(xc==0): alpha_minus_dbeta=(alpha-d*beta) % D else: alpha_minus_dbeta=(alpha-d*beta-xc) % D if silent > 0: # and alpha==7 and beta == 7): print("alpha,beta={0},{1}".format(alpha,beta)) print("c,d={0},{1}".format(c,d)) print("alpha-d*beta={0}".format(alpha_minus_dbeta)) invers=0 for r in range(D): if (r*c - alpha_minus_dbeta) % D ==0: c_div=True invers=r break if c_div and silent > 0: print("invers={0}".format(invers)) print(" inverse(alpha-d*beta) mod c={0}".format(invers)) elif(silent>0): print(" no inverse!") if(c_div): y=invers if xc==0: argu=a*c*y**2+b*d*beta**2+2*b*c*y*beta else: argu=a*c*y**2+2*xc*(a*y+b*beta)+b*d*beta**2+2*b*c*y*beta argu = argu % D2 tmp1=z**argu # exp(2*pi*I*argu) if silent>0:# and alpha==7 and beta==7): print("a,b,c,d={0},{1},{2},{3}".format(a,b,c,d)) print("xc={0}".format(xc)) print("argu={0}".format(argu)) print("exp(...)={0}".format(tmp1)) print("chi={0}".format(chi)) print("sig={0}".format(sig)) if sig == -1: minus_alpha = (D - alpha) % D rho[minus_alpha,beta]=tmp1*chi else: rho[alpha,beta]=tmp1*chi #print "fak=",fak if numeric==0: return [fak*rho,sqrt(QQ(Nc)/QQ(D))] else: return [CF(fak)*rho,RF(sqrt(QQ(Nc)/QQ(D)))]
def idc(n, r, m): e = min(valuation(reduce(gcd, (n, r, m)), p), i - 1) return (e, tuple([x // p ** e for x in (n, r, m)]))