passagemath-lcalc 10.6.40__cp314-cp314-musllinux_1_2_aarch64.whl

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