示例#1
0
    def deriv_at1(self, k=None, prec=None):
        r"""
        Compute `L'(E,1)` using `k` terms of the series for `L'(E,1)`,
        under the assumption that `L(E,1) = 0`.

        The algorithm used is from Section 7.5.3 of Henri Cohen's book
        *A Course in Computational Algebraic Number Theory*.

        INPUT:

        - ``k`` -- number of terms of the series. If zero or ``None``,
          use `k = \sqrt{N}`, where `N` is the conductor.

        - ``prec`` -- numerical precision in bits. If zero or ``None``,
          use a reasonable automatic default.

        OUTPUT:

        A tuple of real numbers ``(L1, err)`` where ``L1`` is an
        approximation for `L'(E,1)` and ``err`` is a bound on the error
        in the approximation.

        .. WARNING::

            This function only makes sense if `L(E)` has positive order
            of vanishing at 1, or equivalently if `L(E,1) = 0`.

        ALGORITHM:

        - Compute the root number eps.  If it is 1, return 0.

        - Compute the Fourier coefficients `a_n`, for `n` up to and
          including `k`.

        - Compute the sum

          .. MATH::

                 2 \cdot \sum_{n=1}^{k} (a_n / n) \cdot E_1(2 \pi n/\sqrt{N}),

          where `N` is the conductor of `E`, and `E_1` is the
          exponential integral function.

        - Compute a bound on the tail end of the series, which is

          .. MATH::

                 2 e^{-2 \pi (k+1) / \sqrt{N}} / (1 - e^{-2 \pi/\sqrt{N}}).

          For a proof see [Grigorov-Jorza-Patrascu-Patrikis-Stein].  This
          is exactly the same as the bound for the approximation to
          `L(E,1)` produced by :meth:`at1`.

        EXAMPLES::

            sage: E = EllipticCurve('37a')
            sage: E.lseries().deriv_at1()
            (0.3059866, 0.000801045)
            sage: E.lseries().deriv_at1(100)
            (0.3059997738340523018204836833216764744526377745903, 1.52493e-45)
            sage: E.lseries().deriv_at1(1000)
            (0.305999773834052301820483683321676474452637774590771998..., 2.75031e-449)

        With less numerical precision, the error is bounded by numerical accuracy::

            sage: L,err = E.lseries().deriv_at1(100, prec=64)
            sage: L,err
            (0.305999773834052302, 5.55318e-18)
            sage: parent(L)
            Real Field with 64 bits of precision
            sage: parent(err)
            Real Field with 24 bits of precision and rounding RNDU

        Rank 2 and rank 3 elliptic curves::

            sage: E = EllipticCurve('389a1')
            sage: E.lseries().deriv_at1()
            (0.0000000, 0.000000)
            sage: E = EllipticCurve((1, 0, 1, -131, 558))  # curve 59450i1
            sage: E.lseries().deriv_at1()
            (-0.00010911444, 0.142428)
            sage: E.lseries().deriv_at1(4000)
            (6.990...e-50, 1.31318e-43)
        """
        sqrtN = sqrt(self.__E.conductor())
        if k:
            k = int(k)
        else:
            k = int(ceil(sqrtN))

        if prec:
            prec = int(prec)
        else:
            # Estimate number of bits for the computation, based on error
            # estimate below (the denominator of that error is close enough
            # to 1 that we can ignore it).
            # 9.065 = 2*Pi/log(2)
            # 1.443 = 1/log(2)
            # 12 is an arbitrary extra number of bits (it is chosen
            #    such that the precision is 24 bits when the conductor
            #    equals 11 and k is the default value 4)
            prec = int(9.065 * k / sqrtN + 1.443 * log(k)) + 12
        R = RealField(prec)
        # Compute error term with bounded precision of 24 bits and
        # round towards +infinity
        Rerror = RealField(24, rnd='RNDU')

        if self.__E.root_number() == 1:
            # Order of vanishing at 1 of L(E) is even and assumed to be
            # positive, so L'(E,1) = 0.
            return (R.zero(), Rerror.zero())

        an = self.__E.anlist(k)  # list of Sage Integers
        pi = R.pi()
        sqrtN = R(self.__E.conductor()).sqrt()
        v = exp_integral.exponential_integral_1(2 * pi / sqrtN, k)

        # Compute series sum and accumulate floating point errors
        L = R.zero()
        error = Rerror.zero()
        # Sum of |an[n]|/n
        sumann = Rerror.zero()

        for n in xrange(1, k + 1):
            term = (v[n - 1] * an[n]) / n
            L += term
            error += term.epsilon(Rerror) * 5 + L.ulp(Rerror)
            sumann += Rerror(an[n].abs()) / n
        L *= 2

        # Add error term for exponential_integral_1() errors.
        # Absolute error for 2*v[i] is 4*max(1, v[0])*2^-prec
        if v[0] > 1.0:
            sumann *= Rerror(v[0])
        error += (sumann >> (prec - 2))

        # Add series error (we use (-2)/(z-1) instead of 2/(1-z)
        # because this causes 1/(1-z) to be rounded up)
        z = (-2 * pi / sqrtN).exp()
        zpow = ((-2 * (k + 1)) * pi / sqrtN).exp()
        error += ((-2) * Rerror(zpow)) / Rerror(z - 1)
        return (L, error)
