openGPMP
Open Source Mathematics Package
primes.cpp
Go to the documentation of this file.
1 
8 #include <chrono>
9 #include <cmath>
10 #include <iostream>
14 #include <vector>
15 
16 void testing_miller(std::vector<int64_t> nums) {
17  /* SEQUENTIAL MILLER-RABIN TEST */
18  std::chrono::steady_clock::time_point start_time =
19  std::chrono::steady_clock::now();
20 
21  gpmp::PrimalityTest prims;
22  std::cout << "Miller-Rabin sequentially without ThreadPool" << std::endl;
23 
24  for (uint64_t n : nums) {
25  if (prims.miller_rabin_prime(n, 120000))
26  std::cout << n << " is prime" << std::endl;
27  else
28  std::cout << n << " is composite" << std::endl;
29  }
30 
31  std::chrono::steady_clock::time_point end_time =
32  std::chrono::steady_clock::now();
33 
34  std::cout << "Time elapsed: "
35  << std::chrono::duration_cast<std::chrono::milliseconds>(
36  end_time - start_time)
37  .count()
38  << " ms" << std::endl;
39 }
40 
41 void testing_miller_thread(std::vector<int64_t> nums) {
42  /* MILLER-RABIN TEST USING THREADPOOL WITH MANUAL ENQUEUE */
43  std::chrono::steady_clock::time_point start_time =
44  std::chrono::steady_clock::now();
45 
46  // declares a threadpool with 4 threads
48 
49  std::vector<std::future<bool>> miller_results;
51  for (auto n : nums) {
52  miller_results.emplace_back(pool->enqueue(
53  [&prim, n]() { return prim.miller_rabin_prime(n, 120000); }));
54  }
55 
56  // Print the results
57  std::cout << "\nResults:\n";
58  std::cout << "Miller-Rabin with ThreadPool" << std::endl;
59  for (size_t i = 0; i < miller_results.size(); i++) {
60  bool is_prime = miller_results[i].get();
61  std::cout << nums[i] << " is " << (is_prime ? "prime" : "composite")
62  << "\n";
63  }
64  delete pool;
65 
66  std::chrono::steady_clock::time_point end_time =
67  std::chrono::steady_clock::now();
68 
69  std::cout << "Time elapsed: "
70  << std::chrono::duration_cast<std::chrono::milliseconds>(
71  end_time - start_time)
72  .count()
73  << " ms" << std::endl;
74 }
75 
76 void testing_new_miller(std::vector<int64_t> nums) {
77  /* MILLER-RABIN USING THREADPOOL DISPATCH UTILITY FUNCTION */
78  std::chrono::steady_clock::time_point start_time =
79  std::chrono::steady_clock::now();
80  auto start = std::chrono::high_resolution_clock::now();
81 
82  std::vector<std::future<bool>> miller_results;
83 
86 
87  for (auto n : nums) {
88  // enqueue the function call to the thread pool using the
89  // ThreadDispatch.dispatch() function
90  miller_results.emplace_back(gpmp::core::ThreadDispatch().dispatch(
91  *pool,
93  &prim,
94  n,
95  120000));
96  }
97 
98  // Print the results
99  std::cout << "\nResults:\n";
100  std::cout << "Miller-Rabin with ThreadPool using ThreadDispatch.dispatch()"
101  << std::endl;
102 
103  for (size_t i = 0; i < miller_results.size(); i++) {
104  bool is_prime = miller_results[i].get();
105  std::cout << nums[i] << " is " << (is_prime ? "prime" : "composite")
106  << "\n";
107  }
108  delete pool;
109 
110  std::chrono::steady_clock::time_point end_time =
111  std::chrono::steady_clock::now();
112 
113  std::cout << "Time elapsed: "
114  << std::chrono::duration_cast<std::chrono::milliseconds>(
115  end_time - start_time)
116  .count()
117  << " ms" << std::endl;
118 }
119 
120 int main() {
121  std::cout << "BASIC NUMBER THEORY OPERATIONS\n" << std::endl;
122  // declare primality class object
124 
125  std::cout << "<--------- IS IT PRIME? --------->\n";
126  int a = 9;
127  // check if an integer is prime or not
128  bool is_it = p.is_prime(a);
129 
130  std::cout << a << " is prime? : ";
131  is_it ? std::cout << "true\n" : std::cout << "false\n" << std::endl;
132 
133  int b = 2;
134  bool is_it2 = p.is_prime(b);
135 
136  std::cout << b << " is prime? : ";
137  is_it2 ? std::cout << "true\n" : std::cout << "false\n" << std::endl;
138  std::cout << "\n";
139 
140  std::cout << "<--------- MILLER-RABIN METHOD --------->\n";
141  int min_num = 1;
142  // display the prime numbers smaller than a given value
143  int max_num = 100;
144  // number of iterations
145  int iters = 4;
146  /*
147  * calculate the solution, the method doesn't return a value,
148  * prints the values
149  */
150  p.miller_rabin(iters, min_num, max_num);
151  p.miller_rabin(iters, 25, 50);
152  p.miller_rabin(iters, 30, 3000);
153 
154  std::cout << "\n";
155 
156  std::cout << "<--------- CARMICHAEL NUMBERS --------->\n";
157  int cm_test = 500;
158  bool carm_num = p.carmichael_num(cm_test);
159 
160  int cm_test1 = 561;
161  bool carm_num1 = p.carmichael_num(cm_test1);
162 
163  int cm_test2 = 1105;
164  bool carm_num2 = p.carmichael_num(cm_test2);
165 
166  std::cout << cm_test << " is a carmichael number : ";
167  carm_num ? std::cout << "true\n" : std::cout << "false\n";
168 
169  std::cout << cm_test1 << " is a carmichael number : ";
170  carm_num1 ? std::cout << "true\n" : std::cout << "false\n";
171 
172  std::cout << cm_test2 << " is a carmichael number : ";
173  carm_num2 ? std::cout << "true\n" : std::cout << "false\n";
174 
175  std::cout << "\n";
176  /*
177  * Power Modulo function
178  */
179  int pow_a = 3;
180  int pow_b = 2;
181  int pow_c = 2;
182  // returns (a^b) % c
183  int pow_res = p.mod_pow(pow_a, pow_b, pow_c);
184  printf("%d ^ %d %% %d = %d\n", pow_a, pow_b, pow_c, pow_res);
185 
186  int pow_d = 5;
187  int pow_e = 2;
188  int pow_f = 7;
189 
190  int pow_res_1 = p.mod_pow(pow_d, pow_e, pow_f);
191  printf("%d ^ %d %% %d = %d\n", pow_d, pow_e, pow_f, pow_res_1);
192 
193  int pow_g = 8;
194  int pow_h = 9;
195  int pow_i = 3;
196 
197  int pow_res_2 = p.mod_pow(pow_g, pow_h, pow_i);
198  printf("%d ^ %d %% %d = %d\n", pow_g, pow_h, pow_i, pow_res_2);
199 
200  bool cmp = p.miller_rabin_prime(5, 4);
201  std::cout << "miller_rabin_prime: " << cmp << "\n";
202  std::cout << "\n";
203  /*
204  * Jacobian
205  */
206 
207  /*
208  * Solovay-Strassen Primality Test
209  */
210  int ss_0 = 15;
211  if (p.solovoy_strassen(ss_0, 50))
212  printf("%d is prime\n", ss_0);
213  else
214  printf("%d is composite\n", ss_0);
215 
216  std::cout << "\n";
217 
218  // example vector of 64 bit integers
219  std::vector<int64_t> nums = {
220  9223372036854775803, 9223372036854775807, 9223372036854775303,
221  4567890123456789LL, 5678901234567890LL, 6789012345678901LL,
222  7890123456789012LL, 8901234567890123LL, 9999999967LL,
223  12345678901234567LL, 987654321987654321LL, 2147483647LL,
224  9223372036854775783LL, 1311768467463790320LL, 7237005577332262210LL,
225  3037000499LL, 2305843009213693951LL, 2305843009213693967LL,
226  2305843009213693971LL, 2305843009213693973LL, 2305843009213693977LL,
227  2305843009213693989LL};
228 
229  testing_miller(nums);
230  std::cout << "<--------- USING THREADPOOL --------->\n";
231 
232  testing_miller_thread(nums);
233  testing_new_miller(nums);
234  testing_miller_thread(nums);
235 
236  // vector if 64 bit integers
237 
238  return 0;
239 }
bool miller_rabin_prime(uint64_t n, uint64_t iters)
Modified primes algorithm.
Definition: prime_test.cpp:183
bool carmichael_num(uint64_t n)
Definition: prime_test.cpp:349
void miller_rabin(uint64_t iters, uint64_t min_val, uint64_t max_val)
Miller-Rabin driver, prints values that satisfy conditions.
Definition: prime_test.cpp:207
uint64_t mod_pow(uint64_t a, uint64_t b, uint64_t m)
Definition: prime_test.cpp:72
bool is_prime(uint64_t n)
Determine if an integer is prime.
Definition: prime_test.cpp:102
bool solovoy_strassen(uint64_t p, uint64_t iters)
Definition: prime_test.cpp:325
A class that provides a function to dispatch a function call to a thread pool and return a future obj...
Definition: threads.hpp:204
auto enqueue(F &&f, Args &&...args) -> std::future< typename std::invoke_result< F, Args... >::type >
Enqueues a task to the thread pool.
Definition: threads.hpp:148
gpmp::PrimalityTest prim
Definition: prime_test.cpp:56
void testing_miller(std::vector< int64_t > nums)
Definition: primes.cpp:16
void testing_new_miller(std::vector< int64_t > nums)
Definition: primes.cpp:76
void testing_miller_thread(std::vector< int64_t > nums)
Definition: primes.cpp:41
int main()
Definition: primes.cpp:120
openGPMP Thread Pool