Guest User

Untitled

a guest
Oct 18th, 2018
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.08 KB | None | 0 0
  1. /**
  2. * Created by Josh Max on 10/12/18
  3. */
  4.  
  5. #include <cmath>
  6. #include <iostream>
  7. #include <vector>
  8. #include <sched.h>
  9. #include <chrono>
  10. #include <map>
  11.  
  12. #define FIRST_NUM 8 // The first number for us to start at
  13. #define INC_NUM 20 // The amount to increment n by each time in graph mode
  14.  
  15. #ifdef HASPLOTLIBS
  16. #include "matplotlibcpp.h"
  17. namespace plt = matplotlibcpp;
  18.  
  19. /**
  20. * Initialize the plotting subsystem.
  21. *
  22. * @param n_max The maximum x value for the graph
  23. */
  24. inline void plot_init(int n_max)
  25. {
  26. // Set the size of output image to 1200x780 pixels
  27. plt::figure_size(1200, 780);
  28.  
  29. // Set x-axis to interval [FIRST_PRIME, N_MAX]
  30. plt::xlim(FIRST_NUM, n_max);
  31.  
  32. // Add the graph title
  33. plt::title("Euclid Algorithm Complexity");
  34. }
  35. #endif
  36.  
  37. /**
  38. * Perform Euclid's algorithm to determine the GCD of two integers.
  39. *
  40. * @param a The first number
  41. * @param b The second number
  42. * @param outres A variable to hold the calculated GCD
  43. * @return The number of modulo operations necessary to find the GCD
  44. */
  45. inline int gcd(int a, int b, int &outres)
  46. {
  47. int mod_oper = 0;
  48. int temp;
  49. while (b != 0)
  50. {
  51. temp = a % b;
  52. a = b;
  53. b = temp;
  54. mod_oper++;
  55. }
  56.  
  57. outres = a; // Place the result of our GCD
  58. return mod_oper; // Return the number of modulo operations
  59. }
  60.  
  61. /**
  62. * Iterate through the GCDs of a series of integer pairs below n and determine the one with the most
  63. * modulo operations required to get its result.
  64. *
  65. * @param timing_ref The timing data for each loop
  66. * @param complx_ref The complexity data for each loop
  67. * @param n The maximum number to iterate to. Should be > 8
  68. */
  69. void do_euclid(std::map<int, int>& timing_ref, std::map<int, int>& complx_ref, int n)
  70. {
  71. // Use the std::chrono high resolution clock instead of the POSIX-y, non-portable gettimeofday()
  72. std::chrono::high_resolution_clock::time_point start_time = std::chrono::high_resolution_clock::now();
  73.  
  74. int mod_max = 0;
  75. int a = FIRST_NUM;
  76. int a_max = a;
  77. int b = FIRST_NUM;
  78. int b_max = b;
  79. int val_gcd = 0;
  80. for (; a < n; a++) // Iterate through all n - 1
  81. {
  82. for (b = FIRST_NUM; b <= n; b++) // We add 1 to a because a = n - 1
  83. {
  84. int gcd_res;
  85. int rc = gcd(a, b, gcd_res);
  86. if (rc > mod_max) {
  87. a_max = a;
  88. b_max = b;
  89. val_gcd = gcd_res;
  90. mod_max = rc;
  91. }
  92. }
  93. }
  94.  
  95. // Get the ending time for our function
  96. std::chrono::high_resolution_clock::time_point end_time = std::chrono::high_resolution_clock::now();
  97. int duration = (int) std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time).count();
  98.  
  99. // Save the timing data
  100. timing_ref[n] = duration;
  101.  
  102. // Add to our discovered complexity vector
  103. complx_ref[n] = mod_max;
  104.  
  105. // Print!
  106. std::cout << "gcd(" << a_max << ", " << b_max << ") = " << val_gcd << " took "
  107. << mod_max << " modulus operations ...time required = " << duration << "us" << std::endl;
  108. }
  109.  
  110. int main(int argc, char** argv)
  111. {
  112. // Plotting stuff
  113. std::vector<double> x_val,
  114. complexity_iters,
  115. gcd_iters,
  116. timing_iters;
  117.  
  118. // Create a map to hold our complexity data
  119. std::map<int, int> timing_data,
  120. calculated_complexity;
  121.  
  122. // Get the maximum n value from the user
  123. int n_max;
  124. std::cout << "Enter max n: ";
  125. std::cin >> n_max;
  126.  
  127. /**
  128. * Set the default scheduler to maximum priority.
  129. *
  130. * Since essentially all modern kernels are preemptable,
  131. * By default there is a high degree of process jitter based
  132. * On the default scheduler settings, so we set our nice value
  133. * To SCHED_MAX. This also prevents automatic scheduler niceness
  134. * Adjustment on some kernels. NOTE: To reduce latency even further,
  135. * SCHED_RR or SCHED_FIFO can be used on Linux kernels with PREEMPT_RT.
  136. */
  137. struct sched_param s_param;
  138. s_param.sched_priority = sched_get_priority_max(SCHED_OTHER);
  139.  
  140. if (sched_setscheduler(0, SCHED_OTHER, &s_param) == -1)
  141. std::cout << "sched_setscheduler() failed" << std::endl;
  142.  
  143. int n = n_max;
  144. #ifdef HASPLOTLIBS
  145. // We're going to plot this data, so we should loop through all n below n_max
  146. for (n = FIRST_NUM; n <= n_max; n += INC_NUM)
  147. {
  148. #endif
  149. do_euclid(timing_data, calculated_complexity, n);
  150. #ifdef HASPLOTLIBS
  151. }
  152. #endif
  153.  
  154. #ifdef HASPLOTLIBS
  155. // Loop through every n increment to build the graph data
  156. for (unsigned long i = FIRST_NUM; i <= n_max; i += INC_NUM)
  157. {
  158. x_val.push_back(i);
  159. complexity_iters.push_back(log((double) 2 / 3 * i) / log((double) 3 / 2));
  160. gcd_iters.push_back(calculated_complexity[i]);
  161. timing_iters.push_back((double) timing_data[i] / (i * i)); // Use O(n^2)
  162. }
  163.  
  164. // Init the plotting library
  165. plot_init(n_max); // We only want to go to n
  166.  
  167. // Name it
  168. plt::named_plot("log_(3/2)(2n/3)", x_val, complexity_iters);
  169. plt::named_plot("gcd(a,b)", x_val, gcd_iters);
  170. plt::named_plot("T(n)/F(n)", x_val, timing_iters);
  171.  
  172. // Enable legend
  173. plt::legend();
  174.  
  175. // Show the generated graph
  176. plt::show();
  177. #endif
  178. }
Add Comment
Please, Sign In to add comment