libjmmcg  release_579_6_g8cffd
A C++ library containing an eclectic mix of useful, advanced components.
prime_numbers.hpp
Go to the documentation of this file.
1 /******************************************************************************
2 ** Copyright © 2012 by J.M.McGuiness, coder@hussar.me.uk
3 **
4 ** This library is free software; you can redistribute it and/or
5 ** modify it under the terms of the GNU Lesser General Public
6 ** License as published by the Free Software Foundation; either
7 ** version 2.1 of the License, or (at your option) any later version.
8 **
9 ** This library is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 ** Lesser General Public License for more details.
13 **
14 ** You should have received a copy of the GNU Lesser General Public
15 ** License along with this library; if not, write to the Free Software
16 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18 
19 #include "config.h"
20 
21 #include <algorithm>
22 #include <bitset>
23 #include <vector>
24 
25 namespace jmmcg { namespace LIBJMMCG_VER_NAMESPACE {
26 
27 namespace dyn {
28  typedef std::vector<unsigned long long> primes_colln;
29 
30  /// Find all of the prime numbers in the range [2...max_num) using the Sieve of Eratosthenes.
31  /**
32  Complexity: time: O(n(log(log(n))))
33 
34  \param max_num The largest number in the range up to which the primes should be found.
35  \return The primes within the range [2...max_num).
36  */
37  inline primes_colln
38  sieve_of_eratosthenes(primes_colln::size_type max_num) noexcept(false) {
39  bool is_prime[max_num];
40  std::fill_n(is_prime, max_num, true);
41  for (primes_colln::size_type i=2; i<std::sqrt(max_num); ++i) {
42  if (is_prime[i]) {
43  for (primes_colln::size_type j=i*i; j<max_num; j+=i) {
44  is_prime[j]=false;
45  }
46  }
47  }
48  primes_colln::size_type num_primes=0;
49  for (primes_colln::size_type i=2; i<max_num; ++i) {
50  if (is_prime[i]) {
51  ++num_primes;
52  }
53  }
54  assert(num_primes<=max_num);
55  primes_colln primes;
56  primes.reserve(num_primes);
57  for (primes_colln::size_type i=2; i<max_num; ++i) {
58  if (is_prime[i]) {
59  primes.push_back(i);
60  }
61  }
62  return primes;
63  }
64 }
65 
66 namespace mpl {
67  template<class E, E MN>
69  public:
70  typedef E element_type;
72 
73  static constexpr element_type max_num=MN;
74 
75  private:
76  static constexpr std::bitset<max_num>
77  filter_primes() noexcept(true) {
78  std::bitset<max_num> is_prime;
79  for (typename primes_colln::size_type i=2; i<std::sqrt(max_num); ++i) {
80  if (!is_prime[i]) {
81  for (std::size_t j=i*i; j<max_num; j+=i) {
82  is_prime[j]=true;
83  }
84  }
85  }
86  return is_prime;
87  }
88 
89 
90  static constexpr typename primes_colln::size_type
91  count_primes(std::bitset<max_num> const &is_prime) noexcept(true) __attribute__((pure)) {
92  typename primes_colln::size_type num_primes=0;
93  for (typename primes_colln::size_type i=2; i<max_num; ++i) {
94  if (is_prime[i]) {
95  ++num_primes;
96  }
97  }
98  return num_primes;
99  }
100 
101  public:
102  static primes_colln
103  result() noexcept(false) {
104  const std::bitset<max_num> is_prime(filter_primes());
105  primes_colln primes;
106  primes.reserve(count_primes(is_prime));
107  for (typename primes_colln::size_type i=2; i<max_num; ++i) {
108  if (!is_prime[i]) {
109  primes.push_back(i);
110  }
111  }
112  return primes;
113  }
114  };
115 }
116 
117 } }