1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
|
///
/// @file Li.cpp
/// @brief Test the offset logarithmic integral function.
/// Li(x) = li(x) - li(2)
///
/// Copyright (C) 2021 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///
#include <primecount-internal.hpp>
#include <imath.hpp>
#include <stdint.h>
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <vector>
using std::max;
using std::size_t;
using namespace primecount;
std::vector<int64_t> 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()
{
for (size_t i = 0; i < Li_table.size(); i++)
{
int p = (int) i + 1;
int64_t x = ipow(10ll, p);
std::cout << "Li(" << x << ") = " << Li(x);
check(Li(x) == Li_table[i]);
}
for (size_t i = 0; i < Li_table.size(); i++)
{
int p = (int) i + 1;
int64_t x = ipow(10ll, p);
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 (int64_t x = 0; x < 300000; x++)
{
int64_t lix = Li(x);
double logx = std::log(max((double) x, 2.0));
if (lix < 0 ||
(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 (int64_t x = 2; x < 30000; x++)
{
int64_t res = Li_inverse(x);
double logx = std::log((double) x);
if (res < 0 ||
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;
}
|