示例#2
0
    def deriv_at1(self, k=0):
        r"""
        Compute $L'(E,1)$ using$ k$ terms of the series for $L'(E,1)$.

        The algorithm used is from page 406 of Henri Cohen's book ``A
        Course in Computational Algebraic Number Theory.''

        The real precision of the computation is the precision of
        Python floats.

        INPUT:
            k -- int; number of terms of the series

        OUTPUT:
            real number -- an approximation for L'(E,1)
            real number -- a bound on the error in the approximation

        ALGORITHM:
        \begin{enumerate}
            \item Compute the root number eps.  If it is 1, return 0.

            \item Compute the Fourier coefficients $a_n$, for $n$ up to and
                  including $k$.

            \item Compute the sum
               $$
                 2 * \sum_{n=1}^{k} (a_n / n) * E_1(2 \pi n/\sqrt{N}),
               $$
               where $N$ is the conductor of $E$, and $E_1$ is the
               exponential integral function.

            \item Compute a bound on the tail end of the series, which is
               $$
                 2 * e^{-2 \pi (k+1) / \sqrt{N}} / (1 - e^{-2 \ pi/\sqrt{N}}).
               $$
               For a proof see [Grigorov-Jorza-Patrascu-Patrikis-Stein].  This
               is exactly the same as the bound for the approximation to
               $L(E,1)$ produced by \code{E.lseries().at1}.
        \end{enumerate}

        EXAMPLES::

            sage: E = EllipticCurve('37a')
            sage: E.lseries().deriv_at1()
            (0.305986660898516, 0.000800351433106958)
            sage: E.lseries().deriv_at1(100)
            (0.305999773834052, 1.52437502288740e-45)
            sage: E.lseries().deriv_at1(1000)
            (0.305999773834052, 0.000000000000000)
        """
        if self.__E.root_number() == 1: return 0
        k = int(k)
        sqrtN = float(self.__E.conductor().sqrt())
        if k == 0: k = int(ceil(sqrtN))
        an = self.__E.anlist(k)           # list of Sage Integers
        # Compute z = e^(-2pi/sqrt(N))
        pi = 3.14159265358979323846
        v = exp_integral.exponential_integral_1(2*pi/sqrtN, k)
        L = 2*float(sum([ (v[n-1] * an[n])/n for n in xrange(1,k+1)]))
        error = 2*exp(-2*pi*(k+1)/sqrtN)/(1-exp(-2*pi/sqrtN))
        return R(L), R(error)
