Advertisement
Guest User

Untitled

a guest
Sep 19th, 2019
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.51 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(1_000_000_000)),
  17. args.next().unwrap_or(Ok(2_000_000_000)),
  18. args.next().unwrap_or(Ok(128)),) {
  19. println!("S15: Finding sexy primes with args {} {} {}", low, high, seg_size_kb, );
  20.  
  21. low = if low < 3 { 3 } else { low | 1 }; // lowest odd >= low
  22. high = (high - 1) | 1; // highest odd <= high
  23.  
  24. // find sieving primes
  25. let sieve_primes = simple_sieve(high);
  26.  
  27. // prepare for parallel segment sieve
  28. let mut candidates_per_seg = seg_size_kb*1024*2;
  29. while (high - low)/candidates_per_seg > 100_000_000 { // increase seg size to reduce mem usage
  30. candidates_per_seg *= 2;
  31. }
  32. dbg!(candidates_per_seg/1024/2);
  33. let segs: Vec<(usize, usize)> = { low..=high }
  34. .step_by(candidates_per_seg)
  35. .map(|seg_low| {
  36. let seg_high = seg_low + candidates_per_seg - 2;
  37. (seg_low, if seg_high > high { high } else { seg_high } + 6)
  38. })
  39. .collect();
  40.  
  41. // do parallel segment sieve
  42. let (sexy_count, nprimes) =
  43. segs.into_par_iter()
  44. .map(|(low, high)| {
  45. // sieve this segment
  46. let sieve_seg = seg_sieve(low, high, &sieve_primes);
  47. // find sexy primes in this segment
  48. let (mut sexy_count, mut nprimes) = (0_usize, 0_usize);
  49. for p in 0..sieve_seg.len() - 6/2 {
  50. if unsafe { !sieve_seg.get_unchecked(p).not_prime } {
  51. nprimes += 1;
  52. if unsafe { !sieve_seg.get_unchecked(p + 6/2).not_prime } {
  53. sexy_count += 1;
  54. }
  55. }
  56. }
  57. (sexy_count, nprimes)
  58. })
  59. .reduce(|| (0, 0),
  60. |a, b| (a.0 + b.0, a.1 + b.1));
  61.  
  62. println!("{} of {} primes are sexy", sexy_count, nprimes);
  63. return;
  64. }
  65. }
  66.  
  67. writeln!(std::io::stderr(), "Usage: sexy_primes [low [high [seg_size_kb]]]").unwrap();
  68. std::process::exit(1);
  69. }
  70.  
  71. fn simple_sieve(mut high: usize) -> Vec<u32> {
  72. // x where x: odd and (x+2)^2 > high and x^2 < high
  73. high = (sqrt(high) - 1) | 1;
  74. dbg!(high);
  75. let mut pvec = vec![false; (high + 1)/2];
  76. let mut primes = vec![];
  77. let n = high >> 1;
  78. let mut i = 3;
  79. while i*i <= high {
  80. if unsafe { !pvec.get_unchecked(i >> 1) } {
  81. primes.push(i as u32);
  82. let mut j = (i*i) >> 1;
  83. while j <= n {
  84. unsafe { *pvec.get_unchecked_mut(j) = true };
  85. j += i;
  86. }
  87. }
  88. i += 2;
  89. }
  90. i >>= 1;
  91. while i <= n {
  92. if unsafe { !pvec.get_unchecked(i) } {
  93. primes.push(((i << 1) | 1) as u32);
  94. }
  95. i += 1;
  96. }
  97. primes
  98. }
  99.  
  100. struct SegPrime {
  101. not_prime: bool,
  102. next: usize,
  103. prev: usize,
  104. }
  105. fn remove(s: &mut Vec<SegPrime>, i: usize) {
  106. s[i].not_prime = true;
  107. let prev = s[i].prev;
  108. let next = s[i].next;
  109. s[prev].next = next;
  110. s[next].prev = prev;
  111. }
  112. fn seg_sieve(low: usize, high: usize, sieve_primes: &Vec<u32>) -> Vec<SegPrime> {
  113. let n = (high + 2 - low) >> 1;
  114. let mut sieve_seg = vec![];
  115. sieve_seg.push(SegPrime { not_prime: false, next: 1, prev: 0});
  116. for i in 1..n {
  117. sieve_seg.push(SegPrime { not_prime: false, next: i + 1, prev: i - 1 });
  118. }
  119. for p in sieve_primes {
  120. let p = *p as usize ;
  121. let mut j = p*p;
  122. if j > high {
  123. break;
  124. }
  125. if j < low {
  126. j = p*(((low - 1)/p + 1) | 1);
  127. }
  128. j = (j - low) >> 1;
  129. while j < n {
  130. unsafe { (*sieve_seg.get_unchecked_mut(j)).not_prime = true };
  131. j += p;
  132. }
  133. }
  134. sieve_seg
  135. }
  136.  
  137. fn sqrt(n: usize) -> usize {
  138. let (mut r1, mut r) = (n, n + 1);
  139. while r1 < r {
  140. r = r1;
  141. r1 = (r1 + n/r1) >> 1
  142. }
  143. r
  144. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement