Rubinstein’s lcalc library - C/C++ Library Interfaces

Skip to content
Back to top
View this page
Edit this page

# Rubinstein’s lcalc library

This is a wrapper around Michael Rubinstein’s lcalc. See http://oto.math.uwaterloo.ca/~mrubinst/L_function_public/CODE/.

AUTHORS:

- Rishikesh (2010): added compute_rank() and hardy_z_function()

- Yann Laigle-Chapuy (2009): refactored

- Rishikesh (2009): initial version

class sage.libs.lcalc.lcalc_Lfunction.Lfunction

  Bases: `object`

  Initialization of \(L\)-function objects. See derived class for details, this class is not supposed to be instantiated directly.

  EXAMPLES:

  Sage

      sage: from sage.libs.lcalc.lcalc_Lfunction import *
      sage: Lfunction_from_character(DirichletGroup(5)[1])
      L-function with complex Dirichlet coefficients

  Python

      >>> from sage.all import *
      >>> from sage.libs.lcalc.lcalc_Lfunction import *
      >>> Lfunction_from_character(DirichletGroup(Integer(5))[Integer(1)])
      L-function with complex Dirichlet coefficients

  compute_rank()

    Compute the analytic rank (the order of vanishing at the center) of of the \(L\)-function.

    EXAMPLES:

    Sage

        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.compute_rank()
        0

    Python

        >>> from sage.all import *
        >>> from sage.libs.lcalc.lcalc_Lfunction import *
        >>> chi = DirichletGroup(Integer(5))[Integer(2)] # This is a quadratic character
        >>> L = Lfunction_from_character(chi, type='int')
        >>> L.compute_rank()
        0

    Sage

        sage: from sage.libs.lcalc.lcalc_Lfunction import *
        sage: E = EllipticCurve([-82,0])
        sage: L = Lfunction_from_elliptic_curve(E, number_of_coeffs=40000)
        sage: L.compute_rank()
        3

    [Python]

        >>> from sage.all import *
        >>> from sage.libs.lcalc.lcalc_Lfunction import *
        >>> E = EllipticCurve([-Integer(82),Integer(0)])
        >>> L = Lfunction_from_elliptic_curve(E, number_of_coeffs=Integer(40000))
        >>> L.compute_rank()
        3

  find_zeros(T1, T2, stepsize)

    Finds zeros on critical line between `T1` and `T2` using step size of stepsize. This function might miss zeros if step size is too large. This function computes the zeros of the \(L\)-function by using change in signs of areal valued function whose zeros coincide with the zeros of \(L\)-function.

    Use `find_zeros_via_N()` for slower but more rigorous computation.

    INPUT:

    - `T1` – a real number giving the lower bound

    - `T2` – a real number giving the upper bound

    - `stepsize` – step size to be used for the zero search

    OUTPUT: list of the imaginary parts of the zeros which were found

    EXAMPLES:

    Sage

        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.find_zeros(5,15,.1)
        [6.64845334472..., 9.83144443288..., 11.9588456260...]
        sage: L = Lfunction_from_character(chi, type='double')
        sage: L.find_zeros(1,15,.1)
        [6.64845334472..., 9.83144443288..., 11.9588456260...]

    Python

        >>> from sage.all import *
        >>> from sage.libs.lcalc.lcalc_Lfunction import *
        >>> chi = DirichletGroup(Integer(5))[Integer(2)] # This is a quadratic character
        >>> L = Lfunction_from_character(chi, type='int')
        >>> L.find_zeros(Integer(5),Integer(15),RealNumber('.1'))
        [6.64845334472..., 9.83144443288..., 11.9588456260...]
        >>> L = Lfunction_from_character(chi, type='double')
        >>> L.find_zeros(Integer(1),Integer(15),RealNumber('.1'))
        [6.64845334472..., 9.83144443288..., 11.9588456260...]

    Sage

        sage: from sage.libs.lcalc.lcalc_Lfunction import *
        sage: chi = DirichletGroup(5)[1]
        sage: L = Lfunction_from_character(chi, type='complex')
        sage: L.find_zeros(-8,8,.1)
        [-4.13290370521..., 6.18357819545...]

    [Python]

        >>> from sage.all import *
        >>> from sage.libs.lcalc.lcalc_Lfunction import *
        >>> chi = DirichletGroup(Integer(5))[Integer(1)]
        >>> L = Lfunction_from_character(chi, type='complex')
        >>> L.find_zeros(-Integer(8),Integer(8),RealNumber('.1'))
        [-4.13290370521..., 6.18357819545...]

    Sage

        sage: from sage.libs.lcalc.lcalc_Lfunction import *
        sage: L = Lfunction_Zeta()
        sage: L.find_zeros(10,29.1,.1)
        [14.1347251417..., 21.0220396387..., 25.0108575801...]

    Python

        >>> from sage.all import *
        >>> from sage.libs.lcalc.lcalc_Lfunction import *
        >>> L = Lfunction_Zeta()
        >>> L.find_zeros(Integer(10),RealNumber('29.1'),RealNumber('.1'))
        [14.1347251417..., 21.0220396387..., 25.0108575801...]

  find_zeros_via_N(count=0, start=0, max_refine=1025, rank=-1)

    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

    - `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 what you are doing.

    - `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)

    OUTPUT: list of the imaginary parts of the zeros that have been found

    EXAMPLES:

    Sage

        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.find_zeros_via_N(3)
        [6.64845334472..., 9.83144443288..., 11.9588456260...]
        sage: L = Lfunction_from_character(chi, type='double')
        sage: L.find_zeros_via_N(3)
        [6.64845334472..., 9.83144443288..., 11.9588456260...]

    Python

        >>> from sage.all import *
        >>> from sage.libs.lcalc.lcalc_Lfunction import *
        >>> chi = DirichletGroup(Integer(5))[Integer(2)] #This is a quadratic character
        >>> L = Lfunction_from_character(chi, type='int')
        >>> L.find_zeros_via_N(Integer(3))
        [6.64845334472..., 9.83144443288..., 11.9588456260...]
        >>> L = Lfunction_from_character(chi, type='double')
        >>> L.find_zeros_via_N(Integer(3))
        [6.64845334472..., 9.83144443288..., 11.9588456260...]

    Sage

        sage: from sage.libs.lcalc.lcalc_Lfunction import *
        sage: chi = DirichletGroup(5)[1]
        sage: L = Lfunction_from_character(chi, type='complex')
        sage: zeros = L.find_zeros_via_N(3)
        sage: (zeros[0] - (-4.13290370521286)).abs() < 1e-8
        True
        sage: (zeros[1]  - 6.18357819545086).abs() < 1e-8
        True
        sage: (zeros[2]  - 8.45722917442320).abs() < 1e-8
        True

    [Python]

        >>> from sage.all import *
        >>> from sage.libs.lcalc.lcalc_Lfunction import *
        >>> chi = DirichletGroup(Integer(5))[Integer(1)]
        >>> L = Lfunction_from_character(chi, type='complex')
        >>> zeros = L.find_zeros_via_N(Integer(3))
        >>> (zeros[Integer(0)] - (-RealNumber('4.13290370521286'))).abs() < RealNumber('1e-8')
        True
        >>> (zeros[Integer(1)]  - RealNumber('6.18357819545086')).abs() < RealNumber('1e-8')
        True
        >>> (zeros[Integer(2)]  - RealNumber('8.45722917442320')).abs() < RealNumber('1e-8')
        True

    Sage

        sage: from sage.libs.lcalc.lcalc_Lfunction import *
        sage: L = Lfunction_Zeta()
        sage: L.find_zeros_via_N(3)
        [14.1347251417..., 21.0220396387..., 25.0108575801...]

    Python

        >>> from sage.all import *
        >>> from sage.libs.lcalc.lcalc_Lfunction import *
        >>> L = Lfunction_Zeta()
        >>> L.find_zeros_via_N(Integer(3))
        [14.1347251417..., 21.0220396387..., 25.0108575801...]

  hardy_z_function(s)

    Compute the Hardy Z-function of the \(L\)-function at s.

    INPUT:

    - `s` – a complex number with imaginary part between -0.5 and 0.5

    EXAMPLES:

    Sage

        sage: from sage.libs.lcalc.lcalc_Lfunction import *
        sage: chi = DirichletGroup(5)[2]  # Quadratic character
        sage: L = Lfunction_from_character(chi, type='int')
        sage: (L.hardy_z_function(0) - 0.231750947504).abs() < 1e-8
        True
        sage: L.hardy_z_function(0.5).imag().abs() < 1e-8
        True

    Python

        >>> from sage.all import *
        >>> from sage.libs.lcalc.lcalc_Lfunction import *
        >>> chi = DirichletGroup(Integer(5))[Integer(2)]  # Quadratic character
        >>> L = Lfunction_from_character(chi, type='int')
        >>> (L.hardy_z_function(Integer(0)) - RealNumber('0.231750947504')).abs() < RealNumber('1e-8')
        True
        >>> L.hardy_z_function(RealNumber('0.5')).imag().abs() < RealNumber('1e-8')
        True

    Sage

        sage: from sage.libs.lcalc.lcalc_Lfunction import *
        sage: chi = DirichletGroup(5)[1]
        sage: L = Lfunction_from_character(chi, type='complex')
        sage: (L.hardy_z_function(0) - 0.793967590477).abs() < 1e-8
        True
        sage: L.hardy_z_function(0.5).imag().abs() < 1e-8
        True

    [Python]

        >>> from sage.all import *
        >>> from sage.libs.lcalc.lcalc_Lfunction import *
        >>> chi = DirichletGroup(Integer(5))[Integer(1)]
        >>> L = Lfunction_from_character(chi, type='complex')
        >>> (L.hardy_z_function(Integer(0)) - RealNumber('0.793967590477')).abs() < RealNumber('1e-8')
        True
        >>> L.hardy_z_function(RealNumber('0.5')).imag().abs() < RealNumber('1e-8')
        True

    Sage

        sage: from sage.libs.lcalc.lcalc_Lfunction import *
        sage: E = EllipticCurve([-82,0])
        sage: L = Lfunction_from_elliptic_curve(E, number_of_coeffs=40000)
        sage: (L.hardy_z_function(2.1) - (-0.006431791768)).abs() < 1e-8
        True

    Python

        >>> from sage.all import *
        >>> from sage.libs.lcalc.lcalc_Lfunction import *
        >>> E = EllipticCurve([-Integer(82),Integer(0)])
        >>> L = Lfunction_from_elliptic_curve(E, number_of_coeffs=Integer(40000))
        >>> (L.hardy_z_function(RealNumber('2.1')) - (-RealNumber('0.006431791768'))).abs() < RealNumber('1e-8')
        True

  value(s, derivative=0)

    Compute the value of the \(L\)-function at `s`.

    INPUT:

    - `s` – a complex number

    - `derivative` – integer (default: 0); the derivative to be evaluated

    - `rotate` – boolean (default: `False`); if True, this returns the value of the Hardy Z-function (sometimes called the Riemann-Siegel Z-function or the Siegel Z-function)

    EXAMPLES:

    Sage

        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.value(0.5) - 0.231750947504016).abs() < 1e-8
        True
        sage: v = L.value(0.2 + 0.4*I)
        sage: (v - (0.102558603193 + 0.190840777924*I)).abs() < 1e-8
        True
        sage: L = Lfunction_from_character(chi, type='double')
        sage: (L.value(0.6) - 0.274633355856345).abs() < 1e-8
        True
        sage: v = L.value(0.6 + I)
        sage: (v - (0.362258705721 + 0.43388825062*I)).abs() < 1e-8
        True

    Python

        >>> from sage.all import *
        >>> from sage.libs.lcalc.lcalc_Lfunction import *
        >>> chi = DirichletGroup(Integer(5))[Integer(2)] # This is a quadratic character
        >>> L = Lfunction_from_character(chi, type='int')
        >>> (L.value(RealNumber('0.5')) - RealNumber('0.231750947504016')).abs() < RealNumber('1e-8')
        True
        >>> v = L.value(RealNumber('0.2') + RealNumber('0.4')*I)
        >>> (v - (RealNumber('0.102558603193') + RealNumber('0.190840777924')*I)).abs() < RealNumber('1e-8')
        True
        >>> L = Lfunction_from_character(chi, type='double')
        >>> (L.value(RealNumber('0.6')) - RealNumber('0.274633355856345')).abs() < RealNumber('1e-8')
        True
        >>> v = L.value(RealNumber('0.6') + I)
        >>> (v - (RealNumber('0.362258705721') + RealNumber('0.43388825062')*I)).abs() < RealNumber('1e-8')
        True

    Sage

        sage: from sage.libs.lcalc.lcalc_Lfunction import *
        sage: chi = DirichletGroup(5)[1]
        sage: L = Lfunction_from_character(chi, type='complex')
        sage: v = L.value(0.5)
        sage: (v - (0.763747880117 + 0.21696476751*I)).abs() < 1e-8
        True
        sage: v = L.value(0.6 + 5*I)
        sage: (v - (0.702723260619 - 1.10178575243*I)).abs() < 1e-8
        True

    [Python]

        >>> from sage.all import *
        >>> from sage.libs.lcalc.lcalc_Lfunction import *
        >>> chi = DirichletGroup(Integer(5))[Integer(1)]
        >>> L = Lfunction_from_character(chi, type='complex')
        >>> v = L.value(RealNumber('0.5'))
        >>> (v - (RealNumber('0.763747880117') + RealNumber('0.21696476751')*I)).abs() < RealNumber('1e-8')
        True
        >>> v = L.value(RealNumber('0.6') + Integer(5)*I)
        >>> (v - (RealNumber('0.702723260619') - RealNumber('1.10178575243')*I)).abs() < RealNumber('1e-8')
        True

    Sage

        sage: from sage.libs.lcalc.lcalc_Lfunction import *
        sage: L = Lfunction_Zeta()
        sage: (L.value(0.5) + 1.46035450880).abs() < 1e-8
        True
        sage: v = L.value(0.4 + 0.5*I)
        sage: (v - (-0.450728958517 - 0.780511403019*I)).abs() < 1e-8
        True

    Python

        >>> from sage.all import *
        >>> from sage.libs.lcalc.lcalc_Lfunction import *
        >>> L = Lfunction_Zeta()
        >>> (L.value(RealNumber('0.5')) + RealNumber('1.46035450880')).abs() < RealNumber('1e-8')
        True
        >>> v = L.value(RealNumber('0.4') + RealNumber('0.5')*I)
        >>> (v - (-RealNumber('0.450728958517') - RealNumber('0.780511403019')*I)).abs() < RealNumber('1e-8')
        True

