Advertisement
Guest User

Untitled

a guest
Sep 21st, 2019
99
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.78 KB | None | 0 0
  1. /* author Bill Wood */
  2.  
  3. use rayon::prelude::*;
  4. use std::io::Write;
  5.  
  6. fn main() {
  7. let mut args = std::env::args()
  8. .skip(1)
  9. .map(|a| a
  10. .split('_')
  11. .fold("".to_string(), |a, s| a + s)
  12. .parse::<usize>());
  13.  
  14. if args.len() <= 3 {
  15. if let (Ok(mut low), Ok(mut high), Ok(seg_size_kb), ) = (
  16. args.next().unwrap_or(Ok(0)),
  17. args.next().unwrap_or(Ok(200)),
  18. args.next().unwrap_or(Ok(128)),) {
  19. println!("S15: Finding sexy primes with args {} {} {}", low, high, seg_size_kb, );
  20.  
  21. let count_two = if low <= 2 && high >= 2 { 1 } else { 0 };
  22. low = if low < 3 { 3 } else { low | 1 }; // lowest odd >= low
  23. high = (high - 1) | 1; // highest odd <= high
  24.  
  25. // find sieving primes
  26. let sieve_primes = simple_sieve(high);
  27.  
  28. // prepare for parallel segment sieve
  29. let mut candidates_per_seg = seg_size_kb*1024*2;
  30. while (high - low)/candidates_per_seg > 100_000_000 { // increase seg size to reduce mem usage
  31. candidates_per_seg *= 2;
  32. }
  33. dbg!(candidates_per_seg/1024/2);
  34. let segs: Vec<(usize, usize)> = { low..=high }
  35. .step_by(candidates_per_seg)
  36. .map(|seg_low| {
  37. let seg_high = seg_low + candidates_per_seg - 2;
  38. (seg_low, if seg_high > high { high } else { seg_high } + 6)
  39. })
  40. .collect();
  41.  
  42. // do parallel segment sieve
  43. let (sexy_count, nprimes) =
  44. segs.into_par_iter()
  45. .map(|(low, high)| {
  46. // sieve this segment
  47. let sieve_seg = seg_sieve(low, high, &sieve_primes);
  48. // find sexy primes in this segment
  49. let (mut sexy_count, mut nprimes) = (0_usize, 0_usize);
  50. for p in 0..sieve_seg.len() - 6/2 {
  51. if unsafe { !sieve_seg.get_unchecked(p) } {
  52. nprimes += 1;
  53. // print!("{} ", (p << 1) + low);
  54. if unsafe { !sieve_seg.get_unchecked(p + 6/2) } {
  55. sexy_count += 1;
  56. }
  57. }
  58. }
  59. (sexy_count, nprimes)
  60. })
  61. .reduce(|| (0, 0),
  62. |a, b| (a.0 + b.0, a.1 + b.1));
  63.  
  64. println!("\n{} of {} primes are sexy", sexy_count, nprimes + count_two);
  65. return;
  66. }
  67. }
  68.  
  69. writeln!(std::io::stderr(), "Usage: sexy_primes [low [high [seg_size_kb]]]").unwrap();
  70. std::process::exit(1);
  71. }
  72.  
  73. fn simple_sieve(mut high: usize) -> Vec<u32> {
  74. // x where x: odd and (x+2)^2 > high and x^2 < high
  75. high = (sqrt(high) - 1) | 1;
  76. dbg!(high);
  77. let mut pvec = vec![false; (high + 1)/2];
  78. let mut primes = vec![];
  79. let n = high >> 1;
  80. let mut i = 3;
  81. while i*i <= high {
  82. if unsafe { !pvec.get_unchecked(i >> 1) } {
  83. primes.push(i as u32);
  84. let mut j = (i*i) >> 1;
  85. while j <= n {
  86. unsafe { *pvec.get_unchecked_mut(j) = true };
  87. j += i;
  88. }
  89. }
  90. i += 2;
  91. }
  92. i >>= 1;
  93. while i <= n {
  94. if unsafe { !pvec.get_unchecked(i) } {
  95. primes.push(((i << 1) | 1) as u32);
  96. }
  97. i += 1;
  98. }
  99. primes
  100. }
  101.  
  102. /*
  103. 2 3 5 7
  104. 3
  105. 5 *
  106. 7 *
  107. 9 x
  108. 11 *
  109. 13
  110. 15 x x
  111. 17
  112. 19
  113. 21 x x
  114. 23
  115. 25 x
  116. 27 x
  117. 29
  118. 31
  119. 33 x
  120. 35 x x
  121. 37 *
  122. 39 x
  123. 41
  124. 43
  125. 45 x x
  126. 47
  127. 49 x
  128. 51 x
  129. 53
  130. 55 x
  131. 57 x
  132. 59
  133. 61
  134. 63 x x
  135. 65 x
  136. 67 *
  137. 69 x
  138. 71
  139. 73
  140. 75 x x
  141. 77 x
  142. 79
  143. 81 x
  144. 83
  145. 85 x
  146. 87 x
  147. 89
  148. 91 x
  149. 93 x
  150. 95 x
  151. 97 *
  152. 99 x
  153. 101
  154. 103
  155. 105 x x x
  156. */
  157. const WHEEL: [usize; 2] = [ 1, 2 ];
  158. const K: usize = 3;
  159. // const WHEEL: [usize; 8] = [ 4/2, 2/2, 4/2, 2/2, 4/2, 6/2, 2/2, 6/2 ];
  160. // const K: usize = 5;
  161. // const WHEEL: [usize; 48] = [ 2/2, 4/2, 2/2, 4/2, 6/2, 2/2, 6/2, 4/2, 2/2, 4/2, 6/2, 6/2, 2/2, 6/2, 4/2, 2/2, 6/2, 4/2, 6/2, 8/2, 4/2, 2/2, 4/2, 2/2, 4/2, 8/2, 6/2, 4/2, 6/2, 2/2, 4/2, 6/2, 2/2, 6/2, 6/2, 4/2, 2/2, 4/2, 6/2, 2/2, 6/2, 4/2, 2/2, 4/2, 2/2, 10/2, 2/2, 10/2 ];
  162. // const K: usize = 7;
  163. fn seg_sieve(low: usize, high: usize, sieve_primes: &Vec<u32>) -> Vec<bool> {
  164. let n = (high + 2 - low) >> 1;
  165. let mut sieve_seg = vec![false; n];
  166. let mut wheel_index;
  167. for p in sieve_primes {
  168. let p = *p as usize;
  169. let mut j = p*p;
  170. if j > high {
  171. break;
  172. }
  173. if j < low {
  174. // j = low - 1 + p - (low - 1)%p;
  175. // j += (low - 1 - j + p*2)/2/p*p*2;
  176. j = p*(((low - 1)/p + 1) | 1);
  177. }
  178. j = (j - low) >> 1;
  179. if p <= K {
  180. while j < n {
  181. unsafe { *sieve_seg.get_unchecked_mut(j) = true };
  182. j += p;
  183. }
  184. } else {
  185. dbg!(p);
  186. while ((j << 1) + low) % K != 0 && j < n {
  187. dbg!((j << 1) + low);
  188. unsafe { *sieve_seg.get_unchecked_mut(j) = true };
  189. j += p;
  190. }
  191. dbg!((j << 1) + low);
  192. j += p;
  193. dbg!();
  194. wheel_index = 0;
  195. while j < n {
  196. dbg!((j << 1) + low);
  197. unsafe { *sieve_seg.get_unchecked_mut(j) = true };
  198. j += p*WHEEL[wheel_index];
  199. wheel_index = if wheel_index == WHEEL.len() - 1 { 0 } else { wheel_index + 1 };
  200. }
  201. }
  202. }
  203. sieve_seg
  204. }
  205.  
  206. fn sqrt(n: usize) -> usize {
  207. let (mut r1, mut r) = (n, n + 1);
  208. while r1 < r {
  209. r = r1;
  210. r1 = (r1 + n/r1) >> 1
  211. }
  212. r
  213. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement