File: P2.cpp

package info (click to toggle)
primecount 8.0%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,640 kB
  • sloc: cpp: 21,835; ansic: 121; sh: 99; makefile: 89
file content (134 lines) | stat: -rw-r--r-- 3,082 bytes parent folder | download | duplicates (2)
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
///
/// @file   P2.cpp
/// @brief  Test the 2nd partial sieve function P2(x, a)
///         that counts the numbers <= x that have exactly
///         2 prime factors each exceeding the a-th prime.
///
/// Copyright (C) 2023 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.hpp>
#include <primecount-internal.hpp>
#include <generate_primes.hpp>
#include <imath.hpp>

#include <stdint.h>
#include <iostream>
#include <cstdlib>
#include <vector>
#include <random>

using std::size_t;
using namespace primecount;

void check(bool OK)
{
  std::cout << "   " << (OK ? "OK" : "ERROR") << "\n";
  if (!OK)
    std::exit(1);
}

int main()
{
  // Test small x values
  {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<int> dist(2, 1000);

    for (int i = 0; i < 100; i++)
    {
      int threads = 1;
      int64_t x = dist(gen);
      auto primes = generate_primes<int64_t>(x);

      for (int a = 1; primes[a] <= isqrt(x); a++)
      {
        int64_t p2 = 0;

        for (size_t b = a + 1; b < primes.size(); b++)
        {
          for (size_t c = b; c < primes.size(); c++)
          {
            if (primes[b] * primes[c] <= x)
              p2++;
            else
              break;
          }
        }

        std::cout << "P2(" << x << ", " << a << ") = " << p2;
        check(p2 == P2(x, primes[a], a, threads));
      }
    }
  }

  // Test medium x values
  {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<int> dist(1000, 200000);

    for (int i = 0; i < 100; i++)
    {
      int threads = 1;
      int64_t x = dist(gen);
      auto primes = generate_primes<int64_t>(x);

      for (int a = 1; primes[a] <= isqrt(x); a++)
      {
        int64_t p2 = 0;

        for (size_t b = a + 1; b < primes.size(); b++)
        {
          for (size_t c = b; c < primes.size(); c++)
          {
            if (primes[b] * primes[c] <= x)
              p2++;
            else
              break;
          }
        }

        std::cout << "P2(" << x << ", " << a << ") = " << p2;
        check(p2 == P2(x, primes[a], a, threads));
      }
    }
  }

  int threads = get_num_threads();

  {
    // Test P2(1e13) and compare with known correct value
    int64_t x = 10000000000000ll;
    int64_t y = 178815;
    int64_t a = 16229;
    int64_t res1 = P2(x, y, a, threads);
    int64_t res2 = 113111712222ll;

    std::cout << "P2(" << x << ", " << y << ", " << a << ") = " << res1;
    check(res1 == res2);
  }

#ifdef HAVE_INT128_T
  {
    // Test P2(1e14) and compare with known correct value
    int128_t x = 100000000000000ll;
    int64_t y = 494134;
    int64_t a = 41080;
    int128_t res1 = P2(x, y, a, threads);
    int128_t res2 = 1026583290763ll;

    std::cout << "P2(" << x << ", " << y << ", " << a << ") = " << res1;
    check(res1 == res2);
  }
#endif

  std::cout << std::endl;
  std::cout << "All tests passed successfully!" << std::endl;

  return 0;
}