Advertisement
Guest User

Untitled

a guest
Oct 14th, 2019
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.58 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(64)),) {
  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*8*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. let segs: Vec<(usize, usize)> = { low..=high }
  33. .step_by(candidates_per_seg)
  34. .map(|seg_low| {
  35. let seg_high = seg_low + candidates_per_seg - 2;
  36. (seg_low, if seg_high > high { high } else { seg_high } + 6)
  37. })
  38. .collect();
  39.  
  40. // do parallel segment sieve
  41. let (sexy_count, nprimes) =
  42. segs.into_par_iter()
  43. .map(|(low, high)| {
  44. // sieve this segment
  45. let sieve_seg = seg_sieve(low, high, &sieve_primes);
  46. // find sexy primes in this segment
  47. let (mut sexy_count, mut nprimes) = (0_usize, 0_usize);
  48. for p in PrimesIter::new(low, high, &sieve_seg) {
  49. if p + 6 <= high {
  50. nprimes += 1;
  51. if !sieve_seg.get(((p - low) >> 1) + 6/2) {
  52. sexy_count += 1;
  53. }
  54. }
  55. }
  56. (sexy_count, nprimes)
  57. })
  58. .reduce(|| (0, 0),
  59. |a, b| (a.0 + b.0, a.1 + b.1));
  60.  
  61. println!("{} of {} primes are sexy", sexy_count, nprimes);
  62. return;
  63. }
  64. }
  65.  
  66. writeln!(std::io::stderr(), "Usage: sexy_primes [low [high [seg_size_kb]]]").unwrap();
  67. std::process::exit(1);
  68. }
  69.  
  70. fn simple_sieve(mut high: usize) -> Vec<u32> {
  71. // x where x: odd and (x+2)^2 > high and x^2 < high
  72. high = (sqrt(high) - 1) | 1;
  73. let mut pvec = vec![false; (high + 1)/2];
  74. let mut primes = vec![];
  75. let n = high >> 1;
  76. let mut i = 3;
  77. while i*i <= high {
  78. if !pvec[i >> 1] {
  79. primes.push(i as u32);
  80. let mut j = (i*i) >> 1;
  81. while j <= n {
  82. pvec[j] = true;
  83. j += i;
  84. }
  85. }
  86. i += 2;
  87. }
  88. i >>= 1;
  89. while i <= n {
  90. if !pvec[i] {
  91. primes.push(((i << 1) | 1) as u32);
  92. }
  93. i += 1;
  94. }
  95. primes
  96. }
  97.  
  98. fn seg_sieve(low: usize, high: usize, sieve_primes: &Vec<u32>) -> Bvec {
  99. let n = (high + 2 - low) >> 1;
  100. let mut sieve_seg = Bvec::new(false, n);
  101. for i in 0..sieve_primes.len() {
  102. let p = sieve_primes[i] as usize;
  103. let mut j = p*p;
  104. if j > high {
  105. break;
  106. }
  107. if j < low {
  108. // j = low - 1 + p - (low - 1)%p;
  109. // j += (low - 1 - j + p*2)/2/p*p*2;
  110. j = p*(((low - 1)/p + 1) | 1);
  111. }
  112. j = (j - low) >> 1;
  113. while j < n {
  114. sieve_seg.set(j, true);
  115. j += p;
  116. }
  117. }
  118. sieve_seg
  119. }
  120.  
  121. fn sqrt(n: usize) -> usize {
  122. let (mut r1, mut r) = (n, n + 1);
  123. while r1 < r {
  124. r = r1;
  125. r1 = (r1 + n/r1) >> 1
  126. }
  127. r
  128. }
  129.  
  130. struct Bvec {
  131. v: Vec<u8>
  132. }
  133. impl Bvec {
  134. fn new(val: bool, s: usize) -> Self {
  135. let valu8 = if val { 255 } else { 0 };
  136. Bvec { v: vec![valu8; (s >> 3) + if (s & 7) == 0 { 0 } else { 1 } ] }
  137. }
  138. #[inline(always)]
  139. fn get(&self, index: usize) -> bool {
  140. self.v[index >> 3] & 1 << (index & 7) != 0
  141. }
  142. #[inline(always)]
  143. fn set(&mut self, mut index: usize, val: bool) {
  144. let bitpos = 1 << (index & 7);
  145. index >>= 3;
  146. if val {
  147. self.v[index] |= bitpos;
  148. } else {
  149. self.v[index] &= !bitpos;
  150. }
  151. }
  152. }
  153.  
  154. struct PrimesIter<'a> {
  155. sieve_index: usize,
  156. base: usize,
  157. low: usize,
  158. high: usize,
  159. cur_byte: u8,
  160. sieve: &'a [u8],
  161. }
  162. impl<'a> Iterator for PrimesIter<'a> {
  163. type Item = usize;
  164. #[inline(always)]
  165. fn next(&mut self) -> Option<Self::Item> {
  166. while self.cur_byte == 0 {
  167. if self.sieve_index >= self.sieve.len() {
  168. return None;
  169. }
  170. self.cur_byte = !self.sieve[self.sieve_index];
  171. self.base = (self.sieve_index << 4) + self.low;
  172. self.sieve_index += 1;
  173. }
  174. let trailing = self.cur_byte.trailing_zeros();
  175. self.cur_byte &= !(1 << trailing);
  176. let prime = self.base + (trailing << 1) as usize;
  177. if prime <= self.high {
  178. Some(prime)
  179. } else {
  180. None
  181. }
  182. }
  183. }
  184. impl<'a> PrimesIter<'a> {
  185. fn new(low: usize, high: usize, sieve: &'a Bvec) -> Self {
  186. PrimesIter { sieve_index: 0, base: 0, low, high, cur_byte: 0, sieve: &sieve.v }
  187. }
  188. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement