Advertisement
Guest User

Untitled

a guest
Sep 18th, 2019
125
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.10 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) } {
  51. nprimes += 1;
  52. if unsafe { !sieve_seg.get_unchecked(p + 6/2) } {
  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. let mut pvec = vec![false; (high + 1)/2];
  75. let mut primes = vec![];
  76. let n = high >> 1;
  77. let mut i = 3;
  78. while i*i <= high {
  79. if unsafe { !pvec.get_unchecked(i >> 1) } {
  80. primes.push(i as u32);
  81. let mut j = (i*i) >> 1;
  82. while j <= n {
  83. unsafe { *pvec.get_unchecked_mut(j) = true };
  84. j += i;
  85. }
  86. }
  87. i += 2;
  88. }
  89. i >>= 1;
  90. while i <= n {
  91. if unsafe { !pvec.get_unchecked(i) } {
  92. primes.push(((i << 1) | 1) as u32);
  93. }
  94. i += 1;
  95. }
  96. primes
  97. }
  98.  
  99. fn seg_sieve(low: usize, high: usize, sieve_primes: &Vec<u32>) -> Vec<bool> {
  100. let n = (high + 2 - low) >> 1;
  101. let mut sieve_seg = vec![false; n];
  102. for i in 0..sieve_primes.len() {
  103. let p = unsafe { *sieve_primes.get_unchecked(i) as usize };
  104. let mut j = p*p;
  105. if j > high {
  106. break;
  107. }
  108. if j < low {
  109. j += (low - 1 - j + p*2)/2/p*p*2;
  110. }
  111. j = (j - low) >> 1;
  112. while j < n {
  113. unsafe { *sieve_seg.get_unchecked_mut(j) = true };
  114. j += p;
  115. }
  116. }
  117. sieve_seg
  118. }
  119.  
  120. fn sqrt(n: usize) -> usize {
  121. let (mut r1, mut r) = (n, n + 1);
  122. while r1 < r {
  123. r = r1;
  124. r1 = (r1 + n/r1) >> 1
  125. }
  126. r
  127. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement