├── lib └── primesieve │ ├── examples │ ├── CMakeLists.txt │ ├── cpp │ │ ├── CMakeLists.txt │ │ ├── count_primes.cpp │ │ ├── nth_prime.cpp │ │ ├── prev_prime.cpp │ │ ├── primesieve_iterator.cpp │ │ └── store_primes_in_vector.cpp │ ├── c │ │ ├── CMakeLists.txt │ │ ├── count_primes.c │ │ ├── nth_prime.c │ │ ├── store_primes_in_array.c │ │ ├── primesieve_iterator.c │ │ └── prev_prime.c │ └── README.md │ ├── doc │ ├── README.md │ ├── RELEASE.md │ ├── CMakeLists.txt │ ├── mainpage.dox │ └── Doxyfile.in │ ├── test │ ├── README.md │ ├── CMakeLists.txt │ ├── count_twins.cpp │ ├── count_triplets.cpp │ ├── count_sextuplets.cpp │ ├── count_quadruplets.cpp │ ├── count_quintuplets.cpp │ ├── nth_prime1.cpp │ ├── count_primes1.cpp │ ├── count_primes2.cpp │ ├── nth_prime3.cpp │ ├── count_primes3.cpp │ ├── number_of_bits.cpp │ ├── isqrt.cpp │ ├── ilog2.cpp │ ├── floorPow2.cpp │ ├── next_prime1.cpp │ ├── generate_n_primes2.c │ ├── generate_primes1.cpp │ ├── generate_n_primes1.cpp │ ├── move_primesieve_iterator.cpp │ ├── generate_primes2.c │ ├── nth_prime2.cpp │ ├── calculator.cpp │ ├── next_prime2.c │ ├── cpu_info.cpp │ ├── prev_prime2.c │ └── prev_prime1.cpp │ ├── .gitignore │ ├── primesieve.pc.in │ ├── scripts │ ├── build_msvc.bat │ ├── update_version.sh │ └── fastest_sieve_size.sh │ ├── include │ └── primesieve │ │ ├── bits.hpp │ │ ├── forward.hpp │ │ ├── IteratorHelper.hpp │ │ ├── primesieve_error.hpp │ │ ├── MemoryPool.hpp │ │ ├── ParallelSieve.hpp │ │ ├── EratSmall.hpp │ │ ├── SievingPrimes.hpp │ │ ├── PrintPrimes.hpp │ │ ├── EratBig.hpp │ │ ├── EratMedium.hpp │ │ ├── CpuInfo.hpp │ │ ├── PrimeGenerator.hpp │ │ ├── littleendian_cast.hpp │ │ ├── PreSieve.hpp │ │ ├── macros.hpp │ │ ├── malloc_vector.hpp │ │ ├── StorePrimes.hpp │ │ ├── config.hpp │ │ ├── PrimeSieve.hpp │ │ ├── iterator.hpp │ │ └── iterator.h │ ├── src │ ├── app │ │ ├── cmdoptions.hpp │ │ ├── help.cpp │ │ └── main.cpp │ ├── SievingPrimes.cpp │ ├── iterator.cpp │ └── MemoryPool.cpp │ ├── COPYING │ └── cmake │ └── primesieveConfig.cmake.in ├── doc └── alpha-tuning-factor.pdf ├── .gitignore ├── include ├── S1.hpp ├── S2Status.hpp ├── SumBits.hpp ├── print.hpp ├── OmpLock.hpp ├── aligned_vector.hpp ├── S2.hpp ├── PiTable.hpp ├── popcnt.hpp ├── S2LoadBalancer.hpp ├── primesum.hpp ├── isqrt.hpp ├── generate.hpp ├── PhiTiny.hpp ├── fast_div.hpp ├── min_max.hpp ├── BitSieve.hpp ├── BinaryIndexedTree.hpp ├── imath.hpp ├── int128_t.hpp ├── primesum-internal.hpp └── Wheel.hpp ├── scripts ├── update_libprimesieve.sh └── worktodo.sh ├── src ├── pi_legendre.cpp ├── nth_prime.cpp ├── PiTable.cpp ├── app │ ├── cmdoptions.hpp │ └── help.cpp ├── PhiTiny.cpp ├── FactorTable.cpp ├── lmo │ └── pi_lmo1.cpp ├── deleglise-rivat │ ├── pi_deleglise_rivat_parallel1.cpp │ └── S2_trivial.cpp ├── S2Status.cpp ├── phi_sum.cpp ├── print.cpp ├── Wheel.cpp ├── S1.cpp └── generate.cpp ├── test ├── libdivide.cpp └── modulo_256-bit.cpp ├── COPYING └── appveyor.yml /lib/primesieve/examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(c) 2 | add_subdirectory(cpp) 3 | -------------------------------------------------------------------------------- /doc/alpha-tuning-factor.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimwalisch/primesum/HEAD/doc/alpha-tuning-factor.pdf -------------------------------------------------------------------------------- /lib/primesieve/doc/README.md: -------------------------------------------------------------------------------- 1 | # Documentation links 2 | 3 | * [ALGORITHMS.md](ALGORITHMS.md) 4 | * [BUILD.md](BUILD.md) 5 | * [RELEASE.md](RELEASE.md) 6 | * [C_Examples.md](C_Examples.md) 7 | * [CPP_Examples.md](CPP_Examples.md) 8 | -------------------------------------------------------------------------------- /lib/primesieve/test/README.md: -------------------------------------------------------------------------------- 1 | primesieve testing 2 | ================== 3 | 4 | Run the commands below from the root primesieve directory. 5 | 6 | ```bash 7 | cmake -DBUILD_TESTS=ON . 8 | make -j 9 | make test 10 | ``` 11 | -------------------------------------------------------------------------------- /lib/primesieve/examples/cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB files "*.cpp") 2 | foreach(file ${files}) 3 | get_filename_component(binary_name ${file} NAME_WE) 4 | add_executable(${binary_name} ${file}) 5 | target_link_libraries(${binary_name} primesieve::primesieve) 6 | endforeach() 7 | -------------------------------------------------------------------------------- /lib/primesieve/examples/c/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | enable_language(C) 2 | file(GLOB files "*.c") 3 | 4 | foreach(file ${files}) 5 | get_filename_component(binary_name ${file} NAME_WE) 6 | add_executable(${binary_name}_c ${file}) 7 | target_link_libraries(${binary_name}_c primesieve::primesieve) 8 | endforeach() 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | *~ 3 | !/.gitignore 4 | !/.travis.yml 5 | *.exe 6 | *.tar.gz 7 | *.zip 8 | *.obj 9 | *.lib 10 | *.o 11 | /primesum* 12 | /build* 13 | Makefile 14 | CMakeCache.txt 15 | CMakeFiles 16 | CMakeScripts 17 | Makefile 18 | cmake_install.cmake 19 | install_manifest.txt 20 | CTestTestfile.cmake 21 | 22 | -------------------------------------------------------------------------------- /lib/primesieve/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | enable_language(C) 2 | file(GLOB files "*.cpp" "*.c") 3 | 4 | foreach(file ${files}) 5 | get_filename_component(binary_name ${file} NAME_WE) 6 | add_executable(${binary_name} ${file}) 7 | target_link_libraries(${binary_name} primesieve::primesieve) 8 | add_test(NAME ${binary_name} COMMAND ${binary_name}) 9 | endforeach() 10 | -------------------------------------------------------------------------------- /lib/primesieve/examples/c/count_primes.c: -------------------------------------------------------------------------------- 1 | /** @example count_primes.c 2 | * C program that shows how to count primes. */ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | int main() 9 | { 10 | uint64_t count = primesieve_count_primes(0, 1000); 11 | printf("Primes below 1000 = %" PRIu64 "\n", count); 12 | 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /lib/primesieve/examples/README.md: -------------------------------------------------------------------------------- 1 | libprimesieve examples 2 | ====================== 3 | 4 | This directory contains C/C++ example programs that show how to 5 | generate primes using libprimesieve. 6 | 7 | Build instructions 8 | ================== 9 | 10 | Run the commands below from the root primesieve directory. 11 | 12 | ```sh 13 | cmake -DBUILD_EXAMPLES=ON . 14 | make -j 15 | ``` 16 | -------------------------------------------------------------------------------- /lib/primesieve/examples/cpp/count_primes.cpp: -------------------------------------------------------------------------------- 1 | /// @example count_primes.cpp 2 | /// This example shows how to count primes. 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | int main() 9 | { 10 | uint64_t count = primesieve::count_primes(0, 1000); 11 | std::cout << "Primes below 1000 = " << count << std::endl; 12 | 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /lib/primesieve/.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | *~ 3 | !/.gitignore 4 | *.exe 5 | *.tar.gz 6 | *.zip 7 | *.obj 8 | *.lib 9 | *.o 10 | *.pc 11 | *.dSYM 12 | CMakeCache.txt 13 | CMakeFiles 14 | CMakeScripts 15 | Makefile 16 | cmake_install.cmake 17 | install_manifest.txt 18 | CTestTestfile.cmake 19 | /primesieve* 20 | /libprimesieve* 21 | doc/primesieve.xml 22 | doc/Doxyfile 23 | doc/html 24 | doc/latex 25 | /build* 26 | -------------------------------------------------------------------------------- /lib/primesieve/primesieve.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@CMAKE_INSTALL_PREFIX@ 2 | bindir=@CMAKE_INSTALL_FULL_BINDIR@ 3 | libdir=@CMAKE_INSTALL_FULL_LIBDIR@ 4 | includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ 5 | 6 | Name: primesieve 7 | Description: Fast C/C++ prime number generator 8 | Version: @PRIMESIEVE_VERSION@ 9 | Libs: -L${libdir} -lprimesieve 10 | Libs.private: @CMAKE_THREAD_LIBS_INIT@ 11 | Cflags: -I${includedir} 12 | -------------------------------------------------------------------------------- /lib/primesieve/examples/cpp/nth_prime.cpp: -------------------------------------------------------------------------------- 1 | /// @example nth_prime.cpp 2 | /// Find the nth prime. 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int main(int, char** argv) 10 | { 11 | uint64_t n = 1000; 12 | 13 | if (argv[1]) 14 | n = std::atol(argv[1]); 15 | 16 | uint64_t nth_prime = primesieve::nth_prime(n); 17 | std::cout << n << "th prime = " << nth_prime << std::endl; 18 | 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /lib/primesieve/examples/cpp/prev_prime.cpp: -------------------------------------------------------------------------------- 1 | /// @example prev_prime.cpp 2 | /// Iterate backwards over primes using primesieve::iterator. 3 | 4 | #include 5 | #include 6 | 7 | int main() 8 | { 9 | primesieve::iterator it; 10 | it.skipto(2000); 11 | uint64_t prime = it.prev_prime(); 12 | 13 | // iterate over primes from 2000 to 1000 14 | for (; prime >= 1000; prime = it.prev_prime()) 15 | std::cout << prime << std::endl; 16 | 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /lib/primesieve/examples/c/nth_prime.c: -------------------------------------------------------------------------------- 1 | /** @example nth_prime.c 2 | * C program that finds the nth prime. */ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int main(int argc, char** argv) 10 | { 11 | uint64_t n = 1000; 12 | 13 | if (argc > 1 && argv[1]) 14 | n = atol(argv[1]); 15 | 16 | uint64_t prime = primesieve_nth_prime(n, 0); 17 | printf("%" PRIu64 "th prime = %" PRIu64 "\n", n, prime); 18 | 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /include/S1.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file S1.hpp 3 | /// @brief S1 function declarations. 4 | /// 5 | /// Copyright (C) 2015 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace primesum { 16 | 17 | int256_t S1(int128_t x, 18 | int64_t y, 19 | int64_t c, 20 | int threads); 21 | 22 | } // namespace 23 | -------------------------------------------------------------------------------- /lib/primesieve/scripts/build_msvc.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | :: === Usage === 4 | :: This script builds a primesieve binary that is suitable for 5 | :: distribution on the internet. The built primesieve binary 6 | :: will only depend on kernel32.dll. 7 | :: 8 | :: 1) Open a Visual Studio Command Prompt 9 | :: 2) cd into primesieve repo 10 | :: 3) Run: scripts/build_msvc.bat 11 | 12 | rmdir /s /q build-msvc 13 | mkdir build-msvc 14 | cd build-msvc 15 | 16 | cl /O2 /EHsc /W3 /D NDEBUG /I ../include ../src/*.cpp ../src/app/*.cpp /Feprimesieve.exe 17 | 18 | echo "" 19 | primesieve.exe --version 20 | 21 | echo "" 22 | primesieve.exe --test 23 | -------------------------------------------------------------------------------- /lib/primesieve/include/primesieve/bits.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file bits.hpp 3 | /// @brief Bitmasks to unset bits in the sieve array 4 | /// 5 | /// Copyright (C) 2017 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #ifndef BITS_HPP 12 | #define BITS_HPP 13 | 14 | enum 15 | { 16 | BIT0 = 0xfe, // 11111110 17 | BIT1 = 0xfd, // 11111101 18 | BIT2 = 0xfb, // 11111011 19 | BIT3 = 0xf7, // 11110111 20 | BIT4 = 0xef, // 11101111 21 | BIT5 = 0xdf, // 11011111 22 | BIT6 = 0xbf, // 10111111 23 | BIT7 = 0x7f // 01111111 24 | }; 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /lib/primesieve/src/app/cmdoptions.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file cmdoptions.hpp 3 | /// 4 | /// Copyright (C) 2018 Kim Walisch, 5 | /// 6 | /// This file is distributed under the BSD License. See the COPYING 7 | /// file in the top level directory. 8 | /// 9 | 10 | #ifndef CMDOPTIONS_HPP 11 | #define CMDOPTIONS_HPP 12 | 13 | #include 14 | #include 15 | 16 | struct CmdOptions 17 | { 18 | std::deque numbers; 19 | int flags = 0; 20 | int sieveSize = 0; 21 | int threads = 0; 22 | bool quiet = false; 23 | bool nthPrime = false; 24 | bool status = true; 25 | bool time = false; 26 | }; 27 | 28 | CmdOptions parseOptions(int, char**); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /lib/primesieve/doc/RELEASE.md: -------------------------------------------------------------------------------- 1 | # How to release a new primesieve version 2 | 3 | * Update the [ChangeLog](../ChangeLog) file. 4 | * Run ```scripts/update_version.sh``` in the root directory of the primesieve git repo to update the version number. 5 | * Run ```scripts\build_msvc.bat``` in the root directory of the primesieve git repo to build a primesieve release binary for Windows. 6 | * Build the Doxygen API documentation using ```cmake . -DBUILD_DOC=ON && make doc``` and update the ```gh_pages``` branch. 7 | * Finally go to the [GitHub website and do the release](https://github.com/kimwalisch/primesieve/releases). The release title should be primesieve-X.Y and the tag name should be vX.Y (e.g. primesieve-1.0 and v1.0). 8 | -------------------------------------------------------------------------------- /scripts/update_libprimesieve.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Run from primecount root directory 4 | test -e ../lib && cd .. 5 | 6 | # Exit immediately if a command exits with a non-zero status 7 | set -e 8 | 9 | cd lib 10 | rm -rf master.tar.gz* 11 | rm -rf primesieve* 12 | wget https://github.com/kimwalisch/primesieve/archive/master.tar.gz 13 | tar xvf master.tar.gz 14 | rm master.tar.gz* 15 | mv primesieve-master primesieve 16 | 17 | git status 18 | echo "" 19 | 20 | read -p "Do you want to commit and push the changes? [y/n] " -n 1 -r 21 | echo # (optional) move to a new line 22 | if [[ $REPLY =~ ^[Yy]$ ]] 23 | then 24 | git add . 25 | git commit -m "Update to latest libprimesieve" 26 | git push 27 | fi 28 | -------------------------------------------------------------------------------- /lib/primesieve/examples/cpp/primesieve_iterator.cpp: -------------------------------------------------------------------------------- 1 | /// @example primesieve_iterator.cpp 2 | /// Iterate over primes using primesieve::iterator. 3 | 4 | #include 5 | #include 6 | 7 | int main() 8 | { 9 | primesieve::iterator it; 10 | uint64_t prime = it.next_prime(); 11 | uint64_t sum = 0; 12 | 13 | // iterate over the primes below 10^9 14 | for (; prime < 1000000000ull; prime = it.next_prime()) 15 | sum += prime; 16 | 17 | std::cout << "Sum of the primes below 10^9 = " << sum << std::endl; 18 | 19 | // generate primes > 1000 20 | it.skipto(1000); 21 | prime = it.next_prime(); 22 | 23 | for (; prime < 1100; prime = it.next_prime()) 24 | std::cout << prime << std::endl; 25 | 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /lib/primesieve/examples/cpp/store_primes_in_vector.cpp: -------------------------------------------------------------------------------- 1 | /// @example store_primes_in_vector.cpp 2 | /// Store primes in a std::vector using primesieve. 3 | 4 | #include 5 | #include 6 | 7 | int main() 8 | { 9 | std::vector primes; 10 | 11 | // Store primes <= 1000 12 | primesieve::generate_primes(1000, &primes); 13 | 14 | primes.clear(); 15 | 16 | // Store primes inside [1000, 2000] 17 | primesieve::generate_primes(1000, 2000, &primes); 18 | 19 | primes.clear(); 20 | 21 | // Store first 1000 primes 22 | primesieve::generate_n_primes(1000, &primes); 23 | 24 | primes.clear(); 25 | 26 | // Store first 10 primes >= 1000 27 | primesieve::generate_n_primes(10, 1000, &primes); 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /lib/primesieve/include/primesieve/forward.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file forward.hpp 3 | /// @brief Forward declarations. 4 | /// 5 | /// Copyright (C) 2019 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #ifndef TYPES_HPP 12 | #define TYPES_HPP 13 | 14 | #include 15 | #include 16 | 17 | namespace primesieve { 18 | 19 | extern const std::array bitValues; 20 | extern const std::array bruijnBitValues; 21 | 22 | int get_num_threads(); 23 | int get_sieve_size(); 24 | 25 | uint64_t get_max_stop(); 26 | uint64_t popcount(const uint64_t* array, uint64_t size); 27 | 28 | } // namespace 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /src/pi_legendre.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file pi_legendre.cpp 3 | /// 4 | /// Copyright (C) 2018 Kim Walisch, 5 | /// 6 | /// This file is distributed under the BSD License. See the COPYING 7 | /// file in the top level directory. 8 | /// 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | namespace primesum { 16 | 17 | /// Count the number of primes <= x using Legendre's formula. 18 | /// Run time: O(x) 19 | /// Memory usage: O(x^(1/2)) 20 | /// 21 | int64_t pi_legendre(int64_t x, int threads) 22 | { 23 | if (x < 2) 24 | return 0; 25 | 26 | int64_t a = pi_legendre(isqrt(x), 1); 27 | int64_t sum = phi(x, a, threads) + a - 1; 28 | 29 | return sum; 30 | } 31 | 32 | } // namespace 33 | -------------------------------------------------------------------------------- /lib/primesieve/examples/c/store_primes_in_array.c: -------------------------------------------------------------------------------- 1 | /** @example store_primes_in_array.c 2 | * Store primes in a C array. */ 3 | 4 | #include 5 | #include 6 | 7 | int main() 8 | { 9 | uint64_t start = 0; 10 | uint64_t stop = 1000; 11 | size_t i; 12 | size_t size; 13 | 14 | /* store the primes below 1000 */ 15 | int* primes = (int*) primesieve_generate_primes(start, stop, &size, INT_PRIMES); 16 | 17 | for (i = 0; i < size; i++) 18 | printf("%i\n", primes[i]); 19 | 20 | primesieve_free(primes); 21 | uint64_t n = 1000; 22 | 23 | /* store the first 1000 primes */ 24 | primes = (int*) primesieve_generate_n_primes(n, start, INT_PRIMES); 25 | 26 | for (i = 0; i < n; i++) 27 | printf("%i\n", primes[i]); 28 | 29 | primesieve_free(primes); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /src/nth_prime.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file nth_prime.cpp 3 | /// @brief Find the nth prime 4 | /// 5 | /// Copyright (C) 2017 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | namespace { 19 | 20 | const std::array primes = { 0, 2, 3, 5, 7, 11, 13, 17, 19, 23 }; 21 | 22 | } 23 | 24 | namespace primesum { 25 | 26 | int64_t nth_prime(int64_t n) 27 | { 28 | if (n >= 10) 29 | throw primesum_error("nth_prime(n): n must be < 10"); 30 | 31 | if (n < 2) 32 | return primes[1]; 33 | else 34 | return primes[n]; 35 | } 36 | 37 | } // namespace 38 | -------------------------------------------------------------------------------- /lib/primesieve/examples/c/primesieve_iterator.c: -------------------------------------------------------------------------------- 1 | /** @example primesieve_iterator.c 2 | * Iterate over primes using C primesieve_iterator. */ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | int main() 9 | { 10 | primesieve_iterator it; 11 | primesieve_init(&it); 12 | 13 | uint64_t sum = 0; 14 | uint64_t prime = 0; 15 | 16 | /* iterate over the primes below 10^9 */ 17 | while ((prime = primesieve_next_prime(&it)) < 1000000000ull) 18 | sum += prime; 19 | 20 | printf("Sum of the primes below 10^9 = %" PRIu64 "\n", sum); 21 | 22 | /* generate primes > 1000 */ 23 | primesieve_skipto(&it, 1000, 1100); 24 | 25 | while ((prime = primesieve_next_prime(&it)) < 1100) 26 | printf("%" PRIu64 "\n", prime); 27 | 28 | primesieve_free_iterator(&it); 29 | 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /lib/primesieve/include/primesieve/IteratorHelper.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file IteratorHelper.hpp 3 | /// 4 | /// Copyright (C) 2018 Kim Walisch, 5 | /// 6 | /// This file is distributed under the BSD License. See the COPYING 7 | /// file in the top level directory. 8 | /// 9 | 10 | #ifndef ITERATOR_HELPER_HPP 11 | #define ITERATOR_HELPER_HPP 12 | 13 | #include 14 | 15 | namespace primesieve { 16 | 17 | class IteratorHelper 18 | { 19 | public: 20 | static void next(uint64_t* start, 21 | uint64_t* stop, 22 | uint64_t stopHint, 23 | uint64_t* dist); 24 | 25 | static void prev(uint64_t* start, 26 | uint64_t* stop, 27 | uint64_t stopHint, 28 | uint64_t* dist); 29 | }; 30 | 31 | } // namespace 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /lib/primesieve/include/primesieve/primesieve_error.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file primesieve_error.hpp 3 | /// @brief The primesieve_error class is used for all 4 | /// exceptions within primesieve. 5 | /// 6 | /// Copyright (C) 2017 Kim Walisch, 7 | /// 8 | /// This file is distributed under the BSD License. See the COPYING 9 | /// file in the top level directory. 10 | /// 11 | 12 | #ifndef PRIMESIEVE_ERROR_HPP 13 | #define PRIMESIEVE_ERROR_HPP 14 | 15 | #include 16 | #include 17 | 18 | namespace primesieve { 19 | 20 | /// primesieve throws a primesieve_error exception 21 | /// if an error occurs e.g. prime > 2^64. 22 | /// 23 | class primesieve_error : public std::runtime_error 24 | { 25 | public: 26 | primesieve_error(const std::string& msg) 27 | : std::runtime_error(msg) 28 | { } 29 | }; 30 | 31 | } // namespace 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /include/S2Status.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file S2Status.hpp 3 | /// 4 | /// Copyright (C) 2018 Kim Walisch, 5 | /// 6 | /// This file is distributed under the BSD License. See the COPYING 7 | /// file in the top level directory. 8 | /// 9 | 10 | #ifndef S2STATUS_HPP 11 | #define S2STATUS_HPP 12 | 13 | #include 14 | 15 | #if defined(_OPENMP) 16 | #include 17 | #endif 18 | 19 | namespace primesum { 20 | 21 | class S2Status 22 | { 23 | public: 24 | S2Status(int128_t x); 25 | void print(int128_t n, int128_t limit); 26 | static double skewed_percent(int128_t x, int128_t y); 27 | private: 28 | bool is_print(double time); 29 | double epsilon_; 30 | double percent_ = -1; 31 | double time_ = 0; 32 | double is_print_ = 1.0 / 20; 33 | int precision_; 34 | 35 | #if defined(_OPENMP) 36 | OmpLock lock_; 37 | #endif 38 | }; 39 | 40 | } // namespace 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /include/SumBits.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file SumBits.hpp 3 | /// @brief Class that returns the sum of the 1 bit indexes 4 | /// inside of a 16-bit word. 5 | /// 6 | /// Copyright (C) 2017 Kim Walisch, 7 | /// 8 | /// This file is distributed under the BSD License. See the COPYING 9 | /// file in the top level directory. 10 | /// 11 | 12 | #ifndef SUMBITS_HPP 13 | #define SUMBITS_HPP 14 | 15 | #include 16 | 17 | namespace primesum { 18 | 19 | class SumBits 20 | { 21 | public: 22 | SumBits() 23 | { 24 | for (int i = 0; i < (1 << 16); i++) 25 | { 26 | sum_bits_[i] = 0; 27 | for (int j = i; j != 0; j &= j - 1) 28 | sum_bits_[i] += (uint8_t) (__builtin_ctzll(j) * 2); 29 | } 30 | } 31 | 32 | template 33 | uint8_t operator[](T i) const 34 | { 35 | return sum_bits_[i]; 36 | } 37 | 38 | private: 39 | uint8_t sum_bits_[1 << 16]; 40 | }; 41 | 42 | } // namespace 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /lib/primesieve/examples/c/prev_prime.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @example prev_prime.c 3 | * Iterate backwards over primes using primesieve_iterator. 4 | * 5 | * Note that primesieve_next_prime() runs up to 2x faster and uses 6 | * only half as much memory as primesieve_prev_prime(). Hence if 7 | * it is possible to write the same algorithm using either 8 | * primesieve_prev_prime() or primesieve_next_prime() then it is 9 | * preferable to use primesieve_next_prime(). 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | int main() 17 | { 18 | primesieve_iterator it; 19 | primesieve_init(&it); 20 | 21 | /* primesieve_skipto(&it, start_number, stop_hint) */ 22 | primesieve_skipto(&it, 2000, 1000); 23 | uint64_t prime; 24 | 25 | /* iterate over primes from 2000 to 1000 */ 26 | while ((prime = primesieve_prev_prime(&it)) >= 1000) 27 | printf("%" PRIu64 "\n", prime); 28 | 29 | primesieve_free_iterator(&it); 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /lib/primesieve/test/count_twins.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file count_twins.cpp 3 | /// @brief Count twin primes inside [10^12, 10^12 + 10^9]. 4 | /// 5 | /// Copyright (C) 2017 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace std; 18 | 19 | void check(bool OK) 20 | { 21 | cout << " " << (OK ? "OK" : "ERROR") << "\n"; 22 | if (!OK) 23 | exit(1); 24 | } 25 | 26 | int main() 27 | { 28 | uint64_t start = (uint64_t) 1e12; 29 | uint64_t stop = (uint64_t)(1e12 + 1e9); 30 | uint64_t count = primesieve::count_twins(start, stop); 31 | cout << "Twin primes inside [10^12, 10^12 + 10^9] = " << count; 32 | check(count == 1730012); 33 | 34 | cout << endl; 35 | cout << "Test passed successfully!" << endl; 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /lib/primesieve/test/count_triplets.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file count_triplets.cpp 3 | /// @brief Count prime triplets inside [10^12, 10^12 + 10^9]. 4 | /// 5 | /// Copyright (C) 2017 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace std; 18 | 19 | void check(bool OK) 20 | { 21 | cout << " " << (OK ? "OK" : "ERROR") << "\n"; 22 | if (!OK) 23 | exit(1); 24 | } 25 | 26 | int main() 27 | { 28 | uint64_t start = (uint64_t) 1e12; 29 | uint64_t stop = (uint64_t)(1e12 + 1e9); 30 | uint64_t count = primesieve::count_triplets(start, stop); 31 | cout << "Prime triplets inside [10^12, 10^12 + 10^9] = " << count; 32 | check(count == 271316); 33 | 34 | cout << endl; 35 | cout << "Test passed successfully!" << endl; 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /lib/primesieve/test/count_sextuplets.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file count_sextuplets.cpp 3 | /// @brief Count prime sextuplets inside [10^12, 10^12 + 10^9]. 4 | /// 5 | /// Copyright (C) 2017 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace std; 18 | 19 | void check(bool OK) 20 | { 21 | cout << " " << (OK ? "OK" : "ERROR") << "\n"; 22 | if (!OK) 23 | exit(1); 24 | } 25 | 26 | int main() 27 | { 28 | uint64_t start = (uint64_t) 1e12; 29 | uint64_t stop = (uint64_t)(1e12 + 1e9); 30 | uint64_t count = primesieve::count_sextuplets(start, stop); 31 | cout << "Prime sextuplets inside [10^12, 10^12 + 10^9] = " << count; 32 | check(count == 42); 33 | 34 | cout << endl; 35 | cout << "Test passed successfully!" << endl; 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /lib/primesieve/doc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package(Doxygen) 2 | 3 | if(DOXYGEN_FOUND) 4 | find_package(LATEX) 5 | find_program(DOT_FONUD dot) 6 | 7 | if(LATEX_COMPILER) 8 | set(HAVE_LATEX "YES") 9 | else() 10 | set(HAVE_LATEX "NO") 11 | endif() 12 | 13 | if(DOT_FONUD) 14 | message(STATUS "Found dot (graphviz): ${DOT_FONUD}") 15 | set(HAVE_DOT "YES") 16 | else() 17 | set(HAVE_DOT "NO") 18 | endif() 19 | 20 | configure_file(Doxyfile.in Doxyfile @ONLY) 21 | add_custom_target(doc COMMAND ${DOXYGEN_EXECUTABLE} Doxyfile) 22 | 23 | if(LATEX_COMPILER) 24 | find_program(MAKE_FONUD make) 25 | 26 | # LaTeX doc (PDF) must be built using make 27 | if(MAKE_FONUD) 28 | add_custom_command(TARGET doc 29 | POST_BUILD 30 | COMMAND "${MAKE_FONUD}" 31 | WORKING_DIRECTORY "latex") 32 | endif() 33 | endif() 34 | endif() 35 | -------------------------------------------------------------------------------- /lib/primesieve/test/count_quadruplets.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file count_quadruplets.cpp 3 | /// @brief Count prime quadruplets inside [10^12, 10^12 + 10^9]. 4 | /// 5 | /// Copyright (C) 2017 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace std; 18 | 19 | void check(bool OK) 20 | { 21 | cout << " " << (OK ? "OK" : "ERROR") << "\n"; 22 | if (!OK) 23 | exit(1); 24 | } 25 | 26 | int main() 27 | { 28 | uint64_t start = (uint64_t) 1e12; 29 | uint64_t stop = (uint64_t)(1e12 + 1e9); 30 | uint64_t count = primesieve::count_quadruplets(start, stop); 31 | cout << "Prime quadruplets inside [10^12, 10^12 + 10^9] = " << count; 32 | check(count == 7171); 33 | 34 | cout << endl; 35 | cout << "Test passed successfully!" << endl; 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /lib/primesieve/test/count_quintuplets.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file count_quintuplets.cpp 3 | /// @brief Count prime quintuplets inside [10^12, 10^12 + 10^9]. 4 | /// 5 | /// Copyright (C) 2017 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace std; 18 | 19 | void check(bool OK) 20 | { 21 | cout << " " << (OK ? "OK" : "ERROR") << "\n"; 22 | if (!OK) 23 | exit(1); 24 | } 25 | 26 | int main() 27 | { 28 | uint64_t start = (uint64_t) 1e12; 29 | uint64_t stop = (uint64_t)(1e12 + 1e9); 30 | uint64_t count = primesieve::count_quintuplets(start, stop); 31 | cout << "Prime quintuplets inside [10^12, 10^12 + 10^9] = " << count; 32 | check(count == 1259); 33 | 34 | cout << endl; 35 | cout << "Test passed successfully!" << endl; 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /include/print.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file print.hpp 3 | /// 4 | /// Copyright (C) 2015 Kim Walisch, 5 | /// 6 | /// This file is distributed under the BSD License. See the COPYING 7 | /// file in the top level directory. 8 | /// 9 | 10 | #ifndef PRINT_HPP 11 | #define PRINT_HPP 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | 19 | namespace primesum { 20 | 21 | void set_print_variables(bool print_variables); 22 | 23 | bool print_result(); 24 | 25 | bool is_print(); 26 | 27 | bool print_variables(); 28 | 29 | void print(const std::string& str); 30 | 31 | void print(int128_t x, int64_t y, int threads); 32 | 33 | void print(int128_t x, int64_t y, int64_t c, int threads); 34 | 35 | void print(int128_t x, int64_t y, int64_t z, int64_t c, double alpha, int threads); 36 | 37 | void print(const std::string& res_name, int256_t res, double time); 38 | 39 | void print_seconds(double seconds); 40 | 41 | } // namespace 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /lib/primesieve/include/primesieve/MemoryPool.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file MemoryPool.hpp 3 | /// 4 | /// Copyright (C) 2020 Kim Walisch, 5 | /// 6 | /// This file is distributed under the BSD License. See the COPYING 7 | /// file in the top level directory. 8 | /// 9 | 10 | #ifndef MEMORYPOOL_HPP 11 | #define MEMORYPOOL_HPP 12 | 13 | #include "Bucket.hpp" 14 | #include "macros.hpp" 15 | 16 | #include 17 | #include 18 | 19 | namespace primesieve { 20 | 21 | class MemoryPool 22 | { 23 | public: 24 | NOINLINE void addBucket(SievingPrime*& sievingPrime); 25 | void freeBucket(Bucket* bucket); 26 | 27 | private: 28 | void allocateBuckets(); 29 | void initBuckets(void* memory, std::size_t bytes); 30 | void increaseAllocCount(); 31 | /// List of empty buckets 32 | Bucket* stock_ = nullptr; 33 | /// Number of buckets to allocate 34 | std::size_t count_ = 64; 35 | /// Pointers of allocated buckets 36 | std::vector> memory_; 37 | }; 38 | 39 | } // namespace 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /src/PiTable.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file PiTable.cpp 3 | /// @brief The PiTable class is a compressed lookup table for 4 | /// prime counts. It uses only (n / 4) bytes of memory 5 | /// and returns the number of primes <= n in O(1) 6 | /// operations. 7 | /// 8 | /// Copyright (C) 2018 Kim Walisch, 9 | /// 10 | /// This file is distributed under the BSD License. See the COPYING 11 | /// file in the top level directory. 12 | /// 13 | 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | 20 | namespace primesum { 21 | 22 | PiTable::PiTable(uint64_t max) : 23 | max_(max) 24 | { 25 | pi_.resize(max / 64 + 1); 26 | primesieve::iterator it(0, max); 27 | 28 | uint64_t pix = 0; 29 | uint64_t prime = 0; 30 | 31 | while ((prime = it.next_prime()) <= max) 32 | pi_[prime / 64].bits |= 1ull << (prime % 64); 33 | 34 | for (auto& i : pi_) 35 | { 36 | i.prime_count = pix; 37 | pix += popcnt64(i.bits); 38 | } 39 | } 40 | 41 | } // namespace 42 | -------------------------------------------------------------------------------- /include/OmpLock.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file OmpLock.hpp 3 | /// @brief The OmpLock and TryLock classes are RAII-style 4 | /// wrappers for OpenMP locks. 5 | /// 6 | /// Copyright (C) 2018 Kim Walisch, 7 | /// 8 | /// This file is distributed under the BSD License. See the COPYING 9 | /// file in the top level directory. 10 | /// 11 | 12 | #ifndef OMPLOCK_HPP 13 | #define OMPLOCK_HPP 14 | 15 | #include 16 | 17 | namespace primesum { 18 | 19 | struct OmpLock 20 | { 21 | OmpLock() 22 | { 23 | omp_init_lock(&lock_); 24 | } 25 | ~OmpLock() 26 | { 27 | omp_destroy_lock(&lock_); 28 | } 29 | omp_lock_t lock_; 30 | }; 31 | 32 | class TryLock 33 | { 34 | public: 35 | TryLock(OmpLock& lock) 36 | { 37 | lock_ = &lock.lock_; 38 | ownsLock_ = (omp_test_lock(lock_) != 0); 39 | } 40 | ~TryLock() 41 | { 42 | if (ownsLock_) 43 | omp_unset_lock(lock_); 44 | } 45 | bool ownsLock() const 46 | { 47 | return ownsLock_; 48 | } 49 | 50 | private: 51 | omp_lock_t* lock_; 52 | bool ownsLock_; 53 | }; 54 | 55 | } // namespace 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /lib/primesieve/include/primesieve/ParallelSieve.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file ParallelSieve.hpp 3 | /// @brief The ParallelSieve class provides an easy API for 4 | /// multi-threaded prime sieving. 5 | /// 6 | /// Copyright (C) 2019 Kim Walisch, 7 | /// 8 | /// This file is distributed under the BSD License. See the COPYING 9 | /// file in the top level directory. 10 | /// 11 | 12 | #ifndef PARALLELSIEVE_HPP 13 | #define PARALLELSIEVE_HPP 14 | 15 | #include "PrimeSieve.hpp" 16 | #include 17 | #include 18 | 19 | namespace primesieve { 20 | 21 | class ParallelSieve : public PrimeSieve 22 | { 23 | public: 24 | using PrimeSieve::sieve; 25 | 26 | ParallelSieve(); 27 | static int getMaxThreads(); 28 | int getNumThreads() const; 29 | int idealNumThreads() const; 30 | void setNumThreads(int numThreads); 31 | bool tryUpdateStatus(uint64_t); 32 | virtual void sieve(); 33 | 34 | private: 35 | std::mutex mutex_; 36 | int numThreads_ = 0; 37 | uint64_t getThreadDistance(int) const; 38 | uint64_t align(uint64_t) const; 39 | }; 40 | 41 | } // namespace 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /scripts/worktodo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Usage: ./worktodo.sh 4 | # Iterates over the numbers in worktodo.txt (one number per line with 5 | # optional flags) and processes them using primesum. 6 | 7 | command -v ./primesum >/dev/null 2>/dev/null 8 | if [ $? -ne 0 ] 9 | then 10 | echo "Error: no primesum binary in current directory." 11 | exit 1 12 | fi 13 | 14 | # check if primesum supports --log option 15 | log_flag=$(./primesum --help | grep Log > /dev/null && echo --log) 16 | 17 | while read first_line < worktodo.txt 18 | do 19 | # Skip empty lines and comments 20 | if [ "$first_line" != "" ] && [ ${first_line:0:1} != "#" ] 21 | then 22 | ./primesum $first_line $log_flag 23 | 24 | # Check if primesum exited successfully 25 | if [ $? -ne 0 ] 26 | then 27 | echo "" 28 | echo "Error in primesum_from_file.sh:" 29 | echo "The following command failed: ./primesum $first_line" 30 | exit 1 31 | fi 32 | fi 33 | 34 | # delete first line from worktodo.txt 35 | tail -n +2 worktodo.txt > .tmp_worktodo.txt 36 | mv -f .tmp_worktodo.txt worktodo.txt 37 | done 38 | -------------------------------------------------------------------------------- /include/aligned_vector.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file aligned_vector.hpp 3 | /// 4 | /// Copyright (C) 2017 Kim Walisch, 5 | /// 6 | /// This file is distributed under the BSD License. See the COPYING 7 | /// file in the top level directory. 8 | /// 9 | 10 | #ifndef ALIGNED_VECTOR_HPP 11 | #define ALIGNED_VECTOR_HPP 12 | 13 | #include 14 | #include 15 | 16 | // Maximum cache line size of current CPUs 17 | #ifndef CACHE_LINE_SIZE 18 | #define CACHE_LINE_SIZE 512 19 | #endif 20 | 21 | namespace primesum { 22 | 23 | /// The aligned_vector class aligns each of its 24 | /// elements on a new cache line in order to avoid 25 | /// false sharing (cache trashing) when multiple 26 | /// threads write to adjacent elements 27 | /// 28 | template 29 | class aligned_vector 30 | { 31 | public: 32 | aligned_vector(std::size_t size) 33 | : vect_(size) { } 34 | std::size_t size() const { return vect_.size(); } 35 | T& operator[](std::size_t pos) { return vect_[pos].val[0]; } 36 | private: 37 | struct align_t 38 | { 39 | T val[CACHE_LINE_SIZE / sizeof(T)]; 40 | }; 41 | std::vector vect_; 42 | }; 43 | 44 | } // namespace 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /src/app/cmdoptions.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file cmdoptions.hpp 3 | /// 4 | /// Copyright (C) 2018 Kim Walisch, 5 | /// 6 | /// This file is distributed under the BSD License. See the COPYING 7 | /// file in the top level directory. 8 | /// 9 | 10 | #ifndef PRIMESUM_CMDOPTIONS_HPP 11 | #define PRIMESUM_CMDOPTIONS_HPP 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | namespace primesum { 18 | 19 | enum OptionValues 20 | { 21 | OPTION_ALPHA, 22 | OPTION_DELEGLISE_RIVAT, 23 | OPTION_DELEGLISE_RIVAT_PARALLEL1, 24 | OPTION_HELP, 25 | OPTION_LMO, 26 | OPTION_LMO1, 27 | OPTION_LMO2, 28 | OPTION_LMO3, 29 | OPTION_LMO4, 30 | OPTION_LMO5, 31 | OPTION_LMO_PARALLEL1, 32 | OPTION_NUMBER, 33 | OPTION_P2, 34 | OPTION_PI, 35 | OPTION_S1, 36 | OPTION_S2_EASY, 37 | OPTION_S2_HARD, 38 | OPTION_S2_TRIVIAL, 39 | OPTION_STATUS, 40 | OPTION_TEST, 41 | OPTION_TIME, 42 | OPTION_THREADS, 43 | OPTION_VERSION 44 | }; 45 | 46 | struct PrimeSumOptions 47 | { 48 | int128_t x = -1; 49 | int64_t option = OPTION_PI; 50 | bool time = false; 51 | }; 52 | 53 | PrimeSumOptions parseOptions(int, char**); 54 | 55 | } // namespace 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /lib/primesieve/include/primesieve/EratSmall.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file EratSmall.hpp 3 | /// 4 | /// Copyright (C) 2019 Kim Walisch, 5 | /// 6 | /// This file is distributed under the BSD License. See the COPYING 7 | /// file in the top level directory. 8 | /// 9 | 10 | #ifndef ERATSMALL_HPP 11 | #define ERATSMALL_HPP 12 | 13 | #include "Bucket.hpp" 14 | #include "macros.hpp" 15 | #include "Wheel.hpp" 16 | 17 | #include 18 | #include 19 | 20 | namespace primesieve { 21 | 22 | /// EratSmall is an implementation of the segmented sieve 23 | /// of Eratosthenes optimized for small sieving primes that 24 | /// have many multiples per segment. 25 | /// 26 | class EratSmall : public Wheel30_t 27 | { 28 | public: 29 | static uint64_t getL1CacheSize(uint64_t); 30 | void init(uint64_t, uint64_t, uint64_t); 31 | void crossOff(uint8_t*, uint64_t); 32 | bool enabled() const { return enabled_; } 33 | private: 34 | uint64_t maxPrime_ = 0; 35 | uint64_t l1CacheSize_ = 0; 36 | std::vector primes_; 37 | bool enabled_ = false; 38 | void storeSievingPrime(uint64_t, uint64_t, uint64_t); 39 | NOINLINE void crossOff(uint8_t*, uint8_t*); 40 | }; 41 | 42 | } // namespace 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /lib/primesieve/include/primesieve/SievingPrimes.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file SievingPrimes.hpp 3 | /// 4 | /// Copyright (C) 2019 Kim Walisch, 5 | /// 6 | /// This file is distributed under the BSD License. See the COPYING 7 | /// file in the top level directory. 8 | /// 9 | 10 | #ifndef SIEVINGPRIMES_HPP 11 | #define SIEVINGPRIMES_HPP 12 | 13 | #include "Erat.hpp" 14 | #include "macros.hpp" 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | namespace primesieve { 21 | 22 | class PreSieve; 23 | 24 | class SievingPrimes : public Erat 25 | { 26 | public: 27 | SievingPrimes() = default; 28 | SievingPrimes(Erat*, PreSieve&); 29 | void init(Erat*, PreSieve&); 30 | uint64_t next(); 31 | private: 32 | uint64_t i_ = 0; 33 | uint64_t size_ = 0; 34 | uint64_t low_ = 0; 35 | uint64_t tinyIdx_ = 0; 36 | uint64_t sieveIdx_ = ~0ull; 37 | std::array primes_; 38 | std::vector tinySieve_; 39 | NOINLINE void fill(); 40 | void tinySieve(); 41 | bool sieveSegment(); 42 | }; 43 | 44 | inline uint64_t SievingPrimes::next() 45 | { 46 | while (i_ >= size_) 47 | fill(); 48 | 49 | return primes_[i_++]; 50 | } 51 | 52 | } // namespace 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /include/S2.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file S2.hpp. 3 | /// @brief S2 function declarations. 4 | /// 5 | /// Copyright (C) 2017 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #ifndef S2_HPP 12 | #define S2_HPP 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | namespace primesum { 19 | 20 | /// ------------------------ S2_trivial() ---------------------------- 21 | 22 | int256_t S2_trivial(int128_t x, 23 | int64_t y, 24 | int64_t z, 25 | int64_t c, 26 | int threads); 27 | 28 | /// ------------------------ S2_easy() ------------------------------- 29 | 30 | int256_t S2_easy(int128_t x, 31 | int64_t y, 32 | int64_t z, 33 | int64_t c, 34 | int threads); 35 | 36 | /// ------------------------ S2_hard() ------------------------------- 37 | 38 | int256_t S2_hard(int128_t x, 39 | int64_t y, 40 | int64_t z, 41 | int64_t c, 42 | int threads); 43 | 44 | } // namespace 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /lib/primesieve/include/primesieve/PrintPrimes.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file PrintPrimes.hpp 3 | /// 4 | /// Copyright (C) 2019 Kim Walisch, 5 | /// 6 | /// This file is distributed under the BSD License. See the COPYING 7 | /// file in the top level directory. 8 | /// 9 | 10 | #ifndef PRINTPRIMES_HPP 11 | #define PRINTPRIMES_HPP 12 | 13 | #include "Erat.hpp" 14 | #include "macros.hpp" 15 | #include "PrimeSieve.hpp" 16 | 17 | #include 18 | #include 19 | 20 | namespace primesieve { 21 | 22 | class Store; 23 | 24 | /// After a segment has been sieved PrintPrimes is 25 | /// used to reconstruct primes and prime k-tuplets from 26 | /// 1 bits of the sieve array 27 | /// 28 | class PrintPrimes : public Erat 29 | { 30 | public: 31 | PrintPrimes(PrimeSieve&); 32 | NOINLINE void sieve(); 33 | private: 34 | uint64_t low_ = 0; 35 | /// Count lookup tables for prime k-tuplets 36 | std::vector kCounts_[6]; 37 | counts_t& counts_; 38 | /// Reference to the associated PrimeSieve object 39 | PrimeSieve& ps_; 40 | void initCounts(); 41 | void print(); 42 | void countPrimes(); 43 | void countkTuplets(); 44 | void printPrimes() const; 45 | void printkTuplets() const; 46 | }; 47 | 48 | } // namespace 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /lib/primesieve/include/primesieve/EratBig.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file EratBig.hpp 3 | /// 4 | /// Copyright (C) 2020 Kim Walisch, 5 | /// 6 | /// This file is distributed under the BSD License. See the COPYING 7 | /// file in the top level directory. 8 | /// 9 | 10 | #ifndef ERATBIG_HPP 11 | #define ERATBIG_HPP 12 | 13 | #include "Bucket.hpp" 14 | #include "macros.hpp" 15 | #include "MemoryPool.hpp" 16 | #include "Wheel.hpp" 17 | 18 | #include 19 | #include 20 | 21 | namespace primesieve { 22 | 23 | /// EratBig is an implementation of the segmented sieve of 24 | /// Eratosthenes optimized for big sieving primes that have 25 | /// very few multiples per segment. 26 | /// 27 | class EratBig : public Wheel210_t 28 | { 29 | public: 30 | void init(uint64_t, uint64_t, uint64_t); 31 | NOINLINE void crossOff(uint8_t*); 32 | bool enabled() const { return enabled_; } 33 | private: 34 | uint64_t maxPrime_ = 0; 35 | uint64_t log2SieveSize_ = 0; 36 | uint64_t moduloSieveSize_ = 0; 37 | std::vector buckets_; 38 | MemoryPool memoryPool_; 39 | bool enabled_ = false; 40 | void storeSievingPrime(uint64_t, uint64_t, uint64_t); 41 | NOINLINE void crossOff(uint8_t*, Bucket*); 42 | }; 43 | 44 | } // namespace 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /include/PiTable.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file PiTable.hpp 3 | /// @brief The PiTable class is a compressed lookup table for 4 | /// prime counts. It uses only (n / 4) bytes of memory 5 | /// and returns the number of primes <= n in O(1) 6 | /// operations. 7 | /// 8 | /// Copyright (C) 2018 Kim Walisch, 9 | /// 10 | /// This file is distributed under the BSD License. See the COPYING 11 | /// file in the top level directory. 12 | /// 13 | 14 | #ifndef PITABLE_HPP 15 | #define PITABLE_HPP 16 | 17 | #include 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | namespace primesum { 24 | 25 | class PiTable 26 | { 27 | public: 28 | PiTable(uint64_t max); 29 | 30 | /// Get number of primes <= n 31 | int64_t operator[](uint64_t n) const 32 | { 33 | assert(n <= max_); 34 | uint64_t bitmask = 0xffffffffffffffffull >> (63 - n % 64); 35 | return pi_[n / 64].prime_count + popcnt64(pi_[n / 64].bits & bitmask); 36 | } 37 | 38 | int64_t size() const 39 | { 40 | return max_ + 1; 41 | } 42 | private: 43 | struct PiData 44 | { 45 | uint64_t prime_count = 0; 46 | uint64_t bits = 0; 47 | }; 48 | 49 | std::vector pi_; 50 | uint64_t max_; 51 | }; 52 | 53 | } // namespace 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /test/libdivide.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file libdivide.cpp 3 | /// @brief Test the branchfree divider of libdivide.h 4 | /// 5 | /// Copyright (C) 2018 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #include 12 | #include 13 | 14 | uint64_t dividends[20] = 15 | { 16 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 63, 101, 511, 17 | 1 << 5, 1 << 9, 1 << 20, 18 | (uint64_t) ((1ull << 31) - 1), 19 | (uint64_t) ((1ull << 63) - 1), 20 | (uint32_t) (~0ull), 21 | (uint64_t) (~0ull) 22 | }; 23 | 24 | int main() 25 | { 26 | for (int i = 0; i < 20; i++) 27 | { 28 | for (int j = 2; j < 10000; j++) 29 | { 30 | libdivide::divider fast_d(j); 31 | uint64_t res1 = dividends[i] / j; 32 | uint64_t res2 = dividends[i] / fast_d; 33 | 34 | if (res1 != res2) 35 | return 1; 36 | } 37 | } 38 | 39 | for (int i = 0; i < 20; i++) 40 | { 41 | for (int j = 2; j < 20; j++) 42 | { 43 | libdivide::divider fast_d(dividends[j]); 44 | uint64_t res1 = dividends[i] / dividends[j]; 45 | uint64_t res2 = dividends[i] / fast_d; 46 | 47 | if (res1 != res2) 48 | return 1; 49 | } 50 | } 51 | 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2016 - 2019, Kim Walisch. 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /lib/primesieve/COPYING: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2010 - 2021, Kim Walisch. 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /lib/primesieve/test/nth_prime1.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file nth_prime1.cpp 3 | /// @brief Test nth_prime for |n| <= 9592 4 | /// 5 | /// Copyright (C) 2017 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | using namespace std; 19 | using namespace primesieve; 20 | 21 | void check(bool OK) 22 | { 23 | cout << " " << (OK ? "OK" : "ERROR") << "\n"; 24 | if (!OK) 25 | exit(1); 26 | } 27 | 28 | int main() 29 | { 30 | uint64_t upperBound = (uint64_t) 1e5; 31 | vector primes; 32 | generate_primes(upperBound, &primes); 33 | int64_t i = primes.size() - 1; 34 | int64_t n = 0; 35 | 36 | // nth_prime(n) forwards 37 | for (uint64_t prime : primes) 38 | { 39 | n++; 40 | uint64_t res = nth_prime(n); 41 | cout << "nth_prime(" << n << ") = " << res; 42 | check(res == prime); 43 | } 44 | 45 | // nth_prime(-n, start) backwards 46 | for (n = 0; i >= 0; i--) 47 | { 48 | n--; 49 | uint64_t res = nth_prime(n, upperBound); 50 | cout << "nth_prime(" << n << ", " << upperBound << ") = " << res; 51 | check(res == primes[i]); 52 | } 53 | 54 | cout << endl; 55 | cout << "All tests passed successfully!" << endl; 56 | 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /include/popcnt.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file popcnt.hpp 3 | /// @brief Functions to count the number of 1 bits inside 4 | /// a 64-bit word. 5 | /// 6 | /// Copyright (C) 2017 Kim Walisch, 7 | /// 8 | /// This file is distributed under the BSD License. See the COPYING 9 | /// file in the top level directory. 10 | /// 11 | 12 | #ifndef POPCNT_HPP 13 | #define POPCNT_HPP 14 | 15 | #include 16 | 17 | #ifndef __has_builtin 18 | #define __has_builtin(x) 0 19 | #endif 20 | 21 | #if defined(__GNUC__) || __has_builtin(__builtin_popcountll) 22 | 23 | inline uint64_t popcnt64(uint64_t x) 24 | { 25 | return __builtin_popcountll(x); 26 | } 27 | 28 | #elif defined(_MSC_VER) && \ 29 | defined(_WIN64) 30 | 31 | #include 32 | 33 | inline uint64_t popcnt64(uint64_t x) 34 | { 35 | return _mm_popcnt_u64(x); 36 | } 37 | 38 | #elif defined(_MSC_VER) && \ 39 | defined(_WIN32) 40 | 41 | #include 42 | 43 | inline uint64_t popcnt64(uint64_t x) 44 | { 45 | return _mm_popcnt_u32((uint32_t) x) + 46 | _mm_popcnt_u32((uint32_t)(x >> 32)); 47 | } 48 | 49 | #else 50 | 51 | inline uint64_t popcnt64(uint64_t x) 52 | { 53 | uint64_t m1 = 0x5555555555555555ull; 54 | uint64_t m2 = 0x3333333333333333ull; 55 | uint64_t m4 = 0x0F0F0F0F0F0F0F0Full; 56 | uint64_t h01 = 0x0101010101010101ull; 57 | 58 | x -= (x >> 1) & m1; 59 | x = (x & m2) + ((x >> 2) & m2); 60 | x = (x + (x >> 4)) & m4; 61 | 62 | return (x * h01) >> 56; 63 | } 64 | 65 | #endif 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /lib/primesieve/test/count_primes1.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file count_primes1.cpp 3 | /// @brief Count the primes up to 10^9. 4 | /// 5 | /// Copyright (C) 2018 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | using namespace std; 20 | using namespace primesieve; 21 | 22 | /// Correct pi(x) values to compare with test results 23 | const uint64_t pix[9] = 24 | { 25 | 4, // pi(10^1) 26 | 25, // pi(10^2) 27 | 168, // pi(10^3) 28 | 1229, // pi(10^4) 29 | 9592, // pi(10^5) 30 | 78498, // pi(10^6) 31 | 664579, // pi(10^7) 32 | 5761455, // pi(10^8) 33 | 50847534 // pi(10^9) 34 | }; 35 | 36 | void check(bool OK) 37 | { 38 | cout << " " << (OK ? "OK" : "ERROR") << "\n"; 39 | if (!OK) 40 | exit(1); 41 | } 42 | 43 | int main() 44 | { 45 | cout << left; 46 | ParallelSieve ps; 47 | ps.setStart(0); 48 | ps.setStop(0); 49 | uint64_t count = 0; 50 | 51 | // pi(x) with x = 10^i for i = 1 to 9 52 | for (int i = 1; i <= 9; i++) 53 | { 54 | count += ps.countPrimes(ps.getStop() + 1, (uint64_t) pow(10.0, i)); 55 | cout << "pi(10^" << i << ") = " << setw(12) << count; 56 | check(count == pix[i - 1]); 57 | } 58 | 59 | cout << endl; 60 | cout << "All tests passed successfully!" << endl; 61 | 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /include/S2LoadBalancer.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file S2LoadBalancer.hpp 3 | /// 4 | /// Copyright (C) 2016 Kim Walisch, 5 | /// 6 | /// This file is distributed under the BSD License. See the COPYING 7 | /// file in the top level directory. 8 | /// 9 | 10 | #ifndef S2LOADBALANCER_HPP 11 | #define S2LOADBALANCER_HPP 12 | 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | namespace primesum { 19 | 20 | class S2LoadBalancer 21 | { 22 | public: 23 | S2LoadBalancer(int128_t x, int64_t y, int64_t z, int64_t threads); 24 | int64_t get_min_segment_size() const; 25 | double get_rsd() const; 26 | void update(int64_t low, 27 | int64_t threads, 28 | int64_t* segment_size, 29 | int64_t* segments_per_thread, 30 | aligned_vector& timings); 31 | private: 32 | void init(int128_t x, int64_t y, int64_t threads); 33 | void set_min_size(int64_t z); 34 | void update(int64_t* segments_per_thread, double seconds, double pivot); 35 | void update_min_size(double divisor); 36 | double get_avg_seconds() const; 37 | double get_pivot(double seconds) const; 38 | bool is_increase(double seconds, double pivot) const; 39 | bool is_decrease(double seconds, double pivot) const; 40 | double x_; 41 | double y_; 42 | double z_; 43 | double rsd_; 44 | double count_; 45 | double total_seconds_; 46 | double min_seconds_; 47 | double decrease_dividend_; 48 | int64_t min_size_; 49 | int64_t sqrtz_; 50 | int64_t smallest_hard_leaf_; 51 | }; 52 | 53 | } // namespace 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /lib/primesieve/test/count_primes2.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file count_primes2.cpp 3 | /// @brief Count the primes within [10^i, 10^i + 10^8] 4 | /// for i = 12 to 19 5 | /// 6 | /// Copyright (C) 2018 Kim Walisch, 7 | /// 8 | /// This file is distributed under the BSD License. See the COPYING 9 | /// file in the top level directory. 10 | /// 11 | 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | using namespace std; 22 | using namespace primesieve; 23 | 24 | const array pix = 25 | { 26 | 3618282, // pi[10^12, 10^12+10^8] 27 | 3342093, // pi[10^13, 10^13+10^8] 28 | 3102679, // pi[10^14, 10^14+10^8] 29 | 2893937, // pi[10^15, 10^15+10^8] 30 | 2714904, // pi[10^16, 10^16+10^8] 31 | 2555873 // pi[10^17, 10^17+10^8] 32 | }; 33 | 34 | void check(bool OK) 35 | { 36 | cout << " " << (OK ? "OK" : "ERROR") << "\n"; 37 | if (!OK) 38 | exit(1); 39 | } 40 | 41 | int main() 42 | { 43 | cout << left; 44 | 45 | for (size_t i = 0; i < pix.size(); i++) 46 | { 47 | size_t j = i + 12; 48 | cout << "Sieving the primes within [10^" << j << ", 10^" << j << " + 10^8]" << endl; 49 | uint64_t start = (uint64_t) pow(10.0, j); 50 | uint64_t stop = start + (uint64_t) 1e8; 51 | uint64_t count = count_primes(start, stop); 52 | cout << "\rPrime count: " << setw(7) << count; 53 | check(count == pix[i]); 54 | } 55 | 56 | cout << endl; 57 | cout << "All tests passed successfully!" << endl; 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /lib/primesieve/cmake/primesieveConfig.cmake.in: -------------------------------------------------------------------------------- 1 | # ==================================================================== 2 | # The primesieve CMake configuration file 3 | # 4 | # Usage from an external project: 5 | # In your CMakeLists.txt, add these lines: 6 | # 7 | # find_package(primesieve REQUIRED) 8 | # target_link_libraries(your_target primesieve::primesieve) 9 | # 10 | # To link against the static libprimesieve use: 11 | # 12 | # find_package(primesieve REQUIRED static) 13 | # target_link_libraries(your_target primesieve::primesieve) 14 | # 15 | # ==================================================================== 16 | 17 | include(CMakeFindDependencyMacro) 18 | find_dependency(Threads QUIET) 19 | 20 | if(@BUILD_STATIC_LIBS@ AND @BUILD_SHARED_LIBS@) 21 | if(primesieve_FIND_COMPONENTS) 22 | string(TOLOWER "${primesieve_FIND_COMPONENTS}" LOWER_COMPONENTS) 23 | if(LOWER_COMPONENTS STREQUAL "static") 24 | set(primesieve_STATIC TRUE) 25 | endif() 26 | endif() 27 | elseif(@BUILD_STATIC_LIBS@) 28 | set(primesieve_STATIC TRUE) 29 | endif() 30 | 31 | if(primesieve_STATIC) 32 | include("${CMAKE_CURRENT_LIST_DIR}/primesieveStatic.cmake") 33 | add_library(primesieve::primesieve INTERFACE IMPORTED) 34 | set_target_properties(primesieve::primesieve PROPERTIES INTERFACE_LINK_LIBRARIES "primesieve::libprimesieve-static") 35 | else() 36 | include("${CMAKE_CURRENT_LIST_DIR}/primesieveShared.cmake") 37 | add_library(primesieve::primesieve INTERFACE IMPORTED) 38 | set_target_properties(primesieve::primesieve PROPERTIES INTERFACE_LINK_LIBRARIES "primesieve::libprimesieve") 39 | endif() 40 | -------------------------------------------------------------------------------- /lib/primesieve/include/primesieve/EratMedium.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file EratMedium.hpp 3 | /// 4 | /// Copyright (C) 2020 Kim Walisch, 5 | /// 6 | /// This file is distributed under the BSD License. See the COPYING 7 | /// file in the top level directory. 8 | /// 9 | 10 | #ifndef ERATMEDIUM_HPP 11 | #define ERATMEDIUM_HPP 12 | 13 | #include "Bucket.hpp" 14 | #include "macros.hpp" 15 | #include "MemoryPool.hpp" 16 | #include "Wheel.hpp" 17 | 18 | #include 19 | #include 20 | 21 | namespace primesieve { 22 | 23 | /// EratMedium is an implementation of the segmented sieve of 24 | /// Eratosthenes optimized for medium sieving primes 25 | /// that have a few multiples per segment. 26 | /// 27 | class EratMedium : public Wheel30_t 28 | { 29 | public: 30 | void init(uint64_t, uint64_t, uint64_t); 31 | bool enabled() const { return enabled_; } 32 | NOINLINE void crossOff(uint8_t*, uint64_t); 33 | private: 34 | bool enabled_ = false; 35 | uint64_t maxPrime_ = 0; 36 | MemoryPool memoryPool_; 37 | std::array buckets_; 38 | void storeSievingPrime(uint64_t, uint64_t, uint64_t); 39 | NOINLINE void crossOff_7(uint8_t*, uint8_t*, Bucket*); 40 | NOINLINE void crossOff_11(uint8_t*, uint8_t*, Bucket*); 41 | NOINLINE void crossOff_13(uint8_t*, uint8_t*, Bucket*); 42 | NOINLINE void crossOff_17(uint8_t*, uint8_t*, Bucket*); 43 | NOINLINE void crossOff_19(uint8_t*, uint8_t*, Bucket*); 44 | NOINLINE void crossOff_23(uint8_t*, uint8_t*, Bucket*); 45 | NOINLINE void crossOff_29(uint8_t*, uint8_t*, Bucket*); 46 | NOINLINE void crossOff_31(uint8_t*, uint8_t*, Bucket*); 47 | }; 48 | 49 | } // namespace 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /lib/primesieve/test/nth_prime3.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file nth_prime3.cpp 3 | /// @brief Long distance nth prime testing. 4 | /// 5 | /// Copyright (C) 2017 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace std; 18 | using namespace primesieve; 19 | 20 | void nth_prime_test(int64_t n, int64_t start, int64_t iters) 21 | { 22 | for (int64_t i = 1; i <= iters; i++) 23 | { 24 | int64_t i_start = (i * start) + 1; 25 | int64_t prime = nth_prime(-n, i_start); 26 | int64_t smaller = nth_prime(n, prime - 1); 27 | int64_t larger = nth_prime(n, prime); 28 | 29 | if (i_start <= smaller || i_start > larger) 30 | { 31 | cerr << endl; 32 | cerr << "nth_prime(" << -n << ", " << i_start << ") = " << prime << " ERROR" << endl; 33 | exit(1); 34 | } 35 | } 36 | } 37 | 38 | int main() 39 | { 40 | // Set a small sieve size in order to 41 | // ensure many segments are sieved 42 | set_sieve_size(16); 43 | 44 | for (int i = 3; i <= 6; i++) 45 | { 46 | for (int j = 8; j <= 10; j++) 47 | { 48 | int64_t n = (int64_t) pow(10.0, i); 49 | int64_t start = (int64_t) pow(10.0, j); 50 | int64_t iters = 5; 51 | 52 | cout << "nth_prime_test(" << n << ", " << start << ", " << iters << ")"; 53 | nth_prime_test(n, start, iters); 54 | cout << " = OK" << endl; 55 | } 56 | } 57 | 58 | cout << endl; 59 | cout << "All tests passed successfully!" << endl; 60 | 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /lib/primesieve/include/primesieve/CpuInfo.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file CpuInfo.hpp 3 | /// 4 | /// Copyright (C) 2020 Kim Walisch, 5 | /// 6 | /// This file is distributed under the BSD License. See the COPYING 7 | /// file in the top level directory. 8 | /// 9 | 10 | #ifndef CPUINFO_HPP 11 | #define CPUINFO_HPP 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | namespace primesieve { 18 | 19 | class CpuInfo 20 | { 21 | public: 22 | CpuInfo(); 23 | bool hasCpuName() const; 24 | bool hasCpuCores() const; 25 | bool hasCpuThreads() const; 26 | bool hasL1Cache() const; 27 | bool hasL2Cache() const; 28 | bool hasL3Cache() const; 29 | bool hasL1Sharing() const; 30 | bool hasL2Sharing() const; 31 | bool hasL3Sharing() const; 32 | bool hasThreadsPerCore() const; 33 | bool hasPrivateL2Cache() const; 34 | bool sysctlL2CacheWorkaround() const; 35 | std::string cpuName() const; 36 | std::string getError() const; 37 | std::size_t l1CacheSize() const; 38 | std::size_t l2CacheSize() const; 39 | std::size_t l3CacheSize() const; 40 | std::size_t l1Sharing() const; 41 | std::size_t l2Sharing() const; 42 | std::size_t l3Sharing() const; 43 | std::size_t cpuCores() const; 44 | std::size_t cpuThreads() const; 45 | std::size_t threadsPerCore() const; 46 | 47 | private: 48 | void init(); 49 | std::size_t cpuCores_; 50 | std::size_t cpuThreads_; 51 | std::size_t threadsPerCore_; 52 | bool sysctlL2CacheWorkaround_; 53 | std::array cacheSizes_; 54 | std::array cacheSharing_; 55 | std::string error_; 56 | }; 57 | 58 | // Singleton 59 | extern const CpuInfo cpuInfo; 60 | 61 | } // namespace 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /lib/primesieve/include/primesieve/PrimeGenerator.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file PrimeGenerator.hpp 3 | /// Generates the primes inside [start, stop] and stores them 4 | /// in a vector. After the primes have been stored in the 5 | /// vector primesieve::iterator iterates over the vector and 6 | /// returns the primes. When there are no more primes left in 7 | /// the vector PrimeGenerator generates new primes. 8 | /// 9 | /// Copyright (C) 2019 Kim Walisch, 10 | /// 11 | /// This file is distributed under the BSD License. See the COPYING 12 | /// file in the top level directory. 13 | /// 14 | 15 | #ifndef PRIMEGENERATOR_HPP 16 | #define PRIMEGENERATOR_HPP 17 | 18 | #include "Erat.hpp" 19 | #include "PreSieve.hpp" 20 | #include "SievingPrimes.hpp" 21 | 22 | #include 23 | #include 24 | 25 | namespace primesieve { 26 | 27 | class PrimeGenerator : public Erat 28 | { 29 | public: 30 | PrimeGenerator(uint64_t start, uint64_t stop); 31 | void fill(std::vector&); 32 | void fill(std::vector& primes, std::size_t* size); 33 | static uint64_t maxCachedPrime(); 34 | 35 | private: 36 | uint64_t low_ = 0; 37 | uint64_t sieveIdx_ = ~0ull; 38 | uint64_t prime_ = 0; 39 | PreSieve preSieve_; 40 | SievingPrimes sievingPrimes_; 41 | bool isInit_ = false; 42 | std::size_t getStartIdx() const; 43 | std::size_t getStopIdx() const; 44 | void initErat(); 45 | void init(std::vector&); 46 | void init(std::vector&, std::size_t*); 47 | bool sieveSegment(std::vector&); 48 | bool sieveSegment(std::vector&, std::size_t*); 49 | void sieveSegment(); 50 | }; 51 | 52 | } // namespace 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /include/primesum.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file primesum.hpp 3 | /// 4 | /// Copyright (C) 2017 Kim Walisch, 5 | /// 6 | /// This file is distributed under the BSD License. 7 | /// 8 | 9 | #ifndef PRIMESUM_HPP 10 | #define PRIMESUM_HPP 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #define PRIMESUM_VERSION "1.7" 17 | #define PRIMESUM_VERSION_MAJOR 1 18 | #define PRIMESUM_VERSION_MINOR 7 19 | 20 | namespace primesum { 21 | 22 | class primesum_error : public std::runtime_error 23 | { 24 | public: 25 | primesum_error(const std::string& msg) 26 | : std::runtime_error(msg) 27 | { } 28 | }; 29 | 30 | /// 128-bit prime summing function. 31 | /// Run time: O(x^(2/3) / (log x)^2) operations, O(x^(1/3) * (log x)^3) space. 32 | /// @param expr Integer arithmetic expression e.g. "1000", "10^22" 33 | /// @pre expr <= get_max_x() 34 | /// 35 | std::string pi(const std::string& x); 36 | 37 | /// Enable/disable printing status information during computation. 38 | void set_print(bool is_print); 39 | 40 | /// Set the number of threads. 41 | void set_num_threads(int num_threads); 42 | 43 | /// Get the currently set number of threads. 44 | int get_num_threads(); 45 | 46 | /// Largest integer supported by pi(const std::string& x). 47 | /// The return type is a string as max may be a 128-bit integer 48 | /// which is not supported by some compilers. 49 | /// @param alpha Tuning factor used in LMO type algorithms. 50 | /// @return for 32-bit CPUs: 2^63-1, 51 | /// for 64-bit CPUs: max >= 10^27 52 | /// 53 | std::string get_max_x(double alpha = 1.0); 54 | 55 | /// Get the primesum version number, in the form “i.j”. 56 | std::string primesum_version(); 57 | 58 | } // namespace 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /src/PhiTiny.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file PhiTiny.cpp 3 | /// @brief phi(x, a) counts the numbers <= x that are not 4 | /// divisible by any of the first a primes. 5 | /// PhiTiny computes phi(x, a) in constant time 6 | /// for a <= 6 using lookup tables. 7 | /// 8 | /// phi(x, a) = (x / pp) * φ(a) + phi(x % pp, a) 9 | /// pp = 2 * 3 * ... * prime[a] 10 | /// φ(a) = \prod_{i=1}^{a} (prime[i] - 1) 11 | /// 12 | /// Copyright (C) 2017 Kim Walisch, 13 | /// 14 | /// This file is distributed under the BSD License. See the COPYING 15 | /// file in the top level directory. 16 | /// 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | namespace primesum { 25 | 26 | const std::array PhiTiny::primes = { 0, 2, 3, 5, 7, 11, 13 }; 27 | 28 | // prime_products[n] = \prod_{i=1}^{n} primes[i] 29 | const std::array PhiTiny::prime_products = { 1, 2, 6, 30, 210, 2310, 30030 }; 30 | 31 | // totients[n] = \prod_{i=1}^{n} (primes[i] - 1) 32 | const std::array PhiTiny::totients = { 1, 1, 2, 8, 48, 480, 5760 }; 33 | 34 | // Number of primes below x 35 | const std::array PhiTiny::pi = { 0, 0, 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5 }; 36 | 37 | // Singleton 38 | const PhiTiny phiTiny; 39 | 40 | PhiTiny::PhiTiny() 41 | { 42 | phi_[0].push_back(0); 43 | 44 | // initialize phi(x % pp, a) lookup tables 45 | for (int a = 1; a <= max_a(); a++) 46 | { 47 | int pp = prime_products[a]; 48 | phi_[a].resize(pp); 49 | 50 | for (int x = 0; x < pp; x++) 51 | { 52 | auto phi_xa = phi(x, a - 1) - phi(x / primes[a], a - 1); 53 | phi_[a][x] = (int16_t) phi_xa; 54 | } 55 | } 56 | } 57 | 58 | } // namespace 59 | -------------------------------------------------------------------------------- /lib/primesieve/test/count_primes3.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file count_primes3.cpp 3 | /// @brief Count the primes within [10^12, 10^12 + 10^9] 4 | /// using random sized intervals. 5 | /// 6 | /// Copyright (C) 2017 Kim Walisch, 7 | /// 8 | /// This file is distributed under the BSD License. See the COPYING 9 | /// file in the top level directory. 10 | /// 11 | 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | using namespace std; 21 | using namespace primesieve; 22 | 23 | void check(bool OK) 24 | { 25 | cout << " " << (OK ? "OK" : "ERROR") << "\n"; 26 | if (!OK) 27 | exit(1); 28 | } 29 | 30 | int main() 31 | { 32 | cout << "Sieving the primes within [10^12, 10^12 + 10^9] randomly" << endl; 33 | 34 | uint64_t count = 0; 35 | uint64_t maxDist = (uint64_t) 1e7; 36 | uint64_t lowerBound = (uint64_t) 1e12; 37 | uint64_t upperBound = lowerBound + (uint64_t) 1e9; 38 | uint64_t start = lowerBound - 1; 39 | uint64_t stop = start; 40 | 41 | random_device rd; 42 | mt19937 gen(rd()); 43 | uniform_int_distribution dist(0, maxDist); 44 | 45 | while (stop < upperBound) 46 | { 47 | start = stop + 1; 48 | stop = min(start + dist(gen), upperBound); 49 | set_sieve_size(1 << (dist(gen) % 13)); 50 | count += count_primes(start, stop); 51 | 52 | cout << "\rRemaining chunk: " 53 | << "\rRemaining chunk: " 54 | << upperBound - stop << flush; 55 | } 56 | 57 | cout << endl << "Prime count: " << count; 58 | check(count == 36190991); 59 | 60 | cout << endl; 61 | cout << "Test passed successfully!" << endl; 62 | 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /lib/primesieve/test/number_of_bits.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file number_of_bits.cpp 3 | /// @brief Test numberOfBits(x) function. 4 | /// 5 | /// Copyright (C) 2018 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | using namespace std; 17 | 18 | void check(bool OK) 19 | { 20 | cout << " " << (OK ? "OK" : "ERROR") << "\n"; 21 | if (!OK) 22 | exit(1); 23 | } 24 | 25 | int main() 26 | { 27 | int8_t i8 = 0; 28 | cout << "numberOfBits(int8_t) = " << (int) numberOfBits(i8); 29 | check(numberOfBits(i8) == 8); 30 | 31 | uint8_t ui8 = 0; 32 | cout << "numberOfBits(uint8_t) = " << (int) numberOfBits(ui8); 33 | check(numberOfBits(ui8) == 8); 34 | 35 | int16_t i16 = 0; 36 | cout << "numberOfBits(int16_t) = " << numberOfBits(i16); 37 | check(numberOfBits(i16) == 16); 38 | 39 | uint16_t ui16 = 0; 40 | cout << "numberOfBits(uint16_t) = " << numberOfBits(ui16); 41 | check(numberOfBits(ui16) == 16); 42 | 43 | int32_t i32 = 0; 44 | cout << "numberOfBits(int32_t) = " << numberOfBits(i32); 45 | check(numberOfBits(i32) == 32); 46 | 47 | uint32_t ui32 = 0; 48 | cout << "numberOfBits(uint32_t) = " << numberOfBits(ui32); 49 | check(numberOfBits(ui32) == 32); 50 | 51 | int64_t i64 = 0; 52 | cout << "numberOfBits(int64_t) = " << numberOfBits(i64); 53 | check(numberOfBits(i64) == 64); 54 | 55 | uint64_t ui64 = 0; 56 | cout << "numberOfBits(uint64_t) = " << numberOfBits(ui64); 57 | check(numberOfBits(ui64) == 64); 58 | 59 | cout << endl; 60 | cout << "All tests passed successfully!" << endl; 61 | 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /lib/primesieve/include/primesieve/littleendian_cast.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file littleendian_cast.hpp 3 | /// @brief Cast bytes in ascending address order on both little and 4 | /// big endian CPUs. 5 | /// 6 | /// Copyright (C) 2020 Kim Walisch, 7 | /// 8 | /// This file is distributed under the BSD License. See the COPYING 9 | /// file in the top level directory. 10 | /// 11 | 12 | #ifndef LITTLEENDIAN_CAST_HPP 13 | #define LITTLEENDIAN_CAST_HPP 14 | 15 | #include 16 | 17 | namespace { 18 | 19 | /// http://c-faq.com/misc/endiantest.html 20 | inline bool is_littleendian() 21 | { 22 | union { 23 | int word; 24 | char c[sizeof(int)]; 25 | } x; 26 | x.word = 1; 27 | return (x.c[0] == 1); 28 | } 29 | 30 | /// Recursively sum bytes using template metaprogramming. 31 | /// e.g. littleendian_cast(array) = 32 | /// return (array[0] << 0) + 33 | /// (array[1] << 8) + 34 | /// (array[2] << 16) + 35 | /// (array[3] << 24); 36 | /// 37 | template 38 | struct littleendian_cast_helper 39 | { 40 | static T sum(const uint8_t* array, T n) 41 | { 42 | n += static_cast(array[INDEX]) << (INDEX * 8); 43 | return littleendian_cast_helper::sum(array, n); 44 | } 45 | }; 46 | 47 | template 48 | struct littleendian_cast_helper 49 | { 50 | static T sum(const uint8_t*, T n) 51 | { 52 | return n; 53 | } 54 | }; 55 | 56 | template 57 | inline T littleendian_cast(const uint8_t* array) 58 | { 59 | if (is_littleendian()) 60 | return *reinterpret_cast(array); 61 | return littleendian_cast_helper::sum(array, 0); 62 | } 63 | 64 | } // namespace 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /lib/primesieve/test/isqrt.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file isqrt.cpp 3 | /// @brief Test integer square root function. 4 | /// 5 | /// Copyright (C) 2017 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | using namespace std; 19 | 20 | void check(bool OK) 21 | { 22 | cout << " " << (OK ? "OK" : "ERROR") << "\n"; 23 | if (!OK) 24 | exit(1); 25 | } 26 | 27 | int main() 28 | { 29 | uint64_t n; 30 | uint64_t res1; 31 | double res2; 32 | 33 | for (n = 0; n < 100000; n++) 34 | { 35 | res1 = isqrt(n); 36 | res2 = sqrt((double) n); 37 | cout << "isqrt(" << n << ") = " << res1; 38 | check(res1 == (uint64_t) res2); 39 | } 40 | 41 | n = (1ull << 32) - 1; 42 | res1 = isqrt(n); 43 | res2 = sqrt((double) n); 44 | cout << "isqrt(" << n << ") = " << res1; 45 | check(res1 == (uint64_t) res2); 46 | 47 | n = 1ull << 32; 48 | res1 = isqrt(n); 49 | res2 = sqrt((double) n); 50 | cout << "isqrt(" << n << ") = " << res1; 51 | check(res1 == (uint64_t) res2); 52 | 53 | n = 1000000000000000000ull - 1; 54 | res1 = isqrt(n); 55 | cout << "isqrt(" << n << ") = " << res1; 56 | check(res1 == 999999999); 57 | 58 | n = 1000000000000000000ull; 59 | res1 = isqrt(n); 60 | cout << "isqrt(" << n << ") = " << res1; 61 | check(res1 == 1000000000); 62 | 63 | n = 18446744073709551615ull; 64 | res1 = isqrt(n); 65 | cout << "isqrt(" << n << ") = " << res1; 66 | check(res1 == 4294967295ull); 67 | 68 | cout << endl; 69 | cout << "All tests passed successfully!" << endl; 70 | 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /lib/primesieve/test/ilog2.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file ilog2.cpp 3 | /// @brief Test ilog2(x) function. 4 | /// Note that the log2(x) function from is not 5 | /// accurate enough near 2^64. 6 | /// 7 | /// Copyright (C) 2017 Kim Walisch, 8 | /// 9 | /// This file is distributed under the BSD License. See the COPYING 10 | /// file in the top level directory. 11 | /// 12 | 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | using namespace std; 21 | 22 | void check(bool OK) 23 | { 24 | cout << " " << (OK ? "OK" : "ERROR") << "\n"; 25 | if (!OK) 26 | exit(1); 27 | } 28 | 29 | int main() 30 | { 31 | uint64_t n; 32 | uint64_t res1; 33 | uint64_t res2; 34 | 35 | for (n = 1; n < 100000; n++) 36 | { 37 | res1 = ilog2(n); 38 | res2 = (uint64_t) log2(n); 39 | cout << "ilog2(" << n << ") = " << res1; 40 | check(res1 == res2); 41 | } 42 | 43 | n = (1ull << 32) - 1; 44 | res1 = ilog2(n); 45 | res2 = (uint64_t) log2(n); 46 | cout << "ilog2(" << n << ") = " << res1; 47 | check(res1 == (uint64_t) res2); 48 | 49 | n = 1ull << 32; 50 | res1 = ilog2(n); 51 | res2 = (uint64_t) log2(n); 52 | cout << "ilog2(" << n << ") = " << res1; 53 | check(res1 == (uint64_t) res2); 54 | 55 | n = (1ull << 63) - 1; 56 | res1 = ilog2(n); 57 | cout << "ilog2(" << n << ") = " << res1; 58 | check(res1 == 62); 59 | 60 | n = 1ull << 63; 61 | res1 = ilog2(n); 62 | cout << "ilog2(" << n << ") = " << res1; 63 | check(res1 == 63); 64 | 65 | n = 18446744073709551615ull; 66 | res1 = ilog2(n); 67 | cout << "ilog2(" << n << ") = " << res1; 68 | check(res1 == 63); 69 | 70 | cout << endl; 71 | cout << "All tests passed successfully!" << endl; 72 | 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /lib/primesieve/doc/mainpage.dox: -------------------------------------------------------------------------------- 1 | /// @mainpage 2 | /// @section About 3 | /// 4 | /// primesieve is a C/C++ library for fast prime number generation. It 5 | /// generates the primes below 10^9 in just 0.2 seconds on a single 6 | /// core of an Intel Core i7-6700 3.4GHz CPU. primesieve can generate 7 | /// primes and prime k-tuplets up to 2^64. primesieve's memory 8 | /// requirement is about pi(sqrt(n)) * 8 bytes per thread, its 9 | /// run-time complexity is O(n log log n) operations. The recommended 10 | /// way to get started is to first have a look at a few C or C++ 11 | /// example programs. The most common use cases are iterating over 12 | /// primes using @link primesieve::iterator::next_prime() next_prime() @endlink 13 | /// or @link primesieve::iterator::prev_prime() prev_prime() @endlink and 14 | /// storing primes in a vector or an array. 15 | /// 16 | /// For more information please visit https://github.com/kimwalisch/primesieve. 17 | /// 18 | /// @section CPP_API C++ API 19 | /// 20 | /// @li @link primesieve.hpp primesieve.hpp @endlink - primesieve C++ header. 21 | /// @li primesieve::iterator - Provides the @link primesieve::iterator::next_prime() next_prime() @endlink and @link primesieve::iterator::prev_prime() prev_prime() @endlink methods. 22 | /// @li C++ examples - Example programs that show how to use libprimesieve. 23 | /// 24 | /// @section C_API C API 25 | /// 26 | /// @li @link primesieve.h primesieve.h @endlink - primesieve C header. 27 | /// @li @link iterator.h primesieve_iterator @endlink - Provides the primesieve_next_prime() and primesieve_prev_prime() functions. 28 | /// @li C examples - Example programs that show how to use libprimesieve. 29 | /// 30 | -------------------------------------------------------------------------------- /src/FactorTable.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file FactorTable.cpp 3 | /// @see FactorTable.hpp for documentation. 4 | /// 5 | /// Copyright (C) 2014 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #include 12 | #include 13 | 14 | namespace primesum { 15 | 16 | const uint8_t AbstractFactorTable::numbers_[48] = 17 | { 18 | 1, 11, 13, 17, 19, 23, 19 | 29, 31, 37, 41, 43, 47, 20 | 53, 59, 61, 67, 71, 73, 21 | 79, 83, 89, 97, 101, 103, 22 | 107, 109, 113, 121, 127, 131, 23 | 137, 139, 143, 149, 151, 157, 24 | 163, 167, 169, 173, 179, 181, 25 | 187, 191, 193, 197, 199, 209 26 | }; 27 | 28 | const int8_t AbstractFactorTable::indexes_[210] = 29 | { 30 | -1, 0, 0, 0, 0, 0, 0, 0, 31 | 0, 0, 0, 1, 1, 2, 2, 2, 32 | 2, 3, 3, 4, 4, 4, 4, 5, 33 | 5, 5, 5, 5, 5, 6, 6, 7, 34 | 7, 7, 7, 7, 7, 8, 8, 8, 35 | 8, 9, 9, 10, 10, 10, 10, 11, 36 | 11, 11, 11, 11, 11, 12, 12, 12, 37 | 12, 12, 12, 13, 13, 14, 14, 14, 38 | 14, 14, 14, 15, 15, 15, 15, 16, 39 | 16, 17, 17, 17, 17, 17, 17, 18, 40 | 18, 18, 18, 19, 19, 19, 19, 19, 41 | 19, 20, 20, 20, 20, 20, 20, 20, 42 | 20, 21, 21, 21, 21, 22, 22, 23, 43 | 23, 23, 23, 24, 24, 25, 25, 25, 44 | 25, 26, 26, 26, 26, 26, 26, 26, 45 | 26, 27, 27, 27, 27, 27, 27, 28, 46 | 28, 28, 28, 29, 29, 29, 29, 29, 47 | 29, 30, 30, 31, 31, 31, 31, 32, 48 | 32, 32, 32, 32, 32, 33, 33, 34, 49 | 34, 34, 34, 34, 34, 35, 35, 35, 50 | 35, 35, 35, 36, 36, 36, 36, 37, 51 | 37, 38, 38, 38, 38, 39, 39, 39, 52 | 39, 39, 39, 40, 40, 41, 41, 41, 53 | 41, 41, 41, 42, 42, 42, 42, 43, 54 | 43, 44, 44, 44, 44, 45, 45, 46, 55 | 46, 46, 46, 46, 46, 46, 46, 46, 56 | 46, 47 57 | }; 58 | 59 | } // namespace 60 | -------------------------------------------------------------------------------- /include/isqrt.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file isqrt.hpp 3 | /// @brief Integer square root function. 4 | /// 5 | /// Copyright (C) 2014 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #ifndef ISQRT_HPP 12 | #define ISQRT_HPP 13 | 14 | #include 15 | 16 | #include 17 | #include 18 | 19 | namespace primesum { 20 | 21 | #if __cplusplus >= 201402L 22 | 23 | /// C++14 compile time square root using binary search 24 | template 25 | constexpr T sqrt_helper(T x, T lo, T hi) 26 | { 27 | if (lo == hi) 28 | return lo; 29 | 30 | const T mid = (lo + hi + 1) / 2; 31 | 32 | if (x / mid < mid) 33 | return sqrt_helper(x, lo, mid - 1); 34 | else 35 | return sqrt_helper(x, mid, hi); 36 | } 37 | 38 | template 39 | constexpr T ct_sqrt(T x) 40 | { 41 | return sqrt_helper(x, 0, x / 2 + 1); 42 | } 43 | 44 | #elif __cplusplus >= 201103L 45 | 46 | #define MID ((lo + hi + 1) / 2) 47 | 48 | /// C++11 compile time square root using binary search 49 | template 50 | constexpr T sqrt_helper(T x, T lo, T hi) 51 | { 52 | return lo == hi ? lo : ((x / MID < MID) 53 | ? sqrt_helper(x, lo, MID - 1) : sqrt_helper(x, MID, hi)); 54 | } 55 | 56 | template 57 | constexpr T ct_sqrt(T x) 58 | { 59 | return sqrt_helper(x, 0, x / 2 + 1); 60 | } 61 | 62 | #endif 63 | 64 | template 65 | inline T isqrt(T x) 66 | { 67 | T r = (T) std::sqrt((double) x); 68 | 69 | #if __cplusplus >= 201103L 70 | static const T sqrt_max = ct_sqrt(prt::numeric_limits::max()); 71 | r = std::min(r, sqrt_max); 72 | #endif 73 | 74 | while (r * r > x) 75 | r--; 76 | while (x - r * r > r * 2) 77 | r++; 78 | 79 | return r; 80 | } 81 | 82 | } // namespace 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /lib/primesieve/test/floorPow2.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file floorPow2.cpp 3 | /// @brief Round down to nearest power of 2. 4 | /// 5 | /// Copyright (C) 2017 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | using namespace std; 19 | 20 | void check(bool OK) 21 | { 22 | cout << " " << (OK ? "OK" : "ERROR") << "\n"; 23 | if (!OK) 24 | exit(1); 25 | } 26 | 27 | uint64_t floorPow2_cmath(uint64_t n) 28 | { 29 | return 1ull << (uint64_t) log2(n); 30 | } 31 | 32 | int main() 33 | { 34 | uint64_t n; 35 | uint64_t res1; 36 | uint64_t res2; 37 | 38 | for (n = 1; n < 100000; n++) 39 | { 40 | res1 = floorPow2(n); 41 | res2 = floorPow2_cmath(n); 42 | cout << "floorPow2(" << n << ") = " << res1; 43 | check(res1 == res2); 44 | } 45 | 46 | n = (1ull << 32) - 1; 47 | res1 = floorPow2(n); 48 | res2 = floorPow2_cmath(n); 49 | cout << "floorPow2(" << n << ") = " << res1; 50 | check(res1 == res2); 51 | 52 | n = 1ull << 32; 53 | res1 = floorPow2(n); 54 | res2 = floorPow2_cmath(n); 55 | cout << "floorPow2(" << n << ") = " << res1; 56 | check(res1 == res2); 57 | 58 | n = (1ull << 63) - 1; 59 | res1 = floorPow2(n); 60 | cout << "floorPow2(" << n << ") = " << res1; 61 | check(res1 == (1ull << 62)); 62 | 63 | n = 1ull << 63; 64 | res1 = floorPow2(n); 65 | cout << "floorPow2(" << n << ") = " << res1; 66 | check(res1 == (1ull << 63)); 67 | 68 | n = 18446744073709551615ull; 69 | res1 = floorPow2(n); 70 | cout << "floorPow2(" << n << ") = " << res1; 71 | check(res1 == (1ull << 63)); 72 | 73 | cout << endl; 74 | cout << "All tests passed successfully!" << endl; 75 | 76 | return 0; 77 | } 78 | -------------------------------------------------------------------------------- /lib/primesieve/include/primesieve/PreSieve.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file PreSieve.hpp 3 | /// 4 | /// Copyright (C) 2020 Kim Walisch, 5 | /// 6 | /// This file is distributed under the BSD License. See the COPYING 7 | /// file in the top level directory. 8 | /// 9 | 10 | #ifndef PRESIEVE_HPP 11 | #define PRESIEVE_HPP 12 | 13 | #include 14 | #include 15 | 16 | namespace primesieve { 17 | 18 | /// PreSieve objects are used to pre-sieve multiples of small primes 19 | /// e.g. <= 19 to speed up the sieve of Eratosthenes. The idea is to 20 | /// allocate an array (buffer_) and remove the multiples of small 21 | /// primes from it at initialization. Then whilst sieving, the 22 | /// buffer_ array is copied to the sieve array at the beginning of 23 | /// each new segment to pre-sieve the multiples of small 24 | /// primes <= maxPrime_. Pre-sieving speeds up my sieve of Eratosthenes 25 | /// implementation by about 20 percent when sieving < 10^10. 26 | /// 27 | /// Memory Usage 28 | /// 29 | /// - PreSieve objects use: primeProduct(maxPrime_) / 30 bytes of memory 30 | /// - PreSieve multiples of primes <= 7 uses 7 bytes 31 | /// - PreSieve multiples of primes <= 11 uses 77 bytes 32 | /// - PreSieve multiples of primes <= 13 uses 1001 bytes 33 | /// - PreSieve multiples of primes <= 17 uses 17.02 kilobytes 34 | /// - PreSieve multiples of primes <= 19 uses 323.32 kilobytes 35 | /// - PreSieve multiples of primes <= 23 uses 7.44 megabytes 36 | /// 37 | class PreSieve 38 | { 39 | public: 40 | void init(uint64_t, uint64_t); 41 | uint64_t getMaxPrime() const { return maxPrime_; } 42 | void copy(uint8_t*, uint64_t, uint64_t) const; 43 | private: 44 | uint64_t maxPrime_ = 0; 45 | uint64_t primeProduct_ = 0; 46 | uint64_t size_ = 0; 47 | std::vector buffer_; 48 | void initBuffer(uint64_t, uint64_t); 49 | }; 50 | 51 | } // namespace 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /include/generate.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file generate.hpp 3 | /// 4 | /// Copyright (C) 2018 Kim Walisch, 5 | /// 6 | /// This file is distributed under the BSD License. See the COPYING 7 | /// file in the top level directory. 8 | /// 9 | 10 | #ifndef GENERATE_HPP 11 | #define GENERATE_HPP 12 | 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | namespace primesum { 19 | 20 | /// Generate a vector with the primes <= max. 21 | /// The primes vector uses 1-indexing i.e. primes[1] = 2. 22 | /// 23 | template 24 | std::vector generate_primes(int64_t max) 25 | { 26 | std::vector primes = { 0 }; 27 | primesieve::generate_primes(max, &primes); 28 | return primes; 29 | } 30 | 31 | /// Generate a vector with the prime sums <= max. 32 | /// The primes vector uses 1-indexing i.e. primes[1] = 2. 33 | /// 34 | template 35 | std::vector generate_prime_sums(int64_t max) 36 | { 37 | std::vector primes = { 0 }; 38 | primesieve::generate_primes(max, &primes); 39 | 40 | for (uint64_t i = 1; i < primes.size(); i++) 41 | primes[i] += primes[i - 1]; 42 | 43 | return primes; 44 | } 45 | 46 | /// Generate a vector with the primes <= max. 47 | /// The primes vector uses 1-indexing i.e. primes[1] = 2. 48 | // 49 | std::vector generate_primes(int64_t max); 50 | 51 | /// Generate a vector with the first n primes. 52 | /// The primes vector uses 1-indexing i.e. primes[1] = 2. 53 | // 54 | std::vector generate_n_primes(int64_t n); 55 | 56 | /// Generate a vector with Möbius function values. 57 | std::vector generate_moebius(int64_t max); 58 | 59 | /// Generate a vector with the least prime 60 | /// factors of the integers <= max. 61 | /// 62 | std::vector generate_lpf(int64_t max); 63 | 64 | /// Generate a vector with the prime counts below max 65 | /// using the sieve of Eratosthenes. 66 | /// 67 | std::vector generate_pi(int64_t max); 68 | 69 | } // namespace 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /include/PhiTiny.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file PhiTiny.hpp 3 | /// @brief phi(x, a) counts the numbers <= x that are not 4 | /// divisible by any of the first a primes. 5 | /// PhiTiny computes phi(x, a) in constant time 6 | /// for a <= 6 using lookup tables. 7 | /// 8 | /// phi(x, a) = (x / pp) * φ(a) + phi(x % pp, a) 9 | /// pp = 2 * 3 * ... * prime[a] 10 | /// φ(a) = \prod_{i=1}^{a} (prime[i] - 1) 11 | /// 12 | /// Copyright (C) 2018 Kim Walisch, 13 | /// 14 | /// This file is distributed under the BSD License. See the COPYING 15 | /// file in the top level directory. 16 | /// 17 | 18 | #ifndef PHITINY_HPP 19 | #define PHITINY_HPP 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | namespace primesum { 28 | 29 | class PhiTiny 30 | { 31 | public: 32 | PhiTiny(); 33 | 34 | template 35 | T phi(T x, int64_t a) const 36 | { 37 | assert(a <= max_a()); 38 | 39 | T pp = prime_products[a]; 40 | return (x / pp) * totients[a] + phi_[a][x % pp]; 41 | } 42 | 43 | static int64_t get_c(int64_t y) 44 | { 45 | assert(y >= 0); 46 | 47 | if (y >= primes.back()) 48 | return max_a(); 49 | else 50 | return pi[y]; 51 | } 52 | 53 | static int64_t max_a() 54 | { 55 | return primes.size() - 1; 56 | } 57 | 58 | private: 59 | std::array, 7> phi_; 60 | static const std::array primes; 61 | static const std::array prime_products; 62 | static const std::array totients; 63 | static const std::array pi; 64 | }; 65 | 66 | extern const PhiTiny phiTiny; 67 | 68 | inline bool is_phi_tiny(int64_t a) 69 | { 70 | return a <= PhiTiny::max_a(); 71 | } 72 | 73 | template 74 | T phi_tiny(T x, int64_t a) 75 | { 76 | if (x <= std::numeric_limits::max()) 77 | return phiTiny.phi((uint32_t) x, a); 78 | else 79 | return phiTiny.phi(x, a); 80 | } 81 | 82 | } // namespace 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # Automated testing using appveyor.com 2 | # https://ci.appveyor.com/projects 3 | 4 | version: 1.0.{build} 5 | 6 | image: 7 | - Ubuntu 8 | - Ubuntu2004 9 | - macos 10 | 11 | branches: 12 | except: 13 | - gh-pages 14 | 15 | platform: 16 | - x64 17 | 18 | configuration: 19 | - Debug 20 | - Release 21 | 22 | for: 23 | # Test using GCC sanitizers 24 | - matrix: 25 | only: 26 | - image: Ubuntu 27 | platform: x64 28 | configuration: Debug 29 | environment: 30 | CFLAGS: "-Wall -Wextra -pedantic -Werror -Wno-long-long -Wno-missing-braces -O1 -g -fsanitize=address -fsanitize=undefined -fno-sanitize-recover=all -fno-omit-frame-pointer" 31 | CXXFLAGS: "-Wall -Wextra -pedantic -Werror -Wno-long-long -Wno-missing-braces -O1 -g -fsanitize=address -fsanitize=undefined -fno-sanitize-recover=all -fno-omit-frame-pointer" 32 | build_script: 33 | - cmake . -DCMAKE_BUILD_TYPE=$CONFIGURATION 34 | - make VERBOSE=1 35 | test_script: 36 | - ./primesum --test 37 | 38 | - matrix: 39 | only: 40 | - image: Ubuntu 41 | platform: x64 42 | configuration: Release 43 | environment: 44 | CFLAGS: "-Wall -Wextra -pedantic -Werror -Wno-long-long -Wno-missing-braces" 45 | CXXFLAGS: "-Wall -Wextra -pedantic -Werror -Wno-long-long -Wno-missing-braces" 46 | build_script: 47 | - cmake . -DCMAKE_BUILD_TYPE=$CONFIGURATION -DCMAKE_INSTALL_PREFIX=$(pwd) 48 | - make VERBOSE=1 49 | - make install 50 | test_script: 51 | - ./primesum --test 52 | 53 | - matrix: 54 | only: 55 | - image: macos 56 | platform: x64 57 | environment: 58 | CFLAGS: "-Wall -Wextra -pedantic -Werror -Wno-long-long -Wno-missing-braces" 59 | CXXFLAGS: "-Wall -Wextra -pedantic -Werror -Wno-long-long -Wno-missing-braces" 60 | build_script: 61 | - cmake . -DCMAKE_BUILD_TYPE=$CONFIGURATION -DCMAKE_INSTALL_PREFIX=$(pwd) 62 | - make VERBOSE=1 63 | - make install 64 | test_script: 65 | - ./primesum --test 66 | -------------------------------------------------------------------------------- /lib/primesieve/doc/Doxyfile.in: -------------------------------------------------------------------------------- 1 | PROJECT_NAME = "primesieve" 2 | PROJECT_NUMBER = @PRIMESIEVE_VERSION@ 3 | INPUT = @PROJECT_SOURCE_DIR@/doc/mainpage.dox \ 4 | @PROJECT_SOURCE_DIR@/include/primesieve.hpp \ 5 | @PROJECT_SOURCE_DIR@/include/primesieve.h \ 6 | @PROJECT_SOURCE_DIR@/include/primesieve/iterator.h \ 7 | @PROJECT_SOURCE_DIR@/include/primesieve/iterator.hpp \ 8 | @PROJECT_SOURCE_DIR@/include/primesieve/primesieve_error.hpp \ 9 | @PROJECT_SOURCE_DIR@/examples/cpp/count_primes.cpp \ 10 | @PROJECT_SOURCE_DIR@/examples/cpp/primesieve_iterator.cpp \ 11 | @PROJECT_SOURCE_DIR@/examples/cpp/nth_prime.cpp \ 12 | @PROJECT_SOURCE_DIR@/examples/cpp/prev_prime.cpp \ 13 | @PROJECT_SOURCE_DIR@/examples/cpp/store_primes_in_vector.cpp \ 14 | @PROJECT_SOURCE_DIR@/examples/c/count_primes.c \ 15 | @PROJECT_SOURCE_DIR@/examples/c/prev_prime.c \ 16 | @PROJECT_SOURCE_DIR@/examples/c/primesieve_iterator.c \ 17 | @PROJECT_SOURCE_DIR@/examples/c/nth_prime.c \ 18 | @PROJECT_SOURCE_DIR@/examples/c/store_primes_in_array.c 19 | HTML_INDEX_NUM_ENTRIES = 3 20 | HTML_TIMESTAMP = NO 21 | JAVADOC_AUTOBRIEF = YES 22 | MULTILINE_CPP_IS_BRIEF = NO 23 | SHOW_NAMESPACES = YES 24 | VERBATIM_HEADERS = NO 25 | EXTRACT_ALL = NO 26 | EXTRACT_STATIC = YES 27 | FILE_PATTERNS = *.cpp *.c *.h *.hpp 28 | EXCLUDE_SYMBOLS = primesieve_generate_next_primes \ 29 | primesieve_generate_prev_primes 30 | RECURSIVE = NO 31 | EXAMPLE_PATTERNS = *.cpp *.c 32 | EXAMPLE_PATH = @PROJECT_SOURCE_DIR@/examples 33 | EXAMPLE_RECURSIVE = YES 34 | GENERATE_LATEX = @HAVE_LATEX@ 35 | FULL_PATH_NAMES = NO 36 | HAVE_DOT = @HAVE_DOT@ 37 | -------------------------------------------------------------------------------- /lib/primesieve/test/next_prime1.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file next_prime1.cpp 3 | /// @brief Test next_prime() of primesieve::iterator. 4 | /// 5 | /// Copyright (C) 2017 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | using namespace std; 20 | 21 | void check(bool OK) 22 | { 23 | cout << " " << (OK ? "OK" : "ERROR") << "\n"; 24 | if (!OK) 25 | exit(1); 26 | } 27 | 28 | int main() 29 | { 30 | vector primes; 31 | primesieve::generate_primes(100000, &primes); 32 | primesieve::iterator it; 33 | uint64_t stop = primes.size() - 1; 34 | uint64_t prime; 35 | 36 | for (uint64_t i = 0; i < stop; i++) 37 | { 38 | it.skipto(primes[i] - 1); 39 | prime = it.next_prime(); 40 | cout << "next_prime(" << primes[i] - 1 << ") = " << prime; 41 | check(prime == primes[i]); 42 | 43 | it.skipto(primes[i]); 44 | prime = it.next_prime(); 45 | cout << "next_prime(" << primes[i] << ") = " << prime; 46 | check(prime == primes[i + 1]); 47 | } 48 | 49 | it.skipto(0); 50 | prime = it.next_prime(); 51 | uint64_t sum = 0; 52 | 53 | // iterate over the primes below 10^9 54 | for (; prime < 1000000000; prime = it.next_prime()) 55 | sum += prime; 56 | 57 | cout << "Sum of the primes below 10^9 = " << sum; 58 | check(sum == 24739512092254535ull); 59 | 60 | it.skipto(primes.back() - 200, primes.back()); 61 | prime = it.next_prime(); 62 | 63 | while (prime <= primes.back()) 64 | prime = it.next_prime(); 65 | 66 | for (uint64_t i = 1; i < 1000; i++) 67 | { 68 | uint64_t old = prime; 69 | uint64_t p = primes[primes.size() - i]; 70 | prime = it.prev_prime(); 71 | cout << "prev_prime(" << old << ") = " << prime; 72 | check(prime == p); 73 | } 74 | 75 | cout << endl; 76 | cout << "All tests passed successfully!" << endl; 77 | 78 | return 0; 79 | } 80 | -------------------------------------------------------------------------------- /include/fast_div.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file fast_div.hpp 3 | /// @brief Integer division of small types is much faster than 4 | /// integer division of large types on most CPUs. The 5 | /// fast_div(x, y) function tries to take advantage of 6 | /// this by casting x and y to smaller types (if possible) 7 | /// before doing the division. 8 | /// 9 | /// Copyright (C) 2018 Kim Walisch, 10 | /// 11 | /// This file is distributed under the BSD License. See the COPYING 12 | /// file in the top level directory. 13 | /// 14 | 15 | #ifndef FAST_DIV_HPP 16 | #define FAST_DIV_HPP 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | namespace primesum { 25 | 26 | template 27 | struct fastdiv 28 | { 29 | typedef typename std::conditional::type>::type type; 32 | }; 33 | 34 | template 35 | typename std::enable_if<(sizeof(X) == sizeof(Y)), X>::type 36 | fast_div(X x, Y y) 37 | { 38 | static_assert(prt::is_integral::value && 39 | prt::is_integral::value, 40 | "fast_div(x, y): types must be integral"); 41 | 42 | using fastdiv_t = typename fastdiv::type; 43 | 44 | if (x <= std::numeric_limits::max() && 45 | y <= std::numeric_limits::max()) 46 | { 47 | return (fastdiv_t) x / (fastdiv_t) y; 48 | } 49 | 50 | return x / y; 51 | } 52 | 53 | template 54 | typename std::enable_if<(sizeof(X) > sizeof(Y)), X>::type 55 | fast_div(X x, Y y) 56 | { 57 | static_assert(prt::is_integral::value && 58 | prt::is_integral::value, 59 | "fast_div(x, y): types must be integral"); 60 | 61 | using fastdiv_t = typename fastdiv::type; 62 | 63 | if (x <= std::numeric_limits::max()) 64 | return (fastdiv_t) x / (fastdiv_t) y; 65 | 66 | return x / y; 67 | } 68 | 69 | } // namespace 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /lib/primesieve/include/primesieve/macros.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file macros.hpp 3 | /// 4 | /// Copyright (C) 2020 Kim Walisch, 5 | /// 6 | /// This file is distributed under the BSD License. See the COPYING 7 | /// file in the top level directory. 8 | /// 9 | 10 | #ifndef MACROS_HPP 11 | #define MACROS_HPP 12 | 13 | #ifndef __has_attribute 14 | #define __has_attribute(x) 0 15 | #endif 16 | 17 | #ifndef __has_builtin 18 | #define __has_builtin(x) 0 19 | #endif 20 | 21 | #ifndef __has_cpp_attribute 22 | #define __has_cpp_attribute(x) 0 23 | #endif 24 | 25 | /// Some functions in primesieve use a large number of variables 26 | /// at the same time. If such functions are inlined then 27 | /// performance drops because not all variables fit into registers 28 | /// which causes register spilling. We annotate such functions 29 | /// with NOINLINE in order to avoid these issues. 30 | /// 31 | #if __has_attribute(noinline) 32 | #define NOINLINE __attribute__((noinline)) 33 | #elif defined(_MSC_VER) 34 | #define NOINLINE __declspec(noinline) 35 | #else 36 | #define NOINLINE 37 | #endif 38 | 39 | #if __cplusplus >= 202002L && \ 40 | __has_cpp_attribute(unlikely) 41 | #define if_unlikely(x) if (x) [[unlikely]] 42 | #elif defined(__GNUC__) || \ 43 | __has_builtin(__builtin_expect) 44 | #define if_unlikely(x) if (__builtin_expect(!!(x), 0)) 45 | #else 46 | #define if_unlikely(x) if (x) 47 | #endif 48 | 49 | #if __cplusplus >= 201703L && \ 50 | __has_cpp_attribute(fallthrough) 51 | #define FALLTHROUGH [[fallthrough]] 52 | #elif __has_attribute(fallthrough) 53 | #define FALLTHROUGH __attribute__((fallthrough)) 54 | #else 55 | #define FALLTHROUGH 56 | #endif 57 | 58 | #if defined(__GNUC__) || \ 59 | __has_builtin(__builtin_unreachable) 60 | #define UNREACHABLE __builtin_unreachable() 61 | #elif defined(_MSC_VER) 62 | #define UNREACHABLE __assume(0) 63 | #else 64 | #define UNREACHABLE 65 | #endif 66 | 67 | /// Use [[maybe_unused]] from C++17 once widely supported 68 | #if defined(NDEBUG) 69 | #define MAYBE_UNUSED(x) 70 | #else 71 | #define MAYBE_UNUSED(x) x 72 | #endif 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /src/lmo/pi_lmo1.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file pi_lmo1.cpp 3 | /// @brief Simple demonstration implementation of the 4 | /// Lagarias-Miller-Odlyzko prime summing algorithm. 5 | /// Usually in the Lagarias-Miller-Odlyzko algorithm phi(x, a) 6 | /// is calculated using a prime sieve but this simple 7 | /// implementation calculates phi(x, a) using the recursive 8 | /// formula with caching. 9 | /// 10 | /// Copyright (C) 2016 Kim Walisch, 11 | /// 12 | /// This file is distributed under the BSD License. See the COPYING 13 | /// file in the top level directory. 14 | /// 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | using namespace std; 29 | 30 | namespace primesum { 31 | 32 | /// Calculate the number of primes below x using the 33 | /// Lagarias-Miller-Odlyzko algorithm. 34 | /// Run time: O(x^(2/3)) operations, O(x^(1/3)) space. 35 | /// 36 | int256_t pi_lmo1(int128_t x) 37 | { 38 | if (x < 2) 39 | return 0; 40 | 41 | int64_t y = iroot<3>(x); 42 | int64_t pi_y = pi_legendre(y, 1); 43 | int64_t c = PhiTiny::get_c(y); 44 | int256_t S1 = 0; 45 | int256_t S2 = 0; 46 | 47 | vector primes = generate_primes(y); 48 | vector lpf = generate_lpf(y); 49 | vector mu = generate_moebius(y); 50 | 51 | // Calculate the contribution of the ordinary leaves 52 | for (int64_t n = 1; n <= y; n++) 53 | if (lpf[n] > primes[c]) 54 | S1 += phi_sum(x / n, c) * (mu[n] * n); 55 | 56 | // Calculate the contribution of the special leaves 57 | for (int64_t b = c + 1; b < pi_y; b++) 58 | for (int128_t m = (y / primes[b]) + 1; m <= y; m++) 59 | if (lpf[m] > primes[b]) 60 | S2 -= phi_sum(x / (primes[b] * m), b - 1) * (mu[m] * m * primes[b]); 61 | 62 | int256_t phi = S1 + S2; 63 | int256_t p2 = P2(x, y, 1); 64 | int256_t sum = phi + prime_sum_tiny(y) - 1 - p2; 65 | 66 | return sum; 67 | } 68 | 69 | } // namespace 70 | -------------------------------------------------------------------------------- /lib/primesieve/include/primesieve/malloc_vector.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file malloc_vector 3 | /// 4 | /// Copyright (C) 2020 Kim Walisch, 5 | /// 6 | /// This file is distributed under the BSD License. See the COPYING 7 | /// file in the top level directory. 8 | /// 9 | 10 | #ifndef MALLOC_VECTOR_HPP 11 | #define MALLOC_VECTOR_HPP 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | namespace { 19 | 20 | /// malloc_vector is a dynamically growing array. 21 | /// It has the same API (though not complete) as std::vector but it 22 | /// uses malloc as its allocator. 23 | /// 24 | template 25 | class malloc_vector 26 | { 27 | public: 28 | malloc_vector() 29 | { 30 | resize(16); 31 | } 32 | 33 | malloc_vector(std::size_t n) 34 | { 35 | resize(n); 36 | } 37 | 38 | ~malloc_vector() 39 | { 40 | if (is_free_) 41 | free((void*) array_); 42 | } 43 | 44 | void push_back(const T& val) 45 | { 46 | array_[size_++] = val; 47 | if (size_ >= capacity_) 48 | resize(size_ * 2); 49 | } 50 | 51 | void reserve(std::size_t n) 52 | { 53 | if (n > capacity_) 54 | resize(n); 55 | } 56 | 57 | void resize(std::size_t n) 58 | { 59 | n = std::max(n, (std::size_t) 16); 60 | T* new_array = (T*) realloc((void*) array_, n * sizeof(T)); 61 | 62 | if (!new_array) 63 | throw std::bad_alloc(); 64 | 65 | array_ = new_array; 66 | capacity_ = n; 67 | size_ = std::min(size_, capacity_); 68 | } 69 | 70 | T& operator[] (T n) 71 | { 72 | return array_[n]; 73 | } 74 | 75 | T* data() 76 | { 77 | return array_; 78 | } 79 | 80 | std::size_t size() const 81 | { 82 | return size_; 83 | } 84 | 85 | void disable_free() 86 | { 87 | is_free_ = false; 88 | } 89 | 90 | public: 91 | using value_type = T; 92 | 93 | private: 94 | T* array_ = nullptr; 95 | std::size_t size_ = 0; 96 | std::size_t capacity_ = 0; 97 | bool is_free_ = true; 98 | }; 99 | 100 | } // namespace 101 | 102 | #endif 103 | -------------------------------------------------------------------------------- /lib/primesieve/test/generate_n_primes2.c: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file generate_n_primes2.c 3 | /// @brief Test n prime number generation. 4 | /// 5 | /// Copyright (C) 2017 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | // primes inside [0, 100] 19 | const uint64_t small_primes[25] = 20 | { 21 | 2, 3, 5, 7, 11, 22 | 13, 17, 19, 23, 29, 23 | 31, 37, 41, 43, 47, 24 | 53, 59, 61, 67, 71, 25 | 73, 79, 83, 89, 97 26 | }; 27 | 28 | // primes inside [10^16, 10^16 + 1000] 29 | const uint64_t large_primes[20] = 30 | { 31 | 10000000000000061ull, 32 | 10000000000000069ull, 33 | 10000000000000079ull, 34 | 10000000000000099ull, 35 | 10000000000000453ull, 36 | 10000000000000481ull, 37 | 10000000000000597ull, 38 | 10000000000000613ull, 39 | 10000000000000639ull, 40 | 10000000000000669ull, 41 | 10000000000000753ull, 42 | 10000000000000793ull, 43 | 10000000000000819ull, 44 | 10000000000000861ull, 45 | 10000000000000897ull, 46 | 10000000000000909ull, 47 | 10000000000000931ull, 48 | 10000000000000949ull, 49 | 10000000000000957ull, 50 | 10000000000000991ull, 51 | }; 52 | 53 | void check(int OK) 54 | { 55 | if (OK) 56 | printf(" OK\n"); 57 | else 58 | { 59 | printf(" ERROR\n"); 60 | exit(1); 61 | } 62 | } 63 | 64 | int main() 65 | { 66 | size_t i; 67 | size_t size = 25; 68 | uint64_t* primes = (uint64_t*) primesieve_generate_n_primes(size, 0, UINT64_PRIMES); 69 | 70 | for (i = 0; i < size; i++) 71 | { 72 | printf("primes[%zu] = %" PRIu64, i, primes[i]); 73 | check(primes[i] == small_primes[i]); 74 | } 75 | 76 | primesieve_free(primes); 77 | size = 20; 78 | primes = (uint64_t*) primesieve_generate_n_primes(size, 10000000000000000ull, UINT64_PRIMES); 79 | 80 | for (i = 0; i < size; i++) 81 | { 82 | printf("primes[%zu] = %" PRIu64, i, primes[i]); 83 | check(primes[i] == large_primes[i]); 84 | } 85 | 86 | primesieve_free(primes); 87 | printf("\n"); 88 | printf("All tests passed successfully!\n"); 89 | 90 | return 0; 91 | } 92 | -------------------------------------------------------------------------------- /lib/primesieve/test/generate_primes1.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file generate_primes1.cpp 3 | /// @brief Test prime number generation. 4 | /// 5 | /// Copyright (C) 2017 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | using namespace std; 19 | using namespace primesieve; 20 | 21 | // primes inside [0, 100] 22 | const uint64_t small_primes[25] = 23 | { 24 | 2, 3, 5, 7, 11, 25 | 13, 17, 19, 23, 29, 26 | 31, 37, 41, 43, 47, 27 | 53, 59, 61, 67, 71, 28 | 73, 79, 83, 89, 97 29 | }; 30 | 31 | // primes inside [10^15, 10^15 + 741] 32 | const uint64_t large_primes[19] = 33 | { 34 | 1000000000000037ull, 35 | 1000000000000091ull, 36 | 1000000000000159ull, 37 | 1000000000000187ull, 38 | 1000000000000223ull, 39 | 1000000000000241ull, 40 | 1000000000000249ull, 41 | 1000000000000259ull, 42 | 1000000000000273ull, 43 | 1000000000000279ull, 44 | 1000000000000297ull, 45 | 1000000000000357ull, 46 | 1000000000000399ull, 47 | 1000000000000403ull, 48 | 1000000000000487ull, 49 | 1000000000000513ull, 50 | 1000000000000613ull, 51 | 1000000000000711ull, 52 | 1000000000000741ull 53 | }; 54 | 55 | void check(bool OK) 56 | { 57 | cout << " " << (OK ? "OK" : "ERROR") << "\n"; 58 | if (!OK) 59 | exit(1); 60 | } 61 | 62 | int main() 63 | { 64 | vector primes; 65 | 66 | generate_primes(100, &primes); 67 | cout << "primes.size() = " << primes.size(); 68 | check(primes.size() == 25); 69 | 70 | for (uint64_t i = 0; i < primes.size(); i++) 71 | { 72 | cout << "primes[" << i << "] = " << primes[i]; 73 | check(primes[i] == small_primes[i]); 74 | } 75 | 76 | primes.clear(); 77 | 78 | generate_primes(1000000000000000ull, 1000000000000741ull, &primes); 79 | cout << "primes.size() = " << primes.size(); 80 | check(primes.size() == 19); 81 | 82 | for (uint64_t i = 0; i < primes.size(); i++) 83 | { 84 | cout << "primes[" << i << "] = " << primes[i]; 85 | check(primes[i] == large_primes[i]); 86 | } 87 | 88 | cout << endl; 89 | cout << "All tests passed successfully!" << endl; 90 | 91 | return 0; 92 | } 93 | -------------------------------------------------------------------------------- /lib/primesieve/scripts/update_version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ $# -ne 1 ] 4 | then 5 | echo "Usage example:" 6 | echo "$ ./update_version.sh 1.2" 7 | echo "" 8 | echo "Updates the primesieve version to 1.2 in all files" 9 | 10 | exit 1 11 | fi 12 | 13 | # Run from primesieve root directory 14 | test -e ../src && cd .. 15 | 16 | new_version=$1 17 | old_version=$(grep "PRIMESIEVE_VERSION " include/primesieve.hpp | cut -f2 -d'"') 18 | 19 | new_major=$(echo $new_version | cut -f1 -d'.') 20 | new_minor=$(echo $new_version | cut -f2 -d'.') 21 | 22 | old_major=$(echo $old_version | cut -f1 -d'.') 23 | old_minor=$(echo $old_version | cut -f2 -d'.') 24 | 25 | new_year=$(date +'%Y') 26 | old_year=$(grep "Copyright (C)" include/primesieve.hpp | cut -f4 -d' ') 27 | 28 | echo "New version: $new_version" 29 | echo "Old version: $old_version" 30 | echo "" 31 | echo "New year: $new_year" 32 | echo "Old year: $old_year" 33 | echo "" 34 | 35 | # Update version 36 | for i in $(echo README.md \ 37 | CMakeLists.txt \ 38 | include/primesieve.hpp \ 39 | include/primesieve.h) 40 | do 41 | echo "Update version in $i" 42 | sed "s/$old_major\.$old_minor/$new_version/g" $i > $i.tmp 43 | mv -f $i.tmp $i 44 | done 45 | 46 | # Update shared libprimesieve version 47 | for i in $(echo CMakeLists.txt) 48 | do 49 | echo "Update shared libprimesieve version in $i" 50 | old_so_major=$(($old_major + 2)) 51 | new_so_major=$(($new_major + 2)) 52 | new_so_version="$new_so_major.$new_minor.0" 53 | sed "s/$old_so_major\.$old_minor\.0/$new_so_version/g" $i > $i.tmp 54 | mv -f $i.tmp $i 55 | done 56 | 57 | # Update version 58 | for i in $(echo include/primesieve.hpp \ 59 | include/primesieve.h) 60 | do 61 | sed "s/PRIMESIEVE_VERSION_MAJOR $old_major/PRIMESIEVE_VERSION_MAJOR $new_major/g" $i > $i.tmp 62 | mv -f $i.tmp $i 63 | sed "s/PRIMESIEVE_VERSION_MINOR $old_minor/PRIMESIEVE_VERSION_MINOR $new_minor/g" $i > $i.tmp 64 | mv -f $i.tmp $i 65 | done 66 | 67 | # Update year 68 | for i in $(echo COPYING \ 69 | src/app/help.cpp) 70 | do 71 | echo "Update year in $i" 72 | sed "s/$old_year/$new_year/g" $i > $i.tmp 73 | mv -f $i.tmp $i 74 | done 75 | 76 | # Update version number in man page 77 | echo "" 78 | cmake . 79 | make -j 80 | echo "" 81 | 82 | echo "Version has been updated!" 83 | -------------------------------------------------------------------------------- /lib/primesieve/test/generate_n_primes1.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file generate_n_primes1.cpp 3 | /// @brief Test n prime number generation. 4 | /// 5 | /// Copyright (C) 2017 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | using namespace std; 19 | using namespace primesieve; 20 | 21 | // primes inside [0, 100] 22 | const uint64_t small_primes[25] = 23 | { 24 | 2, 3, 5, 7, 11, 25 | 13, 17, 19, 23, 29, 26 | 31, 37, 41, 43, 47, 27 | 53, 59, 61, 67, 71, 28 | 73, 79, 83, 89, 97 29 | }; 30 | 31 | // primes inside [18446744073709550681, 18446744073709551533] 32 | const uint64_t large_primes[19] = 33 | { 34 | 18446744073709550681ull, 35 | 18446744073709550717ull, 36 | 18446744073709550719ull, 37 | 18446744073709550771ull, 38 | 18446744073709550773ull, 39 | 18446744073709550791ull, 40 | 18446744073709550873ull, 41 | 18446744073709551113ull, 42 | 18446744073709551163ull, 43 | 18446744073709551191ull, 44 | 18446744073709551253ull, 45 | 18446744073709551263ull, 46 | 18446744073709551293ull, 47 | 18446744073709551337ull, 48 | 18446744073709551359ull, 49 | 18446744073709551427ull, 50 | 18446744073709551437ull, 51 | 18446744073709551521ull, 52 | 18446744073709551533ull 53 | }; 54 | 55 | void check(bool OK) 56 | { 57 | cout << " " << (OK ? "OK" : "ERROR") << "\n"; 58 | if (!OK) 59 | exit(1); 60 | } 61 | 62 | int main() 63 | { 64 | vector primes; 65 | 66 | generate_n_primes(25, &primes); 67 | cout << "primes.size() = " << primes.size(); 68 | check(primes.size() == 25); 69 | 70 | for (uint64_t i = 0; i < primes.size(); i++) 71 | { 72 | cout << "primes[" << i << "] = " << primes[i]; 73 | check(primes[i] == small_primes[i]); 74 | } 75 | 76 | primes.clear(); 77 | 78 | generate_n_primes(19, 18446744073709550672ull, &primes); 79 | cout << "primes.size() = " << primes.size(); 80 | check(primes.size() == 19); 81 | 82 | for (uint64_t i = 0; i < primes.size(); i++) 83 | { 84 | cout << "primes[" << i << "] = " << primes[i]; 85 | check(primes[i] == large_primes[i]); 86 | } 87 | 88 | cout << endl; 89 | cout << "All tests passed successfully!" << endl; 90 | 91 | return 0; 92 | } 93 | -------------------------------------------------------------------------------- /lib/primesieve/test/move_primesieve_iterator.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file move_primesieve_iterator.cpp 3 | /// @brief Test the move constructor and move assignment operators 4 | /// of the primesieve::iterator class. 5 | /// 6 | /// Copyright (C) 2018 Kim Walisch, 7 | /// 8 | /// This file is distributed under the BSD License. See the COPYING 9 | /// file in the top level directory. 10 | /// 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace std; 18 | 19 | void check(bool OK) 20 | { 21 | cout << " " << (OK ? "OK" : "ERROR") << "\n"; 22 | if (!OK) 23 | exit(1); 24 | } 25 | 26 | int main() 27 | { 28 | // test move constructor /////////////////////////////////////////// 29 | 30 | primesieve::iterator it; 31 | uint64_t prime = it.next_prime(); 32 | uint64_t sum = 0; 33 | 34 | // use 1st iterator up to 5e8 35 | for (; prime < 500000000ull; prime = it.next_prime()) 36 | sum += prime; 37 | 38 | // move constructor 39 | primesieve::iterator it2(std::move(it)); 40 | 41 | // use 2nd iterator up to 1e9 42 | for (; prime < 1000000000ull; prime = it2.next_prime()) 43 | sum += prime; 44 | 45 | cout << "Sum of the primes below 10^9 = " << sum; 46 | check(sum == 24739512092254535ull); 47 | 48 | // test move assignment operator /////////////////////////////////// 49 | 50 | // moved from objects can be reused 51 | // but they need to be reset 52 | it.skipto(0); 53 | prime = it.next_prime(); 54 | sum = 0; 55 | 56 | // use 1st iterator up to 6e8 57 | for (; prime < 600000000ull; prime = it.next_prime()) 58 | sum += prime; 59 | 60 | // move assignment operator 61 | it2 = std::move(it); 62 | 63 | // use 2nd iterator up to 1e9 64 | for (; prime < 1000000000ull; prime = it2.next_prime()) 65 | sum += prime; 66 | 67 | cout << "Sum of the primes below 10^9 = " << sum; 68 | check(sum == 24739512092254535ull); 69 | 70 | // test std::vector //////////////////////////////////////////////// 71 | 72 | vector vect; 73 | vect.emplace_back(1000); 74 | prime = vect.back().prev_prime(); 75 | cout << "1st prime < 1000 = " << prime; 76 | check(prime == 997); 77 | 78 | it2.skipto(5); 79 | vect.emplace_back(std::move(it2)); 80 | prime = vect.back().next_prime(); 81 | cout << "1st prime > 5 = " << prime; 82 | check(prime == 7); 83 | 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /lib/primesieve/test/generate_primes2.c: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file generate_primes2.c 3 | /// @brief Test prime number generation. 4 | /// 5 | /// Copyright (C) 2017 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | // primes inside [0, 100] 19 | const uint64_t small_primes[25] = 20 | { 21 | 2, 3, 5, 7, 11, 22 | 13, 17, 19, 23, 29, 23 | 31, 37, 41, 43, 47, 24 | 53, 59, 61, 67, 71, 25 | 73, 79, 83, 89, 97 26 | }; 27 | 28 | // primes inside [18446744073709550681, 18446744073709551533] 29 | const uint64_t large_primes[19] = 30 | { 31 | 18446744073709550681ull, 32 | 18446744073709550717ull, 33 | 18446744073709550719ull, 34 | 18446744073709550771ull, 35 | 18446744073709550773ull, 36 | 18446744073709550791ull, 37 | 18446744073709550873ull, 38 | 18446744073709551113ull, 39 | 18446744073709551163ull, 40 | 18446744073709551191ull, 41 | 18446744073709551253ull, 42 | 18446744073709551263ull, 43 | 18446744073709551293ull, 44 | 18446744073709551337ull, 45 | 18446744073709551359ull, 46 | 18446744073709551427ull, 47 | 18446744073709551437ull, 48 | 18446744073709551521ull, 49 | 18446744073709551533ull 50 | }; 51 | 52 | void check(int OK) 53 | { 54 | if (OK) 55 | printf(" OK\n"); 56 | else 57 | { 58 | printf(" ERROR\n"); 59 | exit(1); 60 | } 61 | } 62 | 63 | int main() 64 | { 65 | size_t i; 66 | size_t size = 0; 67 | uint64_t* primes = (uint64_t*) primesieve_generate_primes(0, 100, &size, UINT64_PRIMES); 68 | printf("primes.size = %zu", size); 69 | check(size == 25); 70 | 71 | for (i = 0; i < size; i++) 72 | { 73 | printf("primes[%zu] = %" PRIu64, i, primes[i]); 74 | check(primes[i] == small_primes[i]); 75 | } 76 | 77 | primesieve_free(primes); 78 | primes = (uint64_t*) primesieve_generate_primes(18446744073709550672ull, 18446744073709551556ull, &size, UINT64_PRIMES); 79 | printf("primes.size = %zu", size); 80 | check(size == 19); 81 | 82 | for (i = 0; i < size; i++) 83 | { 84 | printf("primes[%zu] = %" PRIu64, i, primes[i]); 85 | check(primes[i] == large_primes[i]); 86 | } 87 | 88 | primesieve_free(primes); 89 | printf("\n"); 90 | printf("All tests passed successfully!\n"); 91 | 92 | return 0; 93 | } 94 | -------------------------------------------------------------------------------- /src/app/help.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file help.cpp 3 | /// 4 | /// Copyright (C) 2019 Kim Walisch, 5 | /// 6 | /// This file is distributed under the BSD License. See the COPYING 7 | /// file in the top level directory. 8 | /// 9 | 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace std; 17 | 18 | namespace { 19 | 20 | const string helpMenu( 21 | "Usage: primesum x [OPTION]...\n" 22 | "Sum the primes below x <= 10^31 using fast implementations of the\n" 23 | "combinatorial prime summing function.\n" 24 | "\n" 25 | "Options:\n" 26 | "\n" 27 | " -d, --deleglise_rivat Sum primes using Deleglise-Rivat algorithm\n" 28 | " -l, --lmo Sum primes using Lagarias-Miller-Odlyzko\n" 29 | " -s[N], --status[=N] Show computation progress 1%, 2%, 3%, ...\n" 30 | " [N] digits after decimal point e.g. N=1, 99.9%\n" 31 | " --test Run various correctness tests and exit\n" 32 | " --time Print the time elapsed in seconds\n" 33 | " -t, --threads= Set the number of threads, 1 <= N <= CPU cores\n" 34 | " -v, --version Print version and license information\n" 35 | " -h, --help Print this help menu\n" 36 | "\n" 37 | "Advanced Deleglise-Rivat options:\n" 38 | "\n" 39 | " -a, --alpha= Tuning factor, 1 <= alpha <= x^(1/6)\n" 40 | " --P2 Only compute the 2nd partial sieve function\n" 41 | " --S1 Only compute the ordinary leaves\n" 42 | " --S2_trivial Only compute the trivial special leaves\n" 43 | " --S2_easy Only compute the easy special leaves\n" 44 | " --S2_hard Only compute the hard special leaves\n" 45 | "\n" 46 | "Examples:\n" 47 | "\n" 48 | " primesum 1e13\n" 49 | " primesum 1e13 --status --threads=4" 50 | ); 51 | 52 | const string versionInfo( 53 | "primesum " PRIMESUM_VERSION ", \n" 54 | "Copyright (C) 2016 - 2019 Kim Walisch\n" 55 | "BSD 2-Clause License " 56 | ); 57 | 58 | } // end namespace 59 | 60 | namespace primesum { 61 | 62 | void help() 63 | { 64 | cout << helpMenu << endl; 65 | exit(1); 66 | } 67 | 68 | void version() 69 | { 70 | cout << versionInfo << endl; 71 | exit(1); 72 | } 73 | 74 | } // namespace 75 | -------------------------------------------------------------------------------- /src/deleglise-rivat/pi_deleglise_rivat_parallel1.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file pi_deleglise_rivat_parallel1.cpp 3 | /// @brief Parallel implementation of the Deleglise-Rivat prime 4 | /// counting algorithm. This implementation is identical to 5 | /// pi_deleglise_rivat_parallel2(x) but uses 128-bit integers. 6 | /// 7 | /// Copyright (C) 2016 Kim Walisch, 8 | /// 9 | /// This file is distributed under the BSD License. See the COPYING 10 | /// file in the top level directory. 11 | /// 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | #include 24 | 25 | using namespace std; 26 | using namespace primesum; 27 | 28 | namespace { 29 | 30 | /// Calculate the contribution of the special leaves. 31 | /// @pre y > 0 && c > 1 32 | /// 33 | int256_t S2(int128_t x, 34 | int64_t y, 35 | int64_t z, 36 | int64_t c, 37 | int threads) 38 | { 39 | int256_t s2_trivial = S2_trivial(x, y, z, c, threads); 40 | int256_t s2_easy = S2_easy(x, y, z, c, threads); 41 | int256_t s2_hard = S2_hard(x, y, z, c, threads); 42 | int256_t s2 = s2_trivial + s2_easy + s2_hard; 43 | 44 | return s2; 45 | } 46 | 47 | } // namespace 48 | 49 | namespace primesum { 50 | 51 | /// Calculate the number of primes below x using the 52 | /// Deleglise-Rivat algorithm. 53 | /// Run time: O(x^(2/3) / (log x)^2) operations, O(x^(1/3) * (log x)^3) space. 54 | /// 55 | int256_t pi_deleglise_rivat_parallel1(int128_t x, int threads) 56 | { 57 | if (x < 2) 58 | return 0; 59 | 60 | double alpha = get_alpha_deleglise_rivat(x); 61 | string limit = get_max_x(alpha); 62 | 63 | if (x > to_int128(limit)) 64 | throw primesum_error("pi(x): x must be <= " + limit); 65 | 66 | int64_t y = (int64_t) (iroot<3>(x) * alpha); 67 | int64_t z = (int64_t) (x / y); 68 | int64_t c = PhiTiny::get_c(y); 69 | 70 | print(""); 71 | print("=== pi_deleglise_rivat_parallel1(x) ==="); 72 | print("pi(x) = S1 + S2 + pi(y) - 1 - P2"); 73 | print(x, y, z, c, alpha, threads); 74 | 75 | int256_t p2 = P2(x, y, threads); 76 | int256_t s1 = S1(x, y, c, threads); 77 | int256_t s2 = S2(x, y, z, c, threads); 78 | int256_t phi = s1 + s2; 79 | int256_t sum = phi + prime_sum_tiny(y) - 1 - p2; 80 | 81 | return sum; 82 | } 83 | 84 | } // namespace 85 | -------------------------------------------------------------------------------- /include/min_max.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file min_max.hpp 3 | /// @brief Template min and max functions that allow comparing 4 | /// different types if both types are integral 5 | /// and sizeof(A) >= sizeof(B). 6 | /// 7 | /// Copyright (C) 2017 Kim Walisch, 8 | /// 9 | /// This file is distributed under the BSD License. See the COPYING 10 | /// file in the top level directory. 11 | /// 12 | 13 | #ifndef MIN_MAX_HPP 14 | #define MIN_MAX_HPP 15 | 16 | #include 17 | 18 | #include 19 | #include 20 | 21 | namespace primesum { 22 | 23 | /// Check if A and B are: 24 | /// 1) Same types 25 | /// 2) Different integral types which satisfy: 26 | /// sizeof(A) > sizeof(B) || 27 | /// (sizeof(A) == sizeof(B) && 28 | /// is_unsigned && is_signed) 29 | /// 30 | template 31 | struct is_comparable 32 | { 33 | enum { 34 | value = std::is_same::value || (( 35 | prt::is_integral::value && 36 | prt::is_integral::value) && ( 37 | sizeof(A) > sizeof(B) || ( 38 | sizeof(A) == sizeof(B) && 39 | prt::is_unsigned::value && 40 | prt::is_signed::value))) 41 | }; 42 | }; 43 | 44 | template 45 | inline B min(A a, B b) 46 | { 47 | static_assert(is_comparable::value, 48 | "min(A, B): Cannot compare types A and B"); 49 | 50 | return (B) std::min(a, (A) b); 51 | } 52 | 53 | template 54 | inline T min(T a, T b, T c) 55 | { 56 | return std::min(a, std::min(b, c)); 57 | } 58 | 59 | template 60 | inline B min(A a, B b, B c) 61 | { 62 | static_assert(is_comparable::value, 63 | "min(A, B, B): Cannot compare types A and B"); 64 | 65 | return (B) std::min(a, (A) std::min(b, c)); 66 | } 67 | 68 | template 69 | inline T max(T a, T b, T c) 70 | { 71 | return std::max(a, std::max(b, c)); 72 | } 73 | 74 | template 75 | inline A max(A a, B b) 76 | { 77 | static_assert(is_comparable::value, 78 | "max(A, B): Cannot compare types A and B"); 79 | 80 | return std::max(a, (A) b); 81 | } 82 | 83 | template 84 | inline A max(A a, B b, B c) 85 | { 86 | static_assert(is_comparable::value, 87 | "max(A, B, B): Cannot compare types A and B"); 88 | 89 | return std::max(a, (A) std::max(b, c)); 90 | } 91 | 92 | } // namespace 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /lib/primesieve/test/nth_prime2.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file nth_prime2.cpp 3 | /// @brief Test nth_prime edge cases 4 | /// 5 | /// Copyright (C) 2017 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | using namespace std; 19 | using namespace primesieve; 20 | 21 | void check(bool OK) 22 | { 23 | cout << " " << (OK ? "OK" : "ERROR") << "\n"; 24 | if (!OK) 25 | exit(1); 26 | } 27 | 28 | int main() 29 | { 30 | uint64_t res; 31 | uint64_t start; 32 | int64_t n; 33 | 34 | n = 1; 35 | start = 1; 36 | res = nth_prime(n, start); 37 | cout << "nth_prime(" << n << ", " << start << ") = " << res; 38 | check(res == 2); 39 | 40 | n = 1; 41 | start = 2; 42 | res = nth_prime(n, start); 43 | cout << "nth_prime(" << n << ", " << start << ") = " << res; 44 | check(res == 3); 45 | 46 | n = -1; 47 | start = 102; 48 | res = nth_prime(n, start); 49 | cout << "nth_prime(" << n << ", " << start << ") = " << res; 50 | check(res == 101); 51 | 52 | n = -1; 53 | start = 101; 54 | res = nth_prime(n, start); 55 | cout << "nth_prime(" << n << ", " << start << ") = " << res; 56 | check(res == 97); 57 | 58 | n = -9592; 59 | start = 100000; 60 | res = nth_prime(n, start); 61 | cout << "nth_prime(" << n << ", " << start << ") = " << res; 62 | check(res == 2); 63 | 64 | n = -9591; 65 | start = 100000; 66 | res = nth_prime(n, start); 67 | cout << "nth_prime(" << n << ", " << start << ") = " << res; 68 | check(res == 3); 69 | 70 | try 71 | { 72 | n = -1; 73 | start = 2; 74 | res = nth_prime(n, start); 75 | cerr << "ERROR: nth_prime(" << n << ", " << start << ") = " << res; 76 | return 1; 77 | } 78 | catch (primesieve_error& e) 79 | { 80 | cout << "OK: " << e.what() << endl; 81 | } 82 | 83 | try 84 | { 85 | n = 1; 86 | start = 18446744073709551557ull; 87 | res = nth_prime(n, start); 88 | cerr << "ERROR: nth_prime(" << n << ", " << start << ") = " << res; 89 | return 1; 90 | } 91 | catch (primesieve_error& e) 92 | { 93 | cout << "OK: " << e.what() << endl; 94 | } 95 | 96 | cout << endl; 97 | cout << "All tests passed successfully!" << endl; 98 | 99 | return 0; 100 | } 101 | -------------------------------------------------------------------------------- /src/S2Status.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file S2Status.cpp 3 | /// @brief Print the status of S2(x, y) in percent. 4 | /// Requires use of --status[=N] command-line flag. 5 | /// 6 | /// Copyright (C) 2018 Kim Walisch, 7 | /// 8 | /// This file is distributed under the BSD License. See the COPYING 9 | /// file in the top level directory. 10 | /// 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | using namespace std; 25 | 26 | namespace primesum { 27 | 28 | S2Status::S2Status(int128_t x) 29 | { 30 | precision_ = get_status_precision(x); 31 | int q = ipow(10, precision_); 32 | epsilon_ = 1.0 / q; 33 | } 34 | 35 | /// Dirty hack! 36 | double S2Status::skewed_percent(int128_t x, int128_t y) 37 | { 38 | double exp = 0.96; 39 | double percent = get_percent(x, y); 40 | double base = exp + percent / (101 / (1 - exp)); 41 | double low = pow(base, 100.0); 42 | double dividend = pow(base, percent) - low; 43 | percent = 100 - (100 * dividend / (1 - low)); 44 | 45 | return percent; 46 | } 47 | 48 | #if defined(_OPENMP) 49 | 50 | bool S2Status::is_print(double time) 51 | { 52 | TryLock lock(lock_); 53 | if (lock.ownsLock()) 54 | { 55 | double old = time_; 56 | return old == 0 || 57 | (time - old) >= is_print_; 58 | } 59 | 60 | return false; 61 | } 62 | 63 | #else 64 | 65 | bool S2Status::is_print(double time) 66 | { 67 | double old = time_; 68 | return old == 0 || 69 | (time - old) >= is_print_; 70 | } 71 | 72 | #endif 73 | 74 | void S2Status::print(int128_t n, int128_t limit) 75 | { 76 | double time = get_time(); 77 | 78 | if (is_print(time)) 79 | { 80 | time_ = time; 81 | 82 | double percent = skewed_percent(n, limit); 83 | double old = percent_; 84 | 85 | if ((percent - old) >= epsilon_) 86 | { 87 | percent_ = percent; 88 | ostringstream status; 89 | ostringstream out; 90 | 91 | status << "Status: " << fixed << setprecision(precision_) << percent << "%"; 92 | size_t spaces = status.str().length(); 93 | string reset_line = "\r" + string(spaces,' ') + "\r"; 94 | out << reset_line << status.str(); 95 | cout << out.str() << flush; 96 | } 97 | } 98 | } 99 | 100 | } //namespace 101 | -------------------------------------------------------------------------------- /lib/primesieve/include/primesieve/StorePrimes.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file StorePrimes.hpp 3 | /// @brief Store primes in a vector. 4 | /// 5 | /// Copyright (C) 2018 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #ifndef STOREPRIMES_HPP 12 | #define STOREPRIMES_HPP 13 | 14 | #include "iterator.hpp" 15 | #include "primesieve_error.hpp" 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | namespace primesieve { 24 | 25 | /// primeCountApprox(x) >= pi(x) 26 | inline std::size_t prime_count_approx(uint64_t start, uint64_t stop) 27 | { 28 | if (start > stop) 29 | return 0; 30 | if (stop <= 10) 31 | return 4; 32 | 33 | // pi(x) <= x / (log(x) - 1.1) + 5, for x >= 4 34 | double x = (double) stop; 35 | double logx = std::log(x); 36 | double div = logx - 1.1; 37 | double pix = (stop - start) / div + 5; 38 | 39 | return (std::size_t) pix; 40 | } 41 | 42 | template 43 | inline void store_primes(uint64_t start, 44 | uint64_t stop, 45 | T& primes) 46 | { 47 | if (start > 0) 48 | start--; 49 | if (~stop == 0) 50 | stop--; 51 | 52 | if (start < stop) 53 | { 54 | using V = typename T::value_type; 55 | std::size_t size = primes.size() + prime_count_approx(start, stop); 56 | primes.reserve(size); 57 | 58 | primesieve::iterator it(start, stop); 59 | uint64_t prime = it.next_prime(); 60 | for (; prime <= stop; prime = it.next_prime()) 61 | primes.push_back((V) prime); 62 | } 63 | } 64 | 65 | template 66 | inline void store_n_primes(uint64_t n, 67 | uint64_t start, 68 | T& primes) 69 | { 70 | if (n == 0) 71 | return; 72 | if (start > 0) 73 | start--; 74 | 75 | std::size_t size = primes.size() + (std::size_t) n; 76 | primes.reserve(size); 77 | using V = typename T::value_type; 78 | 79 | double x = (double) start; 80 | x = std::max(10.0, x); 81 | uint64_t logx = (uint64_t) std::log(x); 82 | uint64_t dist = n * (logx + 1); 83 | uint64_t stop = start + dist; 84 | 85 | primesieve::iterator it(start, stop); 86 | uint64_t prime = it.next_prime(); 87 | for (; n > 0; n--, prime = it.next_prime()) 88 | primes.push_back((V) prime); 89 | 90 | if (~prime == 0) 91 | throw primesieve_error("cannot generate primes > 2^64"); 92 | } 93 | 94 | } // namespace 95 | 96 | #endif 97 | -------------------------------------------------------------------------------- /include/BitSieve.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file BitSieve.hpp 3 | /// @brief The BitSieve class is a bit array for prime sieving 4 | /// that packs 128 numbers into 8 bytes i.e. each bit 5 | /// corresponds to an odd integer. 6 | /// 7 | /// Copyright (C) 2017 Kim Walisch, 8 | /// 9 | /// This file is distributed under the BSD License. See the COPYING 10 | /// file in the top level directory. 11 | /// 12 | 13 | #ifndef BITSIEVE_HPP 14 | #define BITSIEVE_HPP 15 | 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | namespace primesum { 25 | 26 | class BitSieve 27 | { 28 | public: 29 | BitSieve(std::size_t size); 30 | 31 | /// Pre-sieve the multiples >= low of the first c primes. 32 | /// @warning Also removes the first c primes. 33 | /// @pre c < 10 34 | /// 35 | void pre_sieve(uint64_t c, 36 | uint64_t low); 37 | 38 | /// Compute the sum of the unsieved numbers inside [start, stop] 39 | int128_t sum(uint64_t low, 40 | uint64_t start, 41 | uint64_t stop) const; 42 | 43 | /// Sum the unsieved numbers inside [start, stop]. 44 | /// As an optimization this method counts either forwards or 45 | /// backwards depending on what's faster. 46 | /// 47 | int128_t sum(uint64_t start, 48 | uint64_t stop, 49 | uint64_t low, 50 | uint64_t high, 51 | int128_t sum_0_start, 52 | int128_t sum_low_high) const 53 | { 54 | if (start > stop) 55 | return 0; 56 | 57 | if (stop - start < (high - low) - stop) 58 | return sum(low, start, stop); 59 | else 60 | return sum_low_high - sum_0_start - sum(low, stop + 1, (high - 1) - low); 61 | } 62 | 63 | void set(uint64_t pos) 64 | { 65 | assert(pos < size_); 66 | assert(pos % 2 == 0); 67 | sieve_[pos >> 7] |= set_bit_[pos & 127]; 68 | } 69 | 70 | void unset(uint64_t pos) 71 | { 72 | assert(pos < size_); 73 | assert(pos % 2 == 0); 74 | sieve_[pos >> 7] &= ~set_bit_[pos & 127]; 75 | } 76 | 77 | bool operator[](uint64_t pos) const 78 | { 79 | assert(pos < size_); 80 | assert(pos % 2 == 0); 81 | return (sieve_[pos >> 7] & set_bit_[pos & 127]) != 0; 82 | } 83 | 84 | std::size_t size() const 85 | { 86 | return size_; 87 | } 88 | 89 | private: 90 | static const std::array set_bit_; 91 | std::vector sieve_; 92 | std::size_t size_; 93 | }; 94 | 95 | } // namespace 96 | 97 | #endif 98 | -------------------------------------------------------------------------------- /lib/primesieve/test/calculator.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file calculator.cpp 3 | /// @brief test program for calculator.hpp 4 | /// 5 | /// Copyright (C) 2018 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define STR1(s) #s 20 | #define TOSTRING(s) STR1(s) 21 | 22 | /// Test expressions 23 | #define EXPR1 45345 + 0 + 0xdf234 - 1000 % 7 24 | #define EXPR2 (0 + 0xdf234 - 1000) * 3 / 2 % 999 25 | #define EXPR3 1 << 16 26 | #define EXPR4 (0 + ~(0xdf234 & 1000) * 3) / -2 27 | #define EXPR5 ((1 << 16) + (1 << 16)) >> 0X5 28 | #define EXPR6 1+(((2+(3+(4+(5+6)* -7)/8))&127)<<1) *-3 29 | #define EXPR7 100000000 + (1 << 16) + (1 << 16) 30 | #define EXPR8 1-~1 31 | #define EXPR9 1- ~1*0xfFa/( ((((8+(6|(4 *(2*(1)*3)*5)|7)+9))))) 32 | #define EXPRa ((12|13)<<8)>>((1|127) %10&(31+7)) 33 | #define EXPRb ((((((((((5)))))) ))))- ((((((((( 6))))))))) 34 | 35 | using namespace std; 36 | 37 | template 38 | void compare(T result, const string& str) 39 | { 40 | T r = calculator::eval(str); 41 | cout << (r == result ? "Correct: " : "Error: "); 42 | cout << setw(50) << str << " = " << setw(10) << r; 43 | if (r != result) 44 | { 45 | cout << " != " << result; 46 | exit(1); 47 | } 48 | cout << endl; 49 | } 50 | 51 | int main() 52 | { 53 | cout.setf(ios::left); 54 | 55 | compare(EXPR1, TOSTRING(EXPR1)); 56 | compare(EXPR2, TOSTRING(EXPR2)); 57 | compare(EXPR3, TOSTRING(EXPR3)); 58 | compare(EXPR4, TOSTRING(EXPR4)); 59 | compare(EXPR5, TOSTRING(EXPR5)); 60 | compare(EXPR6, TOSTRING(EXPR6)); 61 | compare(EXPR7, TOSTRING(EXPR7)); 62 | compare(EXPR8, TOSTRING(EXPR8)); 63 | compare(EXPR9, TOSTRING(EXPR9)); 64 | compare(EXPRa, TOSTRING(EXPRa)); 65 | compare(EXPRb, TOSTRING(EXPRb)); 66 | 67 | compare(calculator::eval("1e18"), "1000000000000000000"); 68 | compare(calculator::eval("3e18"), "3000000000000000000"); 69 | compare(calculator::eval("10^0"), "1"); 70 | compare(calculator::eval("10^1"), "10"); 71 | compare(calculator::eval("37^2"), "1369"); 72 | compare(calculator::eval("101^3"), "1030301"); 73 | compare(calculator::eval("3^30"), "205891132094649"); 74 | compare(calculator::eval("2^62-1"), "4611686018427387903"); 75 | 76 | cout << "All tests passed successfully!" << endl; 77 | 78 | return 0; 79 | } 80 | -------------------------------------------------------------------------------- /include/BinaryIndexedTree.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file BinaryIndexedTree.hpp 3 | /// @brief The BinaryIndexedTree class is a binary indexed 4 | /// tree (a.k.a. Fenwick tree) that keeps track of 5 | /// the number of unsieved elements (sieve[i] = 1) 6 | /// in the sieve array. Whenever an element is 7 | /// crossed-off for the first time in the sieve array 8 | /// we update the binary indexed tree. Both updating 9 | /// and querying the binary indexed tree O(log n) 10 | /// operations. 11 | /// 12 | /// The implementation is based on the paper: 13 | /// 14 | /// Tomás Oliveira e Silva, Computing pi(x): the combinatorial method, 15 | /// Revista do DETUA, vol. 4, no. 6, March 2006, pp. 767-768. 16 | /// http://sweet.ua.pt/tos/bib/5.4.pdf 17 | /// 18 | /// Copyright (C) 2018 Kim Walisch, 19 | /// 20 | /// This file is distributed under the BSD License. See the COPYING 21 | /// file in the top level directory. 22 | /// 23 | 24 | #ifndef BINARYINDEXEDTREE_HPP 25 | #define BINARYINDEXEDTREE_HPP 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | namespace primesum { 32 | 33 | class BinaryIndexedTree 34 | { 35 | public: 36 | /// Initialize binary indexed tree from sieve array 37 | template 38 | void init(const T& sieve, int64_t low) 39 | { 40 | size_ = sieve.size() / 2; 41 | tree_.resize(size_); 42 | 43 | for (int64_t i = 0; i < size_; i++) 44 | { 45 | int64_t i2 = i * 2; 46 | tree_[i] = (low + i2) * sieve[i2]; 47 | int64_t k = (i + 1) & ~i; 48 | for (int64_t j = i; k >>= 1; j &= j - 1) 49 | tree_[i] += tree_[j - 1]; 50 | } 51 | } 52 | 53 | /// Update (decrement by 1) the counters after 54 | /// that an element has been crossed-off for the 55 | /// first time in the sieve array. 56 | /// Runtime: O(log N) 57 | /// 58 | void update(int64_t n, int64_t low) 59 | { 60 | int64_t pos = n - low; 61 | pos >>= 1; 62 | do { 63 | tree_[pos] -= n; 64 | pos |= pos + 1; 65 | } 66 | while (pos < size_); 67 | } 68 | 69 | /// Get the number of unsieved elements <= pos 70 | /// in the current segment (sieve array). 71 | /// Runtime: O(log N) 72 | /// 73 | int128_t sum(int64_t pos) const 74 | { 75 | pos >>= 1; 76 | int128_t sum = tree_[pos++]; 77 | while ((pos &= pos - 1) != 0) 78 | sum += tree_[pos - 1]; 79 | return sum; 80 | } 81 | 82 | private: 83 | std::vector tree_; 84 | int64_t size_ = 0; 85 | }; 86 | 87 | } // namespace 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /src/phi_sum.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file phi_sum.cpp 3 | /// 4 | /// Copyright (C) 2017 Kim Walisch, 5 | /// 6 | /// This file is distributed under the BSD License. See the COPYING 7 | /// file in the top level directory. 8 | /// 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | 20 | using namespace std; 21 | using namespace primesum; 22 | 23 | namespace { 24 | 25 | const array small_primes_ = { 0, 2, 3, 5, 7, 11, 13, 17, 19, 23 }; 26 | 27 | template 28 | int128_t phi_sum128(int64_t x, 29 | int64_t a, 30 | Primes&& primes) 31 | { 32 | int128_t sum = 0; 33 | 34 | for (; a > 0; a--) 35 | { 36 | if (x <= primes[a]) 37 | return sum + SIGN; 38 | 39 | int64_t x2 = fast_div(x, primes[a]); 40 | sum += phi_sum128<-SIGN>(x2, a - 1, primes) * primes[a]; 41 | } 42 | 43 | int128_t n = x; 44 | int128_t fx = (n * (n + 1)) >> 1; 45 | sum += fx * SIGN; 46 | 47 | return sum; 48 | } 49 | 50 | template 51 | int256_t phi_sum256(int128_t x, 52 | int64_t a, 53 | Primes&& primes) 54 | { 55 | int256_t sum = 0; 56 | 57 | for (; a > 0; a--) 58 | { 59 | if (x <= primes[a]) 60 | return sum + SIGN; 61 | 62 | int128_t x2 = fast_div(x, primes[a]); 63 | int256_t phi_sum; 64 | 65 | if (x2 <= numeric_limits::max()) 66 | phi_sum = phi_sum128<-SIGN>((int64_t) x2, a - 1, primes); 67 | else 68 | phi_sum = phi_sum256<-SIGN>(x2, a - 1, primes); 69 | 70 | sum += phi_sum * primes[a]; 71 | } 72 | 73 | int256_t n = x; 74 | int256_t fx = (n * (n + 1)) >> 1; 75 | sum += fx * SIGN; 76 | 77 | return sum; 78 | } 79 | 80 | } // namespace 81 | 82 | namespace primesum { 83 | 84 | int128_t phi_sum(int64_t x, int64_t a) 85 | { 86 | if (x < 1) 87 | return 0; 88 | 89 | if (a < 10) 90 | return phi_sum128<1>(x, a, small_primes_); 91 | else 92 | return phi_sum128<1>(x, a, generate_n_primes(a)); 93 | } 94 | 95 | int256_t phi_sum(int128_t x, int64_t a) 96 | { 97 | if (x <= numeric_limits::max()) 98 | return phi_sum((int64_t) x, a); 99 | 100 | if (a < 10) 101 | return phi_sum256<1>(x, a, small_primes_); 102 | else 103 | return phi_sum256<1>(x, a, generate_n_primes(a)); 104 | } 105 | 106 | } // namespace 107 | -------------------------------------------------------------------------------- /lib/primesieve/include/primesieve/config.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file config.hpp 3 | /// @brief primesieve compile time constants. 4 | /// 5 | /// Copyright (C) 2020 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #ifndef CONFIG_HPP 12 | #define CONFIG_HPP 13 | 14 | #include 15 | 16 | namespace { 17 | namespace config { 18 | 19 | enum { 20 | /// Number of sieving primes per Bucket in EratSmall, EratMedium 21 | /// and EratBig objects, affects performance by about 3%. 22 | /// @pre BUCKET_BYTES must be a power of 2. 23 | /// 24 | /// - For x86-64 CPUs after 2010 use 8192 25 | /// - For x86-64 CPUs before 2010 use 4096 26 | /// - For PowerPC G4 CPUs 2003 use 2048 27 | /// 28 | BUCKET_BYTES = 1 << 13, 29 | 30 | /// The MemoryPool allocates at most MAX_ALLOC_BYTES of new 31 | /// memory when it runs out of buckets. 32 | /// 33 | MAX_ALLOC_BYTES = (1 << 20) * 16, 34 | 35 | /// iterator::prev_prime() caches at least MIN_CACHE_ITERATOR 36 | /// bytes of primes. Larger is usually faster but also 37 | /// requires more memory. 38 | /// 39 | MIN_CACHE_ITERATOR = (1 << 20) * 8, 40 | 41 | /// iterator::prev_prime() maximum cache size in bytes, used 42 | /// if pi(sqrt(n)) * 8 bytes > MAX_CACHE_ITERATOR. 43 | /// 44 | MAX_CACHE_ITERATOR = (1 << 20) * 1024 45 | }; 46 | 47 | /// Sieving primes <= (sieveSize in bytes * FACTOR_ERATSMALL) 48 | /// are processed in EratSmall. The ideal value for 49 | /// FACTOR_ERATSMALL has been determined experimentally by 50 | /// running benchmarks near 10^10. 51 | /// @pre FACTOR_ERATSMALL >= 0 && <= 3 52 | /// 53 | const double FACTOR_ERATSMALL = 0.175; 54 | 55 | /// Sieving primes > (sieveSize in bytes * FACTOR_ERATSMALL) 56 | /// and <= (sieveSize in bytes * FACTOR_ERATMEDIUM) 57 | /// are processed in EratMedium. The ideal value for 58 | /// FACTOR_ERATMEDIUM has been determined experimentally by 59 | /// running benchmarks near 10^14. 60 | /// 61 | /// @pre FACTOR_ERATMEDIUM >= 0 && <= 9 62 | /// FACTOR_ERATMEDIUM * max(sieveSize) / 30 * 6 + 6 <= max(multipleIndex) 63 | /// FACTOR_ERATMEDIUM * 2^22 / 30 * 6 + 6 <= 2^23 - 1 64 | /// FACTOR_ERATMEDIUM <= ((2^23 - 7) * 30) / (2^22 * 6) 65 | /// FACTOR_ERATMEDIUM <= 9.999991655 66 | /// 67 | const double FACTOR_ERATMEDIUM = 5.0; 68 | 69 | /// Each thread sieves at least a distance of MIN_THREAD_DISTANCE 70 | /// in order to reduce the initialization overhead. 71 | /// @pre MIN_THREAD_DISTANCE >= 100 72 | /// 73 | const uint64_t MIN_THREAD_DISTANCE = (uint64_t) 1e7; 74 | 75 | } // namespace config 76 | } // namespace 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /lib/primesieve/test/next_prime2.c: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file next_prime2.c 3 | /// @brief Test primesieve_next_prime(). 4 | /// 5 | /// Copyright (C) 2017 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | void check(int OK) 19 | { 20 | if (OK) 21 | printf(" OK\n"); 22 | else 23 | { 24 | printf(" ERROR\n"); 25 | exit(1); 26 | } 27 | } 28 | 29 | int main() 30 | { 31 | size_t size = 0; 32 | uint64_t* primes = (uint64_t*) primesieve_generate_primes(0, 100000, &size, UINT64_PRIMES); 33 | primesieve_iterator it; 34 | primesieve_init(&it); 35 | 36 | uint64_t i; 37 | uint64_t old; 38 | uint64_t prime; 39 | uint64_t max_prime = primes[size - 1]; 40 | uint64_t sum = 0; 41 | 42 | for (i = 0; i < size - 1; i++) 43 | { 44 | primesieve_skipto(&it, primes[i] - 1, max_prime); 45 | prime = primesieve_next_prime(&it); 46 | printf("next_prime(%" PRIu64 ") = %" PRIu64, primes[i] - 1, prime); 47 | check(prime == primes[i]); 48 | 49 | primesieve_skipto(&it, primes[i], max_prime); 50 | prime = primesieve_next_prime(&it); 51 | printf("next_prime(%" PRIu64 ") = %" PRIu64, primes[i], prime); 52 | check(prime == primes[i + 1]); 53 | } 54 | 55 | primesieve_skipto(&it, 0, max_prime); 56 | 57 | // iterate over the primes below 10^9 58 | while ((prime = primesieve_next_prime(&it)) < 1000000000) 59 | sum += prime; 60 | 61 | printf("Sum of the primes below 10^9 = %" PRIu64, sum); 62 | check(sum == 24739512092254535ull); 63 | 64 | primesieve_skipto(&it, max_prime / 2, max_prime); 65 | prime = primesieve_next_prime(&it); 66 | 67 | while (prime <= max_prime) 68 | prime = primesieve_next_prime(&it); 69 | 70 | for (i = 1; i < 1000; i++) 71 | { 72 | old = prime; 73 | prime = primesieve_prev_prime(&it); 74 | printf("prev_prime(%" PRIu64 ") = %" PRIu64, old, prime); 75 | check(prime == primes[size - i]); 76 | } 77 | 78 | primesieve_skipto(&it, 18446744073709551556ull, 0); 79 | prime = primesieve_next_prime(&it); 80 | printf("next_prime(18446744073709551556) = %" PRIu64, prime); 81 | check(prime == 18446744073709551557ull); 82 | 83 | for (i = 0; i < 100; i++) 84 | { 85 | old = prime; 86 | prime = primesieve_next_prime(&it); 87 | printf("next_prime(%" PRIu64 ") = %" PRIu64, old, prime); 88 | check(prime == 18446744073709551615ull); 89 | } 90 | 91 | primesieve_free(primes); 92 | primesieve_free_iterator(&it); 93 | 94 | printf("\n"); 95 | printf("All tests passed successfully!\n"); 96 | 97 | return 0; 98 | } 99 | -------------------------------------------------------------------------------- /lib/primesieve/src/SievingPrimes.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file SievingPrimes.cpp 3 | /// Generates the sieving primes up n^(1/2). 4 | /// 5 | /// Copyright (C) 2019 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | namespace primesieve { 22 | 23 | SievingPrimes::SievingPrimes(Erat* erat, PreSieve& preSieve) 24 | { 25 | init(erat, preSieve); 26 | } 27 | 28 | void SievingPrimes::init(Erat* erat, PreSieve& preSieve) 29 | { 30 | Erat::init(preSieve.getMaxPrime() + 1, 31 | isqrt(erat->getStop()), 32 | erat->getSieveSize(), 33 | preSieve); 34 | 35 | tinySieve(); 36 | } 37 | 38 | /// Sieve up to n^(1/4) 39 | void SievingPrimes::tinySieve() 40 | { 41 | uint64_t n = isqrt(stop_); 42 | tinySieve_.resize(n + 1, true); 43 | 44 | for (uint64_t i = 3; i * i <= n; i += 2) 45 | if (tinySieve_[i]) 46 | for (uint64_t j = i * i; j <= n; j += i * 2) 47 | tinySieve_[j] = false; 48 | 49 | tinyIdx_ = start_; 50 | tinyIdx_ += ~tinyIdx_ & 1; 51 | } 52 | 53 | void SievingPrimes::fill() 54 | { 55 | if (sieveIdx_ >= sieveSize_) 56 | if (!sieveSegment()) 57 | return; 58 | 59 | uint64_t num = 0; 60 | uint64_t maxSize = primes_.size(); 61 | assert(maxSize >= 64); 62 | 63 | // Fill the buffer with at least (maxSize - 64) primes. 64 | // Each loop iteration can generate up to 64 primes 65 | // so we have to stop generating primes once there is 66 | // not enough space for 64 more primes. 67 | do 68 | { 69 | uint64_t bits = littleendian_cast(&sieve_[sieveIdx_]); 70 | 71 | for (; bits != 0; bits &= bits - 1) 72 | primes_[num++] = nextPrime(bits, low_); 73 | 74 | low_ += 8 * 30; 75 | sieveIdx_ += 8; 76 | } 77 | while (num <= maxSize - 64 && 78 | sieveIdx_ < sieveSize_); 79 | 80 | i_ = 0; 81 | size_ = num; 82 | } 83 | 84 | bool SievingPrimes::sieveSegment() 85 | { 86 | if (hasNextSegment()) 87 | { 88 | sieveIdx_ = 0; 89 | uint64_t high = segmentHigh_; 90 | 91 | for (uint64_t& i = tinyIdx_; i * i <= high; i += 2) 92 | if (tinySieve_[i]) 93 | addSievingPrime(i); 94 | 95 | Erat::sieveSegment(); 96 | return true; 97 | } 98 | else 99 | { 100 | i_ = 0; 101 | size_ = 1; 102 | primes_[0] = ~0ull; 103 | return false; 104 | } 105 | } 106 | 107 | } // namespace 108 | -------------------------------------------------------------------------------- /include/imath.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file imath.hpp 3 | /// @brief Integer math functions used in primesum. 4 | /// 5 | /// Copyright (C) 2018 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #ifndef IMATH_HPP 12 | #define IMATH_HPP 13 | 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | namespace primesum { 24 | 25 | inline int64_t isquare(int64_t x) 26 | { 27 | return x * x; 28 | } 29 | 30 | template 31 | inline A ceil_div(A a, B b) 32 | { 33 | assert(b > 0); 34 | return (A) ((a + b - 1) / b); 35 | } 36 | 37 | template 38 | inline T number_of_bits(T) 39 | { 40 | return (T) std::numeric_limits::digits; 41 | } 42 | 43 | template 44 | inline T next_power_of_2(T x) 45 | { 46 | if (x == 0) 47 | return 1; 48 | 49 | x--; 50 | for (T i = 1; i < number_of_bits(x); i += i) 51 | x |= (x >> i); 52 | 53 | return ++x; 54 | } 55 | 56 | template 57 | inline T prev_power_of_2(T x) 58 | { 59 | for (T i = 1; i < number_of_bits(x); i += i) 60 | x |= (x >> i); 61 | 62 | return x - (x >> 1); 63 | } 64 | 65 | template 66 | inline int ilog(T x) 67 | { 68 | return (int) std::log((double) x); 69 | } 70 | 71 | template 72 | inline T ipow(T x, int n) 73 | { 74 | T r = 1; 75 | for (int i = 0; i < n; i++) 76 | r *= x; 77 | 78 | return r; 79 | } 80 | 81 | /// Integer nth root 82 | template 83 | inline T iroot(T x) 84 | { 85 | if (N == 0) 86 | return 0; 87 | 88 | T r = (T) std::pow((double) x, 1.0 / N); 89 | 90 | // fix root too large 91 | for (; r > 0; r--) 92 | { 93 | if (ipow(r, N - 1) <= x / r) 94 | break; 95 | } 96 | 97 | // fix root too small 98 | while (ipow(r + 1, N - 1) <= x / (r + 1)) 99 | r += 1; 100 | 101 | return r; 102 | } 103 | 104 | template 105 | inline T2 in_between(T1 min, T2 x, T3 max) 106 | { 107 | if (x < min) 108 | return (T2) min; 109 | if (x > max) 110 | return (T2) max; 111 | 112 | return x; 113 | } 114 | 115 | /// Count the number of primes <= x using binary search. 116 | /// @pre primes[1] = 2, primes[3] = 3, ... 117 | /// @pre x <= primes.back() 118 | /// 119 | template 120 | inline T2 pi_bsearch(const std::vector& primes, T2 x) 121 | { 122 | assert(primes.size() < 2 || primes[1] == 2); 123 | auto start = primes.begin() + 1; 124 | return (T2) (std::upper_bound(start, primes.end(), x) - start); 125 | } 126 | 127 | } // namespace 128 | 129 | #endif 130 | -------------------------------------------------------------------------------- /lib/primesieve/test/cpu_info.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file cpu_info.cpp 3 | /// @brief Detect the CPUs' cache sizes 4 | /// 5 | /// Copyright (C) 2018 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #include 12 | #include 13 | 14 | using namespace std; 15 | using namespace primesieve; 16 | 17 | int main() 18 | { 19 | const CpuInfo cpu; 20 | string error = cpu.getError(); 21 | 22 | if (!error.empty()) 23 | { 24 | cerr << "Error: " << error << endl; 25 | return 1; 26 | } 27 | 28 | if (!cpu.hasCpuCores() && 29 | cpu.cpuCores() > 0) 30 | { 31 | cerr << "Invalid CPU cores: " << cpu.cpuCores() << endl; 32 | return 1; 33 | } 34 | 35 | if (!cpu.hasCpuThreads() && 36 | cpu.cpuThreads() > 0) 37 | { 38 | cerr << "Invalid CPU threads: " << cpu.cpuThreads() << endl; 39 | return 1; 40 | } 41 | 42 | if (!cpu.hasL1Cache() && 43 | cpu.l1CacheSize() > 0) 44 | { 45 | cerr << "Invalid L1 cache size: " << cpu.l1CacheSize() << endl; 46 | return 1; 47 | } 48 | 49 | if (!cpu.hasL2Cache() && 50 | cpu.l2CacheSize() > 0) 51 | { 52 | cerr << "Invalid L2 cache size: " << cpu.l2CacheSize() << endl; 53 | return 1; 54 | } 55 | 56 | if (!cpu.hasL3Cache() && 57 | cpu.l3CacheSize() > 0) 58 | { 59 | cerr << "Invalid L3 cache size: " << cpu.l3CacheSize() << endl; 60 | return 1; 61 | } 62 | 63 | if (!cpu.hasL1Sharing() && 64 | cpu.l1Sharing() > 0) 65 | { 66 | cerr << "Invalid L1 cache sharing: " << cpu.l1Sharing() << endl; 67 | return 1; 68 | } 69 | 70 | if (!cpu.hasL2Sharing() && 71 | cpu.l2Sharing() > 0) 72 | { 73 | cerr << "Invalid L2 cache sharing: " << cpu.l2Sharing() << endl; 74 | return 1; 75 | } 76 | 77 | if (!cpu.hasL3Sharing() && 78 | cpu.l3Sharing() > 0) 79 | { 80 | cerr << "Invalid L3 cache sharing: " << cpu.l3Sharing() << endl; 81 | return 1; 82 | } 83 | 84 | if (!cpu.hasThreadsPerCore() && 85 | cpu.threadsPerCore() > 0) 86 | { 87 | cerr << "Invalid threads per CPU core: " << cpu.threadsPerCore() << endl; 88 | return 1; 89 | } 90 | 91 | if (cpu.hasCpuName()) 92 | cout << cpu.cpuName() << endl; 93 | 94 | cout << "L1 cache size: " << (cpu.l1CacheSize() >> 10) << " KiB" << endl; 95 | cout << "L2 cache size: " << (cpu.l2CacheSize() >> 10) << " KiB" << endl; 96 | cout << "L3 cache size: " << (cpu.l3CacheSize() >> 10) << " KiB" << endl; 97 | 98 | if (cpu.hasL2Cache()) 99 | { 100 | if (cpu.hasPrivateL2Cache()) 101 | cout << "L2 cache: private" << endl; 102 | else 103 | cout << "L2 cache: shared" << endl; 104 | } 105 | 106 | return 0; 107 | } 108 | -------------------------------------------------------------------------------- /lib/primesieve/test/prev_prime2.c: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file prev_prime2.cpp 3 | /// @brief Test primesieve_prev_prime(). 4 | /// 5 | /// Copyright (C) 2018 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | void check(int OK) 19 | { 20 | if (OK) 21 | printf(" OK\n"); 22 | else 23 | { 24 | printf(" ERROR\n"); 25 | exit(1); 26 | } 27 | } 28 | 29 | int main() 30 | { 31 | size_t size = 0; 32 | uint64_t* primes = (uint64_t*) primesieve_generate_primes(0, 100000, &size, UINT64_PRIMES); 33 | primesieve_iterator it; 34 | primesieve_init(&it); 35 | 36 | uint64_t i; 37 | uint64_t prime; 38 | uint64_t sum = 0; 39 | uint64_t old, p1, p2; 40 | 41 | for (i = size - 1; i > 0; i--) 42 | { 43 | primesieve_skipto(&it, primes[i] + 1, 0); 44 | prime = primesieve_prev_prime(&it); 45 | printf("prev_prime(%" PRIu64 ") = %" PRIu64, primes[i] + 1, prime); 46 | check(prime == primes[i]); 47 | 48 | primesieve_skipto(&it, primes[i], 0); 49 | prime = primesieve_prev_prime(&it); 50 | printf("prev_prime(%" PRIu64 ") = %" PRIu64, primes[i], prime); 51 | check(prime == primes[i - 1]); 52 | } 53 | 54 | primesieve_skipto(&it, 100000000, 0); 55 | 56 | // iterate over the primes below 10^8 57 | while ((prime = primesieve_prev_prime(&it)) > 0) 58 | sum += prime; 59 | 60 | printf("Sum of the primes below 10^8 = %" PRIu64, sum); 61 | check(sum == 279209790387276ull); 62 | 63 | for (i = 0; i < 1000; i++) 64 | { 65 | prime = primesieve_prev_prime(&it); 66 | printf("prev_prime(0) = %" PRIu64, prime); 67 | check(prime == 0); 68 | } 69 | 70 | for (i = 0; i < 1000; i++) 71 | { 72 | old = prime; 73 | prime = primesieve_next_prime(&it); 74 | printf("next_prime(%" PRIu64 ") = %" PRIu64, old, prime); 75 | check(prime == primes[i]); 76 | } 77 | 78 | primesieve_skipto(&it, primes[size - 1], 0); 79 | 80 | for (i = 0; i < 1000; i++) 81 | { 82 | p1 = primes[size - (i + 1)]; 83 | p2 = primes[size - (i + 2)]; 84 | prime = primesieve_prev_prime(&it); 85 | printf("prev_prime(%" PRIu64 ") = %" PRIu64, p1, prime); 86 | check(prime == p2); 87 | } 88 | 89 | for (i = 0; i < 1000; i++) 90 | { 91 | old = prime; 92 | p1 = size - 1000 + i; 93 | prime = primesieve_next_prime(&it); 94 | printf("next_prime(%" PRIu64 ") = %" PRIu64, old, prime); 95 | check(prime == primes[p1]); 96 | } 97 | 98 | primesieve_free(primes); 99 | primesieve_free_iterator(&it); 100 | 101 | printf("\n"); 102 | printf("All tests passed successfully!\n"); 103 | 104 | return 0; 105 | } 106 | -------------------------------------------------------------------------------- /lib/primesieve/src/app/help.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file help.cpp 3 | /// @brief help() and version() functions of the primesieve 4 | /// console application. 5 | /// 6 | /// Copyright (C) 2021 Kim Walisch, 7 | /// 8 | /// This file is distributed under the BSD License. See the COPYING 9 | /// file in the top level directory. 10 | /// 11 | 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | using namespace std; 19 | 20 | namespace { 21 | 22 | const string helpMenu 23 | { 24 | "Usage: primesieve [START] STOP [OPTION]...\n" 25 | "Generate the primes and/or prime k-tuplets inside [START, STOP]\n" 26 | "(< 2^64) using the segmented sieve of Eratosthenes.\n" 27 | "\n" 28 | "Options:\n" 29 | " -c, --count[=NUM+] Count primes and/or prime k-tuplets, NUM <= 6.\n" 30 | " Count primes: -c or --count (default option),\n" 31 | " count twin primes: -c2 or --count=2,\n" 32 | " count prime triplets: -c3 or --count=3, ...\n" 33 | " --cpu-info Print CPU information (cache sizes).\n" 34 | " -d, --dist=DIST Sieve the interval [START, START + DIST].\n" 35 | " -h, --help Print this help menu.\n" 36 | " -n, --nth-prime Find the nth prime.\n" 37 | " primesieve 100 -n: finds the 100th prime,\n" 38 | " primesieve 2 100 -n: finds the 2nd prime > 100.\n" 39 | " --no-status Turn off the progressing status.\n" 40 | " -p, --print[=NUM] Print primes or prime k-tuplets, NUM <= 6.\n" 41 | " Print primes: -p or --print,\n" 42 | " print twin primes: -p2 or --print=2,\n" 43 | " print prime triplets: -p3 or --print=3, ...\n" 44 | " -q, --quiet Quiet mode, prints less output.\n" 45 | " -s, --size=SIZE Set the sieve size in KiB, SIZE <= 4096.\n" 46 | " By default primesieve uses a sieve size that\n" 47 | " matches your CPU's L1 cache size or half of\n" 48 | " your CPU's L2 cache size (per core).\n" 49 | " --test Run various sieving tests.\n" 50 | " -t, --threads=NUM Set the number of threads, NUM <= CPU cores.\n" 51 | " Default setting: use all available CPU cores.\n" 52 | " --time Print the time elapsed in seconds.\n" 53 | " -v, --version Print version and license information." 54 | }; 55 | 56 | } // namespace 57 | 58 | void help(int exitCode) 59 | { 60 | cout << helpMenu << endl; 61 | exit(exitCode); 62 | } 63 | 64 | void version() 65 | { 66 | cout << "primesieve " << primesieve::primesieve_version(); 67 | cout << ", " << endl; 68 | cout << "Copyright (C) 2010 - 2021 Kim Walisch" << endl; 69 | cout << "BSD 2-Clause License " << endl; 70 | exit(0); 71 | } 72 | -------------------------------------------------------------------------------- /lib/primesieve/test/prev_prime1.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file prev_prime1.cpp 3 | /// @brief Test prev_prime() of primesieve::iterator. 4 | /// 5 | /// Copyright (C) 2017 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | using namespace std; 20 | 21 | void check(bool OK) 22 | { 23 | cout << " " << (OK ? "OK" : "ERROR") << "\n"; 24 | if (!OK) 25 | exit(1); 26 | } 27 | 28 | int main() 29 | { 30 | vector primes; 31 | primesieve::generate_primes(100000, &primes); 32 | primesieve::iterator it; 33 | uint64_t back = primes.size() - 1; 34 | uint64_t prime; 35 | 36 | for (uint64_t i = back; i > 0; i--) 37 | { 38 | it.skipto(primes[i] + 1); 39 | prime = it.prev_prime(); 40 | cout << "prev_prime(" << primes[i] + 1 << ") = " << prime; 41 | check(prime == primes[i]); 42 | 43 | it.skipto(primes[i]); 44 | prime = it.prev_prime(); 45 | cout << "prev_prime(" << primes[i] << ") = " << prime; 46 | check(prime == primes[i - 1]); 47 | } 48 | 49 | it.skipto(100000000); 50 | prime = it.prev_prime(); 51 | uint64_t sum = 0; 52 | 53 | // iterate over the primes below 10^8 54 | for (; prime > 0; prime = it.prev_prime()) 55 | sum += prime; 56 | 57 | cout << "Sum of the primes below 10^8 = " << sum; 58 | check(sum == 279209790387276ull); 59 | 60 | for (uint64_t i = 0; i < 1000; i++) 61 | { 62 | prime = it.prev_prime(); 63 | cout << "prev_prime(0) = " << prime; 64 | check(prime == 0); 65 | } 66 | 67 | for (uint64_t i = 0; i < 1000; i++) 68 | { 69 | uint64_t old = prime; 70 | prime = it.next_prime(); 71 | cout << "next_prime(" << old << ") = " << prime; 72 | check(prime == primes[i]); 73 | } 74 | 75 | it.skipto(primes.back()); 76 | 77 | for (uint64_t i = 0; i < 1000; i++) 78 | { 79 | prime = it.prev_prime(); 80 | uint64_t p1 = primes.size() - (i + 1); 81 | uint64_t p2 = primes.size() - (i + 2); 82 | cout << "prev_prime(" << primes[p1] << ") = " << prime; 83 | check(prime == primes[p2]); 84 | } 85 | 86 | for (uint64_t i = 0; i < 1000; i++) 87 | { 88 | uint64_t old = prime; 89 | uint64_t j = primes.size() - 1000 + i; 90 | prime = it.next_prime(); 91 | cout << "next_prime(" << old << ") = " << prime; 92 | check(prime == primes[j]); 93 | } 94 | 95 | it.skipto(18446744073709551615ull, 18446744073709551557ull); 96 | prime = it.prev_prime(); 97 | cout << "prev_prime(" << 18446744073709551615ull << ") = " << prime; 98 | check(prime == 18446744073709551557ull); 99 | 100 | cout << endl; 101 | cout << "All tests passed successfully!" << endl; 102 | 103 | return 0; 104 | } 105 | -------------------------------------------------------------------------------- /src/print.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file print.cpp 3 | /// 4 | /// Copyright (C) 2017 Kim Walisch, 5 | /// 6 | /// This file is distributed under the BSD License. See the COPYING 7 | /// file in the top level directory. 8 | /// 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | using namespace std; 21 | 22 | namespace { 23 | 24 | bool print_ = false; 25 | 26 | bool print_variables_ = false; 27 | 28 | } 29 | 30 | namespace primesum { 31 | 32 | void set_print(bool is_print) 33 | { 34 | print_ = is_print; 35 | } 36 | 37 | void set_print_variables(bool print_variables) 38 | { 39 | print_variables_ = print_variables; 40 | } 41 | 42 | bool print_result() 43 | { 44 | return !print_variables(); 45 | } 46 | 47 | bool is_print() 48 | { 49 | return print_; 50 | } 51 | 52 | bool print_variables() 53 | { 54 | return print_variables_; 55 | } 56 | 57 | void print(const string& str) 58 | { 59 | if (is_print()) 60 | cout << str << endl; 61 | } 62 | 63 | void print(int128_t x, int64_t y, int64_t z, int64_t c, double alpha, int threads) 64 | { 65 | if (is_print()) 66 | { 67 | cout << "x = " << x << endl; 68 | cout << "y = " << y << endl; 69 | cout << "z = " << z << endl; 70 | cout << "c = " << c << endl; 71 | cout << "alpha = " << fixed << setprecision(3) << alpha << endl; 72 | cout << "threads = " << threads << endl; 73 | } 74 | } 75 | 76 | void print(int128_t x, int64_t y, int threads) 77 | { 78 | if (print_variables()) 79 | { 80 | int128_t z = x / y; 81 | cout << "x = " << x << endl; 82 | cout << "y = " << y << endl; 83 | cout << "z = " << z << endl; 84 | cout << "alpha = " << fixed << setprecision(3) << get_alpha(x, y) << endl; 85 | cout << "threads = " << threads << endl; 86 | cout << endl; 87 | } 88 | } 89 | 90 | void print(int128_t x, int64_t y, int64_t c, int threads) 91 | { 92 | if (print_variables()) 93 | { 94 | int128_t z = x / y; 95 | cout << "x = " << x << endl; 96 | cout << "y = " << y << endl; 97 | cout << "z = " << z << endl; 98 | cout << "c = " << c << endl; 99 | cout << "alpha = " << fixed << setprecision(3) << get_alpha(x, y) << endl; 100 | cout << "threads = " << threads << endl; 101 | cout << endl; 102 | } 103 | } 104 | 105 | void print(const string& res_str, int256_t res, double time) 106 | { 107 | if (is_print()) 108 | { 109 | cout << "\r" << string(50,' ') << "\r"; 110 | cout << "Status: 100%" << endl; 111 | cout << res_str << " = " << res << endl; 112 | print_seconds(get_time() - time); 113 | } 114 | } 115 | 116 | void print_seconds(double seconds) 117 | { 118 | cout << "Seconds: " << fixed << setprecision(3) << seconds << endl; 119 | } 120 | 121 | } // namespace 122 | -------------------------------------------------------------------------------- /lib/primesieve/src/iterator.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file iterator.cpp 3 | /// 4 | /// Copyright (C) 2019 Kim Walisch, 5 | /// 6 | /// This file is distributed under the BSD License. See the COPYING 7 | /// file in the top level directory. 8 | /// 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | namespace { 19 | 20 | template 21 | void clear(std::unique_ptr& ptr) 22 | { 23 | ptr.reset(nullptr); 24 | } 25 | 26 | } // namespace 27 | 28 | namespace primesieve { 29 | 30 | iterator::~iterator() = default; 31 | 32 | iterator::iterator(iterator&&) noexcept = default; 33 | 34 | iterator& iterator::operator=(iterator&&) noexcept = default; 35 | 36 | iterator::iterator(uint64_t start, 37 | uint64_t stop_hint) 38 | { 39 | skipto(start, stop_hint); 40 | } 41 | 42 | void iterator::skipto(uint64_t start, 43 | uint64_t stop_hint) 44 | { 45 | start_ = start; 46 | stop_ = start; 47 | stop_hint_ = stop_hint; 48 | i_ = 0; 49 | last_idx_ = 0; 50 | dist_ = 0; 51 | clear(primeGenerator_); 52 | primes_.clear(); 53 | } 54 | 55 | void iterator::generate_next_primes() 56 | { 57 | while (true) 58 | { 59 | if (!primeGenerator_) 60 | { 61 | IteratorHelper::next(&start_, &stop_, stop_hint_, &dist_); 62 | auto p = new PrimeGenerator(start_, stop_); 63 | primeGenerator_.reset(p); 64 | primes_.resize(256); 65 | } 66 | 67 | primeGenerator_->fill(primes_, &last_idx_); 68 | 69 | // There are 3 different cases here: 70 | // 1) The primes array contains a few primes (<= 256). 71 | // In this case we return the primes to the user. 72 | // 2) The primes array is empty because the next 73 | // prime > stop. In this case we reset the 74 | // primeGenerator object, increase the start & stop 75 | // numbers and sieve the next segment. 76 | // 3) The next prime > 2^64. In this case the primes 77 | // array contains an error code (UINT64_MAX) which 78 | // is returned to the user. 79 | if (last_idx_ == 0) 80 | clear(primeGenerator_); 81 | else 82 | break; 83 | } 84 | 85 | i_ = 0; 86 | last_idx_--; 87 | } 88 | 89 | void iterator::generate_prev_primes() 90 | { 91 | if (primeGenerator_) 92 | start_ = primes_.front(); 93 | 94 | primes_.clear(); 95 | 96 | while (primes_.empty()) 97 | { 98 | IteratorHelper::prev(&start_, &stop_, stop_hint_, &dist_); 99 | if (start_ <= 2) 100 | primes_.push_back(0); 101 | auto p = new PrimeGenerator(start_, stop_); 102 | primeGenerator_.reset(p); 103 | primeGenerator_->fill(primes_); 104 | clear(primeGenerator_); 105 | } 106 | 107 | last_idx_ = primes_.size() - 1; 108 | i_ = last_idx_; 109 | } 110 | 111 | } // namespace 112 | -------------------------------------------------------------------------------- /lib/primesieve/scripts/fastest_sieve_size.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Find the fastest sieve size for the user's CPU. 4 | # Usage: 5 | # ./find_fastest_sieve_size.sh 6 | # Description: 7 | # This script runs prime counting benchmarks using different 8 | # sieve sizes and reports the time elapsed in seconds. The 9 | # fastest timing indicates the best sieve size for the user's 10 | # CPU. Note that we run single and multi-threaded benchmarks 11 | # for small, medium and large primes. 12 | 13 | # Find the primesieve binary 14 | command -v ./primesieve >/dev/null 2>/dev/null 15 | if [ $? -eq 0 ] 16 | then 17 | primesieve="./primesieve" 18 | else 19 | command -v ../primesieve >/dev/null 2>/dev/null 20 | if [ $? -eq 0 ] 21 | then 22 | primesieve="../primesieve" 23 | else 24 | command -v build/primesieve >/dev/null 2>/dev/null 25 | if [ $? -eq 0 ] 26 | then 27 | primesieve="build/primesieve" 28 | else 29 | command -v primesieve >/dev/null 2>/dev/null 30 | if [ $? -eq 0 ] 31 | then 32 | primesieve="primesieve" 33 | else 34 | echo "Error: failed to find primesieve binary." 35 | exit 1 36 | fi 37 | fi 38 | fi 39 | fi 40 | 41 | # Print CPU info 42 | $primesieve --cpu-info 43 | 44 | start=(0 1e15 1e18) 45 | label=("Small primes" "Medium primes" "Large primes") 46 | cpuCores=$($primesieve --cpu-info | grep 'Number of cores' | cut -f2 -d':' | cut -f2 -d' ') 47 | threads=$($primesieve --cpu-info | grep 'Number of threads' | cut -f2 -d':' | cut -f2 -d' ') 48 | l1CacheSize=$($primesieve --cpu-info | grep 'L1 cache size' | cut -f2 -d':' | cut -f2 -d' ') 49 | l2CacheSize=$($primesieve --cpu-info | grep 'L2 cache size' | cut -f2 -d':' | cut -f2 -d' ') 50 | 51 | if [ -z "$cpuCores" ] || \ 52 | [ "$cpuCores" = "unknown" ] 53 | then 54 | cpuCores=1 55 | fi 56 | 57 | if [ -z "$threads" ] || \ 58 | [ "$threads" = "unknown" ] 59 | then 60 | threads=1 61 | fi 62 | 63 | if [ -z "$l1CacheSize" ] || \ 64 | [ "$l1CacheSize" = "unknown" ] 65 | then 66 | l1CacheSize=8 67 | fi 68 | 69 | if [ -z "$l2CacheSize" ] || \ 70 | [ "$l2CacheSize" = "unknown" ] 71 | then 72 | l2CacheSize=1024 73 | fi 74 | 75 | printTitle() { 76 | echo 77 | echo "=== $1: $2-threaded benchmark ===" 78 | echo 79 | } 80 | 81 | for i in {0..2} 82 | do 83 | printTitle "${label[$i]}" "single" 84 | 85 | for ((size=$l1CacheSize; size<=$l2CacheSize; size*=2)) 86 | do 87 | $primesieve ${start[$i]} -d1e11 -t1 -s$size 88 | sleep 1 89 | done 90 | 91 | if [ "$threads" -gt 1 ] 92 | then 93 | printTitle "${label[$i]}" "multi" 94 | dist=$((10**11 * $cpuCores)) 95 | 96 | for ((size=$l1CacheSize; size<=$l2CacheSize; size*=2)) 97 | do 98 | $primesieve ${start[$i]} -d$dist -s$size 99 | sleep 1 100 | done 101 | fi 102 | done 103 | -------------------------------------------------------------------------------- /src/deleglise-rivat/S2_trivial.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file S2_trivial.cpp 3 | /// @brief Calculate the contribution of the trivial special leaves 4 | /// in parallel using OpenMP. 5 | /// 6 | /// Copyright (C) 2018 Kim Walisch, 7 | /// 8 | /// This file is distributed under the BSD License. See the COPYING 9 | /// file in the top level directory. 10 | /// 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | using namespace std; 25 | using namespace primesum; 26 | 27 | namespace { 28 | 29 | template 30 | int256_t S2_trivial_OpenMP(int128_t x, 31 | int64_t y, 32 | int64_t z, 33 | int64_t c, 34 | PrimeSums& prime_sums, 35 | int threads) 36 | { 37 | int64_t thread_threshold = ipow(10, 7); 38 | threads = ideal_num_threads(threads, y, thread_threshold); 39 | 40 | PiTable pi(y); 41 | int64_t sqrtz = isqrt(z); 42 | int64_t prime_c = nth_prime(c); 43 | int256_t s2_trivial = 0; 44 | 45 | // Find all trivial leaves: n = primes[b] * primes[l] 46 | // which satisfy phi(x / n), b - 1) = 1 47 | #pragma omp parallel for num_threads(threads) reduction(+: s2_trivial) 48 | for (int64_t i = 0; i < threads; i++) 49 | { 50 | int64_t start = max(prime_c, sqrtz) + 1; 51 | int64_t thread_interval = ceil_div(y - start, threads); 52 | start += thread_interval * i; 53 | int64_t stop = min(start + thread_interval, y); 54 | primesieve::iterator iter(start - 1, stop); 55 | int128_t prime; 56 | 57 | while ((prime = iter.next_prime()) < stop) 58 | { 59 | int64_t xn = (int64_t) max(x / (prime * prime), prime); 60 | int256_t diff = prime_sums[pi[y]] - prime_sums[pi[xn]]; 61 | s2_trivial += diff * prime; 62 | } 63 | } 64 | 65 | return s2_trivial; 66 | } 67 | 68 | } // namespace 69 | 70 | namespace primesum { 71 | 72 | int256_t S2_trivial(int128_t x, 73 | int64_t y, 74 | int64_t z, 75 | int64_t c, 76 | int threads) 77 | { 78 | print(""); 79 | print("=== S2_trivial(x, y) ==="); 80 | print("Computation of the trivial special leaves"); 81 | print(x, y, c, threads); 82 | 83 | double time = get_time(); 84 | int256_t s2_trivial; 85 | 86 | // uses less memory 87 | if (y <= numeric_limits::max()) 88 | { 89 | auto prime_sums = generate_prime_sums(y); 90 | s2_trivial = S2_trivial_OpenMP(x, y, z, c, prime_sums, threads); 91 | } 92 | else 93 | { 94 | auto prime_sums = generate_prime_sums(y); 95 | s2_trivial = S2_trivial_OpenMP(x, y, z, c, prime_sums, threads); 96 | } 97 | 98 | print("S2_trivial", s2_trivial, time); 99 | return s2_trivial; 100 | } 101 | 102 | } // namespace 103 | -------------------------------------------------------------------------------- /src/Wheel.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file Wheel.cpp 3 | /// @brief Data structures related to wheel factorization. 4 | /// Wheel factorization is used to skip multiples of 5 | /// small primes in the sieve of Eratosthenes. 6 | /// 7 | /// Copyright (C) 2017 Kim Walisch, 8 | /// 9 | /// This file is distributed under the BSD License. See the COPYING 10 | /// file in the top level directory. 11 | /// 12 | 13 | #include 14 | 15 | namespace primesum { 16 | 17 | const InitWheel Wheel::init[210] = 18 | { 19 | {1, 0}, {0, 0}, {9, 1}, {8, 1}, {7, 1}, {6, 1}, {5, 1}, {4, 1}, 20 | {3, 1}, {2, 1}, {1, 1}, {0, 1}, {1, 2}, {0, 2}, {3, 3}, {2, 3}, 21 | {1, 3}, {0, 3}, {1, 4}, {0, 4}, {3, 5}, {2, 5}, {1, 5}, {0, 5}, 22 | {5, 6}, {4, 6}, {3, 6}, {2, 6}, {1, 6}, {0, 6}, {1, 7}, {0, 7}, 23 | {5, 8}, {4, 8}, {3, 8}, {2, 8}, {1, 8}, {0, 8}, {3, 9}, {2, 9}, 24 | {1, 9}, {0, 9}, {1, 10}, {0, 10}, {3, 11}, {2, 11}, {1, 11}, {0, 11}, 25 | {5, 12}, {4, 12}, {3, 12}, {2, 12}, {1, 12}, {0, 12}, {5, 13}, {4, 13}, 26 | {3, 13}, {2, 13}, {1, 13}, {0, 13}, {1, 14}, {0, 14}, {5, 15}, {4, 15}, 27 | {3, 15}, {2, 15}, {1, 15}, {0, 15}, {3, 16}, {2, 16}, {1, 16}, {0, 16}, 28 | {1, 17}, {0, 17}, {5, 18}, {4, 18}, {3, 18}, {2, 18}, {1, 18}, {0, 18}, 29 | {3, 19}, {2, 19}, {1, 19}, {0, 19}, {5, 20}, {4, 20}, {3, 20}, {2, 20}, 30 | {1, 20}, {0, 20}, {7, 21}, {6, 21}, {5, 21}, {4, 21}, {3, 21}, {2, 21}, 31 | {1, 21}, {0, 21}, {3, 22}, {2, 22}, {1, 22}, {0, 22}, {1, 23}, {0, 23}, 32 | {3, 24}, {2, 24}, {1, 24}, {0, 24}, {1, 25}, {0, 25}, {3, 26}, {2, 26}, 33 | {1, 26}, {0, 26}, {7, 27}, {6, 27}, {5, 27}, {4, 27}, {3, 27}, {2, 27}, 34 | {1, 27}, {0, 27}, {5, 28}, {4, 28}, {3, 28}, {2, 28}, {1, 28}, {0, 28}, 35 | {3, 29}, {2, 29}, {1, 29}, {0, 29}, {5, 30}, {4, 30}, {3, 30}, {2, 30}, 36 | {1, 30}, {0, 30}, {1, 31}, {0, 31}, {3, 32}, {2, 32}, {1, 32}, {0, 32}, 37 | {5, 33}, {4, 33}, {3, 33}, {2, 33}, {1, 33}, {0, 33}, {1, 34}, {0, 34}, 38 | {5, 35}, {4, 35}, {3, 35}, {2, 35}, {1, 35}, {0, 35}, {5, 36}, {4, 36}, 39 | {3, 36}, {2, 36}, {1, 36}, {0, 36}, {3, 37}, {2, 37}, {1, 37}, {0, 37}, 40 | {1, 38}, {0, 38}, {3, 39}, {2, 39}, {1, 39}, {0, 39}, {5, 40}, {4, 40}, 41 | {3, 40}, {2, 40}, {1, 40}, {0, 40}, {1, 41}, {0, 41}, {5, 42}, {4, 42}, 42 | {3, 42}, {2, 42}, {1, 42}, {0, 42}, {3, 43}, {2, 43}, {1, 43}, {0, 43}, 43 | {1, 44}, {0, 44}, {3, 45}, {2, 45}, {1, 45}, {0, 45}, {1, 46}, {0, 46}, 44 | {9, 47}, {8, 47}, {7, 47}, {6, 47}, {5, 47}, {4, 47}, {3, 47}, {2, 47}, 45 | {1, 47}, {0, 47} 46 | }; 47 | 48 | const NextWheel Wheel::next[48] = 49 | { 50 | {10, 1}, {2, 2}, { 4, 3}, {2, 4}, 51 | { 4, 5}, {6, 6}, { 2, 7}, {6, 8}, 52 | { 4, 9}, {2, 10}, { 4, 11}, {6, 12}, 53 | { 6, 13}, {2, 14}, { 6, 15}, {4, 16}, 54 | { 2, 17}, {6, 18}, { 4, 19}, {6, 20}, 55 | { 8, 21}, {4, 22}, { 2, 23}, {4, 24}, 56 | { 2, 25}, {4, 26}, { 8, 27}, {6, 28}, 57 | { 4, 29}, {6, 30}, { 2, 31}, {4, 32}, 58 | { 6, 33}, {2, 34}, { 6, 35}, {6, 36}, 59 | { 4, 37}, {2, 38}, { 4, 39}, {6, 40}, 60 | { 2, 41}, {6, 42}, { 4, 43}, {2, 44}, 61 | { 4, 45}, {2, 46}, {10, 47}, {2, 0} 62 | }; 63 | 64 | } // namespace 65 | -------------------------------------------------------------------------------- /include/int128_t.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file int128_t.hpp 3 | /// @brief Support for int128_t, uint128_t types. 4 | /// 5 | /// Copyright (C) 2018 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #ifndef INT128_T_HPP 12 | #define INT128_T_HPP 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | /// The __int128_t type (GCC/Clang) is not well supported by 19 | /// the C++ standard library (in 2016) so we have to define 20 | /// some functions ourselves. We also define typedefs so we 21 | /// can use int128_t instead of __int128_t. Once this is done 22 | /// int128_t can be used like a regular integer type. 23 | /// 24 | #if !defined(INT128_MAX) && \ 25 | defined(__SIZEOF_INT128__) 26 | 27 | #include 28 | #include 29 | 30 | namespace primesum { 31 | 32 | using int128_t = __int128_t; 33 | using uint128_t = __uint128_t; 34 | 35 | inline std::ostream& operator<<(std::ostream& stream, uint128_t n) 36 | { 37 | std::string str; 38 | 39 | while (n > 0) 40 | { 41 | str += '0' + n % 10; 42 | n /= 10; 43 | } 44 | if (str.empty()) 45 | str = "0"; 46 | 47 | stream << std::string(str.rbegin(), str.rend()); 48 | return stream; 49 | } 50 | 51 | inline std::ostream& operator<<(std::ostream& stream, int128_t n) 52 | { 53 | if (n < 0) 54 | { 55 | stream << "-"; 56 | n = -n; 57 | } 58 | stream << (uint128_t) n; 59 | return stream; 60 | } 61 | 62 | } // namespace 63 | 64 | #endif 65 | 66 | namespace primesum { 67 | 68 | /// Portable namespace, includes functions which (unlike the versions 69 | /// form the C++ standard library) work with the int128_t and 70 | /// uint128_t types (2014). 71 | /// 72 | namespace prt { 73 | 74 | template 75 | struct numeric_limits 76 | { 77 | static constexpr T max() 78 | { 79 | return std::numeric_limits::max(); 80 | } 81 | }; 82 | 83 | template <> 84 | struct numeric_limits 85 | { 86 | static constexpr int128_t min() { return ((int128_t) 1) << 127; } 87 | static constexpr int128_t max() { return ~min(); } 88 | }; 89 | 90 | template <> 91 | struct numeric_limits 92 | { 93 | static constexpr uint128_t min() { return 0; } 94 | static constexpr uint128_t max() { return ~min(); } 95 | }; 96 | 97 | template 98 | struct is_integral 99 | { 100 | enum 101 | { 102 | value = std::is_integral::value || 103 | std::is_same::value || 104 | std::is_same::value 105 | }; 106 | }; 107 | 108 | template 109 | struct is_signed 110 | { 111 | enum 112 | { 113 | value = std::is_signed::value || 114 | std::is_same::value 115 | }; 116 | }; 117 | 118 | template 119 | struct is_unsigned 120 | { 121 | enum 122 | { 123 | value = std::is_unsigned::value || 124 | std::is_same::value 125 | }; 126 | }; 127 | 128 | } // namespace prt 129 | } // namespace primesum 130 | 131 | #endif 132 | -------------------------------------------------------------------------------- /include/primesum-internal.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file primesum-internal.hpp 3 | /// @brief primesum internal function definitions. 4 | /// 5 | /// Copyright (C) 2018 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #ifndef PRIMESUM_INTERNAL_HPP 12 | #define PRIMESUM_INTERNAL_HPP 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | namespace primesum { 26 | 27 | /// Silence unused parameter compiler warning 28 | template 29 | void unused_param(const T&) 30 | { } 31 | 32 | std::string pi(const std::string& x, int threads); 33 | 34 | /// Calculate the number of primes below x using Legendre's formula. 35 | /// Run time: O(x) operations, O(x^(1/2)) space. 36 | /// 37 | int64_t pi_legendre(int64_t x); 38 | 39 | /// Calculate the nth prime using a combination of the counting 40 | /// function and the sieve of Eratosthenes. 41 | /// Run time: O(x^(2/3) / (log x)^2) operations, O(x^(1/2)) space. 42 | /// @pre n <= 216289611853439384 43 | /// 44 | int64_t nth_prime(int64_t n); 45 | 46 | /// Partial sieve function (a.k.a. Legendre-sum). 47 | /// phi(x, a) counts the numbers <= x that are not divisible 48 | /// by any of the first a primes. 49 | /// 50 | int64_t phi(int64_t x, int64_t a); 51 | 52 | int256_t pi(int128_t x, int threads); 53 | 54 | int256_t pi(int128_t x); 55 | 56 | int256_t pi_deleglise_rivat(int128_t x, int threads); 57 | 58 | int256_t pi_deleglise_rivat_parallel1(int128_t x, int threads); 59 | 60 | int64_t pi_legendre(int64_t x, int threads); 61 | 62 | int256_t pi_lmo(int128_t x, int threads); 63 | 64 | int256_t pi_lmo1(int128_t x); 65 | 66 | int64_t pi_lmo2(int64_t x); 67 | 68 | int64_t pi_lmo3(int64_t x); 69 | 70 | int64_t pi_lmo4(int64_t x); 71 | 72 | int64_t pi_lmo5(int64_t x); 73 | 74 | int256_t pi_lmo_parallel1(int128_t x, int threads); 75 | 76 | int64_t phi(int64_t x, int64_t a, int threads); 77 | 78 | int128_t phi_sum(int64_t x, int64_t a); 79 | 80 | int256_t phi_sum(int128_t x, int64_t a); 81 | 82 | int256_t P2(int128_t x, int64_t y, int threads); 83 | 84 | int128_t prime_sum_tiny(int64_t x); 85 | 86 | void set_status_precision(int precision); 87 | 88 | int get_status_precision(int128_t x); 89 | 90 | void set_alpha(double alpha); 91 | 92 | double get_alpha(); 93 | 94 | double get_alpha(int128_t x, int64_t y); 95 | 96 | double get_alpha_lmo(int128_t x); 97 | 98 | double get_alpha_deleglise_rivat(int128_t x); 99 | 100 | double get_time(); 101 | 102 | int ideal_num_threads(int threads, int64_t sieve_limit, int64_t thread_threshold = 100000); 103 | 104 | int128_t to_int128(const std::string& expr); 105 | 106 | template 107 | double get_percent(T low, T limit) 108 | { 109 | double percent = (100.0 * low) / std::max(1, limit); 110 | return in_between(0, percent, 100); 111 | } 112 | 113 | bool test(); 114 | 115 | } // namespace 116 | 117 | #endif 118 | -------------------------------------------------------------------------------- /lib/primesieve/src/app/main.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file main.cpp 3 | /// @brief primesieve console application. 4 | /// 5 | /// Copyright (C) 2018 Kim Walisch, 6 | /// 7 | /// This file is distributed under the BSD License. See the COPYING 8 | /// file in the top level directory. 9 | /// 10 | 11 | #include 12 | #include "cmdoptions.hpp" 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | using namespace std; 21 | using namespace primesieve; 22 | 23 | namespace { 24 | 25 | void printSettings(const ParallelSieve& ps) 26 | { 27 | cout << "Sieve size = " << ps.getSieveSize() << " KiB" << endl; 28 | cout << "Threads = " << ps.idealNumThreads() << endl; 29 | } 30 | 31 | void printSeconds(double sec) 32 | { 33 | cout << "Seconds: " << fixed << setprecision(3) << sec << endl; 34 | } 35 | 36 | /// Count & print primes and prime k-tuplets 37 | void sieve(CmdOptions& opt) 38 | { 39 | ParallelSieve ps; 40 | auto& numbers = opt.numbers; 41 | 42 | if (opt.flags) 43 | ps.setFlags(opt.flags); 44 | if (opt.status) 45 | ps.addFlags(PRINT_STATUS); 46 | if (opt.sieveSize) 47 | ps.setSieveSize(opt.sieveSize); 48 | if (opt.threads) 49 | ps.setNumThreads(opt.threads); 50 | if (ps.isPrint()) 51 | ps.setNumThreads(1); 52 | if (numbers.size() < 2) 53 | numbers.push_front(0); 54 | 55 | ps.setStart(numbers[0]); 56 | ps.setStop(numbers[1]); 57 | 58 | if (!opt.quiet) 59 | printSettings(ps); 60 | 61 | ps.sieve(); 62 | 63 | const string text[6] = 64 | { 65 | "Primes: ", 66 | "Twin primes: ", 67 | "Prime triplets: ", 68 | "Prime quadruplets: ", 69 | "Prime quintuplets: ", 70 | "Prime sextuplets: " 71 | }; 72 | 73 | if (opt.time) 74 | printSeconds(ps.getSeconds()); 75 | 76 | for (int i = 0; i < 6; i++) 77 | if (ps.isCount(i)) 78 | cout << text[i] << ps.getCount(i) << endl; 79 | } 80 | 81 | void nthPrime(CmdOptions& opt) 82 | { 83 | ParallelSieve ps; 84 | auto& numbers = opt.numbers; 85 | 86 | if (opt.flags) 87 | ps.setFlags(opt.flags); 88 | if (opt.sieveSize) 89 | ps.setSieveSize(opt.sieveSize); 90 | if (opt.threads) 91 | ps.setNumThreads(opt.threads); 92 | if (numbers.size() < 2) 93 | numbers.push_back(0); 94 | 95 | int64_t n = numbers[0]; 96 | uint64_t start = numbers[1]; 97 | uint64_t nthPrime = 0; 98 | ps.setStart(start); 99 | ps.setStop(start + abs(n * 20)); 100 | 101 | if (!opt.quiet) 102 | printSettings(ps); 103 | 104 | nthPrime = ps.nthPrime(n, start); 105 | 106 | if (opt.time) 107 | printSeconds(ps.getSeconds()); 108 | 109 | cout << "Nth prime: " << nthPrime << endl; 110 | } 111 | 112 | } // namespace 113 | 114 | int main(int argc, char* argv[]) 115 | { 116 | try 117 | { 118 | CmdOptions opt = parseOptions(argc, argv); 119 | 120 | if (opt.nthPrime) 121 | nthPrime(opt); 122 | else 123 | sieve(opt); 124 | } 125 | catch (exception& e) 126 | { 127 | cerr << "primesieve: " << e.what() << endl 128 | << "Try 'primesieve --help' for more information." << endl; 129 | return 1; 130 | } 131 | 132 | return 0; 133 | } 134 | -------------------------------------------------------------------------------- /include/Wheel.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file Wheel.hpp 3 | /// @brief Data structures related to wheel factorization. 4 | /// Wheel factorization is used to skip multiples of 5 | /// small primes in the sieve of Eratosthenes. 6 | /// 7 | /// Copyright (C) 2017 Kim Walisch, 8 | /// 9 | /// This file is distributed under the BSD License. See the COPYING 10 | /// file in the top level directory. 11 | /// 12 | 13 | #ifndef WHEEL_HPP 14 | #define WHEEL_HPP 15 | 16 | #include 17 | 18 | #include 19 | #include 20 | 21 | namespace primesum { 22 | 23 | /// The InitWheel data structure is used to calculate the 24 | /// first multiple >= start of a sieving prime 25 | /// 26 | struct InitWheel 27 | { 28 | int8_t next_multiple_factor; 29 | int8_t wheel_index; 30 | }; 31 | 32 | /// The NextWheel data structure is used to calculate the 33 | /// next multiple of a sieving prime 34 | /// 35 | struct NextWheel 36 | { 37 | int8_t next_multiple_factor; 38 | int8_t next_wheel_index; 39 | }; 40 | 41 | /// For each sieving prime we create a WheelItem which 42 | /// contains the sieving prime's next multiple and the 43 | /// wheel index of that multiple 44 | /// 45 | struct WheelItem 46 | { 47 | WheelItem(int64_t multiple, int64_t index) : 48 | next_multiple(multiple), 49 | wheel_index((int8_t) index) 50 | { } 51 | 52 | void set(int64_t multiple, 53 | int64_t next_wheel_index) 54 | { 55 | next_multiple = multiple; 56 | wheel_index = (int8_t) next_wheel_index; 57 | } 58 | 59 | int64_t next_multiple; 60 | int8_t wheel_index; 61 | }; 62 | 63 | /// 4th wheel, skips multiples of 2, 3, 5 and 7 64 | class Wheel 65 | { 66 | public: 67 | /// Calculate the first multiple >= low of each prime. 68 | /// When sieving special leaves both multiples 69 | /// and primes are crossed-off. 70 | /// 71 | template 72 | Wheel(Primes& primes, 73 | int64_t size, 74 | int64_t low) 75 | { 76 | wheel_.reserve(size); 77 | wheel_.emplace_back(0, 0); 78 | 79 | for (int64_t b = 1; b < size; b++) 80 | { 81 | int64_t prime = primes[b]; 82 | int64_t quotient = ceil_div(low, prime); 83 | 84 | // first multiple >= low 85 | int64_t multiple = prime * quotient; 86 | 87 | // calculate the next multiple of prime that 88 | // is not divisible by any of the wheel's 89 | // prime factors (2, 3, 5, 7) 90 | int64_t next_multiple_factor = init[quotient % 210].next_multiple_factor; 91 | int64_t wheel_index = init[quotient % 210].wheel_index; 92 | multiple += prime * next_multiple_factor; 93 | 94 | wheel_.emplace_back(multiple, wheel_index); 95 | } 96 | } 97 | 98 | static int64_t next_multiple_factor(int64_t* wheel_index) 99 | { 100 | int64_t next_multiple_factor = next[*wheel_index].next_multiple_factor; 101 | *wheel_index = next[*wheel_index].next_wheel_index; 102 | return next_multiple_factor; 103 | } 104 | 105 | WheelItem& operator[](int64_t i) 106 | { 107 | return wheel_[i]; 108 | } 109 | private: 110 | 111 | static const InitWheel init[210]; 112 | static const NextWheel next[48]; 113 | std::vector wheel_; 114 | }; 115 | 116 | } // namespace 117 | 118 | #endif 119 | -------------------------------------------------------------------------------- /lib/primesieve/include/primesieve/PrimeSieve.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file PrimeSieve.hpp 3 | /// @brief PrimeSieve is a high level class that manages prime 4 | /// sieving. It is used for printing and counting primes 5 | /// and for computing the nth prime. 6 | /// 7 | /// Copyright (C) 2020 Kim Walisch, 8 | /// 9 | /// This file is distributed under the BSD License. See the COPYING 10 | /// file in the top level directory. 11 | /// 12 | 13 | #ifndef PRIMESIEVE_CLASS_HPP 14 | #define PRIMESIEVE_CLASS_HPP 15 | 16 | #include "PreSieve.hpp" 17 | #include 18 | #include 19 | 20 | namespace primesieve { 21 | 22 | using counts_t = std::array; 23 | class ParallelSieve; 24 | 25 | enum 26 | { 27 | COUNT_PRIMES = 1 << 0, 28 | COUNT_TWINS = 1 << 1, 29 | COUNT_TRIPLETS = 1 << 2, 30 | COUNT_QUADRUPLETS = 1 << 3, 31 | COUNT_QUINTUPLETS = 1 << 4, 32 | COUNT_SEXTUPLETS = 1 << 5, 33 | PRINT_PRIMES = 1 << 6, 34 | PRINT_TWINS = 1 << 7, 35 | PRINT_TRIPLETS = 1 << 8, 36 | PRINT_QUADRUPLETS = 1 << 9, 37 | PRINT_QUINTUPLETS = 1 << 10, 38 | PRINT_SEXTUPLETS = 1 << 11, 39 | PRINT_STATUS = 1 << 12 40 | }; 41 | 42 | class PrimeSieve 43 | { 44 | public: 45 | PrimeSieve(); 46 | PrimeSieve(ParallelSieve*); 47 | virtual ~PrimeSieve(); 48 | // Getters 49 | uint64_t getStart() const; 50 | uint64_t getStop() const; 51 | uint64_t getDistance() const; 52 | int getSieveSize() const; 53 | double getSeconds() const; 54 | PreSieve& getPreSieve(); 55 | // Setters 56 | void setStart(uint64_t); 57 | void setStop(uint64_t); 58 | void updateStatus(uint64_t); 59 | void setSieveSize(int); 60 | void setFlags(int); 61 | void addFlags(int); 62 | // Bool is* 63 | bool isCount(int) const; 64 | bool isCountPrimes() const; 65 | bool isCountkTuplets() const; 66 | bool isPrint() const; 67 | bool isPrint(int) const; 68 | bool isPrintPrimes() const; 69 | bool isPrintkTuplets() const; 70 | bool isFlag(int) const; 71 | bool isFlag(int, int) const; 72 | bool isStatus() const; 73 | // Sieve 74 | virtual void sieve(); 75 | void sieve(uint64_t, uint64_t); 76 | void sieve(uint64_t, uint64_t, int); 77 | // nth prime 78 | uint64_t nthPrime(uint64_t); 79 | uint64_t nthPrime(int64_t, uint64_t); 80 | // Count 81 | counts_t& getCounts(); 82 | uint64_t getCount(int) const; 83 | uint64_t countPrimes(uint64_t, uint64_t); 84 | 85 | protected: 86 | /// Sieve primes >= start_ 87 | uint64_t start_ = 0; 88 | /// Sieve primes <= stop_ 89 | uint64_t stop_ = 0; 90 | /// Time elapsed of sieve() 91 | double seconds_ = 0; 92 | /// Sieving status in percent 93 | double percent_ = 0; 94 | /// Prime number and prime k-tuplet counts 95 | counts_t counts_; 96 | void reset(); 97 | void setStatus(double); 98 | 99 | private: 100 | uint64_t sievedDistance_ = 0; 101 | uint64_t updateDistance_ = 0; 102 | /// Default flags 103 | int flags_ = COUNT_PRIMES; 104 | /// Sieve size in KiB 105 | int sieveSize_ = 0; 106 | /// Status updates must be synchronized by main thread 107 | ParallelSieve* parent_ = nullptr; 108 | PreSieve preSieve_; 109 | void processSmallPrimes(); 110 | static void printStatus(double, double); 111 | }; 112 | 113 | } // namespace 114 | 115 | #endif 116 | -------------------------------------------------------------------------------- /src/S1.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file S1.cpp 3 | /// 4 | /// Copyright (C) 2018 Kim Walisch, 5 | /// 6 | /// This file is distributed under the BSD License. See the COPYING 7 | /// file in the top level directory. 8 | /// 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | 20 | using namespace std; 21 | using namespace primesum; 22 | 23 | namespace { 24 | 25 | /// Recursively iterate over the square free numbers coprime to the 26 | /// first b primes and calculate the sum of the ordinary leaves. 27 | /// This algorithm is based on section 2.2 of the paper: 28 | /// Douglas Staple, "The Combinatorial Algorithm For Computing pi(x)", 29 | /// arXiv:1503.01839, 6 March 2015. 30 | /// 31 | template 32 | typename next_larger_type::type 33 | S1_OpenMP_thread(X x, 34 | int64_t y, 35 | int64_t b, 36 | int64_t c, 37 | X square_free, 38 | vector

