#include <primecount.hpp>
#include <primecount-internal.hpp>
#include <imath.hpp>
#include <PhiTiny.hpp>
#include <int128_t.hpp>
#include <print.hpp>
#include <S.hpp>
#include <stdint.h>
#include <string>
using namespace primecount;
namespace {
template <typename T>
T S2(T x,
int64_t y,
int64_t z,
int64_t c,
T s2_approx,
int threads,
bool is_print)
{
T s2_trivial = S2_trivial(x, y, z, c, threads, is_print);
T s2_easy = S2_easy(x, y, z, c, threads, is_print);
T s2_hard_approx = s2_approx - (s2_trivial + s2_easy);
T s2_hard = S2_hard(x, y, z, c, s2_hard_approx, threads, is_print);
T s2 = s2_trivial + s2_easy + s2_hard;
return s2;
}
}
namespace primecount {
int64_t pi_deleglise_rivat_64(int64_t x,
int threads,
bool is_print)
{
if (x < 2)
return 0;
double alpha = get_alpha_deleglise_rivat(x);
int64_t x13 = iroot<3>(x);
int64_t y = (int64_t) (x13 * alpha);
int64_t z = x / y;
int64_t pi_y = pi_noprint(y, threads);
int64_t c = PhiTiny::get_c(y);
if (is_print)
{
print("");
print("=== pi_deleglise_rivat_64(x) ===");
print("pi(x) = S1 + S2 + pi(y) - 1 - P2");
print(x, y, z, c, threads);
}
int64_t p2 = P2(x, y, threads, is_print);
int64_t s1 = S1(x, y, c, threads, is_print);
int64_t s2_approx = S2_approx(x, pi_y, p2, s1);
int64_t s2 = S2(x, y, z, c, s2_approx, threads, is_print);
int64_t phi = s1 + s2;
int64_t sum = phi + pi_y - 1 - p2;
return sum;
}
#if defined(HAVE_INT128_T)
int128_t pi_deleglise_rivat_128(int128_t x,
int threads,
bool is_print)
{
if (x < 2)
return 0;
double alpha = get_alpha_deleglise_rivat(x);
maxint_t limit = get_max_x(alpha);
if (x > limit)
throw primecount_error("pi(x): x must be <= " + to_string(limit));
int64_t y = (int64_t) (iroot<3>(x) * alpha);
int64_t z = (int64_t) (x / y);
int64_t pi_y = pi_noprint(y, threads);
int64_t c = PhiTiny::get_c(y);
if (is_print)
{
print("");
print("=== pi_deleglise_rivat_128(x) ===");
print("pi(x) = S1 + S2 + pi(y) - 1 - P2");
print(x, y, z, c, threads);
}
int128_t p2 = P2(x, y, threads, is_print);
int128_t s1 = S1(x, y, c, threads, is_print);
int128_t s2_approx = S2_approx(x, pi_y, p2, s1);
int128_t s2 = S2(x, y, z, c, s2_approx, threads, is_print);
int128_t phi = s1 + s2;
int128_t sum = phi + pi_y - 1 - p2;
return sum;
}
#endif
}