Pierpont primes: Difference between revisions
Content added Content deleted
m (More efficient implementation of n-smooth number generator) |
|||
Line 365: | Line 365: | ||
{{libheader|GMP}} |
{{libheader|GMP}} |
||
<lang cpp>#include <cassert> |
<lang cpp>#include <cassert> |
||
⚫ | |||
#include <iomanip> |
#include <iomanip> |
||
#include <iostream> |
#include <iostream> |
||
⚫ | |||
#include <vector> |
#include <vector> |
||
#include <gmpxx.h> |
#include <gmpxx.h> |
||
Line 373: | Line 373: | ||
using big_int = mpz_class; |
using big_int = mpz_class; |
||
bool is_prime(const big_int& n) |
bool is_prime(const big_int& n) { |
||
{ |
|||
return mpz_probab_prime_p(n.get_mpz_t(), 25); |
return mpz_probab_prime_p(n.get_mpz_t(), 25); |
||
} |
} |
||
template <typename integer> |
|||
class n_smooth_generator |
class n_smooth_generator { |
||
{ |
|||
public: |
public: |
||
explicit n_smooth_generator( |
explicit n_smooth_generator(size_t n); |
||
integer next(); |
|||
size_t size() const { |
|||
return results_.size(); |
|||
⚫ | |||
private: |
private: |
||
std::vector< |
std::vector<size_t> primes_; |
||
std:: |
std::vector<size_t> index_; |
||
std::vector<integer> results_; |
|||
std::vector<integer> queue_; |
|||
}; |
}; |
||
template <typename integer> |
|||
n_smooth_generator::n_smooth_generator( |
n_smooth_generator<integer>::n_smooth_generator(size_t n) { |
||
{ |
|||
for ( |
for (size_t p = 2; p <= n; ++p) { |
||
⚫ | |||
⚫ | |||
⚫ | |||
primes_.push_back(p); |
primes_.push_back(p); |
||
queue_.push_back(p); |
|||
⚫ | |||
} |
} |
||
index_.assign(primes_.size(), 0); |
|||
results_.push_back(1); |
|||
} |
} |
||
template <typename integer> |
|||
integer n_smooth_generator<integer>::next() { |
|||
{ |
|||
integer last = results_.back(); |
|||
⚫ | |||
big_int result = *numbers_.begin(); |
|||
if (queue_[i] == last) |
|||
numbers_.erase(numbers_.begin()); |
|||
queue_[i] = results_[++index_[i]] * primes_[i]; |
|||
⚫ | |||
numbers_.insert(result * prime); |
|||
results_.push_back(*min_element(queue_.begin(), queue_.end())); |
|||
return |
return last; |
||
} |
} |
||
void print_vector(const std::vector<big_int>& numbers) |
void print_vector(const std::vector<big_int>& numbers) { |
||
for (size_t i = 0, n = numbers.size(); i < n; ++i) { |
|||
{ |
|||
⚫ | |||
⚫ | |||
std::cout << std::setw(9) << numbers[i]; |
std::cout << std::setw(9) << numbers[i]; |
||
if ((i + 1) % 10 == 0) |
if ((i + 1) % 10 == 0) |
||
Line 419: | Line 424: | ||
} |
} |
||
int main() |
int main() { |
||
{ |
|||
const int max = 250; |
const int max = 250; |
||
std::vector<big_int> first, second; |
std::vector<big_int> first, second; |
||
int count1 = 0; |
int count1 = 0; |
||
int count2 = 0; |
int count2 = 0; |
||
n_smooth_generator smooth_gen(3); |
n_smooth_generator<big_int> smooth_gen(3); |
||
big_int p1, p2; |
big_int p1, p2; |
||
while (count1 < max || count2 < max) |
while (count1 < max || count2 < max) { |
||
{ |
|||
big_int n = smooth_gen.next(); |
big_int n = smooth_gen.next(); |
||
if (count1 < max && is_prime(n + 1)) |
if (count1 < max && is_prime(n + 1)) { |
||
⚫ | |||
p1 = n + 1; |
p1 = n + 1; |
||
if (first.size() < 50) |
if (first.size() < 50) |
||
Line 438: | Line 440: | ||
++count1; |
++count1; |
||
} |
} |
||
if (count2 < max && is_prime(n - 1)) |
if (count2 < max && is_prime(n - 1)) { |
||
{ |
|||
p2 = n - 1; |
p2 = n - 1; |
||
if (second.size() < 50) |
if (second.size() < 50) |
||
Line 454: | Line 455: | ||
std::cout << "250th Pierpont prime of the first kind: " << p1 << '\n'; |
std::cout << "250th Pierpont prime of the first kind: " << p1 << '\n'; |
||
std::cout << "250th Pierpont prime of the second kind: " << p2 << '\n'; |
std::cout << "250th Pierpont prime of the second kind: " << p2 << '\n'; |
||
return 0; |
return 0; |
||
}</lang> |
}</lang> |