Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupport News AboutSign UpSign In
| Download
Views: 184607
1
#This is the version of twistedlseries before I started trying to parallelise it, maybe load this instead
2
3
4
from psage.number_fields.sqrt5.misc import *
5
from psage.lseries.eulerprod import LSeriesEllipticCurve, LSeriesEllipticCurveSqrt5, LSeriesTwist
6
7
def _iter__OK_mod_p(OK,P):
8
M = P.pari_hnf().sage().diagonal()
9
from itertools import product
10
reps = product(*map(range,M))
11
B = OK.basis()
12
return [sum(i*j for i,j in zip(r,B)) for r in reps]
13
14
def totally_positive_generator(p):
15
K = p.ring()
16
units = K.unit_group().gens()
17
x = p.gens_reduced()
18
assert len(x)==1, "p not pricipally generated!"
19
x = x[0]
20
M = Matrix(GF(2),[[phi(g)<0 for phi in K.real_embeddings()] for g in units])
21
v = vector(GF(2),[phi(x)<0 for phi in K.real_embeddings()])
22
x *= prod(g for g,e in zip(units,M.solve_left(v)) if e)
23
assert x.is_totally_positive(), "Totally positive generator does not exist!"
24
return x
25
26
# Given an element of a number field and a modulus prod primes returns
27
def rep(alpha, primes):
28
return [p.ideallog(alpha)[0] for p in primes]
29
30
# Hecke characters of number fields
31
class NFChar():
32
# Initialise a new Hecke character of order order, factored conductor should be a list of primes,
33
# rootlist a list of integers of the same length that describe the power of zeta that the gene
34
def __init__(self, factored_conductor, rootlist, order, zeta = None, prec = None):
35
assert all(p.is_prime() for p in factored_conductor), "factored_conductor contains an element that is not prime"
36
assert len(set(factored_conductor)) == len(factored_conductor), "factored_conductor contains duplicate elements"
37
self._factored_conductor = factored_conductor
38
self._primes_conductor = [p.smallest_integer() for p in factored_conductor]
39
self._conductor = prod(factored_conductor)
40
self._m = totally_positive_generator(self._conductor)
41
self._rootlist = rootlist
42
assert gcd(rootlist+[order])==1, "the order of the character is not %s"%(order)
43
self._field = factored_conductor[0].number_field()
44
self._ring = self._field.maximal_order()
45
self._degree = self._field.absolute_degree()
46
self._order = order
47
if prec == None:
48
self._CC = CC
49
else:
50
self._CC = ComplexField(prec)
51
if zeta is None:
52
self._zeta = self._CC.zeta(order)
53
else:
54
#assert zeta**d==1,"order of zeta does not appear to be %s"%order
55
self._zeta = zeta
56
57
assert self._field.class_number()==1,"Class number of base field is not 1"
58
59
for p in factored_conductor:
60
assert ZZ(order).divides(p.norm() - 1), "order %s does not divide order of (O/%s)^*, which is %s"%(order,p,p.norm()-1)
61
62
self._pows = [self._zeta**d for d in range(order)]
63
64
if False:
65
self._logs = dict()
66
for p in self._factored_conductor:
67
self._logs[p] = dict()
68
kp = p.residue_field()
69
for x in kp:
70
if x == 0:
71
continue
72
self._logs[p][x] = p.ideallog(kp.lift(x))[0]
73
74
for g in self._field.unit_group().gens():
75
assert self._call_nf_elt(self._field(g)) == 1, " character is not 1 on units"
76
77
78
def __call__(self, p):
79
p = self._field.ideal(p)
80
x = p.gens_reduced()
81
assert len(x)==1, "Do not know how to evaluate on a non principal ideal!"
82
return self._call_nf_elt(p.gens_reduced()[0])
83
84
@cached_method
85
def _iter_rep_mod_m(self):
86
return _iter__OK_mod_p(self._ring,self._conductor)
87
88
89
def _call_nf_elt(self, alpha):
90
fact = self._factored_conductor
91
rootlist = self._rootlist
92
93
for p,q in zip(self._primes_conductor,fact):
94
if p.divides(alpha.norm()) and alpha in q:
95
return 0
96
#return m.ideallog(p.gens_reduced()[0])
97
if False: # new
98
reps = [self._logs[p][p.residue_field()(alpha)] for p in fact]
99
reps = rep(alpha, [prime for prime in fact])
100
101
return self._pows[sum([rootlist[i]*reps[i] for i in range(len(rootlist))]) % self._order]
102
103
def gauss_sum(self):
104
assert self._ring.discriminant()==5, "only implemented for sqrt5"
105
tau = 0
106
sqrt5 = (self._field*5).factor()[0][0].gens_reduced()[0]
107
#print sqrt5
108
for alpha in self._iter_rep_mod_m():
109
#print tau
110
a = alpha/self._m#*sqrt5
111
a = a.trace()
112
den = a.denominator()
113
num = a.numerator()
114
tau += self._call_nf_elt(alpha)*self._CC.zeta(den)^(num%den)
115
return tau
116
117
def conjugate(self):
118
return NFChar(self._factored_conductor, [-d for d in self._rootlist], self._order, self._zeta, self._CC.prec())
119
120
def is_primitive(self):
121
return all(i%self._order != 0 for i in self._rootlist)
122
123
def conductor(self):
124
K = self._factored_conductor[0].number_field()
125
return ZZ(prod(self._factored_conductor).norm())#*K.discriminant())
126
127
def order(self):
128
return self._order
129
130
def __repr__(self):
131
return "Hecke character of modulus %s and order %s"%(self._conductor,self._order)
132
133
# Search for all characters of the base field of E (which for now must be Qsqrt5) that are
134
# of order D and have conductor norm less than bound, for each pair of complex conjugate characters, only 1 is used.
135
# When a character is found the twist is computed (and optionally the functional equation checked)
136
# then the twist is evaluated at 1 and the result is printed and added to a list, which is returned.
137
def value_search(E, D, bound, checkfe=False, lower=0, prec=None):
138
LE = LSeriesEllipticCurveSqrt5(E)
139
omega = prod([E.period_lattice(phi).basis(prec=1000)[0] for phi in F.embeddings(RR)])
140
ideals = E.base_field().ideals_of_bdd_norm(bound)
141
values = []
142
n_values = []
143
chis = []
144
print len(ideals),ideals
145
if prec is None:
146
one = CC(1)
147
else:
148
one = ComplexField(prec)(1)
149
# we could also use for m in E.base_field().primes_of_bounded_norm_iter(bound):
150
for nm in ideals:
151
if nm < lower:
152
continue
153
if nm % 5 == 0 or nm % 31 == 0:
154
continue
155
for m in ideals[nm]:
156
if nm == 1:
157
continue
158
fact = [prime for (prime, i) in m.factor()]
159
if max([i for (prime, i) in m.factor()]) > 1:
160
continue
161
for t in Integers(D)^len(fact):
162
try:
163
if 0 in list(t):
164
continue
165
if t[0].lift() > D/2: # Only take one character in each conjugacy class
166
continue
167
rootlist = list(t.lift())
168
chi = NFChar(fact,rootlist,D, CC.zeta(D))
169
print m,m.norm(),m.factor(), rootlist
170
LEchi = LE.twist(chi,epsilon='solve')
171
if checkfe:
172
LEchi.check_functional_equation(1.2)
173
LEchi.check_functional_equation(1.1)
174
val = LEchi(one)
175
print "raw value",val
176
normalised = val*chi.conjugate().gauss_sum()*CC(sqrt(5))/omega
177
print "normalised",normalised
178
print "algdeprts",algdep(normalised, 2, known_bits=53).roots(CC)
179
values += [val]
180
n_values += [normalised]
181
chis += [chi]
182
183
except AssertionError: # Character didn't work, try the next
184
pass
185
except RuntimeError:
186
print "Error, maybe conductor was wrong?!"
187
return values,n_values,chis
188
189
190