From b3927f40f84277d85f51fa6a05f7ad2c0bf64b1b Mon Sep 17 00:00:00 2001 From: Kim Walisch Date: Mon, 8 Jan 2024 10:11:06 +0100 Subject: [PATCH] Add more tests --- test/Li.cpp | 101 +++++++++++++++++++++++++++++++++++++ test/Ri.cpp | 127 +++++++++++++++++++++++++++++++++++++++++++++++ test/moebius.cpp | 99 ++++++++++++++++++++++++++++++++++++ 3 files changed, 327 insertions(+) create mode 100644 test/Li.cpp create mode 100644 test/Ri.cpp create mode 100644 test/moebius.cpp diff --git a/test/Li.cpp b/test/Li.cpp new file mode 100644 index 000000000..f1f674a69 --- /dev/null +++ b/test/Li.cpp @@ -0,0 +1,101 @@ +/// +/// @file Li.cpp +/// @brief Test the offset logarithmic integral function. +/// Li(x) = li(x) - li(2) +/// +/// Copyright (C) 2024 Kim Walisch, +/// +/// This file is distributed under the BSD License. See the COPYING +/// file in the top level directory. +/// + +#include + +#include +#include +#include +#include +#include + +using std::max; +using std::size_t; +using namespace primesieve; + +std::vector Li_table = +{ + 5, // Li(10^1) + 29, // Li(10^2) + 176, // Li(10^3) + 1245, // Li(10^4) + 9628, // Li(10^5) + 78626, // Li(10^6) + 664917, // Li(10^7) + 5762208, // Li(10^8) + 50849233, // Li(10^9) + 455055613, // Li(10^10) + 4118066399ll, // Li(10^11) + 37607950279ll, // Li(10^12) + 346065645809ll, // Li(10^13) + 3204942065690ll, // Li(10^14) + 29844571475286ll // Li(10^15) +}; + +void check(bool OK) +{ + std::cout << " " << (OK ? "OK" : "ERROR") << "\n"; + if (!OK) + std::exit(1); +} + +int main() +{ + uint64_t x = 1; + for (size_t i = 0; i < Li_table.size(); i++) + { + x *= 10; + std::cout << "Li(" << x << ") = " << Li(x); + check(Li(x) == Li_table[i]); + } + + x = 1; + for (size_t i = 0; i < Li_table.size(); i++) + { + x *= 10; + std::cout << "Li_inverse(" << Li_table[i] << ") = " << Li_inverse(Li_table[i]); + check(Li_inverse(Li_table[i]) <= x && + Li_inverse(Li_table[i] + 1) > x); + } + + // Sanity checks for small values of Li(x) + for (x = 0; x < 300000; x++) + { + uint64_t lix = Li(x); + double logx = std::log(max((double) x, 2.0)); + + if ((x >= 11 && lix < x / logx) || + (x >= 2 && lix > x * logx)) + { + std::cout << "Li(" << x << ") = " << lix << " ERROR" << std::endl; + std::exit(1); + } + } + + // Sanity checks for small values of Li_inverse(x) + for (x = 2; x < 30000; x++) + { + uint64_t res = Li_inverse(x); + double logx = std::log((double) x); + + if (res < x || + (x >= 4 && res > x * logx * logx)) + { + std::cout << "Li_inverse(" << x << ") = " << res << " ERROR" << std::endl; + std::exit(1); + } + } + + std::cout << std::endl; + std::cout << "All tests passed successfully!" << std::endl; + + return 0; +} diff --git a/test/Ri.cpp b/test/Ri.cpp new file mode 100644 index 000000000..ad71c321a --- /dev/null +++ b/test/Ri.cpp @@ -0,0 +1,127 @@ +/// +/// @file Ri.cpp +/// @brief Test the Riemann R function. +/// +/// Copyright (C) 2024 Kim Walisch, +/// +/// This file is distributed under the BSD License. See the COPYING +/// file in the top level directory. +/// + +#include + +#include +#include +#include +#include +#include + +using std::max; +using std::size_t; +using namespace primesieve; + +std::vector Ri_table = +{ + 4, // Ri(10^1) + 25, // Ri(10^2) + 168, // Ri(10^3) + 1226, // Ri(10^4) + 9587, // Ri(10^5) + 78527, // Ri(10^6) + 664667, // Ri(10^7) + 5761551, // Ri(10^8) + 50847455, // Ri(10^9) + 455050683, // Ri(10^10) + 4118052494ll, // Ri(10^11) + 37607910542ll, // Ri(10^12) + 346065531065ll, // Ri(10^13) + 3204941731601ll // Ri(10^14) +}; + +void check(bool OK) +{ + std::cout << " " << (OK ? "OK" : "ERROR") << "\n"; + if (!OK) + std::exit(1); +} + +int main() +{ + uint64_t x = 1; + for (size_t i = 0; i < Ri_table.size(); i++) + { + x *= 10; + std::cout << "Ri(" << x << ") = " << Ri(x); + check(Ri(x) == Ri_table[i]); + } + + x = 1; + for (size_t i = 0; i < Ri_table.size(); i++) + { + x *= 10; + std::cout << "Ri_inverse(" << Ri_table[i] << ") = " << Ri_inverse(Ri_table[i]); + check(Ri_inverse(Ri_table[i]) < x && + Ri_inverse(Ri_table[i] + 1) >= x); + } + + // Sanity checks for tiny values of Ri(x) + for (x = 0; x < 10000; x++) + { + uint64_t rix = Ri(x); + double logx = std::log(max((double) x, 2.0)); + + if ((x >= 20 && rix < x / logx) || + (x >= 2 && rix > x * logx)) + { + std::cout << "Ri(" << x << ") = " << rix << " ERROR" << std::endl; + std::exit(1); + } + } + + // Sanity checks for small values of Ri(x) + for (; x < 100000; x += 101) + { + uint64_t rix = Ri(x); + double logx = std::log(max((double) x, 2.0)); + + if ((x >= 20 && rix < x / logx) || + (x >= 2 && rix > x * logx)) + { + std::cout << "Ri(" << x << ") = " << rix << " ERROR" << std::endl; + std::exit(1); + } + } + + // Sanity checks for tiny values of Ri_inverse(x) + for (x = 2; x < 1000; x++) + { + uint64_t res = Ri_inverse(x); + double logx = std::log((double) x); + + if (res < x || + (x >= 5 && res > x * logx * logx)) + { + std::cout << "Ri_inverse(" << x << ") = " << res << " ERROR" << std::endl; + std::exit(1); + } + } + + // Sanity checks for small values of Ri_inverse(x) + for (; x < 100000; x += 101) + { + uint64_t res = Ri_inverse(x); + double logx = std::log((double) x); + + if (res < x || + (x >= 5 && res > x * logx * logx)) + { + std::cout << "Ri_inverse(" << x << ") = " << res << " ERROR" << std::endl; + std::exit(1); + } + } + + std::cout << std::endl; + std::cout << "All tests passed successfully!" << std::endl; + + return 0; +} diff --git a/test/moebius.cpp b/test/moebius.cpp new file mode 100644 index 000000000..579ac0d97 --- /dev/null +++ b/test/moebius.cpp @@ -0,0 +1,99 @@ +/// +/// @file moebius.cpp +/// @brief Test the generate_moebius(n) function +/// @link https://en.wikipedia.org/wiki/Moebius_function +/// +/// Copyright (C) 2024 Kim Walisch, +/// +/// This file is distributed under the BSD License. See the COPYING +/// file in the top level directory. +/// + +#include + +#include +#include +#include +#include + +using std::size_t; +using namespace primesieve; + +/// Values of mu(n) for the first 1000 integers +/// https://oeis.org/A008683/b008683.txt +std::vector moebius = +{ + 0, 1, -1, -1, 0, -1, 1, -1, 0, 0, 1, -1, 0, -1, 1, 1, 0, -1, 0, -1, + 0, 1, 1, -1, 0, 0, 1, 0, 0, -1, -1, -1, 0, 1, 1, 1, 0, -1, 1, 1, + 0, -1, -1, -1, 0, 0, 1, -1, 0, 0, 0, 1, 0, -1, 0, 1, 0, 1, 1, -1, + 0, -1, 1, 0, 0, 1, -1, -1, 0, 1, -1, -1, 0, -1, 1, 0, 0, 1, -1, -1, + 0, 0, 1, -1, 0, 1, 1, 1, 0, -1, 0, 1, 0, 1, 1, 1, 0, -1, 0, 0, + 0, -1, -1, -1, 0, -1, 1, -1, 0, -1, -1, 1, 0, -1, -1, 1, 0, 0, 1, 1, + 0, 0, 1, 1, 0, 0, 0, -1, 0, 1, -1, -1, 0, 1, 1, 0, 0, -1, -1, -1, + 0, 1, 1, 1, 0, 1, 1, 0, 0, -1, 0, -1, 0, 0, -1, 1, 0, -1, 1, 1, + 0, 1, 0, -1, 0, -1, 1, -1, 0, 0, -1, 0, 0, -1, -1, 0, 0, 1, 1, -1, + 0, -1, -1, 1, 0, 1, -1, 1, 0, 0, -1, -1, 0, -1, 1, -1, 0, -1, 0, -1, + 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, -1, 0, 1, 1, 1, 0, 1, 1, 1, + 0, 1, -1, -1, 0, 0, 1, -1, 0, -1, -1, -1, 0, -1, 0, 1, 0, 1, -1, -1, + 0, -1, 0, 0, 0, 0, -1, 1, 0, 1, 0, -1, 0, 1, 1, -1, 0, -1, -1, 1, + 0, 0, 1, -1, 0, 1, -1, 1, 0, -1, 0, -1, 0, -1, 1, 0, 0, -1, 1, 0, + 0, -1, -1, -1, 0, -1, -1, 1, 0, 0, -1, 1, 0, -1, 0, 1, 0, 0, 1, 1, + 0, 1, 1, 1, 0, 1, 0, -1, 0, 1, -1, -1, 0, -1, 1, 0, 0, -1, -1, 1, + 0, 1, -1, 1, 0, 0, 1, 1, 0, 1, 1, -1, 0, 0, 1, 1, 0, -1, 0, 1, + 0, 1, 0, 0, 0, -1, 1, -1, 0, -1, 0, 0, 0, -1, -1, 1, 0, -1, 1, -1, + 0, 0, 1, 0, 0, 1, -1, -1, 0, 0, -1, 1, 0, -1, -1, 0, 0, 1, 0, -1, + 0, 1, 1, -1, 0, -1, 1, 0, 0, -1, 1, 1, 0, 1, 1, 1, 0, -1, 1, -1, + 0, -1, -1, 1, 0, 0, -1, 1, 0, -1, -1, 1, 0, 1, 0, 1, 0, 1, -1, -1, + 0, -1, 1, 0, 0, 0, -1, 1, 0, -1, -1, -1, 0, -1, -1, -1, 0, 1, -1, -1, + 0, 0, -1, -1, 0, 1, 1, 1, 0, -1, 0, 1, 0, 1, 1, -1, 0, -1, 1, 0, + 0, -1, 1, -1, 0, -1, 1, -1, 0, 1, -1, 1, 0, 1, -1, 0, 0, 0, 1, -1, + 0, 1, 1, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, -1, 0, 0, 1, -1, -1, + 0, 1, 1, -1, 0, 1, -1, 0, 0, -1, 1, 1, 0, 0, 1, 1, 0, 1, -1, 1, + 0, -1, 0, -1, 0, 0, 1, 1, 0, 0, -1, 0, 0, 1, -1, 1, 0, 1, 1, 0, + 0, -1, 1, 1, 0, 1, 1, -1, 0, 0, 0, 1, 0, 1, 1, -1, 0, -1, 0, 1, + 0, -1, 1, -1, 0, 1, 1, 0, 0, -1, 1, -1, 0, 1, -1, 0, 0, -1, 0, 1, + 0, 1, -1, 1, 0, 0, 1, -1, 0, 1, -1, 1, 0, -1, 0, -1, 0, 1, -1, -1, + 0, -1, -1, 0, 0, 0, -1, -1, 0, -1, -1, 1, 0, -1, 1, -1, 0, -1, -1, -1, + 0, 0, 1, 1, 0, 0, 1, -1, 0, 1, 0, -1, 0, 1, 1, 1, 0, 0, -1, 0, + 0, -1, -1, -1, 0, -1, -1, -1, 0, 1, 0, -1, 0, -1, -1, 1, 0, 0, -1, -1, + 0, -1, 1, -1, 0, -1, 0, 1, 0, 1, -1, 1, 0, -1, 1, 0, 0, -1, -1, 1, + 0, 1, -1, -1, 0, 1, 0, 1, 0, 1, 1, -1, 0, 0, 1, 1, 0, 1, 1, 1, + 0, -1, 0, 1, 0, -1, 1, 1, 0, -1, -1, 0, 0, 1, 1, -1, 0, 1, 1, -1, + 0, 1, 0, 1, 0, 0, 0, -1, 0, 0, -1, 1, 0, -1, 1, 0, 0, 1, 0, -1, + 0, -1, -1, -1, 0, 1, 1, 0, 0, 1, 0, -1, 0, 1, -1, 1, 0, -1, 1, -1, + 0, -1, -1, 1, 0, 0, 1, 1, 0, -1, 1, 1, 0, -1, 0, 0, 0, -1, 1, 1, + 0, 1, -1, 0, 0, 1, -1, -1, 0, 1, -1, 1, 0, 1, 1, -1, 0, -1, 1, 1, + 0, 0, 1, 1, 0, -1, -1, 1, 0, -1, 0, -1, 0, 1, -1, 1, 0, 1, 1, 0, + 0, -1, -1, -1, 0, 0, -1, -1, 0, -1, -1, 1, 0, 0, -1, 1, 0, 0, 1, -1, + 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, -1, -1, 0, 0, -1, 1, -1, + 0, -1, 1, -1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, -1, 0, 0, -1, 1, 1, + 0, -1, 0, -1, 0, -1, 1, -1, 0, 1, -1, 0, 0, 1, -1, 1, 0, -1, 1, 1, + 0, 1, -1, -1, 0, 1, -1, -1, 0, 0, 1, -1, 0, 1, 1, -1, 0, 1, 0, -1, + 0, 1, 1, 1, 0, 0, 1, 0, 0, -1, 1, 0, 0, 1, 1, -1, 0, -1, -1, 1, + 0, -1, -1, 1, 0, 0, -1, -1, 0, 1, 0, 1, 0, -1, 0, 1, 0, -1, 1, 1, + 0, 0, -1, 0, 0, 1, 1, -1, 0, -1, -1, -1, 0, 1, 1, 0, 0, -1, -1, 1, + 0, 0, 1, -1, 0, 1, -1, -1, 0, 1, 0, -1, 0, 1, -1, 1, 0, -1, 1, 0 +}; + +void check(bool OK) +{ + std::cout << " " << (OK ? "OK" : "ERROR") << "\n"; + if (!OK) + std::exit(1); +} + +int main() +{ + auto mu = generate_moebius(moebius.size() - 1); + + for (size_t i = 1; i < mu.size(); i++) + { + std::cout << "mu(" << i << ") = " << mu[i]; + check(mu[i] == moebius[i]); + } + + std::cout << std::endl; + std::cout << "All tests passed successfully!" << std::endl; + + return 0; +}