From e60448cd3f18b2a8ee3ed3811ee4018662f7a55d Mon Sep 17 00:00:00 2001 From: Vincent Delecroix <20100.delecroix@gmail.com> Date: Fri, 30 Mar 2018 15:46:38 +0200 Subject: [PATCH] primecount interface as an optional Cython module --- src/module_list.py | 4 + src/sage/interfaces/primecount.pyx | 157 +++++++++++++++++++++++++++++ src/sage/libs/primecount.pxd | 29 ++++++ 3 files changed, 190 insertions(+) create mode 100644 src/sage/interfaces/primecount.pyx create mode 100644 src/sage/libs/primecount.pxd diff --git a/src/module_list.py b/src/module_list.py index c661ee06212..8974fba4b7f 100644 --- a/src/module_list.py +++ b/src/module_list.py @@ -437,6 +437,10 @@ def uname_specific(name, value, alternative): ## ################################ + OptionalExtension("sage.interfaces.primecount", + ["sage/interfaces/primecount.pyx"], + package = "primecount"), + Extension('*', ['sage/interfaces/*.pyx']), ################################ diff --git a/src/sage/interfaces/primecount.pyx b/src/sage/interfaces/primecount.pyx new file mode 100644 index 00000000000..9e04734ed15 --- /dev/null +++ b/src/sage/interfaces/primecount.pyx @@ -0,0 +1,157 @@ +r""" +Interface to the primecount library +""" +#***************************************************************************** +# Copyright (C) 2018 Vincent Delecroix <20100.delecroix@gmail.com> +# +# Distributed under the terms of the GNU General Public License (GPL) +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# http://www.gnu.org/licenses/ +#***************************************************************************** + +from libc.stdint cimport int64_t +from libcpp.string cimport string as cppstring +from cpython.int cimport PyInt_FromString + +from cysignals.signals cimport sig_on, sig_off + +cimport sage.libs.primecount as primecount + +cdef inline int _do_sig(int64_t n): + "threshold for sig_on/sig_off" + return n >> 26 + +cpdef int64_t prime_pi(int64_t n, method=None) except -1: + r""" + Return the number of prime numbers smaller or equal than ``n``. + + INPUT: + + - ``n`` - an integer + + - ``method`` - ``None`` or a string that determines the primecount + function to be called + + - ``"deleglise_rivat"`` + - ``"legendre"`` + - ``"lehmer"`` + - ``"lmo"`` + - ``"meissel"`` + - ``"primesieve"`` + + EXAMPLES:: + + sage: from sage.interfaces.primecount import prime_pi # optional - primecount + + sage: prime_pi(1000) # optional - primecount + 168 + sage: prime_pi(1000, "deleglise_rivat") # optional - primecount + 168 + sage: prime_pi(1000, "legendre") # optional - primecount + 168 + sage: prime_pi(1000, "lehmer") # optional - primecount + 168 + sage: prime_pi(1000, "lmo") # optional - primecount + 168 + sage: prime_pi(1000, "meissel") # optional - primecount + 168 + sage: prime_pi(1000, "primesieve") # optional - primecount + 168 + sage: prime_pi(1000, "youpi") # optional - primecount + Traceback (most recent call last): + ... + ValueError: unknown method 'youpi' + """ + cdef int64_t ans + if method is None: + if _do_sig(n): sig_on() + ans = primecount.pi(n) + if _do_sig(n): sig_off() + elif method == "deleglise_rivat": + if _do_sig(n): sig_on() + ans = primecount.pi_deleglise_rivat(n) + if _do_sig(n): sig_off() + elif method == "legendre": + if _do_sig(n): sig_on() + ans = primecount.pi_legendre(n) + if _do_sig(n): sig_off() + elif method == "lehmer": + if _do_sig(n): sig_on() + ans = primecount.pi_lehmer(n) + if _do_sig(n): sig_off() + elif method == "lmo": + if _do_sig(n): sig_on() + ans = primecount.pi_lmo(n) + if _do_sig(n): sig_off() + elif method == "meissel": + if _do_sig(n): sig_on() + ans = primecount.pi_meissel(n) + if _do_sig(n): sig_off() + elif method == "primesieve": + if _do_sig(n): sig_on() + ans = primecount.pi_primesieve(n) + if _do_sig(n): sig_off() + else: + raise ValueError("unknown method {!r}".format(method)) + + return ans + +cpdef prime_pi_128(n): + r""" + Return the number of prime number smaller than ``n``. + + EXAMPLES:: + + sage: from sage.interfaces.primecount import prime_pi_128 # optional - primecount + + sage: prime_pi_128(1000) # optional - primecount + 168 + sage: nth_prime_128(2**65) # not tested + ? + """ + cdef cppstring s = str(n) + cdef bytes ans + sig_on() + ans = primecount.pi(s) + sig_off() + return PyInt_FromString(ans, NULL, 10) + +cpdef int64_t nth_prime(int64_t n) except -1: + r""" + Return the ``n``-th prime integer. + + EXAMPLES:: + + sage: from sage.interfaces.primecount import nth_prime # optional - primecount + + sage: nth_prime(168) # optional - primecount + 997 + """ + if n <= 0: + raise ValueError("n must be positive") + + cdef int64_t ans + if _do_sig(n): sig_on() + ans = primecount.nth_prime(n) + if _do_sig(n): sig_off() + return ans + +cpdef int64_t phi(int64_t x, int64_t a): + r""" + Return the number of integers smaller or equal than ``x`` by any of the + first ``a`` primes. + + This is sometimes called a "partial sieve function" or "Legendre-sum". + + EXAMPLES:: + + sage: from sage.interfaces.primecount import phi # optional - primecount + + sage: phi(1000, 3) # optional - primecount + 266 + sage: phi(2**30, 100) # optional - primecount + 95446716 + """ + return primecount.phi(x, a) + diff --git a/src/sage/libs/primecount.pxd b/src/sage/libs/primecount.pxd new file mode 100644 index 00000000000..0be31ab3f35 --- /dev/null +++ b/src/sage/libs/primecount.pxd @@ -0,0 +1,29 @@ +# distutils: libraries = primecount +# distutils: language = c++ + +from libc.stdint cimport int64_t +from libcpp.string cimport string as cppstring + +cdef extern from "primecount.hpp" namespace "primecount": + int64_t pi(int64_t x) + + cppstring pi(const cppstring& x) + + int64_t pi_deleglise_rivat(int64_t x) + int64_t pi_legendre(int64_t x) + int64_t pi_lehmer(int64_t x) + int64_t pi_lmo(int64_t x) + int64_t pi_meissel(int64_t x) + int64_t pi_primesieve(int64_t x) + + int64_t nth_prime(int64_t n) + + int64_t phi(int64_t x, int64_t a) + + void set_num_threads(int num_threads) + int get_num_threads() + + cppstring get_max_x() + cppstring get_max_x(double alpha) + + cppstring primecount_version()