class sage.libs.lcalc.lcalc_Lfunction.Lfunction_C

  Bases: `Lfunction`

  The `Lfunction_C` class is used to represent \(L\)-functions with complex Dirichlet Coefficients. We assume that \(L\)-functions satisfy the following functional equation.

  \[\Lambda(s) = \omega Q^s \overline{\Lambda(1-\bar s)}\]

  where

  \[\Lambda(s) = Q^s \left( \prod_{j=1}^a \Gamma(\kappa_j s + \gamma_j) \right) L(s)\]

  See (23) in arXiv math/0412181

  INPUT:

  - `what_type_L` – integer; this should be set to 1 if the coefficients are periodic and 0 otherwise

  - `dirichlet_coefficient` – list of Dirichlet coefficients of the \(L\)-function. Only first \(M\) coefficients are needed if they are periodic.

  - `period` – if the coefficients are periodic, this should be the period of the coefficients

  - `Q` – see above

  - `OMEGA` – see above

  - `kappa` – list of the values of \(\kappa_j\) in the functional equation

  - `gamma` – list of the values of \(\gamma_j\) in the functional equation

  - `pole` – list of the poles of \(L\)-function

  - `residue` – list of the residues of the \(L\)-function

  Note

  If an \(L\)-function satisfies \(\Lambda(s) = \omega Q^s \Lambda(k-s)\), by replacing \(s\) by \(s+(k-1)/2\), one can get it in the form we need.

