Path: blob/master/src/sage/libs/lcalc/lcalc_Lfunction.pyx
8815 views
r"""1Rubinstein's lcalc library23This is a wrapper around Michael Rubinstein's lcalc.4See http://oto.math.uwaterloo.ca/~mrubinst/L_function_public/CODE/.56AUTHORS:78- Rishikesh (2010): added compute_rank() and hardy_z_function()9- Yann Laigle-Chapuy (2009): refactored10- Rishikesh (2009): initial version11"""12#*****************************************************************************13# Copyright (C) 2009 William Stein <[email protected]>14#15# Distributed under the terms of the GNU General Public License (GPL)16#17# This code is distributed in the hope that it will be useful,18# but WITHOUT ANY WARRANTY; without even the implied warranty of19# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU20# General Public License for more details.21#22# The full text of the GPL is available at:23#24# http://www.gnu.org/licenses/25#*****************************************************************************2627include "sage/ext/interrupt.pxi"28include "sage/ext/stdsage.pxi"29include "sage/ext/cdefs.pxi"30include "sage/libs/mpfr.pxd"3132from sage.rings.integer cimport Integer3334from sage.rings.complex_number cimport ComplexNumber35from sage.rings.complex_field import ComplexField36CCC = ComplexField()3738from sage.rings.real_mpfr cimport RealNumber39from sage.rings.real_mpfr import RealField40RRR = RealField()41pi = RRR.pi()4243initialize_globals()4445##############################################################################46# Lfunction: base class for L-functions47##############################################################################4849cdef class Lfunction:50# virtual class51def __init__(self, name, what_type_L, dirichlet_coefficient,52period, Q, OMEGA, gamma, lambd, pole, residue):53"""54Initialization of L-function objects.55See derived class for details, this class is not supposed to be56instantiated directly.5758EXAMPLES::5960sage: from sage.libs.lcalc.lcalc_Lfunction import *61sage: Lfunction_from_character(DirichletGroup(5)[1])62L-function with complex Dirichlet coefficients63"""64cdef int i #for indexing loops65cdef Integer tmpi #for accessing integer values66cdef RealNumber tmpr #for accessing real values67cdef ComplexNumber tmpc #for accessing complexe values6869cdef char *NAME = name70cdef int what_type = what_type_L7172tmpi = Integer(period)73cdef int Period = mpz_get_si(tmpi.value)74tmpr = RRR(Q)75cdef double q=mpfr_get_d(tmpr.value,GMP_RNDN)76tmpc = CCC(OMEGA)77cdef c_Complex w=new_Complex(mpfr_get_d(tmpc.__re,GMP_RNDN), mpfr_get_d(tmpc.__im, GMP_RNDN))7879cdef int A=len(gamma)80cdef double *g=new_doubles(A+1)81cdef c_Complex *l=new_Complexes(A+1)82for i from 0 <= i < A:83tmpr = RRR(gamma[i])84g[i+1] = mpfr_get_d(tmpr.value,GMP_RNDN)85tmpc = CCC(lambd[i])86l[i+1] = new_Complex(mpfr_get_d(tmpc.__re,GMP_RNDN), mpfr_get_d(tmpc.__im, GMP_RNDN))8788cdef int n_poles = len(pole)89cdef c_Complex *p = new_Complexes(n_poles +1)90cdef c_Complex *r = new_Complexes(n_poles +1)91for i from 0 <= i < n_poles:92tmpc=CCC(pole[i])93p[i+1] = new_Complex(mpfr_get_d(tmpc.__re,GMP_RNDN), mpfr_get_d(tmpc.__im, GMP_RNDN))94tmpc=CCC(residue[i])95r[i+1] = new_Complex(mpfr_get_d(tmpc.__re,GMP_RNDN), mpfr_get_d(tmpc.__im, GMP_RNDN))9697self.__init_fun(NAME, what_type, dirichlet_coefficient, Period, q, w, A, g, l, n_poles, p, r)9899repr_name = str(NAME)100if str(repr_name) != "":101repr_name += ": "102103self._repr = repr_name + "L-function"104105del_doubles(g)106del_Complexes(l)107del_Complexes(p)108del_Complexes(r)109110def __repr__(self):111"""112Return string representation of this L-function.113114EXAMPLES::115116sage: from sage.libs.lcalc.lcalc_Lfunction import *117sage: Lfunction_from_character(DirichletGroup(5)[1])118L-function with complex Dirichlet coefficients119120sage: Lfunction_Zeta()121The Riemann zeta function122"""123return self._repr124125def value(self, s, derivative=0):126"""127Computes the value of the L-function at ``s``128129INPUT:130131- ``s`` - a complex number132- ``derivative`` - integer (default: 0) the derivative to be evaluated133- ``rotate`` - (default: False) If True, this returns the value of the134Hardy Z-function (sometimes called the Riemann-Siegel Z-function or135the Siegel Z-function).136137EXAMPLES::138139sage: chi=DirichletGroup(5)[2] #This is a quadratic character140sage: from sage.libs.lcalc.lcalc_Lfunction import *141sage: L=Lfunction_from_character(chi, type="int")142sage: L.value(.5)1430.231750947504... + 5.75329642226...e-18*I144sage: L.value(.2+.4*I)1450.102558603193... + 0.190840777924...*I146147sage: L=Lfunction_from_character(chi, type="double")148sage: L.value(.6)1490.274633355856... + 6.59869267328...e-18*I150sage: L.value(.6+I)1510.362258705721... + 0.433888250620...*I152153sage: chi=DirichletGroup(5)[1]154sage: L=Lfunction_from_character(chi, type="complex")155sage: L.value(.5)1560.763747880117... + 0.216964767518...*I157sage: L.value(.6+5*I)1580.702723260619... - 1.10178575243...*I159160sage: L=Lfunction_Zeta()161sage: L.value(.5)162-1.46035450880...163sage: L.value(.4+.5*I)164-0.450728958517... - 0.780511403019...*I165"""166cdef ComplexNumber complexified_s = CCC(s)167cdef c_Complex z = new_Complex(mpfr_get_d(complexified_s.__re,GMP_RNDN), mpfr_get_d(complexified_s.__im, GMP_RNDN))168cdef c_Complex result = self.__value(z, derivative)169return CCC(result.real(),result.imag())170171def hardy_z_function(self, s):172"""173Computes the Hardy Z-function of the L-function at s174175INPUT:176177- ``s`` - a complex number with imaginary part between -0.5 and 0.5178179EXAMPLES::180181sage: chi=DirichletGroup(5)[2] #This is a quadratic character182sage: from sage.libs.lcalc.lcalc_Lfunction import *183sage: L=Lfunction_from_character(chi, type="int")184sage: L.hardy_z_function(0)1850.231750947504...186sage: L.hardy_z_function(.5).imag().abs() < 1.0e-16187True188sage: L.hardy_z_function(.4+.3*I)1890.2166144222685... - 0.00408187127850...*I190sage: chi=DirichletGroup(5)[1]191sage: L=Lfunction_from_character(chi,type="complex")192sage: L.hardy_z_function(0)1930.7939675904771...194sage: L.hardy_z_function(.5).imag().abs() < 1.0e-16195True196sage: E=EllipticCurve([-82,0])197sage: L=Lfunction_from_elliptic_curve(E, number_of_coeffs=40000)198sage: L.hardy_z_function(2.1)199-0.00643179176869...200sage: L.hardy_z_function(2.1).imag().abs() < 1.0e-16201True202"""203#This takes s -> .5 + I*s204cdef ComplexNumber complexified_s = CCC(0.5)+ CCC(0,1)*CCC(s)205cdef c_Complex z = new_Complex(mpfr_get_d(complexified_s.__re,GMP_RNDN), mpfr_get_d(complexified_s.__im, GMP_RNDN))206cdef c_Complex result = self.__hardy_z_function(z)207return CCC(result.real(),result.imag())208209210def compute_rank(self):211"""212Computes the analytic rank (the order of vanishing at the center) of213of the L-function214215EXAMPLES::216217sage: chi=DirichletGroup(5)[2] #This is a quadratic character218sage: from sage.libs.lcalc.lcalc_Lfunction import *219sage: L=Lfunction_from_character(chi, type="int")220sage: L.compute_rank()2210222sage: E=EllipticCurve([-82,0])223sage: L=Lfunction_from_elliptic_curve(E, number_of_coeffs=40000)224sage: L.compute_rank()2253226"""227return self.__compute_rank()228229def __N(self, T):230"""231Compute the number of zeroes upto height `T` using the formula for232`N(T)` with the error of `S(T)`. Please do not use this. It is only233for debugging234235EXAMPLES::236237sage: from sage.libs.lcalc.lcalc_Lfunction import *238sage: chi=DirichletGroup(5)[2] #This is a quadratic character239sage: L=Lfunction_from_character(chi, type="complex")240sage: L.__N(10)2413.17043978326...242"""243cdef RealNumber real_T=RRR(T)244cdef double double_T = mpfr_get_d(real_T.value, GMP_RNDN)245cdef double res_d = self.__typedN(double_T)246return RRR(res_d)247248def find_zeros(self, T1, T2, stepsize):249"""250Finds zeros on critical line between ``T1`` and ``T2`` using step size251of stepsize. This function might miss zeros if step size is too252large. This function computes the zeros of the L-function by using253change in signs of areal valued function whose zeros coincide with254the zeros of L-function.255256Use find_zeros_via_N for slower but more rigorous computation.257258INPUT:259260- ``T1`` -- a real number giving the lower bound261- ``T2`` -- a real number giving the upper bound262- ``stepsize`` -- step size to be used for the zero search263264OUTPUT:265266list -- A list of the imaginary parts of the zeros which were found.267268EXAMPLES::269270sage: from sage.libs.lcalc.lcalc_Lfunction import *271sage: chi=DirichletGroup(5)[2] #This is a quadratic character272sage: L=Lfunction_from_character(chi, type="int")273sage: L.find_zeros(5,15,.1)274[6.64845334472..., 9.83144443288..., 11.9588456260...]275276sage: L=Lfunction_from_character(chi, type="double")277sage: L.find_zeros(1,15,.1)278[6.64845334472..., 9.83144443288..., 11.9588456260...]279280sage: chi=DirichletGroup(5)[1]281sage: L=Lfunction_from_character(chi, type="complex")282sage: L.find_zeros(-8,8,.1)283[-4.13290370521..., 6.18357819545...]284285sage: L=Lfunction_Zeta()286sage: L.find_zeros(10,29.1,.1)287[14.1347251417..., 21.0220396387..., 25.0108575801...]288"""289cdef doublevec result290cdef double myresult291cdef int i292cdef RealNumber real_T1 = RRR(T1)293cdef RealNumber real_T2 = RRR(T2)294cdef RealNumber real_stepsize = RRR(stepsize)295sig_on()296self.__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)297sig_off()298i=result.size()299returnvalue = []300for i in range(result.size()):301returnvalue.append( RRR(result.ind(i)))302result.clear()303return returnvalue304305#The default values are from L.h. See L.h306def find_zeros_via_N(self, count=0, do_negative=False, max_refine=1025,307rank=-1, test_explicit_formula=0):308"""309Finds ``count`` number of zeros with positive imaginary part310starting at real axis. This function also verifies that all311the zeros have been found.312313INPUT:314315- ``count`` - number of zeros to be found316- ``do_negative`` - (default: False) False to ignore zeros below the317real axis.318- ``max_refine`` - when some zeros are found to be missing, the step319size used to find zeros is refined. max_refine gives an upper limit320on when lcalc should give up. Use default value unless you know321what you are doing.322- ``rank`` - integer (default: -1) analytic rank of the L-function.323If -1 is passed, then we attempt to compute it. (Use default if in324doubt)325- ``test_explicit_formula`` - integer (default: 0) If nonzero, test326the explicit fomula for additional confidence that all the zeros327have been found and are accurate. This is still being tested, so328using the default is recommended.329330331OUTPUT:332333list -- A list of the imaginary parts of the zeros that have been found334335EXAMPLES::336337sage: from sage.libs.lcalc.lcalc_Lfunction import *338sage: chi=DirichletGroup(5)[2] #This is a quadratic character339sage: L=Lfunction_from_character(chi, type="int")340sage: L.find_zeros_via_N(3)341[6.64845334472..., 9.83144443288..., 11.9588456260...]342343sage: L=Lfunction_from_character(chi, type="double")344sage: L.find_zeros_via_N(3)345[6.64845334472..., 9.83144443288..., 11.9588456260...]346347sage: chi=DirichletGroup(5)[1]348sage: L=Lfunction_from_character(chi, type="complex")349sage: L.find_zeros_via_N(3)350[6.18357819545..., 8.45722917442..., 12.6749464170...]351352sage: L=Lfunction_Zeta()353sage: L.find_zeros_via_N(3)354[14.1347251417..., 21.0220396387..., 25.0108575801...]355"""356cdef Integer count_I = Integer(count)357cdef Integer do_negative_I = Integer(do_negative)358cdef RealNumber max_refine_R = RRR(max_refine)359cdef Integer rank_I = Integer(rank)360cdef Integer test_explicit_I = Integer(test_explicit_formula)361cdef doublevec result362sig_on()363self.__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)364sig_off()365returnvalue = []366for i in range(result.size()):367returnvalue.append( RRR(result.ind(i)))368result.clear()369return returnvalue370371#### Needs to be overriden372cdef 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):373raise NotImplementedError374375cdef c_Complex __value(self,c_Complex s,int derivative):376raise NotImplementedError377378cdef c_Complex __hardy_z_function(self,c_Complex s):379raise NotImplementedError380381cdef int __compute_rank(self):382raise NotImplementedError383384cdef double __typedN(self,double T):385raise NotImplementedError386387cdef void __find_zeros_v(self,double T1, double T2, double stepsize, doublevec *result):388raise NotImplementedError389390cdef void __find_zeros_via_N_v(self, long count,int do_negative,double max_refine, int rank, int test_explicit_formula, doublevec *result):391raise NotImplementedError392393##############################################################################394# Lfunction_I: L-functions with integer Dirichlet Coefficients395##############################################################################396397cdef class Lfunction_I(Lfunction):398r"""399The ``Lfunction_I`` class is used to represent L-functions400with integer Dirichlet Coefficients. We assume that L-functions401satisfy the following functional equation.402403.. math::404405\Lambda(s) = \omega Q^s \overline{\Lambda(1-\bar s)}406407where408409.. math::410411\Lambda(s) = Q^s \left( \prod_{j=1}^a \Gamma(\kappa_j s + \gamma_j) \right) L(s)412413414415See (23) in http://arxiv.org/abs/math/0412181416417INPUT:418419- ``what_type_L`` - integer, this should be set to 1 if the coefficients are420periodic and 0 otherwise.421422- ``dirichlet_coefficient`` - List of dirichlet coefficients of the423L-function. Only first `M` coefficients are needed if they are periodic.424425- ``period`` - If the coefficients are periodic, this should be the426period of the coefficients.427428- ``Q`` - See above429430- ``OMEGA`` - See above431432- ``kappa`` - List of the values of `\kappa_j` in the functional equation433434435- ``gamma`` - List of the values of `\gamma_j` in the functional equation436437- ``pole`` - List of the poles of L-function438439- ``residue`` - List of the residues of the L-function440441NOTES:442443If an L-function satisfies `\Lambda(s) = \omega Q^s \Lambda(k-s)`,444by replacing `s` by `s+(k-1)/2`, one can get it in the form we need.445"""446447def __init__(self, name, what_type_L, dirichlet_coefficient,448period, Q, OMEGA, gamma, lambd, pole, residue):449r"""450Initialize an L-function with integer coefficients451452EXAMPLES::453454sage: from sage.libs.lcalc.lcalc_Lfunction import *455sage: chi=DirichletGroup(5)[2] #This is a quadratic character456sage: L=Lfunction_from_character(chi, type="int")457sage: type(L)458<type 'sage.libs.lcalc.lcalc_Lfunction.Lfunction_I'>459"""460Lfunction.__init__(self, name, what_type_L, dirichlet_coefficient, period, Q, OMEGA, gamma,lambd, pole,residue)461self._repr += " with integer Dirichlet coefficients"462463### override464cdef 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):465cdef int N = len(dirichlet_coeff)466cdef Integer tmpi467cdef int * coeffs = new_ints(N+1) #lcalc ignores 0the coefficient468for i from 0 <= i< N by 1:469tmpi=Integer(dirichlet_coeff[i])470coeffs[i+1] = mpz_get_si(tmpi.value)471self.thisptr=new_c_Lfunction_I(NAME, what_type, N, coeffs, Period, q, w, A, g, l, n_poles, p, r)472del_ints(coeffs)473474cdef inline c_Complex __value(self,c_Complex s,int derivative):475return (<c_Lfunction_I *>(self.thisptr)).value(s, derivative, "pure")476477cdef inline c_Complex __hardy_z_function(self,c_Complex s):478return (<c_Lfunction_I *>(self.thisptr)).value(s, 0, "rotated pure")479480cdef int __compute_rank(self):481return (<c_Lfunction_I *>(self.thisptr)).compute_rank()482483cdef void __find_zeros_v(self, double T1, double T2, double stepsize, doublevec *result):484(<c_Lfunction_I *>self.thisptr).find_zeros_v(T1,T2,stepsize,result[0])485486cdef double __typedN(self, double T):487return (<c_Lfunction_I *>self.thisptr).N(T)488489cdef void __find_zeros_via_N_v(self, long count,int do_negative,double max_refine, int rank, int test_explicit_formula, doublevec *result):490(<c_Lfunction_I *>self.thisptr).find_zeros_via_N_v(count, do_negative, max_refine, rank, test_explicit_formula, result[0])491492### debug tools493def _print_data_to_standard_output(self):494"""495This is used in debugging. It prints out information from496the C++ object behind the scenes. It will use standard output.497498EXAMPLES::499500sage: from sage.libs.lcalc.lcalc_Lfunction import *501sage: chi=DirichletGroup(5)[2] #This is a quadratic character502sage: L=Lfunction_from_character(chi, type="int")503sage: L._print_data_to_standard_output() # tol 1e-15504-----------------------------------------------505<BLANKLINE>506Name of L_function:507number of dirichlet coefficients = 5508coefficients are periodic509b[1] = 1510b[2] = -1511b[3] = -1512b[4] = 1513b[5] = 0514<BLANKLINE>515Q = 1.26156626101516OMEGA = (1,0)517a = 1 (the quasi degree)518gamma[1] =0.5 lambda[1] =(0,0)519<BLANKLINE>520<BLANKLINE>521number of poles (of the completed L function) = 0522-----------------------------------------------523<BLANKLINE>524"""525(<c_Lfunction_I *>self.thisptr).print_data_L()526527def __dealloc__(self):528"""529Deallocate memory used530"""531del_c_Lfunction_I(<c_Lfunction_I *>(self.thisptr))532533##############################################################################534# Lfunction_D: L-functions with double (real) Dirichlet Coefficients535##############################################################################536537cdef class Lfunction_D(Lfunction):538r"""539The ``Lfunction_D`` class is used to represent L-functions540with real Dirichlet coefficients. We assume that L-functions541satisfy the following functional equation.542543.. math::544545\Lambda(s) = \omega Q^s \overline{\Lambda(1-\bar s)}546547where548549.. math::550551\Lambda(s) = Q^s \left( \prod_{j=1}^a \Gamma(\kappa_j s + \gamma_j) \right) L(s)552553See (23) in http://arxiv.org/abs/math/0412181554555INPUT:556557- ``what_type_L`` - integer, this should be set to 1 if the coefficients are558periodic and 0 otherwise.559560- ``dirichlet_coefficient`` - List of dirichlet coefficients of the561L-function. Only first `M` coefficients are needed if they are periodic.562563- ``period`` - If the coefficients are periodic, this should be the564period of the coefficients.565566- ``Q`` - See above567568- ``OMEGA`` - See above569570- ``kappa`` - List of the values of `\kappa_j` in the functional equation571572- ``gamma`` - List of the values of `\gamma_j` in the functional equation573574- ``pole`` - List of the poles of L-function575576- ``residue`` - List of the residues of the L-function577578NOTES:579If an L-function satisfies `\Lambda(s) = \omega Q^s \Lambda(k-s)`,580by replacing `s` by `s+(k-1)/2`, one can get it in the form we need.581"""582def __init__(self, name, what_type_L, dirichlet_coefficient,583period, Q, OMEGA, gamma, lambd, pole, residue):584r"""585Initialize an L-function with real coefficients586587EXAMPLES::588589sage: from sage.libs.lcalc.lcalc_Lfunction import *590sage: chi=DirichletGroup(5)[2] #This is a quadratic character591sage: L=Lfunction_from_character(chi, type="double")592sage: type(L)593<type 'sage.libs.lcalc.lcalc_Lfunction.Lfunction_D'>594"""595Lfunction.__init__(self, name, what_type_L, dirichlet_coefficient, period, Q, OMEGA, gamma,lambd, pole,residue)596self._repr += " with real Dirichlet coefficients"597598### override599cdef 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):600cdef int i601cdef RealNumber tmpr602cdef int N = len(dirichlet_coeff)603cdef double * coeffs = new_doubles(N+1)#lcalc ignores 0th position604for i from 0 <= i< N by 1:605tmpr=RRR(dirichlet_coeff[i])606coeffs[i+1] = mpfr_get_d(tmpr.value, GMP_RNDN)607self.thisptr=new_c_Lfunction_D(NAME, what_type, N, coeffs, Period, q, w, A, g, l, n_poles, p, r)608del_doubles(coeffs)609610cdef inline c_Complex __value(self,c_Complex s,int derivative):611return (<c_Lfunction_D *>(self.thisptr)).value(s, derivative, "pure")612613614cdef inline c_Complex __hardy_z_function(self,c_Complex s):615return (<c_Lfunction_D *>(self.thisptr)).value(s, 0, "rotated pure")616617cdef inline int __compute_rank(self):618return (<c_Lfunction_D *>(self.thisptr)).compute_rank()619620cdef void __find_zeros_v(self, double T1, double T2, double stepsize, doublevec *result):621(<c_Lfunction_D *>self.thisptr).find_zeros_v(T1,T2,stepsize,result[0])622623cdef double __typedN(self, double T):624return (<c_Lfunction_D *>self.thisptr).N(T)625626cdef void __find_zeros_via_N_v(self, long count,int do_negative,double max_refine, int rank, int test_explicit_formula, doublevec *result):627(<c_Lfunction_D *>self.thisptr).find_zeros_via_N_v(count, do_negative, max_refine, rank, test_explicit_formula, result[0])628629### debug tools630def _print_data_to_standard_output(self):631"""632This is used in debugging. It prints out information from633the C++ object behind the scenes. It will use standard output.634635EXAMPLES::636637sage: from sage.libs.lcalc.lcalc_Lfunction import *638sage: chi=DirichletGroup(5)[2] #This is a quadratic character639sage: L=Lfunction_from_character(chi, type="double")640sage: L._print_data_to_standard_output() # tol 1e-15641-----------------------------------------------642<BLANKLINE>643Name of L_function:644number of dirichlet coefficients = 5645coefficients are periodic646b[1] = 1647b[2] = -1648b[3] = -1649b[4] = 1650b[5] = 0651<BLANKLINE>652Q = 1.26156626101653OMEGA = (1,0)654a = 1 (the quasi degree)655gamma[1] =0.5 lambda[1] =(0,0)656<BLANKLINE>657<BLANKLINE>658number of poles (of the completed L function) = 0659-----------------------------------------------660<BLANKLINE>661662"""663(<c_Lfunction_D *>self.thisptr).print_data_L()664665def __dealloc__(self):666"""667Deallocate memory used668"""669del_c_Lfunction_D(<c_Lfunction_D *>(self.thisptr))670671##############################################################################672# Lfunction_C: L-functions with Complex Dirichlet Coefficients673##############################################################################674675cdef class Lfunction_C:676r"""677The ``Lfunction_C`` class is used to represent L-functions678with complex Dirichlet Coefficients. We assume that L-functions679satisfy the following functional equation.680681.. math::682683\Lambda(s) = \omega Q^s \overline{\Lambda(1-\bar s)}684685where686687.. math::688689\Lambda(s) = Q^s \left( \prod_{j=1}^a \Gamma(\kappa_j s + \gamma_j) \right) L(s)690691See (23) in http://arxiv.org/abs/math/0412181692693INPUT:694695- ``what_type_L`` - integer, this should be set to 1 if the coefficients are696periodic and 0 otherwise.697698- ``dirichlet_coefficient`` - List of dirichlet coefficients of the699L-function. Only first `M` coefficients are needed if they are periodic.700701- ``period`` - If the coefficients are periodic, this should be the702period of the coefficients.703704- ``Q`` - See above705706- ``OMEGA`` - See above707708- ``kappa`` - List of the values of `\kappa_j` in the functional equation709710- ``gamma`` - List of the values of `\gamma_j` in the functional equation711712- ``pole`` - List of the poles of L-function713714- ``residue`` - List of the residues of the L-function715716NOTES:717If an L-function satisfies `\Lambda(s) = \omega Q^s \Lambda(k-s)`,718by replacing `s` by `s+(k-1)/2`, one can get it in the form we need.719"""720721def __init__(self, name, what_type_L, dirichlet_coefficient,722period, Q, OMEGA, gamma, lambd, pole, residue):723r"""724Initialize an L-function with complex coefficients725726EXAMPLES::727728sage: from sage.libs.lcalc.lcalc_Lfunction import *729sage: chi=DirichletGroup(5)[1]730sage: L=Lfunction_from_character(chi, type="complex")731sage: type(L)732<type 'sage.libs.lcalc.lcalc_Lfunction.Lfunction_C'>733"""734Lfunction.__init__(self, name, what_type_L, dirichlet_coefficient, period, Q, OMEGA, gamma,lambd, pole,residue)735self._repr += " with complex Dirichlet coefficients"736737### override738cdef 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):739cdef int i740cdef int N = len(dirichlet_coeff)741cdef ComplexNumber tmpc742743cdef c_Complex * coeffs = new_Complexes(N+1)744coeffs[0]=new_Complex(0,0)745for i from 0 <= i< N by 1:746tmpc=CCC(dirichlet_coeff[i])747coeffs[i+1] = new_Complex(mpfr_get_d(tmpc.__re,GMP_RNDN), mpfr_get_d(tmpc.__im, GMP_RNDN))748749self.thisptr = new_c_Lfunction_C(NAME, what_type, N, coeffs, Period, q, w, A, g, l, n_poles, p, r)750751del_Complexes(coeffs)752753cdef inline c_Complex __value(self,c_Complex s,int derivative):754return (<c_Lfunction_C *>(self.thisptr)).value(s, derivative, "pure")755756757cdef inline c_Complex __hardy_z_function(self,c_Complex s):758return (<c_Lfunction_C *>(self.thisptr)).value(s, 0,"rotated pure")759760cdef inline int __compute_rank(self):761return (<c_Lfunction_C *>(self.thisptr)).compute_rank()762763764cdef void __find_zeros_v(self, double T1, double T2, double stepsize, doublevec *result):765(<c_Lfunction_C *>self.thisptr).find_zeros_v(T1,T2,stepsize,result[0])766767cdef double __typedN(self, double T):768return (<c_Lfunction_C *>self.thisptr).N(T)769770cdef void __find_zeros_via_N_v(self, long count,int do_negative,double max_refine, int rank, int test_explicit_formula, doublevec *result):771(<c_Lfunction_C *>self.thisptr).find_zeros_via_N_v(count, do_negative, max_refine, rank, test_explicit_formula, result[0])772773### debug tools774def _print_data_to_standard_output(self):775"""776This is used in debugging. It prints out information from777the C++ object behind the scenes. It will use standard output.778779EXAMPLES::780781sage: from sage.libs.lcalc.lcalc_Lfunction import *782sage: chi=DirichletGroup(5)[1]783sage: L=Lfunction_from_character(chi, type="complex")784sage: L._print_data_to_standard_output() # tol 1e-15785-----------------------------------------------786<BLANKLINE>787Name of L_function:788number of dirichlet coefficients = 5789coefficients are periodic790b[1] = (1,0)791b[2] = (0,1)792b[3] = (0,-1)793b[4] = (-1,0)794b[5] = (0,0)795<BLANKLINE>796Q = 1.26156626101797OMEGA = (0.850650808352,0.525731112119)798a = 1 (the quasi degree)799gamma[1] =0.5 lambda[1] =(0.5,0)800<BLANKLINE>801<BLANKLINE>802number of poles (of the completed L function) = 0803-----------------------------------------------804<BLANKLINE>805806807"""808(<c_Lfunction_C *>self.thisptr).print_data_L()809810def __dealloc__(self):811"""812Deallocate memory used813"""814del_c_Lfunction_C(<c_Lfunction_C *>(self.thisptr))815816817##############################################################################818#Zeta function819##############################################################################820821cdef class Lfunction_Zeta(Lfunction):822r"""823The ``Lfunction_Zeta`` class is used to generate the Riemann zeta function.824"""825def __init__(self):826r"""827Initialize the Riemann zeta function.828829EXAMPLES::830831sage: from sage.libs.lcalc.lcalc_Lfunction import *832sage: sage.libs.lcalc.lcalc_Lfunction.Lfunction_Zeta()833The Riemann zeta function834"""835self.thisptr = new_c_Lfunction_Zeta()836self._repr = "The Riemann zeta function"837838cdef inline c_Complex __value(self,c_Complex s,int derivative):839return (<c_Lfunction_Zeta *>(self.thisptr)).value(s, derivative, "pure")840841842cdef inline c_Complex __hardy_z_function(self,c_Complex s):843return (<c_Lfunction_Zeta *>(self.thisptr)).value(s, 0, "rotated pure")844845cdef inline int __compute_rank(self):846return (<c_Lfunction_Zeta *>(self.thisptr)).compute_rank()847848849cdef void __find_zeros_v(self, double T1, double T2, double stepsize, doublevec *result):850(<c_Lfunction_Zeta *>self.thisptr).find_zeros_v(T1,T2,stepsize,result[0])851852cdef double __typedN(self, double T):853return (<c_Lfunction_Zeta *>self.thisptr).N(T)854855cdef void __find_zeros_via_N_v(self, long count,int do_negative,double max_refine, int rank, int test_explicit_formula, doublevec *result):856(<c_Lfunction_Zeta *>self.thisptr).find_zeros_via_N_v(count, do_negative, max_refine, rank, test_explicit_formula, result[0])857858def __dealloc__(self):859"""860Deallocate memory used861"""862del_c_Lfunction_Zeta(<c_Lfunction_Zeta *>(self.thisptr))863864##############################################################################865# Tools866##############################################################################867868def Lfunction_from_character(chi, type="complex"):869"""870Given a primitive Dirichlet character, this function returns871an lcalc L-function object for the L-function of the character.872873INPUT:874875- `chi` - A Dirichlet character876- `use_type` - string (default: "complex") type used for the Dirichlet877coefficients. This can be "int", "double" or "complex".878879OUTPUT:880881L-function object for `chi`.882883EXAMPLES::884885sage: from sage.libs.lcalc.lcalc_Lfunction import Lfunction_from_character886sage: Lfunction_from_character(DirichletGroup(5)[1])887L-function with complex Dirichlet coefficients888sage: Lfunction_from_character(DirichletGroup(5)[2], type="int")889L-function with integer Dirichlet coefficients890sage: Lfunction_from_character(DirichletGroup(5)[2], type="double")891L-function with real Dirichlet coefficients892sage: Lfunction_from_character(DirichletGroup(5)[1], type="int")893Traceback (most recent call last):894...895ValueError: For non quadratic characters you must use type="complex"896897"""898if (not chi.is_primitive()):899raise TypeError("Dirichlet character is not primitive")900901modulus=chi.modulus()902if (chi(-1) == 1):903a=0904else:905a=1906907Q=(RRR(modulus/pi)).sqrt()908poles=[]909residues=[]910period=modulus911OMEGA=1.0/ ( CCC(0,1)**a * (CCC(modulus)).sqrt()/chi.gauss_sum() )912913if type == "complex":914dir_coeffs=[CCC(chi(n)) for n in xrange(1,modulus+1)]915return Lfunction_C("", 1,dir_coeffs, period,Q,OMEGA,[.5],[a/2.],poles,residues)916if not type in ["double","int"]:917raise ValueError("unknown type")918if chi.order() != 2:919raise ValueError("For non quadratic characters you must use type=\"complex\"")920if type == "double":921dir_coeffs=[RRR(chi(n)) for n in xrange(1,modulus+1)]922return Lfunction_D("", 1,dir_coeffs, period,Q,OMEGA,[.5],[a/2.],poles,residues)923if type == "int":924dir_coeffs=[Integer(chi(n)) for n in xrange(1,modulus+1)]925return Lfunction_I("", 1,dir_coeffs, period,Q,OMEGA,[.5],[a/2.],poles,residues)926927928def Lfunction_from_elliptic_curve(E, number_of_coeffs=10000):929"""930Given an elliptic curve E, return an L-function object for931the function `L(s, E)`.932933INPUT:934935- ``E`` - An elliptic curve936- ``number_of_coeffs`` - integer (default: 10000) The number of937coefficients to be used when constructing the L-function object. Right938now this is fixed at object creation time, and is not automatically939set intelligently.940941OUTPUT:942943L-function object for ``L(s, E)``.944945EXAMPLES::946947sage: from sage.libs.lcalc.lcalc_Lfunction import Lfunction_from_elliptic_curve948sage: L = Lfunction_from_elliptic_curve(EllipticCurve('37'))949sage: L950L-function with real Dirichlet coefficients951sage: L.value(0.5).abs() < 1e-15 # "noisy" zero on some platforms (see #9615)952True953sage: L.value(0.5, derivative=1)9540.305999...955"""956Q=(RRR(E.conductor())).sqrt()/(RRR(2*pi))957poles=[]958residues=[]959import sage.libs.lcalc.lcalc_Lfunction960dir_coeffs=E.anlist(number_of_coeffs)961dir_coeffs=[RRR(dir_coeffs[i])/(RRR(i)).sqrt() for i in xrange(1,number_of_coeffs)]962OMEGA=E.root_number()963return Lfunction_D("", 2,dir_coeffs, 0,Q,OMEGA,[1],[.5],poles,residues)964965966