Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/libs/lcalc/lcalc_Lfunction.pyx
8815 views
1
r"""
2
Rubinstein's lcalc library
3
4
This is a wrapper around Michael Rubinstein's lcalc.
5
See http://oto.math.uwaterloo.ca/~mrubinst/L_function_public/CODE/.
6
7
AUTHORS:
8
9
- Rishikesh (2010): added compute_rank() and hardy_z_function()
10
- Yann Laigle-Chapuy (2009): refactored
11
- Rishikesh (2009): initial version
12
"""
13
#*****************************************************************************
14
# Copyright (C) 2009 William Stein <[email protected]>
15
#
16
# Distributed under the terms of the GNU General Public License (GPL)
17
#
18
# This code is distributed in the hope that it will be useful,
19
# but WITHOUT ANY WARRANTY; without even the implied warranty of
20
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21
# General Public License for more details.
22
#
23
# The full text of the GPL is available at:
24
#
25
# http://www.gnu.org/licenses/
26
#*****************************************************************************
27
28
include "sage/ext/interrupt.pxi"
29
include "sage/ext/stdsage.pxi"
30
include "sage/ext/cdefs.pxi"
31
include "sage/libs/mpfr.pxd"
32
33
from sage.rings.integer cimport Integer
34
35
from sage.rings.complex_number cimport ComplexNumber
36
from sage.rings.complex_field import ComplexField
37
CCC = ComplexField()
38
39
from sage.rings.real_mpfr cimport RealNumber
40
from sage.rings.real_mpfr import RealField
41
RRR = RealField()
42
pi = RRR.pi()
43
44
initialize_globals()
45
46
##############################################################################
47
# Lfunction: base class for L-functions
48
##############################################################################
49
50
cdef class Lfunction:
51
# virtual class
52
def __init__(self, name, what_type_L, dirichlet_coefficient,
53
period, Q, OMEGA, gamma, lambd, pole, residue):
54
"""
55
Initialization of L-function objects.
56
See derived class for details, this class is not supposed to be
57
instantiated directly.
58
59
EXAMPLES::
60
61
sage: from sage.libs.lcalc.lcalc_Lfunction import *
62
sage: Lfunction_from_character(DirichletGroup(5)[1])
63
L-function with complex Dirichlet coefficients
64
"""
65
cdef int i #for indexing loops
66
cdef Integer tmpi #for accessing integer values
67
cdef RealNumber tmpr #for accessing real values
68
cdef ComplexNumber tmpc #for accessing complexe values
69
70
cdef char *NAME = name
71
cdef int what_type = what_type_L
72
73
tmpi = Integer(period)
74
cdef int Period = mpz_get_si(tmpi.value)
75
tmpr = RRR(Q)
76
cdef double q=mpfr_get_d(tmpr.value,GMP_RNDN)
77
tmpc = CCC(OMEGA)
78
cdef c_Complex w=new_Complex(mpfr_get_d(tmpc.__re,GMP_RNDN), mpfr_get_d(tmpc.__im, GMP_RNDN))
79
80
cdef int A=len(gamma)
81
cdef double *g=new_doubles(A+1)
82
cdef c_Complex *l=new_Complexes(A+1)
83
for i from 0 <= i < A:
84
tmpr = RRR(gamma[i])
85
g[i+1] = mpfr_get_d(tmpr.value,GMP_RNDN)
86
tmpc = CCC(lambd[i])
87
l[i+1] = new_Complex(mpfr_get_d(tmpc.__re,GMP_RNDN), mpfr_get_d(tmpc.__im, GMP_RNDN))
88
89
cdef int n_poles = len(pole)
90
cdef c_Complex *p = new_Complexes(n_poles +1)
91
cdef c_Complex *r = new_Complexes(n_poles +1)
92
for i from 0 <= i < n_poles:
93
tmpc=CCC(pole[i])
94
p[i+1] = new_Complex(mpfr_get_d(tmpc.__re,GMP_RNDN), mpfr_get_d(tmpc.__im, GMP_RNDN))
95
tmpc=CCC(residue[i])
96
r[i+1] = new_Complex(mpfr_get_d(tmpc.__re,GMP_RNDN), mpfr_get_d(tmpc.__im, GMP_RNDN))
97
98
self.__init_fun(NAME, what_type, dirichlet_coefficient, Period, q, w, A, g, l, n_poles, p, r)
99
100
repr_name = str(NAME)
101
if str(repr_name) != "":
102
repr_name += ": "
103
104
self._repr = repr_name + "L-function"
105
106
del_doubles(g)
107
del_Complexes(l)
108
del_Complexes(p)
109
del_Complexes(r)
110
111
def __repr__(self):
112
"""
113
Return string representation of this L-function.
114
115
EXAMPLES::
116
117
sage: from sage.libs.lcalc.lcalc_Lfunction import *
118
sage: Lfunction_from_character(DirichletGroup(5)[1])
119
L-function with complex Dirichlet coefficients
120
121
sage: Lfunction_Zeta()
122
The Riemann zeta function
123
"""
124
return self._repr
125
126
def value(self, s, derivative=0):
127
"""
128
Computes the value of the L-function at ``s``
129
130
INPUT:
131
132
- ``s`` - a complex number
133
- ``derivative`` - integer (default: 0) the derivative to be evaluated
134
- ``rotate`` - (default: False) If True, this returns the value of the
135
Hardy Z-function (sometimes called the Riemann-Siegel Z-function or
136
the Siegel Z-function).
137
138
EXAMPLES::
139
140
sage: chi=DirichletGroup(5)[2] #This is a quadratic character
141
sage: from sage.libs.lcalc.lcalc_Lfunction import *
142
sage: L=Lfunction_from_character(chi, type="int")
143
sage: L.value(.5)
144
0.231750947504... + 5.75329642226...e-18*I
145
sage: L.value(.2+.4*I)
146
0.102558603193... + 0.190840777924...*I
147
148
sage: L=Lfunction_from_character(chi, type="double")
149
sage: L.value(.6)
150
0.274633355856... + 6.59869267328...e-18*I
151
sage: L.value(.6+I)
152
0.362258705721... + 0.433888250620...*I
153
154
sage: chi=DirichletGroup(5)[1]
155
sage: L=Lfunction_from_character(chi, type="complex")
156
sage: L.value(.5)
157
0.763747880117... + 0.216964767518...*I
158
sage: L.value(.6+5*I)
159
0.702723260619... - 1.10178575243...*I
160
161
sage: L=Lfunction_Zeta()
162
sage: L.value(.5)
163
-1.46035450880...
164
sage: L.value(.4+.5*I)
165
-0.450728958517... - 0.780511403019...*I
166
"""
167
cdef ComplexNumber complexified_s = CCC(s)
168
cdef c_Complex z = new_Complex(mpfr_get_d(complexified_s.__re,GMP_RNDN), mpfr_get_d(complexified_s.__im, GMP_RNDN))
169
cdef c_Complex result = self.__value(z, derivative)
170
return CCC(result.real(),result.imag())
171
172
def hardy_z_function(self, s):
173
"""
174
Computes the Hardy Z-function of the L-function at s
175
176
INPUT:
177
178
- ``s`` - a complex number with imaginary part between -0.5 and 0.5
179
180
EXAMPLES::
181
182
sage: chi=DirichletGroup(5)[2] #This is a quadratic character
183
sage: from sage.libs.lcalc.lcalc_Lfunction import *
184
sage: L=Lfunction_from_character(chi, type="int")
185
sage: L.hardy_z_function(0)
186
0.231750947504...
187
sage: L.hardy_z_function(.5).imag().abs() < 1.0e-16
188
True
189
sage: L.hardy_z_function(.4+.3*I)
190
0.2166144222685... - 0.00408187127850...*I
191
sage: chi=DirichletGroup(5)[1]
192
sage: L=Lfunction_from_character(chi,type="complex")
193
sage: L.hardy_z_function(0)
194
0.7939675904771...
195
sage: L.hardy_z_function(.5).imag().abs() < 1.0e-16
196
True
197
sage: E=EllipticCurve([-82,0])
198
sage: L=Lfunction_from_elliptic_curve(E, number_of_coeffs=40000)
199
sage: L.hardy_z_function(2.1)
200
-0.00643179176869...
201
sage: L.hardy_z_function(2.1).imag().abs() < 1.0e-16
202
True
203
"""
204
#This takes s -> .5 + I*s
205
cdef ComplexNumber complexified_s = CCC(0.5)+ CCC(0,1)*CCC(s)
206
cdef c_Complex z = new_Complex(mpfr_get_d(complexified_s.__re,GMP_RNDN), mpfr_get_d(complexified_s.__im, GMP_RNDN))
207
cdef c_Complex result = self.__hardy_z_function(z)
208
return CCC(result.real(),result.imag())
209
210
211
def compute_rank(self):
212
"""
213
Computes the analytic rank (the order of vanishing at the center) of
214
of the L-function
215
216
EXAMPLES::
217
218
sage: chi=DirichletGroup(5)[2] #This is a quadratic character
219
sage: from sage.libs.lcalc.lcalc_Lfunction import *
220
sage: L=Lfunction_from_character(chi, type="int")
221
sage: L.compute_rank()
222
0
223
sage: E=EllipticCurve([-82,0])
224
sage: L=Lfunction_from_elliptic_curve(E, number_of_coeffs=40000)
225
sage: L.compute_rank()
226
3
227
"""
228
return self.__compute_rank()
229
230
def __N(self, T):
231
"""
232
Compute the number of zeroes upto height `T` using the formula for
233
`N(T)` with the error of `S(T)`. Please do not use this. It is only
234
for debugging
235
236
EXAMPLES::
237
238
sage: from sage.libs.lcalc.lcalc_Lfunction import *
239
sage: chi=DirichletGroup(5)[2] #This is a quadratic character
240
sage: L=Lfunction_from_character(chi, type="complex")
241
sage: L.__N(10)
242
3.17043978326...
243
"""
244
cdef RealNumber real_T=RRR(T)
245
cdef double double_T = mpfr_get_d(real_T.value, GMP_RNDN)
246
cdef double res_d = self.__typedN(double_T)
247
return RRR(res_d)
248
249
def find_zeros(self, T1, T2, stepsize):
250
"""
251
Finds zeros on critical line between ``T1`` and ``T2`` using step size
252
of stepsize. This function might miss zeros if step size is too
253
large. This function computes the zeros of the L-function by using
254
change in signs of areal valued function whose zeros coincide with
255
the zeros of L-function.
256
257
Use find_zeros_via_N for slower but more rigorous computation.
258
259
INPUT:
260
261
- ``T1`` -- a real number giving the lower bound
262
- ``T2`` -- a real number giving the upper bound
263
- ``stepsize`` -- step size to be used for the zero search
264
265
OUTPUT:
266
267
list -- A list of the imaginary parts of the zeros which were found.
268
269
EXAMPLES::
270
271
sage: from sage.libs.lcalc.lcalc_Lfunction import *
272
sage: chi=DirichletGroup(5)[2] #This is a quadratic character
273
sage: L=Lfunction_from_character(chi, type="int")
274
sage: L.find_zeros(5,15,.1)
275
[6.64845334472..., 9.83144443288..., 11.9588456260...]
276
277
sage: L=Lfunction_from_character(chi, type="double")
278
sage: L.find_zeros(1,15,.1)
279
[6.64845334472..., 9.83144443288..., 11.9588456260...]
280
281
sage: chi=DirichletGroup(5)[1]
282
sage: L=Lfunction_from_character(chi, type="complex")
283
sage: L.find_zeros(-8,8,.1)
284
[-4.13290370521..., 6.18357819545...]
285
286
sage: L=Lfunction_Zeta()
287
sage: L.find_zeros(10,29.1,.1)
288
[14.1347251417..., 21.0220396387..., 25.0108575801...]
289
"""
290
cdef doublevec result
291
cdef double myresult
292
cdef int i
293
cdef RealNumber real_T1 = RRR(T1)
294
cdef RealNumber real_T2 = RRR(T2)
295
cdef RealNumber real_stepsize = RRR(stepsize)
296
sig_on()
297
self.__find_zeros_v( mpfr_get_d(real_T1.value, GMP_RNDN), mpfr_get_d(real_T2.value, GMP_RNDN), mpfr_get_d(real_stepsize.value, GMP_RNDN),&result)
298
sig_off()
299
i=result.size()
300
returnvalue = []
301
for i in range(result.size()):
302
returnvalue.append( RRR(result.ind(i)))
303
result.clear()
304
return returnvalue
305
306
#The default values are from L.h. See L.h
307
def find_zeros_via_N(self, count=0, do_negative=False, max_refine=1025,
308
rank=-1, test_explicit_formula=0):
309
"""
310
Finds ``count`` number of zeros with positive imaginary part
311
starting at real axis. This function also verifies that all
312
the zeros have been found.
313
314
INPUT:
315
316
- ``count`` - number of zeros to be found
317
- ``do_negative`` - (default: False) False to ignore zeros below the
318
real axis.
319
- ``max_refine`` - when some zeros are found to be missing, the step
320
size used to find zeros is refined. max_refine gives an upper limit
321
on when lcalc should give up. Use default value unless you know
322
what you are doing.
323
- ``rank`` - integer (default: -1) analytic rank of the L-function.
324
If -1 is passed, then we attempt to compute it. (Use default if in
325
doubt)
326
- ``test_explicit_formula`` - integer (default: 0) If nonzero, test
327
the explicit fomula for additional confidence that all the zeros
328
have been found and are accurate. This is still being tested, so
329
using the default is recommended.
330
331
332
OUTPUT:
333
334
list -- A list of the imaginary parts of the zeros that have been found
335
336
EXAMPLES::
337
338
sage: from sage.libs.lcalc.lcalc_Lfunction import *
339
sage: chi=DirichletGroup(5)[2] #This is a quadratic character
340
sage: L=Lfunction_from_character(chi, type="int")
341
sage: L.find_zeros_via_N(3)
342
[6.64845334472..., 9.83144443288..., 11.9588456260...]
343
344
sage: L=Lfunction_from_character(chi, type="double")
345
sage: L.find_zeros_via_N(3)
346
[6.64845334472..., 9.83144443288..., 11.9588456260...]
347
348
sage: chi=DirichletGroup(5)[1]
349
sage: L=Lfunction_from_character(chi, type="complex")
350
sage: L.find_zeros_via_N(3)
351
[6.18357819545..., 8.45722917442..., 12.6749464170...]
352
353
sage: L=Lfunction_Zeta()
354
sage: L.find_zeros_via_N(3)
355
[14.1347251417..., 21.0220396387..., 25.0108575801...]
356
"""
357
cdef Integer count_I = Integer(count)
358
cdef Integer do_negative_I = Integer(do_negative)
359
cdef RealNumber max_refine_R = RRR(max_refine)
360
cdef Integer rank_I = Integer(rank)
361
cdef Integer test_explicit_I = Integer(test_explicit_formula)
362
cdef doublevec result
363
sig_on()
364
self.__find_zeros_via_N_v(mpz_get_si(count_I.value), mpz_get_si(do_negative_I.value), mpfr_get_d(max_refine_R.value, GMP_RNDN), mpz_get_si(rank_I.value), mpz_get_si(test_explicit_I.value), &result)
365
sig_off()
366
returnvalue = []
367
for i in range(result.size()):
368
returnvalue.append( RRR(result.ind(i)))
369
result.clear()
370
return returnvalue
371
372
#### Needs to be overriden
373
cdef void __init_fun(self, char *NAME, int what_type, dirichlet_coeff, long long Period, double q, c_Complex w, int A, double *g, c_Complex *l, int n_poles, c_Complex *p, c_Complex *r):
374
raise NotImplementedError
375
376
cdef c_Complex __value(self,c_Complex s,int derivative):
377
raise NotImplementedError
378
379
cdef c_Complex __hardy_z_function(self,c_Complex s):
380
raise NotImplementedError
381
382
cdef int __compute_rank(self):
383
raise NotImplementedError
384
385
cdef double __typedN(self,double T):
386
raise NotImplementedError
387
388
cdef void __find_zeros_v(self,double T1, double T2, double stepsize, doublevec *result):
389
raise NotImplementedError
390
391
cdef void __find_zeros_via_N_v(self, long count,int do_negative,double max_refine, int rank, int test_explicit_formula, doublevec *result):
392
raise NotImplementedError
393
394
##############################################################################
395
# Lfunction_I: L-functions with integer Dirichlet Coefficients
396
##############################################################################
397
398
cdef class Lfunction_I(Lfunction):
399
r"""
400
The ``Lfunction_I`` class is used to represent L-functions
401
with integer Dirichlet Coefficients. We assume that L-functions
402
satisfy the following functional equation.
403
404
.. math::
405
406
\Lambda(s) = \omega Q^s \overline{\Lambda(1-\bar s)}
407
408
where
409
410
.. math::
411
412
\Lambda(s) = Q^s \left( \prod_{j=1}^a \Gamma(\kappa_j s + \gamma_j) \right) L(s)
413
414
415
416
See (23) in http://arxiv.org/abs/math/0412181
417
418
INPUT:
419
420
- ``what_type_L`` - integer, this should be set to 1 if the coefficients are
421
periodic and 0 otherwise.
422
423
- ``dirichlet_coefficient`` - List of dirichlet coefficients of the
424
L-function. Only first `M` coefficients are needed if they are periodic.
425
426
- ``period`` - If the coefficients are periodic, this should be the
427
period of the coefficients.
428
429
- ``Q`` - See above
430
431
- ``OMEGA`` - See above
432
433
- ``kappa`` - List of the values of `\kappa_j` in the functional equation
434
435
436
- ``gamma`` - List of the values of `\gamma_j` in the functional equation
437
438
- ``pole`` - List of the poles of L-function
439
440
- ``residue`` - List of the residues of the L-function
441
442
NOTES:
443
444
If an L-function satisfies `\Lambda(s) = \omega Q^s \Lambda(k-s)`,
445
by replacing `s` by `s+(k-1)/2`, one can get it in the form we need.
446
"""
447
448
def __init__(self, name, what_type_L, dirichlet_coefficient,
449
period, Q, OMEGA, gamma, lambd, pole, residue):
450
r"""
451
Initialize an L-function with integer coefficients
452
453
EXAMPLES::
454
455
sage: from sage.libs.lcalc.lcalc_Lfunction import *
456
sage: chi=DirichletGroup(5)[2] #This is a quadratic character
457
sage: L=Lfunction_from_character(chi, type="int")
458
sage: type(L)
459
<type 'sage.libs.lcalc.lcalc_Lfunction.Lfunction_I'>
460
"""
461
Lfunction.__init__(self, name, what_type_L, dirichlet_coefficient, period, Q, OMEGA, gamma,lambd, pole,residue)
462
self._repr += " with integer Dirichlet coefficients"
463
464
### override
465
cdef void __init_fun(self, char *NAME, int what_type, dirichlet_coeff, long long Period, double q, c_Complex w, int A, double *g, c_Complex *l, int n_poles, c_Complex *p, c_Complex *r):
466
cdef int N = len(dirichlet_coeff)
467
cdef Integer tmpi
468
cdef int * coeffs = new_ints(N+1) #lcalc ignores 0the coefficient
469
for i from 0 <= i< N by 1:
470
tmpi=Integer(dirichlet_coeff[i])
471
coeffs[i+1] = mpz_get_si(tmpi.value)
472
self.thisptr=new_c_Lfunction_I(NAME, what_type, N, coeffs, Period, q, w, A, g, l, n_poles, p, r)
473
del_ints(coeffs)
474
475
cdef inline c_Complex __value(self,c_Complex s,int derivative):
476
return (<c_Lfunction_I *>(self.thisptr)).value(s, derivative, "pure")
477
478
cdef inline c_Complex __hardy_z_function(self,c_Complex s):
479
return (<c_Lfunction_I *>(self.thisptr)).value(s, 0, "rotated pure")
480
481
cdef int __compute_rank(self):
482
return (<c_Lfunction_I *>(self.thisptr)).compute_rank()
483
484
cdef void __find_zeros_v(self, double T1, double T2, double stepsize, doublevec *result):
485
(<c_Lfunction_I *>self.thisptr).find_zeros_v(T1,T2,stepsize,result[0])
486
487
cdef double __typedN(self, double T):
488
return (<c_Lfunction_I *>self.thisptr).N(T)
489
490
cdef void __find_zeros_via_N_v(self, long count,int do_negative,double max_refine, int rank, int test_explicit_formula, doublevec *result):
491
(<c_Lfunction_I *>self.thisptr).find_zeros_via_N_v(count, do_negative, max_refine, rank, test_explicit_formula, result[0])
492
493
### debug tools
494
def _print_data_to_standard_output(self):
495
"""
496
This is used in debugging. It prints out information from
497
the C++ object behind the scenes. It will use standard output.
498
499
EXAMPLES::
500
501
sage: from sage.libs.lcalc.lcalc_Lfunction import *
502
sage: chi=DirichletGroup(5)[2] #This is a quadratic character
503
sage: L=Lfunction_from_character(chi, type="int")
504
sage: L._print_data_to_standard_output() # tol 1e-15
505
-----------------------------------------------
506
<BLANKLINE>
507
Name of L_function:
508
number of dirichlet coefficients = 5
509
coefficients are periodic
510
b[1] = 1
511
b[2] = -1
512
b[3] = -1
513
b[4] = 1
514
b[5] = 0
515
<BLANKLINE>
516
Q = 1.26156626101
517
OMEGA = (1,0)
518
a = 1 (the quasi degree)
519
gamma[1] =0.5 lambda[1] =(0,0)
520
<BLANKLINE>
521
<BLANKLINE>
522
number of poles (of the completed L function) = 0
523
-----------------------------------------------
524
<BLANKLINE>
525
"""
526
(<c_Lfunction_I *>self.thisptr).print_data_L()
527
528
def __dealloc__(self):
529
"""
530
Deallocate memory used
531
"""
532
del_c_Lfunction_I(<c_Lfunction_I *>(self.thisptr))
533
534
##############################################################################
535
# Lfunction_D: L-functions with double (real) Dirichlet Coefficients
536
##############################################################################
537
538
cdef class Lfunction_D(Lfunction):
539
r"""
540
The ``Lfunction_D`` class is used to represent L-functions
541
with real Dirichlet coefficients. We assume that L-functions
542
satisfy the following functional equation.
543
544
.. math::
545
546
\Lambda(s) = \omega Q^s \overline{\Lambda(1-\bar s)}
547
548
where
549
550
.. math::
551
552
\Lambda(s) = Q^s \left( \prod_{j=1}^a \Gamma(\kappa_j s + \gamma_j) \right) L(s)
553
554
See (23) in http://arxiv.org/abs/math/0412181
555
556
INPUT:
557
558
- ``what_type_L`` - integer, this should be set to 1 if the coefficients are
559
periodic and 0 otherwise.
560
561
- ``dirichlet_coefficient`` - List of dirichlet coefficients of the
562
L-function. Only first `M` coefficients are needed if they are periodic.
563
564
- ``period`` - If the coefficients are periodic, this should be the
565
period of the coefficients.
566
567
- ``Q`` - See above
568
569
- ``OMEGA`` - See above
570
571
- ``kappa`` - List of the values of `\kappa_j` in the functional equation
572
573
- ``gamma`` - List of the values of `\gamma_j` in the functional equation
574
575
- ``pole`` - List of the poles of L-function
576
577
- ``residue`` - List of the residues of the L-function
578
579
NOTES:
580
If an L-function satisfies `\Lambda(s) = \omega Q^s \Lambda(k-s)`,
581
by replacing `s` by `s+(k-1)/2`, one can get it in the form we need.
582
"""
583
def __init__(self, name, what_type_L, dirichlet_coefficient,
584
period, Q, OMEGA, gamma, lambd, pole, residue):
585
r"""
586
Initialize an L-function with real coefficients
587
588
EXAMPLES::
589
590
sage: from sage.libs.lcalc.lcalc_Lfunction import *
591
sage: chi=DirichletGroup(5)[2] #This is a quadratic character
592
sage: L=Lfunction_from_character(chi, type="double")
593
sage: type(L)
594
<type 'sage.libs.lcalc.lcalc_Lfunction.Lfunction_D'>
595
"""
596
Lfunction.__init__(self, name, what_type_L, dirichlet_coefficient, period, Q, OMEGA, gamma,lambd, pole,residue)
597
self._repr += " with real Dirichlet coefficients"
598
599
### override
600
cdef void __init_fun(self, char *NAME, int what_type, dirichlet_coeff, long long Period, double q, c_Complex w, int A, double *g, c_Complex *l, int n_poles, c_Complex *p, c_Complex *r):
601
cdef int i
602
cdef RealNumber tmpr
603
cdef int N = len(dirichlet_coeff)
604
cdef double * coeffs = new_doubles(N+1)#lcalc ignores 0th position
605
for i from 0 <= i< N by 1:
606
tmpr=RRR(dirichlet_coeff[i])
607
coeffs[i+1] = mpfr_get_d(tmpr.value, GMP_RNDN)
608
self.thisptr=new_c_Lfunction_D(NAME, what_type, N, coeffs, Period, q, w, A, g, l, n_poles, p, r)
609
del_doubles(coeffs)
610
611
cdef inline c_Complex __value(self,c_Complex s,int derivative):
612
return (<c_Lfunction_D *>(self.thisptr)).value(s, derivative, "pure")
613
614
615
cdef inline c_Complex __hardy_z_function(self,c_Complex s):
616
return (<c_Lfunction_D *>(self.thisptr)).value(s, 0, "rotated pure")
617
618
cdef inline int __compute_rank(self):
619
return (<c_Lfunction_D *>(self.thisptr)).compute_rank()
620
621
cdef void __find_zeros_v(self, double T1, double T2, double stepsize, doublevec *result):
622
(<c_Lfunction_D *>self.thisptr).find_zeros_v(T1,T2,stepsize,result[0])
623
624
cdef double __typedN(self, double T):
625
return (<c_Lfunction_D *>self.thisptr).N(T)
626
627
cdef void __find_zeros_via_N_v(self, long count,int do_negative,double max_refine, int rank, int test_explicit_formula, doublevec *result):
628
(<c_Lfunction_D *>self.thisptr).find_zeros_via_N_v(count, do_negative, max_refine, rank, test_explicit_formula, result[0])
629
630
### debug tools
631
def _print_data_to_standard_output(self):
632
"""
633
This is used in debugging. It prints out information from
634
the C++ object behind the scenes. It will use standard output.
635
636
EXAMPLES::
637
638
sage: from sage.libs.lcalc.lcalc_Lfunction import *
639
sage: chi=DirichletGroup(5)[2] #This is a quadratic character
640
sage: L=Lfunction_from_character(chi, type="double")
641
sage: L._print_data_to_standard_output() # tol 1e-15
642
-----------------------------------------------
643
<BLANKLINE>
644
Name of L_function:
645
number of dirichlet coefficients = 5
646
coefficients are periodic
647
b[1] = 1
648
b[2] = -1
649
b[3] = -1
650
b[4] = 1
651
b[5] = 0
652
<BLANKLINE>
653
Q = 1.26156626101
654
OMEGA = (1,0)
655
a = 1 (the quasi degree)
656
gamma[1] =0.5 lambda[1] =(0,0)
657
<BLANKLINE>
658
<BLANKLINE>
659
number of poles (of the completed L function) = 0
660
-----------------------------------------------
661
<BLANKLINE>
662
663
"""
664
(<c_Lfunction_D *>self.thisptr).print_data_L()
665
666
def __dealloc__(self):
667
"""
668
Deallocate memory used
669
"""
670
del_c_Lfunction_D(<c_Lfunction_D *>(self.thisptr))
671
672
##############################################################################
673
# Lfunction_C: L-functions with Complex Dirichlet Coefficients
674
##############################################################################
675
676
cdef class Lfunction_C:
677
r"""
678
The ``Lfunction_C`` class is used to represent L-functions
679
with complex Dirichlet Coefficients. We assume that L-functions
680
satisfy the following functional equation.
681
682
.. math::
683
684
\Lambda(s) = \omega Q^s \overline{\Lambda(1-\bar s)}
685
686
where
687
688
.. math::
689
690
\Lambda(s) = Q^s \left( \prod_{j=1}^a \Gamma(\kappa_j s + \gamma_j) \right) L(s)
691
692
See (23) in http://arxiv.org/abs/math/0412181
693
694
INPUT:
695
696
- ``what_type_L`` - integer, this should be set to 1 if the coefficients are
697
periodic and 0 otherwise.
698
699
- ``dirichlet_coefficient`` - List of dirichlet coefficients of the
700
L-function. Only first `M` coefficients are needed if they are periodic.
701
702
- ``period`` - If the coefficients are periodic, this should be the
703
period of the coefficients.
704
705
- ``Q`` - See above
706
707
- ``OMEGA`` - See above
708
709
- ``kappa`` - List of the values of `\kappa_j` in the functional equation
710
711
- ``gamma`` - List of the values of `\gamma_j` in the functional equation
712
713
- ``pole`` - List of the poles of L-function
714
715
- ``residue`` - List of the residues of the L-function
716
717
NOTES:
718
If an L-function satisfies `\Lambda(s) = \omega Q^s \Lambda(k-s)`,
719
by replacing `s` by `s+(k-1)/2`, one can get it in the form we need.
720
"""
721
722
def __init__(self, name, what_type_L, dirichlet_coefficient,
723
period, Q, OMEGA, gamma, lambd, pole, residue):
724
r"""
725
Initialize an L-function with complex coefficients
726
727
EXAMPLES::
728
729
sage: from sage.libs.lcalc.lcalc_Lfunction import *
730
sage: chi=DirichletGroup(5)[1]
731
sage: L=Lfunction_from_character(chi, type="complex")
732
sage: type(L)
733
<type 'sage.libs.lcalc.lcalc_Lfunction.Lfunction_C'>
734
"""
735
Lfunction.__init__(self, name, what_type_L, dirichlet_coefficient, period, Q, OMEGA, gamma,lambd, pole,residue)
736
self._repr += " with complex Dirichlet coefficients"
737
738
### override
739
cdef void __init_fun(self, char *NAME, int what_type, dirichlet_coeff, long long Period, double q, c_Complex w, int A, double *g, c_Complex *l, int n_poles, c_Complex *p, c_Complex *r):
740
cdef int i
741
cdef int N = len(dirichlet_coeff)
742
cdef ComplexNumber tmpc
743
744
cdef c_Complex * coeffs = new_Complexes(N+1)
745
coeffs[0]=new_Complex(0,0)
746
for i from 0 <= i< N by 1:
747
tmpc=CCC(dirichlet_coeff[i])
748
coeffs[i+1] = new_Complex(mpfr_get_d(tmpc.__re,GMP_RNDN), mpfr_get_d(tmpc.__im, GMP_RNDN))
749
750
self.thisptr = new_c_Lfunction_C(NAME, what_type, N, coeffs, Period, q, w, A, g, l, n_poles, p, r)
751
752
del_Complexes(coeffs)
753
754
cdef inline c_Complex __value(self,c_Complex s,int derivative):
755
return (<c_Lfunction_C *>(self.thisptr)).value(s, derivative, "pure")
756
757
758
cdef inline c_Complex __hardy_z_function(self,c_Complex s):
759
return (<c_Lfunction_C *>(self.thisptr)).value(s, 0,"rotated pure")
760
761
cdef inline int __compute_rank(self):
762
return (<c_Lfunction_C *>(self.thisptr)).compute_rank()
763
764
765
cdef void __find_zeros_v(self, double T1, double T2, double stepsize, doublevec *result):
766
(<c_Lfunction_C *>self.thisptr).find_zeros_v(T1,T2,stepsize,result[0])
767
768
cdef double __typedN(self, double T):
769
return (<c_Lfunction_C *>self.thisptr).N(T)
770
771
cdef void __find_zeros_via_N_v(self, long count,int do_negative,double max_refine, int rank, int test_explicit_formula, doublevec *result):
772
(<c_Lfunction_C *>self.thisptr).find_zeros_via_N_v(count, do_negative, max_refine, rank, test_explicit_formula, result[0])
773
774
### debug tools
775
def _print_data_to_standard_output(self):
776
"""
777
This is used in debugging. It prints out information from
778
the C++ object behind the scenes. It will use standard output.
779
780
EXAMPLES::
781
782
sage: from sage.libs.lcalc.lcalc_Lfunction import *
783
sage: chi=DirichletGroup(5)[1]
784
sage: L=Lfunction_from_character(chi, type="complex")
785
sage: L._print_data_to_standard_output() # tol 1e-15
786
-----------------------------------------------
787
<BLANKLINE>
788
Name of L_function:
789
number of dirichlet coefficients = 5
790
coefficients are periodic
791
b[1] = (1,0)
792
b[2] = (0,1)
793
b[3] = (0,-1)
794
b[4] = (-1,0)
795
b[5] = (0,0)
796
<BLANKLINE>
797
Q = 1.26156626101
798
OMEGA = (0.850650808352,0.525731112119)
799
a = 1 (the quasi degree)
800
gamma[1] =0.5 lambda[1] =(0.5,0)
801
<BLANKLINE>
802
<BLANKLINE>
803
number of poles (of the completed L function) = 0
804
-----------------------------------------------
805
<BLANKLINE>
806
807
808
"""
809
(<c_Lfunction_C *>self.thisptr).print_data_L()
810
811
def __dealloc__(self):
812
"""
813
Deallocate memory used
814
"""
815
del_c_Lfunction_C(<c_Lfunction_C *>(self.thisptr))
816
817
818
##############################################################################
819
#Zeta function
820
##############################################################################
821
822
cdef class Lfunction_Zeta(Lfunction):
823
r"""
824
The ``Lfunction_Zeta`` class is used to generate the Riemann zeta function.
825
"""
826
def __init__(self):
827
r"""
828
Initialize the Riemann zeta function.
829
830
EXAMPLES::
831
832
sage: from sage.libs.lcalc.lcalc_Lfunction import *
833
sage: sage.libs.lcalc.lcalc_Lfunction.Lfunction_Zeta()
834
The Riemann zeta function
835
"""
836
self.thisptr = new_c_Lfunction_Zeta()
837
self._repr = "The Riemann zeta function"
838
839
cdef inline c_Complex __value(self,c_Complex s,int derivative):
840
return (<c_Lfunction_Zeta *>(self.thisptr)).value(s, derivative, "pure")
841
842
843
cdef inline c_Complex __hardy_z_function(self,c_Complex s):
844
return (<c_Lfunction_Zeta *>(self.thisptr)).value(s, 0, "rotated pure")
845
846
cdef inline int __compute_rank(self):
847
return (<c_Lfunction_Zeta *>(self.thisptr)).compute_rank()
848
849
850
cdef void __find_zeros_v(self, double T1, double T2, double stepsize, doublevec *result):
851
(<c_Lfunction_Zeta *>self.thisptr).find_zeros_v(T1,T2,stepsize,result[0])
852
853
cdef double __typedN(self, double T):
854
return (<c_Lfunction_Zeta *>self.thisptr).N(T)
855
856
cdef void __find_zeros_via_N_v(self, long count,int do_negative,double max_refine, int rank, int test_explicit_formula, doublevec *result):
857
(<c_Lfunction_Zeta *>self.thisptr).find_zeros_via_N_v(count, do_negative, max_refine, rank, test_explicit_formula, result[0])
858
859
def __dealloc__(self):
860
"""
861
Deallocate memory used
862
"""
863
del_c_Lfunction_Zeta(<c_Lfunction_Zeta *>(self.thisptr))
864
865
##############################################################################
866
# Tools
867
##############################################################################
868
869
def Lfunction_from_character(chi, type="complex"):
870
"""
871
Given a primitive Dirichlet character, this function returns
872
an lcalc L-function object for the L-function of the character.
873
874
INPUT:
875
876
- `chi` - A Dirichlet character
877
- `use_type` - string (default: "complex") type used for the Dirichlet
878
coefficients. This can be "int", "double" or "complex".
879
880
OUTPUT:
881
882
L-function object for `chi`.
883
884
EXAMPLES::
885
886
sage: from sage.libs.lcalc.lcalc_Lfunction import Lfunction_from_character
887
sage: Lfunction_from_character(DirichletGroup(5)[1])
888
L-function with complex Dirichlet coefficients
889
sage: Lfunction_from_character(DirichletGroup(5)[2], type="int")
890
L-function with integer Dirichlet coefficients
891
sage: Lfunction_from_character(DirichletGroup(5)[2], type="double")
892
L-function with real Dirichlet coefficients
893
sage: Lfunction_from_character(DirichletGroup(5)[1], type="int")
894
Traceback (most recent call last):
895
...
896
ValueError: For non quadratic characters you must use type="complex"
897
898
"""
899
if (not chi.is_primitive()):
900
raise TypeError("Dirichlet character is not primitive")
901
902
modulus=chi.modulus()
903
if (chi(-1) == 1):
904
a=0
905
else:
906
a=1
907
908
Q=(RRR(modulus/pi)).sqrt()
909
poles=[]
910
residues=[]
911
period=modulus
912
OMEGA=1.0/ ( CCC(0,1)**a * (CCC(modulus)).sqrt()/chi.gauss_sum() )
913
914
if type == "complex":
915
dir_coeffs=[CCC(chi(n)) for n in xrange(1,modulus+1)]
916
return Lfunction_C("", 1,dir_coeffs, period,Q,OMEGA,[.5],[a/2.],poles,residues)
917
if not type in ["double","int"]:
918
raise ValueError("unknown type")
919
if chi.order() != 2:
920
raise ValueError("For non quadratic characters you must use type=\"complex\"")
921
if type == "double":
922
dir_coeffs=[RRR(chi(n)) for n in xrange(1,modulus+1)]
923
return Lfunction_D("", 1,dir_coeffs, period,Q,OMEGA,[.5],[a/2.],poles,residues)
924
if type == "int":
925
dir_coeffs=[Integer(chi(n)) for n in xrange(1,modulus+1)]
926
return Lfunction_I("", 1,dir_coeffs, period,Q,OMEGA,[.5],[a/2.],poles,residues)
927
928
929
def Lfunction_from_elliptic_curve(E, number_of_coeffs=10000):
930
"""
931
Given an elliptic curve E, return an L-function object for
932
the function `L(s, E)`.
933
934
INPUT:
935
936
- ``E`` - An elliptic curve
937
- ``number_of_coeffs`` - integer (default: 10000) The number of
938
coefficients to be used when constructing the L-function object. Right
939
now this is fixed at object creation time, and is not automatically
940
set intelligently.
941
942
OUTPUT:
943
944
L-function object for ``L(s, E)``.
945
946
EXAMPLES::
947
948
sage: from sage.libs.lcalc.lcalc_Lfunction import Lfunction_from_elliptic_curve
949
sage: L = Lfunction_from_elliptic_curve(EllipticCurve('37'))
950
sage: L
951
L-function with real Dirichlet coefficients
952
sage: L.value(0.5).abs() < 1e-15 # "noisy" zero on some platforms (see #9615)
953
True
954
sage: L.value(0.5, derivative=1)
955
0.305999...
956
"""
957
Q=(RRR(E.conductor())).sqrt()/(RRR(2*pi))
958
poles=[]
959
residues=[]
960
import sage.libs.lcalc.lcalc_Lfunction
961
dir_coeffs=E.anlist(number_of_coeffs)
962
dir_coeffs=[RRR(dir_coeffs[i])/(RRR(i)).sqrt() for i in xrange(1,number_of_coeffs)]
963
OMEGA=E.root_number()
964
return Lfunction_D("", 2,dir_coeffs, 0,Q,OMEGA,[1],[.5],poles,residues)
965
966