class sage.libs.lcalc.lcalc_Lfunction.Lfunction_D

  Bases: `Lfunction`

  The `Lfunction_D` class is used to represent \(L\)-functions with real Dirichlet coefficients. We assume that \(L\)-functions satisfy the following functional equation.

  \[\Lambda(s) = \omega Q^s \overline{\Lambda(1-\bar s)}\]

  where

  \[\Lambda(s) = Q^s \left( \prod_{j=1}^a \Gamma(\kappa_j s + \gamma_j) \right) L(s)\]

  See (23) in arXiv math/0412181

  INPUT:

  - `what_type_L` – integer; this should be set to 1 if the coefficients are periodic and 0 otherwise

  - `dirichlet_coefficient` – list of Dirichlet coefficients of the \(L\)-function. Only first \(M\) coefficients are needed if they are periodic.

  - `period` – if the coefficients are periodic, this should be the period of the coefficients

  - `Q` – see above

  - `OMEGA` – see above

  - `kappa` – list of the values of \(\kappa_j\) in the functional equation

  - `gamma` – list of the values of \(\gamma_j\) in the functional equation

  - `pole` – list of the poles of \(L\)-function

  - `residue` – list of the residues of the \(L\)-function

  Note

  If an \(L\)-function satisfies \(\Lambda(s) = \omega Q^s \Lambda(k-s)\), by replacing \(s\) by \(s+(k-1)/2\), one can get it in the form we need.

