diff --git a/src/sage/lfunctions/lcalc.py b/src/sage/lfunctions/lcalc.py index aabbd47..6efa5fe 100644 --- a/src/sage/lfunctions/lcalc.py +++ b/src/sage/lfunctions/lcalc.py @@ -225,19 +225,54 @@ class LCalc(SageObject): EXAMPLES:: sage: I = CC.0 - sage: lcalc.values_along_line(0.5, 0.5+20*I, 5) - [(0.500000000, -1.46035451), (0.500000000 + 4.00000000*I, 0.606783764 + 0.0911121400*I), (0.500000000 + 8.00000000*I, 1.24161511 + 0.360047588*I), (0.500000000 + 12.0000000*I, 1.01593665 - 0.745112472*I), (0.500000000 + 16.0000000*I, 0.938545408 + 1.21658782*I)] + sage: values = lcalc.values_along_line(0.5, 0.5+20*I, 5) + sage: values[0][0] # abs tol 1e-8 + 0.5 + sage: values[0][1] # abs tol 1e-8 + -1.46035451 + 0.0*I + sage: values[1][0] # abs tol 1e-8 + 0.5 + 4.0*I + sage: values[1][1] # abs tol 1e-8 + 0.606783764 + 0.0911121400*I + sage: values[2][0] # abs tol 1e-8 + 0.5 + 8.0*I + sage: values[2][1] # abs tol 1e-8 + 1.24161511 + 0.360047588*I + sage: values[3][0] # abs tol 1e-8 + 0.5 + 12.0*I + sage: values[3][1] # abs tol 1e-8 + 1.01593665 - 0.745112472*I + sage: values[4][0] # abs tol 1e-8 + 0.5 + 16.0*I + sage: values[4][1] # abs tol 1e-8 + 0.938545408 + 1.21658782*I Sometimes warnings are printed (by lcalc) when this command is run:: sage: E = EllipticCurve('389a') - sage: E.lseries().values_along_line(0.5, 3, 5) - [(0.000000000, 0.209951303), - (0.500000000, -...e-16), - (1.00000000, 0.133768433), - (1.50000000, 0.360092864), - (2.00000000, 0.552975867)] + sage: values = E.lseries().values_along_line(0.5, 3, 5) + sage: values[0][0] # abs tol 1e-8 + 0.0 + sage: values[0][1] # abs tol 1e-8 + 0.209951303 + 0.0*I + sage: values[1][0] # abs tol 1e-8 + 0.5 + sage: values[1][1] # abs tol 1e-8 + 0.0 + 0.0*I + sage: values[2][0] # abs tol 1e-8 + 1.0 + sage: values[2][1] # abs tol 1e-8 + 0.133768433 - 0.0*I + sage: values[3][0] # abs tol 1e-8 + 1.5 + sage: values[3][1] # abs tol 1e-8 + 0.360092864 - 0.0*I + sage: values[4][0] # abs tol 1e-8 + 2.0 + sage: values[4][1] # abs tol 1e-8 + 0.552975867 + 0.0*I + """ L = self._compute_L(L) CC = sage.rings.all.ComplexField(prec) @@ -281,8 +316,31 @@ class LCalc(SageObject): EXAMPLES:: - sage: lcalc.twist_values(0.5, -10, 10) - [(-8, 1.10042141), (-7, 1.14658567), (-4, 0.667691457), (-3, 0.480867558), (5, 0.231750947), (8, 0.373691713)] + sage: values = lcalc.twist_values(0.5, -10, 10) + sage: values[0][0] + -8 + sage: values[0][1] # abs tol 1e-8 + 1.10042141 + 0.0*I + sage: values[1][0] + -7 + sage: values[1][1] # abs tol 1e-8 + 1.14658567 + 0.0*I + sage: values[2][0] + -4 + sage: values[2][1] # abs tol 1e-8 + 0.667691457 + 0.0*I + sage: values[3][0] + -3 + sage: values[3][1] # abs tol 1e-8 + 0.480867558 + 0.0*I + sage: values[4][0] + 5 + sage: values[4][1] # abs tol 1e-8 + 0.231750947 + 0.0*I + sage: values[5][0] + 8 + sage: values[5][1] # abs tol 1e-8 + 0.373691713 + 0.0*I """ L = self._compute_L(L) CC = sage.rings.all.ComplexField(prec) diff --git a/src/sage/lfunctions/zero_sums.pyx b/src/sage/lfunctions/zero_sums.pyx index 225fe7d..8b0e566 100644 --- a/src/sage/lfunctions/zero_sums.pyx +++ b/src/sage/lfunctions/zero_sums.pyx @@ -829,8 +829,11 @@ cdef class LFunctionZeroSum_abstract(SageObject): EXAMPLES:: sage: E = EllipticCurve("11a") - sage: E.lseries().zeros(2) - [6.36261389, 8.60353962] + sage: zeros = E.lseries().zeros(2) + sage: zeros[0] # abs tol 1e-8 + 6.36261389 + sage: zeros[1] # abs tol 1e-8 + 8.60353962 E is a rank zero curve; the lowest zero has imaginary part ~6.36. The zero sum with tau=0 indicates that there are no zeros at the central diff --git a/src/sage/libs/lcalc/lcalc_Lfunction.pxd b/src/sage/libs/lcalc/lcalc_Lfunction.pxd index d1dbb5d..5edf084 100644 --- a/src/sage/libs/lcalc/lcalc_Lfunction.pxd +++ b/src/sage/libs/lcalc/lcalc_Lfunction.pxd @@ -21,7 +21,7 @@ cdef extern from "lcalc_sage.h": int (* compute_rank) () double (* N) (double T) void (* find_zeros_v)(double T1, double T2, double stepsize, doublevec result ) - void (*find_zeros_via_N_v)(long count,int do_negative,double max_refine, int rank, int test_explicit_formula, doublevec result) + int (*find_zeros)(long count, long start, double max_refine, int rank, const char* message_stamp, doublevec* result) void (*print_data_L)() #Constructor and destructor @@ -38,7 +38,7 @@ cdef extern from "lcalc_sage.h": double (* N) (double T) double *dirichlet_coefficient void (* find_zeros_v)(double T1, double T2, double stepsize, doublevec result ) - void (*find_zeros_via_N_v)(long count,int do_negative,double max_refine, int rank, int test_explicit_formula, doublevec result) + int (*find_zeros)(long count, long start, double max_refine, int rank, const char* message_stamp, doublevec* result) void (*print_data_L)() #Constructor and destructor @@ -54,7 +54,7 @@ cdef extern from "lcalc_sage.h": int (* compute_rank) () double (* N) (double T) void (* find_zeros_v)(double T1, double T2, double stepsize, doublevec result ) - void (*find_zeros_via_N_v)(long count,int do_negative,double max_refine, int rank, int test_explicit_formula, doublevec result) + int (*find_zeros)(long count, long start, double max_refine, int rank, const char* message_stamp, doublevec* result) void (*print_data_L)() #Constructor and destructor @@ -70,7 +70,7 @@ cdef extern from "lcalc_sage.h": int (* compute_rank) () double (* N) (double T) void (* find_zeros_v)(double T1, double T2, double stepsize, doublevec result ) - void (*find_zeros_via_N_v)(long count,int do_negative,double max_refine, int rank, int test_explicit_formula, doublevec result)#puts result in vector result + int (*find_zeros)(long count, long start, double max_refine, int rank, const char* message_stamp, doublevec* result) void (*find_zeros_via_N)(long count,int do_negative,double max_refine, int rank, int test_explicit_formula, char *filename) #puts result in filename #Constructor and destructor @@ -111,7 +111,7 @@ cdef class Lfunction: #strange bug, replacing Double with double gives me a compile error cdef Double __typedN(self, double T) cdef void __find_zeros_v(self, double T1, double T2, double stepsize,doublevec *result) - cdef void __find_zeros_via_N_v(self, long count,int do_negative,double max_refine, int rank, int test_explicit_formula,doublevec *result) + cdef int __find_zeros(self, long count, long start, double max_refine, int rank, const char* message_stamp, doublevec* result) cdef str _repr diff --git a/src/sage/libs/lcalc/lcalc_Lfunction.pyx b/src/sage/libs/lcalc/lcalc_Lfunction.pyx index 7e54d7e..88a6e13 100644 --- a/src/sage/libs/lcalc/lcalc_Lfunction.pyx +++ b/src/sage/libs/lcalc/lcalc_Lfunction.pyx @@ -143,29 +143,29 @@ cdef class Lfunction: sage: chi = DirichletGroup(5)[2] #This is a quadratic character sage: from sage.libs.lcalc.lcalc_Lfunction import * sage: L=Lfunction_from_character(chi, type="int") - sage: L.value(.5) # abs tol 3e-15 + sage: L.value(.5) # abs tol 1e-8 0.231750947504016 + 5.75329642226136e-18*I - sage: L.value(.2+.4*I) - 0.102558603193... + 0.190840777924...*I + sage: L.value(.2+.4*I) # abs tol 1e-8 + 0.102558603193 + 0.190840777924*I sage: L=Lfunction_from_character(chi, type="double") - sage: L.value(.6) # abs tol 3e-15 + sage: L.value(.6) # abs tol 1e-8 0.274633355856345 + 6.59869267328199e-18*I - sage: L.value(.6+I) - 0.362258705721... + 0.433888250620...*I + sage: L.value(.6+I) # abs tol 1e-8 + 0.362258705721 + 0.433888250620*I sage: chi = DirichletGroup(5)[1] sage: L=Lfunction_from_character(chi, type="complex") - sage: L.value(.5) - 0.763747880117... + 0.216964767518...*I - sage: L.value(.6+5*I) - 0.702723260619... - 1.10178575243...*I + sage: L.value(.5) # abs tol 1e-8 + 0.763747880117 + 0.216964767518*I + sage: L.value(.6+5*I) # abs tol 1e-8 + 0.702723260619 - 1.10178575243*I sage: L=Lfunction_Zeta() - sage: L.value(.5) - -1.46035450880... - sage: L.value(.4+.5*I) - -0.450728958517... - 0.780511403019...*I + sage: L.value(.5) # abs tol 1e-8 + -1.46035450880 + 0.0*I + sage: L.value(.4+.5*I) # abs tol 1e-8 + -0.450728958517 - 0.780511403019*I """ cdef ComplexNumber complexified_s = CCC(s) cdef c_Complex z = new_Complex(mpfr_get_d(complexified_s.__re, MPFR_RNDN), mpfr_get_d(complexified_s.__im, MPFR_RNDN)) @@ -185,23 +185,21 @@ cdef class Lfunction: sage: chi = DirichletGroup(5)[2] # Quadratic character sage: from sage.libs.lcalc.lcalc_Lfunction import * sage: L = Lfunction_from_character(chi, type="int") - sage: L.hardy_z_function(0) - 0.231750947504... - sage: L.hardy_z_function(.5).imag() # abs tol 1e-15 + sage: L.hardy_z_function(0) # abs tol 1e-8 + 0.231750947504 + 0.0*I + sage: L.hardy_z_function(.5).imag() # abs tol 1e-8 1.17253174178320e-17 - sage: L.hardy_z_function(.4+.3*I) - 0.2166144222685... - 0.00408187127850...*I sage: chi = DirichletGroup(5)[1] sage: L = Lfunction_from_character(chi, type="complex") - sage: L.hardy_z_function(0) - 0.793967590477... - sage: L.hardy_z_function(.5).imag() # abs tol 1e-15 + sage: L.hardy_z_function(0) # abs tol 1e-8 + 0.793967590477 + 0.0*I + sage: L.hardy_z_function(.5).imag() # abs tol 1e-8 0.000000000000000 sage: E = EllipticCurve([-82,0]) sage: L = Lfunction_from_elliptic_curve(E, number_of_coeffs=40000) - sage: L.hardy_z_function(2.1) - -0.00643179176869... - sage: L.hardy_z_function(2.1).imag() # abs tol 1e-15 + sage: L.hardy_z_function(2.1) # abs tol 1e-8 + -0.00643179176863296 - 1.47189978221606e-19*I + sage: L.hardy_z_function(2.1).imag() # abs tol 1e-8 -3.93833660115668e-19 """ #This takes s -> .5 + I*s @@ -241,8 +239,8 @@ cdef class Lfunction: sage: from sage.libs.lcalc.lcalc_Lfunction import * sage: chi = DirichletGroup(5)[2] #This is a quadratic character sage: L=Lfunction_from_character(chi, type="complex") - sage: L.__N(10) - 3.17043978326... + sage: L.__N(10) # abs tol 1e-8 + 4.0 """ cdef RealNumber real_T=RRR(T) cdef double double_T = mpfr_get_d(real_T.value, MPFR_RNDN) @@ -307,18 +305,21 @@ cdef class Lfunction: return returnvalue #The default values are from L.h. See L.h - def find_zeros_via_N(self, count=0, do_negative=False, max_refine=1025, - rank=-1, test_explicit_formula=0): + def find_zeros_via_N(self, count=0, start=0, max_refine=1025, rank=-1): """ - Finds ``count`` number of zeros with positive imaginary part - starting at real axis. This function also verifies that all - the zeros have been found. + Find ``count`` zeros (in order of increasing magnitude) and output + their imaginary parts. This function verifies that no zeros + are missed, and that all values output are indeed zeros. + + If this L-function is self-dual (if its Dirichlet coefficients + are real, up to a tolerance of 1e-6), then only the zeros with + positive imaginary parts are output. Their conjugates, which + are also zeros, are not output. INPUT: - ``count`` - number of zeros to be found - - ``do_negative`` - (default: False) False to ignore zeros below the - real axis. + - ``start`` - (default: 0) how many initial zeros to skip - ``max_refine`` - when some zeros are found to be missing, the step size used to find zeros is refined. max_refine gives an upper limit on when lcalc should give up. Use default value unless you know @@ -326,13 +327,9 @@ cdef class Lfunction: - ``rank`` - integer (default: -1) analytic rank of the L-function. If -1 is passed, then we attempt to compute it. (Use default if in doubt) - - ``test_explicit_formula`` - integer (default: 0) If nonzero, test - the explicit formula for additional confidence that all the zeros - have been found and are accurate. This is still being tested, so - using the default is recommended. OUTPUT: - + list -- A list of the imaginary parts of the zeros that have been found EXAMPLES:: @@ -349,21 +346,26 @@ cdef class Lfunction: sage: chi = DirichletGroup(5)[1] sage: L=Lfunction_from_character(chi, type="complex") - sage: L.find_zeros_via_N(3) - [6.18357819545..., 8.45722917442..., 12.6749464170...] + sage: zeros = L.find_zeros_via_N(3) + sage: zeros[0] # abs tol 1e-8 + -4.13290370521286 + sage: zeros[1] # abs tol 1e-8 + 6.18357819545086 + sage: zeros[2] # abs tol 1e-8 + 8.45722917442320 sage: L=Lfunction_Zeta() sage: L.find_zeros_via_N(3) [14.1347251417..., 21.0220396387..., 25.0108575801...] """ - cdef Integer count_I = Integer(count) - cdef Integer do_negative_I = Integer(do_negative) - cdef RealNumber max_refine_R = RRR(max_refine) - cdef Integer rank_I = Integer(rank) - cdef Integer test_explicit_I = Integer(test_explicit_formula) + + # This is the default value for message_stamp, but we have to + # pass it explicitly since we're passing in the next argument, + # our &result pointer. + cdef const char* message_stamp = "" cdef doublevec result sig_on() - 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, MPFR_RNDN), mpz_get_si(rank_I.value), mpz_get_si(test_explicit_I.value), &result) + self.__find_zeros(count, start, max_refine, rank, message_stamp, &result) sig_off() returnvalue = [] for i in range(result.size()): @@ -390,7 +392,7 @@ cdef class Lfunction: cdef void __find_zeros_v(self,double T1, double T2, double stepsize, doublevec *result): raise NotImplementedError - cdef void __find_zeros_via_N_v(self, long count,int do_negative,double max_refine, int rank, int test_explicit_formula, doublevec *result): + cdef int __find_zeros(self, long count, long start, double max_refine, int rank, const char* message_stamp, doublevec *result): raise NotImplementedError ############################################################################## @@ -486,8 +488,8 @@ cdef class Lfunction_I(Lfunction): cdef double __typedN(self, double T): return (self.thisptr).N(T) - cdef void __find_zeros_via_N_v(self, long count,int do_negative,double max_refine, int rank, int test_explicit_formula, doublevec *result): - (self.thisptr).find_zeros_via_N_v(count, do_negative, max_refine, rank, test_explicit_formula, result[0]) + cdef int __find_zeros(self, long count, long start, double max_refine, int rank, const char* message_stamp, doublevec *result): + (self.thisptr).find_zeros(count, start, max_refine, rank, message_stamp, result) # debug tools def _print_data_to_standard_output(self): @@ -500,7 +502,7 @@ cdef class Lfunction_I(Lfunction): sage: from sage.libs.lcalc.lcalc_Lfunction import * sage: chi = DirichletGroup(5)[2] #This is a quadratic character sage: L=Lfunction_from_character(chi, type="int") - sage: L._print_data_to_standard_output() # tol 1e-15 + sage: L._print_data_to_standard_output() # tol 1e-8 ----------------------------------------------- Name of L_function: @@ -624,8 +626,8 @@ cdef class Lfunction_D(Lfunction): cdef double __typedN(self, double T): return (self.thisptr).N(T) - cdef void __find_zeros_via_N_v(self, long count,int do_negative,double max_refine, int rank, int test_explicit_formula, doublevec *result): - (self.thisptr).find_zeros_via_N_v(count, do_negative, max_refine, rank, test_explicit_formula, result[0]) + cdef int __find_zeros(self, long count, long start,double max_refine, int rank, const char* message_stamp, doublevec *result): + (self.thisptr).find_zeros(count, start, max_refine, rank, message_stamp, result) # debug tools def _print_data_to_standard_output(self): @@ -638,7 +640,7 @@ cdef class Lfunction_D(Lfunction): sage: from sage.libs.lcalc.lcalc_Lfunction import * sage: chi = DirichletGroup(5)[2] #This is a quadratic character sage: L=Lfunction_from_character(chi, type="double") - sage: L._print_data_to_standard_output() # tol 1e-15 + sage: L._print_data_to_standard_output() # tol 1e-8 ----------------------------------------------- Name of L_function: @@ -769,8 +771,8 @@ cdef class Lfunction_C: cdef double __typedN(self, double T): return (self.thisptr).N(T) - cdef void __find_zeros_via_N_v(self, long count,int do_negative,double max_refine, int rank, int test_explicit_formula, doublevec *result): - (self.thisptr).find_zeros_via_N_v(count, do_negative, max_refine, rank, test_explicit_formula, result[0]) + cdef int __find_zeros(self, long count, long start, double max_refine, int rank, const char* message_stamp, doublevec *result): + (self.thisptr).find_zeros(count, start, max_refine, rank, message_stamp, result) # debug tools def _print_data_to_standard_output(self): @@ -783,7 +785,7 @@ cdef class Lfunction_C: sage: from sage.libs.lcalc.lcalc_Lfunction import * sage: chi = DirichletGroup(5)[1] sage: L=Lfunction_from_character(chi, type="complex") - sage: L._print_data_to_standard_output() # tol 1e-15 + sage: L._print_data_to_standard_output() # tol 1e-8 ----------------------------------------------- Name of L_function: @@ -854,8 +856,8 @@ cdef class Lfunction_Zeta(Lfunction): cdef double __typedN(self, double T): return (self.thisptr).N(T) - cdef void __find_zeros_via_N_v(self, long count,int do_negative,double max_refine, int rank, int test_explicit_formula, doublevec *result): - (self.thisptr).find_zeros_via_N_v(count, do_negative, max_refine, rank, test_explicit_formula, result[0]) + cdef int __find_zeros(self, long count, long start, double max_refine, int rank, const char* message_stamp, doublevec *result): + (self.thisptr).find_zeros(count, start, max_refine, rank, message_stamp, result) def __dealloc__(self): """ @@ -950,10 +952,11 @@ def Lfunction_from_elliptic_curve(E, number_of_coeffs=10000): sage: L = Lfunction_from_elliptic_curve(EllipticCurve('37')) sage: L L-function with real Dirichlet coefficients - sage: L.value(0.5).abs() < 1e-15 # "noisy" zero on some platforms (see #9615) + sage: L.value(0.5).abs() < 1e-8 # "noisy" zero on some platforms (see #9615) True - sage: L.value(0.5, derivative=1) - 0.305999... + sage: L.value(0.5, derivative=1) # abs tol 1e-6 + 0.305999773835200 + 0.0*I + """ import sage.libs.lcalc.lcalc_Lfunction Q = RRR(E.conductor()).sqrt() / RRR(2 * pi) diff --git a/src/sage/libs/lcalc/lcalc_sage.h b/src/sage/libs/lcalc/lcalc_sage.h index 4985289..891a40c 100644 --- a/src/sage/libs/lcalc/lcalc_sage.h +++ b/src/sage/libs/lcalc/lcalc_sage.h @@ -1,4 +1,4 @@ -#include "Lfunction/L.h" +#include "lcalc/L.h" int *new_ints(int l) { return new int[l]; @@ -62,4 +62,3 @@ void testL(L_function *L) cout << "Value at 1" << L->value(1.0) <value(.5+I) <