示例#3
0
    def deriv_at1(self, k=None, prec=None):
        r"""
        Compute `L'(E,1)` using `k` terms of the series for `L'(E,1)`,
        under the assumption that `L(E,1) = 0`.

        The algorithm used is from Section 7.5.3 of Henri Cohen's book
        ``A Course in Computational Algebraic Number Theory.''

        INPUT:

        - ``k`` -- number of terms of the series. If zero or ``None``,
          use `k = \sqrt(N)`, where `N` is the conductor.

        - ``prec`` -- numerical precision in bits. If zero or ``None``,
          use a reasonable automatic default.

        OUTPUT:

        A tuple of real numbers ``(L1, err)`` where ``L1`` is an
        approximation for `L'(E,1)` and ``err`` is a bound on the error
        in the approximation.

        .. WARNING::

            This function only makes sense if `L(E)` has positive order
            of vanishing at 1, or equivalently if `L(E,1) = 0`.

        ALGORITHM:

        - Compute the root number eps.  If it is 1, return 0.

        - Compute the Fourier coefficients `a_n`, for `n` up to and
          including `k`.

        - Compute the sum

          .. MATH::

                 2 * \sum_{n=1}^{k} (a_n / n) * E_1(2 \pi n/\sqrt{N}),

          where `N` is the conductor of `E`, and `E_1` is the
          exponential integral function.

        - Compute a bound on the tail end of the series, which is

          .. MATH::

                 2 e^{-2 \pi (k+1) / \sqrt{N}} / (1 - e^{-2 \pi/\sqrt{N}}).

          For a proof see [Grigorov-Jorza-Patrascu-Patrikis-Stein].  This
          is exactly the same as the bound for the approximation to
          `L(E,1)` produced by :meth:`at1`.

        EXAMPLES::

            sage: E = EllipticCurve('37a')
            sage: E.lseries().deriv_at1()
            (0.3059866, 0.000801045)
            sage: E.lseries().deriv_at1(100)
            (0.3059997738340523018204836833216764744526377745903, 1.52493e-45)
            sage: E.lseries().deriv_at1(1000)
            (0.305999773834052301820483683321676474452637774590771998..., 2.75031e-449)

        With less numerical precision, the error is bounded by numerical accuracy::

            sage: L,err = E.lseries().deriv_at1(100, prec=64)
            sage: L,err
            (0.305999773834052302, 5.55318e-18)
            sage: parent(L)
            Real Field with 64 bits of precision
            sage: parent(err)
            Real Field with 24 bits of precision and rounding RNDU

        Rank 2 and rank 3 elliptic curves::

            sage: E = EllipticCurve('389a1')
            sage: E.lseries().deriv_at1()
            (0.0000000, 0.000000)
            sage: E = EllipticCurve((1, 0, 1, -131, 558))  # curve 59450i1
            sage: E.lseries().deriv_at1()
            (-0.00010911444, 0.142428)
            sage: E.lseries().deriv_at1(4000)
            (6.9902290...e-50, 1.31318e-43)
        """
        sqrtN = sqrt(self.__E.conductor())
        if k:
            k = int(k)
        else:
            k = int(ceil(sqrtN))

        if prec:
            prec = int(prec)
        else:
            # Estimate number of bits for the computation, based on error
            # estimate below (the denominator of that error is close enough
            # to 1 that we can ignore it).
            # 9.065 = 2*Pi/log(2)
            # 1.443 = 1/log(2)
            # 12 is an arbitrary extra number of bits (it is chosen
            #    such that the precision is 24 bits when the conductor
            #    equals 11 and k is the default value 4)
            prec = int(9.065*k/sqrtN + 1.443*log(k)) + 12
        R = RealField(prec)
        # Compute error term with bounded precision of 24 bits and
        # round towards +infinity
        Rerror = RealField(24, rnd='RNDU')

        if self.__E.root_number() == 1:
           # Order of vanishing at 1 of L(E) is even and assumed to be
           # positive, so L'(E,1) = 0.
           return (R.zero(), Rerror.zero())

        an = self.__E.anlist(k)  # list of Sage Integers
        pi = R.pi()
        sqrtN = R(self.__E.conductor()).sqrt()
        v = exp_integral.exponential_integral_1(2*pi/sqrtN, k)

        # Compute series sum and accumulate floating point errors
        L = R.zero()
        error = Rerror.zero()
        # Sum of |an[n]|/n
        sumann = Rerror.zero()

        for n in xrange(1,k+1):
            term = (v[n-1] * an[n])/n
            L += term
            error += term.epsilon(Rerror)*5 + L.ulp(Rerror)
            sumann += Rerror(an[n].abs())/n
        L *= 2

        # Add error term for exponential_integral_1() errors.
        # Absolute error for 2*v[i] is 4*max(1, v[0])*2^-prec
        if v[0] > 1.0:
            sumann *= Rerror(v[0])
        error += (sumann >> (prec - 2))

        # Add series error (we use (-2)/(z-1) instead of 2/(1-z)
        # because this causes 1/(1-z) to be rounded up)
        z = (-2*pi/sqrtN).exp()
        zpow = ((-2*(k+1))*pi/sqrtN).exp()
        error += ((-2)*Rerror(zpow)) / Rerror(z - 1)
        return (L, error)