class sage.libs.lcalc.lcalc_Lfunction.Lfunction_I

  Bases: `Lfunction`

  The `Lfunction_I` class is used to represent \(L\)-functions with integer Dirichlet Coefficients. We assume that \(L\)-functions satisfy the following functional equation.

  \[\Lambda(s) = \omega Q^s \overline{\Lambda(1-\bar s)}\]

  where

  \[\Lambda(s) = Q^s \left( \prod_{j=1}^a \Gamma(\kappa_j s + \gamma_j) \right) L(s)\]

  See (23) in arXiv math/0412181

  INPUT:

  - `what_type_L` – integer; this should be set to 1 if the coefficients are periodic and 0 otherwise

  - `dirichlet_coefficient` – list of Dirichlet coefficients of the \(L\)-function. Only first \(M\) coefficients are needed if they are periodic.

  - `period` – if the coefficients are periodic, this should be the period of the coefficients

  - `Q` – see above

  - `OMEGA` – see above

  - `kappa` – list of the values of \(\kappa_j\) in the functional equation

  - `gamma` – list of the values of \(\gamma_j\) in the functional equation

  - `pole` – list of the poles of \(L\)-function

  - `residue` – list of the residues of the \(L\)-function

  Note

  If an \(L\)-function satisfies \(\Lambda(s) = \omega Q^s \Lambda(k-s)\), by replacing \(s\) by \(s+(k-1)/2\), one can get it in the form we need.