& primes) 39 | { 40 | using res_t = typename next_larger_type::type; 41 | 42 | res_t s1_sum = 0; 43 | 44 | for (b += 1; b < (int64_t) primes.size(); b++) 45 | { 46 | X next = square_free * primes[b]; 47 | if (next > y) break; 48 | s1_sum += phi_sum(x / next, c) * (MU * next); 49 | s1_sum += S1_OpenMP_thread<-MU>(x, y, b, c, next, primes); 50 | } 51 | 52 | return s1_sum; 53 | } 54 | 55 | /// Calculate the contribution of the ordinary leaves in parallel. 56 | /// Run time: O(y * log(log(y))) operations. 57 | /// Space complexity: O(y / log(y)). 58 | /// 59 | template 60 | typename next_larger_type::type 61 | S1_OpenMP_master(X x, 62 | Y y, 63 | int64_t c, 64 | int threads) 65 | { 66 | int64_t thread_threshold = ipow(10, 6); 67 | threads = ideal_num_threads(threads, y, thread_threshold); 68 | vector primes = generate_primes(y); 69 | auto s1_sum = phi_sum(x, c); 70 | 71 | #pragma omp parallel for schedule(static, 1) num_threads(threads) reduction (+: s1_sum) 72 | for (int64_t b = c + 1; b < (int64_t) primes.size(); b++) 73 | { 74 | s1_sum -= phi_sum(x / primes[b], c) * primes[b]; 75 | s1_sum += S1_OpenMP_thread<1>(x, y, b, c, (X) primes[b], primes); 76 | } 77 | 78 | return s1_sum; 79 | } 80 | 81 | } // namespace 82 | 83 | namespace primesum { 84 | 85 | int256_t S1(int128_t x, 86 | int64_t y, 87 | int64_t c, 88 | int threads) 89 | { 90 | print(""); 91 | print("=== S1(x, y) ==="); 92 | print("Computation of the ordinary leaves"); 93 | print(x, y, c, threads); 94 | 95 | double time = get_time(); 96 | int256_t s1_sum; 97 | 98 | // uses less memory 99 | if (y <= numeric_limits::max()) 100 | { 101 | if (x <= numeric_limits::max()) 102 | s1_sum = S1_OpenMP_master((int64_t) x, (uint32_t) y, c, threads); 103 | else 104 | s1_sum = S1_OpenMP_master(x, (uint32_t) y, c, threads); 105 | } 106 | else 107 | s1_sum = S1_OpenMP_master(x, y, c, threads); 108 | 109 | print("S1_sum", s1_sum, time); 110 | return s1_sum; 111 | } 112 | 113 | } // namespace 114 | -------------------------------------------------------------------------------- /lib/primesieve/src/MemoryPool.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file MemoryPool.cpp 3 | /// EratMedium and EratBig may use millions of buckets for 4 | /// storing the sieving primes that are required to cross off 5 | /// multiples. As many memory allocations/deallocations are 6 | /// bad for performance the MemoryPool initially allocates a 7 | /// large number of buckets (using a single memory allocation) 8 | /// and puts the buckets into its stock. The MemoryPool can 9 | /// then serve buckets to EratMedium and EratBig without 10 | /// doing any memory allocation as long as the MemoryPool's 11 | /// stock is not empty. 12 | /// 13 | /// Copyright (C) 2020 Kim Walisch, 14 | /// 15 | /// This file is distributed under the BSD License. See the COPYING 16 | /// file in the top level directory. 17 | /// 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | #include 26 | 27 | using std::size_t; 28 | 29 | namespace primesieve { 30 | 31 | void MemoryPool::addBucket(SievingPrime*& sievingPrime) 32 | { 33 | if (!stock_) 34 | allocateBuckets(); 35 | 36 | Bucket* bucket = stock_; 37 | stock_ = stock_->next(); 38 | bucket->setNext(nullptr); 39 | 40 | // In case we add a bucket to the front of a 41 | // non empty bucket list we need to set the 42 | // next pointer of the new bucket to the bucket 43 | // that was previously at the front of the list. 44 | if (sievingPrime) 45 | { 46 | Bucket* old = Bucket::get(sievingPrime); 47 | old->setEnd(sievingPrime); 48 | bucket->setNext(old); 49 | } 50 | 51 | sievingPrime = bucket->begin(); 52 | } 53 | 54 | void MemoryPool::freeBucket(Bucket* bucket) 55 | { 56 | bucket->reset(); 57 | bucket->setNext(stock_); 58 | stock_ = bucket; 59 | } 60 | 61 | void MemoryPool::allocateBuckets() 62 | { 63 | if (memory_.empty()) 64 | memory_.reserve(128); 65 | 66 | // Allocate a large chunk of memory 67 | size_t bytes = count_ * sizeof(Bucket); 68 | char* memory = new char[bytes]; 69 | memory_.emplace_back(memory); 70 | void* ptr = memory; 71 | 72 | // Align pointer address to sizeof(Bucket) 73 | if (!std::align(sizeof(Bucket), sizeof(Bucket), ptr, bytes)) 74 | throw primesieve_error("MemoryPool: failed to align memory!"); 75 | 76 | initBuckets(ptr, bytes); 77 | increaseAllocCount(); 78 | } 79 | 80 | void MemoryPool::initBuckets(void* memory, size_t bytes) 81 | { 82 | Bucket* buckets = (Bucket*) memory; 83 | count_ = bytes / sizeof(Bucket); 84 | size_t i = 0; 85 | 86 | if ((size_t) buckets % sizeof(Bucket) != 0) 87 | throw primesieve_error("MemoryPool: failed to align memory!"); 88 | 89 | if (count_ < 10) 90 | throw primesieve_error("MemoryPool: insufficient buckets allocated!"); 91 | 92 | for (; i + 1 < count_; i++) 93 | { 94 | buckets[i].reset(); 95 | buckets[i].setNext(&buckets[i + 1]); 96 | } 97 | 98 | buckets[i].reset(); 99 | buckets[i].setNext(nullptr); 100 | stock_ = buckets; 101 | } 102 | 103 | void MemoryPool::increaseAllocCount() 104 | { 105 | count_ += count_ / 8; 106 | size_t maxCount = config::MAX_ALLOC_BYTES / sizeof(Bucket); 107 | count_ = std::min(count_, maxCount); 108 | } 109 | 110 | } // namespace 111 | -------------------------------------------------------------------------------- /lib/primesieve/include/primesieve/iterator.hpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file iterator.hpp 3 | /// @brief The iterator class allows to easily iterate (forwards 4 | /// and backwards) over prime numbers. 5 | /// 6 | /// Copyright (C) 2019 Kim Walisch, 7 | /// 8 | /// This file is distributed under the BSD License. See the COPYING 9 | /// file in the top level directory. 10 | /// 11 | 12 | #ifndef PRIMESIEVE_ITERATOR_HPP 13 | #define PRIMESIEVE_ITERATOR_HPP 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | namespace primesieve { 21 | 22 | class PrimeGenerator; 23 | 24 | uint64_t get_max_stop(); 25 | 26 | /// primesieve::iterator allows to easily iterate over primes both 27 | /// forwards and backwards. Generating the first prime has a 28 | /// complexity of O(r log log r) operations with r = n^0.5, after that 29 | /// any additional prime is generated in amortized O(log n log log n) 30 | /// operations. The memory usage is PrimePi(n^0.5) * 8 bytes. 31 | /// 32 | class iterator 33 | { 34 | public: 35 | /// Create a new iterator object. 36 | /// @param start Generate primes > start (or < start). 37 | /// @param stop_hint Stop number optimization hint, gives significant 38 | /// speed up if few primes are generated. E.g. if 39 | /// you want to generate the primes below 1000 use 40 | /// stop_hint = 1000. 41 | /// 42 | iterator(uint64_t start = 0, uint64_t stop_hint = get_max_stop()); 43 | 44 | /// primesieve::iterator objects cannot be copied. 45 | iterator(const iterator&) = delete; 46 | iterator& operator=(const iterator&) = delete; 47 | 48 | /// primesieve::iterator objects support move semantics. 49 | iterator(iterator&&) noexcept; 50 | iterator& operator=(iterator&&) noexcept; 51 | 52 | ~iterator(); 53 | 54 | /// Reset the primesieve iterator to start. 55 | /// @param start Generate primes > start (or < start). 56 | /// @param stop_hint Stop number optimization hint, gives significant 57 | /// speed up if few primes are generated. E.g. if 58 | /// you want to generate the primes below 1000 use 59 | /// stop_hint = 1000. 60 | /// 61 | void skipto(uint64_t start, uint64_t stop_hint = get_max_stop()); 62 | 63 | /// Get the next prime. 64 | /// Returns UINT64_MAX if next prime > 2^64. 65 | /// 66 | uint64_t next_prime() 67 | { 68 | if (i_++ == last_idx_) 69 | generate_next_primes(); 70 | return primes_[i_]; 71 | } 72 | 73 | /// Get the previous prime. 74 | /// prev_prime(n) returns 0 for n <= 2. 75 | /// Note that next_prime() runs up to 2x faster than prev_prime(). 76 | /// Hence if the same algorithm can be written using either 77 | /// prev_prime() or next_prime() it is preferable to use next_prime(). 78 | /// 79 | uint64_t prev_prime() 80 | { 81 | if (i_-- == 0) 82 | generate_prev_primes(); 83 | return primes_[i_]; 84 | } 85 | 86 | private: 87 | std::size_t i_; 88 | std::size_t last_idx_; 89 | std::vector primes_; 90 | uint64_t start_; 91 | uint64_t stop_; 92 | uint64_t stop_hint_; 93 | uint64_t dist_; 94 | std::unique_ptr primeGenerator_; 95 | void generate_next_primes(); 96 | void generate_prev_primes(); 97 | }; 98 | 99 | } // namespace 100 | 101 | #endif 102 | -------------------------------------------------------------------------------- /src/generate.cpp: -------------------------------------------------------------------------------- 1 | /// 2 | /// @file generate.cpp 3 | /// 4 | /// Copyright (C) 2018 Kim Walisch, 5 | /// 6 | /// This file is distributed under the BSD License. See the COPYING 7 | /// file in the top level directory. 8 | /// 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | using namespace std; 19 | 20 | namespace primesum { 21 | 22 | /// Generate a vector with the primes <= max. 23 | /// The primes vector uses 1-indexing i.e. primes[1] = 2. 24 | /// 25 | vector generate_primes(int64_t max) 26 | { 27 | vector primes = { 0 }; 28 | primesieve::generate_primes(max, &primes); 29 | return primes; 30 | } 31 | 32 | /// Generate a vector with the first n primes. 33 | /// The primes vector uses 1-indexing i.e. primes[1] = 2. 34 | /// 35 | vector generate_n_primes(int64_t n) 36 | { 37 | vector primes = { 0 }; 38 | primesieve::generate_n_primes(n, &primes); 39 | return primes; 40 | } 41 | 42 | /// Generate a vector with the prime counts <= max 43 | /// using the sieve of Eratosthenes 44 | /// 45 | vector generate_pi(int64_t max) 46 | { 47 | int64_t sqrt = isqrt(max); 48 | int64_t size = max + 1; 49 | vector sieve(size, 1); 50 | 51 | for (int64_t i = 2; i <= sqrt; i++) 52 | if (sieve[i]) 53 | for (int64_t j = i * i; j < size; j += i) 54 | sieve[j] = 0; 55 | 56 | vector pi(size, 0); 57 | int32_t pix = 0; 58 | 59 | for (int64_t i = 2; i < size; i++) 60 | { 61 | pix += sieve[i]; 62 | pi[i] = pix; 63 | } 64 | 65 | return pi; 66 | } 67 | 68 | /// Generate a vector with Möbius function values. 69 | /// This implementation is based on code by Rick Sladkey: 70 | /// https://mathoverflow.net/q/99545 71 | /// 72 | vector generate_moebius(int64_t max) 73 | { 74 | int64_t sqrt = isqrt(max); 75 | int64_t size = max + 1; 76 | vector mu(size, 1); 77 | 78 | for (int64_t i = 2; i <= sqrt; i++) 79 | { 80 | if (mu[i] == 1) 81 | { 82 | for (int64_t j = i; j < size; j += i) 83 | mu[j] *= (int32_t) -i; 84 | for (int64_t j = i * i; j < size; j += i * i) 85 | mu[j] = 0; 86 | } 87 | } 88 | 89 | for (int64_t i = 2; i < size; i++) 90 | { 91 | if (mu[i] == i) 92 | mu[i] = 1; 93 | else if (mu[i] == -i) 94 | mu[i] = -1; 95 | else if (mu[i] < 0) 96 | mu[i] = 1; 97 | else if (mu[i] > 0) 98 | mu[i] = -1; 99 | } 100 | 101 | return mu; 102 | } 103 | 104 | /// Generate a vector with the least prime factors 105 | /// of the integers <= max 106 | /// 107 | vector generate_lpf(int64_t max) 108 | { 109 | int64_t sqrt = isqrt(max); 110 | int64_t size = max + 1; 111 | vector lpf(size, 1); 112 | 113 | for (int64_t i = 2; i <= sqrt; i++) 114 | if (lpf[i] == 1) 115 | for (int64_t j = i * i; j < size; j += i) 116 | if (lpf[j] == 1) 117 | lpf[j] = (int32_t) i; 118 | 119 | for (int64_t i = 2; i < size; i++) 120 | if (lpf[i] == 1) 121 | lpf[i] = (int32_t) i; 122 | 123 | // phi(x / 1, c) contributes to the sum in the 124 | // Lagarias-Miller-Odlyzko prime counting algorithm, 125 | // thus set lpf[1] = MAX (normally lpf[1] = 1) 126 | if (lpf.size() > 1) 127 | lpf[1] = numeric_limits::max(); 128 | 129 | return lpf; 130 | } 131 | 132 | } // namespace 133 | -------------------------------------------------------------------------------- /test/modulo_256-bit.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | using namespace primesum; 9 | using namespace std; 10 | 11 | typedef boost::multiprecision::int256_t boost_int256_t; 12 | 13 | int main(int argc, char** argv) 14 | { 15 | random_device rd; 16 | mt19937 gen(rd()); 17 | uniform_int_distribution dist(1, std::numeric_limits::max()); 18 | 19 | random_device rd2; 20 | mt19937 gen2(rd2()); 21 | uniform_int_distribution dist2(1, std::numeric_limits::max()); 22 | 23 | int iters = 10000; 24 | 25 | if (argc > 1) 26 | iters = atoi(argv[1]); 27 | 28 | // Test random dividends and small quotients 29 | for (int i = 0; i < iters; i++) 30 | { 31 | int256_t x1 = 1; 32 | boost_int256_t y1 = 1; 33 | 34 | for (int i = 0; i < 4; i++) 35 | { 36 | int64_t a = dist(gen); 37 | int256_t x2 = 1; 38 | boost_int256_t y2 = 1; 39 | 40 | x1 *= a; x1 += 1; 41 | y1 *= a; y1 += 1; 42 | 43 | for (int j = 1; j < 17; j++) 44 | { 45 | x2 = j; 46 | y2 = j; 47 | 48 | auto res1 = x1 % x2; 49 | auto res2 = y1 % y2; 50 | 51 | // std::cout << y1 << " % " << y2 << " == " << res2 << "\n"; 52 | 53 | if ((uint64_t) res1 != (uint64_t) res2) 54 | { 55 | std::cerr << x1 << std::endl; 56 | std::cerr << x2 << std::endl; 57 | std::cerr << y1 << std::endl; 58 | std::cerr << y2 << std::endl; 59 | std::cerr << (x1 % x2) << " != " << (y1 % y2) << std::endl; 60 | return 1; 61 | } 62 | } 63 | } 64 | } 65 | 66 | // Test random dividends and quotients 67 | for (int i = 0; i < iters; i++) 68 | { 69 | int256_t x1 = 1; 70 | boost_int256_t y1 = 1; 71 | 72 | for (int i = 0; i < 4; i++) 73 | { 74 | int64_t a = dist(gen); 75 | int256_t x2 = 1; 76 | boost_int256_t y2 = 1; 77 | 78 | x1 *= a; x1 += 1; 79 | y1 *= a; y1 += 1; 80 | 81 | for (int j = 0; j < 17; j++) 82 | { 83 | int64_t b = dist2(gen); 84 | 85 | x2 *= b; x2 += 1; 86 | y2 *= b; y2 += 1; 87 | 88 | auto res1 = x1 % x2; 89 | auto res2 = y1 % y2; 90 | 91 | // std::cout << y1 << " % " << y2 << " == " << res2 << "\n"; 92 | 93 | do 94 | { 95 | if ((uint64_t) res1 != (uint64_t) res2) 96 | { 97 | std::cerr << x1 << std::endl; 98 | std::cerr << x2 << std::endl; 99 | std::cerr << y1 << std::endl; 100 | std::cerr << y2 << std::endl; 101 | std::cerr << (x1 % x2) << " != " << (y1 % y2) << std::endl; 102 | return 1; 103 | } 104 | 105 | res1 >>= 64; 106 | res2 >>= 64; 107 | } 108 | while (res2 != 0); 109 | } 110 | } 111 | } 112 | 113 | return 0; 114 | } 115 | -------------------------------------------------------------------------------- /lib/primesieve/include/primesieve/iterator.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file iterator.h 3 | * @brief primesieve_iterator allows to easily iterate over primes 4 | * both forwards and backwards. Generating the first prime 5 | * has a complexity of O(r log log r) operations with 6 | * r = n^0.5, after that any additional prime is generated in 7 | * amortized O(log n log log n) operations. The memory usage 8 | * is about PrimePi(n^0.5) * 8 bytes. 9 | * 10 | * The @link primesieve_iterator.c primesieve_iterator.c 11 | * @endlink example shows how to use primesieve_iterator. 12 | * If any error occurs primesieve_next_prime() and 13 | * primesieve_prev_prime() return PRIMESIEVE_ERROR. 14 | * Furthermore primesieve_iterator.is_error is initialized 15 | * to 0 and set to 1 if any error occurs. 16 | * 17 | * Copyright (C) 2019 Kim Walisch, 18 | * 19 | * This file is distributed under the BSD License. See the COPYING 20 | * file in the top level directory. 21 | */ 22 | 23 | #ifndef PRIMESIEVE_ITERATOR_H 24 | #define PRIMESIEVE_ITERATOR_H 25 | 26 | #include 27 | #include 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | /** 34 | * C prime iterator, please refer to @link iterator.h iterator.h 35 | * @endlink for more information. 36 | */ 37 | typedef struct 38 | { 39 | size_t i; 40 | size_t last_idx; 41 | uint64_t start; 42 | uint64_t stop; 43 | uint64_t stop_hint; 44 | uint64_t dist; 45 | uint64_t* primes; 46 | void* vector; 47 | void* primeGenerator; 48 | int is_error; 49 | } primesieve_iterator; 50 | 51 | /** Initialize the primesieve iterator before first using it */ 52 | void primesieve_init(primesieve_iterator* it); 53 | 54 | /** Free all memory */ 55 | void primesieve_free_iterator(primesieve_iterator* it); 56 | 57 | /** 58 | * Reset the primesieve iterator to start. 59 | * @param start Generate primes > start (or < start). 60 | * @param stop_hint Stop number optimization hint. E.g. if you want 61 | * to generate the primes below 1000 use 62 | * stop_hint = 1000, if you don't know use 63 | * primesieve_get_max_stop(). 64 | */ 65 | void primesieve_skipto(primesieve_iterator* it, uint64_t start, uint64_t stop_hint); 66 | 67 | /** Internal use */ 68 | void primesieve_generate_next_primes(primesieve_iterator*); 69 | 70 | /** Internal use */ 71 | void primesieve_generate_prev_primes(primesieve_iterator*); 72 | 73 | /** 74 | * Get the next prime. 75 | * Returns UINT64_MAX if next prime > 2^64. 76 | */ 77 | static inline uint64_t primesieve_next_prime(primesieve_iterator* it) 78 | { 79 | if (it->i++ == it->last_idx) 80 | primesieve_generate_next_primes(it); 81 | return it->primes[it->i]; 82 | } 83 | 84 | /** 85 | * Get the previous prime. 86 | * primesieve_prev_prime(n) returns 0 for n <= 2. 87 | * Note that primesieve_next_prime() runs up to 2x faster than 88 | * primesieve_prev_prime(). Hence if the same algorithm can be written 89 | * using either primesieve_prev_prime() or primesieve_next_prime() 90 | * it is preferable to use primesieve_next_prime(). 91 | */ 92 | static inline uint64_t primesieve_prev_prime(primesieve_iterator* it) 93 | { 94 | if (it->i-- == 0) 95 | primesieve_generate_prev_primes(it); 96 | return it->primes[it->i]; 97 | } 98 | 99 | #ifdef __cplusplus 100 | } /* extern "C" */ 101 | #endif 102 | 103 | #endif 104 | --------------------------------------------------------------------------------