示例#4
0
    def deriv_at1(self, k=0):
        r"""
        Compute $L'(E,1)$ using$ k$ terms of the series for $L'(E,1)$.

        The algorithm used is from page 406 of Henri Cohen's book ``A
        Course in Computational Algebraic Number Theory.''

        The real precision of the computation is the precision of
        Python floats.

        INPUT:
            k -- int; number of terms of the series

        OUTPUT:
            real number -- an approximation for L'(E,1)
            real number -- a bound on the error in the approximation

        ALGORITHM:
        \begin{enumerate}
            \item Compute the root number eps.  If it is 1, return 0.

            \item Compute the Fourier coefficients $a_n$, for $n$ up to and
                  including $k$.

            \item Compute the sum
               $$
                 2 * \sum_{n=1}^{k} (a_n / n) * E_1(2 \pi n/\sqrt{N}),
               $$
               where $N$ is the conductor of $E$, and $E_1$ is the
               exponential integral function.

            \item Compute a bound on the tail end of the series, which is
               $$
                 2 * e^{-2 \pi (k+1) / \sqrt{N}} / (1 - e^{-2 \ pi/\sqrt{N}}).
               $$
               For a proof see [Grigorov-Jorza-Patrascu-Patrikis-Stein].  This
               is exactly the same as the bound for the approximation to
               $L(E,1)$ produced by \code{E.lseries().at1}.
        \end{enumerate}

        EXAMPLES::

            sage: E = EllipticCurve('37a')
            sage: E.lseries().deriv_at1()
            (0.305986660898516, 0.000800351433106958)
            sage: E.lseries().deriv_at1(100)
            (0.305999773834052, 1.52437502288740e-45)
            sage: E.lseries().deriv_at1(1000)
            (0.305999773834052, 0.000000000000000)
        """
        if self.__E.root_number() == 1: return 0
        k = int(k)
        sqrtN = float(self.__E.conductor().sqrt())
        if k == 0: k = int(ceil(sqrtN))
        an = self.__E.anlist(k)  # list of Sage Integers
        # Compute z = e^(-2pi/sqrt(N))
        pi = 3.14159265358979323846
        v = exp_integral.exponential_integral_1(2 * pi / sqrtN, k)
        L = 2 * float(sum([(v[n - 1] * an[n]) / n for n in xrange(1, k + 1)]))
        error = 2 * exp(-2 * pi * (k + 1) / sqrtN) / (1 - exp(-2 * pi / sqrtN))
        return R(L), R(error)