class sage.libs.lcalc.lcalc_Lfunction.Lfunction_Zeta

  Bases: `Lfunction`

  The `Lfunction_Zeta` class is used to generate the Riemann zeta function.

sage.libs.lcalc.lcalc_Lfunction.Lfunction_from_character(chi, type='complex')

  Given a primitive Dirichlet character, this function returns an lcalc \(L\)-function object for the \(L\)-function of the character.

  INPUT:

  - `chi` – a Dirichlet character

  - `use_type` – string (default: `'complex'`); type used for the Dirichlet coefficients. This can be `'int'`, `'double'` or `'complex'`.

  OUTPUT: \(L\)-function object for `chi`

  EXAMPLES:

  Sage

      sage: from sage.libs.lcalc.lcalc_Lfunction import Lfunction_from_character
      sage: Lfunction_from_character(DirichletGroup(5)[1])
      L-function with complex Dirichlet coefficients
      sage: Lfunction_from_character(DirichletGroup(5)[2], type='int')
      L-function with integer Dirichlet coefficients
      sage: Lfunction_from_character(DirichletGroup(5)[2], type='double')
      L-function with real Dirichlet coefficients
      sage: Lfunction_from_character(DirichletGroup(5)[1], type='int')
      Traceback (most recent call last):
      ...
      ValueError: For non quadratic characters you must use type="complex"

  Python

      >>> from sage.all import *
      >>> from sage.libs.lcalc.lcalc_Lfunction import Lfunction_from_character
      >>> Lfunction_from_character(DirichletGroup(Integer(5))[Integer(1)])
      L-function with complex Dirichlet coefficients
      >>> Lfunction_from_character(DirichletGroup(Integer(5))[Integer(2)], type='int')
      L-function with integer Dirichlet coefficients
      >>> Lfunction_from_character(DirichletGroup(Integer(5))[Integer(2)], type='double')
      L-function with real Dirichlet coefficients
      >>> Lfunction_from_character(DirichletGroup(Integer(5))[Integer(1)], type='int')
      Traceback (most recent call last):
      ...
      ValueError: For non quadratic characters you must use type="complex"

sage.libs.lcalc.lcalc_Lfunction.Lfunction_from_elliptic_curve(E, number_of_coeffs=10000)

  Given an elliptic curve E, return an \(L\)-function object for the function \(L(s, E)\).

  INPUT:

  - `E` – an elliptic curve

  - `number_of_coeffs` – integer (default: 10000); the number of coefficients to be used when constructing the \(L\)-function object. Right now this is fixed at object creation time, and is not automatically set intelligently.

  OUTPUT: \(L\)-function object for `L(s, E)`

  EXAMPLES:

  Sage

      sage: from sage.libs.lcalc.lcalc_Lfunction import Lfunction_from_elliptic_curve
      sage: L = Lfunction_from_elliptic_curve(EllipticCurve('37'))
      sage: L
      L-function with real Dirichlet coefficients
      sage: L.value(0.5).abs() < 1e-8
      True
      sage: (L.value(0.5, derivative=1) - 0.305999773835200).abs() < 1e-6
      True

  Python

      >>> from sage.all import *
      >>> from sage.libs.lcalc.lcalc_Lfunction import Lfunction_from_elliptic_curve
      >>> L = Lfunction_from_elliptic_curve(EllipticCurve('37'))
      >>> L
      L-function with real Dirichlet coefficients
      >>> L.value(RealNumber('0.5')).abs() < RealNumber('1e-8')
      True
      >>> (L.value(RealNumber('0.5'), derivative=Integer(1)) - RealNumber('0.305999773835200')).abs() < RealNumber('1e-6')
      True