Advertisement
Guest User

Untitled

a guest
Sep 18th, 2019
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.09 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 = low | 1; // lowest odd >= low
  22. if low < 3 {
  23. low = 3;
  24. }
  25. high = (high - 1) | 1; // highest odd <= high
  26.  
  27. // prepare for parallel segment sieve
  28. let primes_per_seg = seg_size_kb.next_power_of_two()*1024*8*2;
  29. let mut seg_low = low;
  30. let mut segs = vec![];
  31. while seg_low < high {
  32. let mut seg_high = seg_low + primes_per_seg - 2;
  33. if seg_high > high {
  34. seg_high = high;
  35. }
  36. segs.push((seg_low, seg_high + 6));
  37. seg_low = seg_high + 2;
  38. }
  39. let lookup_table = PrimesIter::lookup_table_gen();
  40.  
  41. // get sieving primes
  42. let sieve_primes = simple_sieve(high);
  43. // find sexy primes
  44. let (sexy_count, nprimes) =
  45. segs.into_par_iter()
  46. .map(|(low, high)| {
  47. let n = (high + 2 - low) >> 1;
  48. let mut sieve_seg = Bvec::new(false, n);
  49. for i in 0..sieve_primes.len() {
  50. let p = sieve_primes[i] as usize;
  51. let mut j = p*p;
  52. if j > high {
  53. break;
  54. }
  55. if j < low {
  56. j += (low - 1 - j + p*2)/2/p*p*2;
  57. }
  58. j = (j - low) >> 1;
  59. while j < n {
  60. sieve_seg.set(j, true);
  61. j += p;
  62. }
  63. }
  64.  
  65. let (mut sexy_count, mut nprimes) = (0_usize, 0_usize);
  66. for p in PrimesIter::new(low, high, &sieve_seg, &lookup_table) {
  67. if p + 6 <= high {
  68. nprimes += 1;
  69. if !sieve_seg.get(((p - low) >> 1) + 6/2) {
  70. sexy_count += 1;
  71. }
  72. }
  73. }
  74. (sexy_count, nprimes)
  75. })
  76. .reduce(|| (0, 0),
  77. |a, b| (a.0 + b.0, a.1 + b.1));
  78.  
  79. println!("{} of {} primes are sexy", sexy_count, nprimes);
  80. return;
  81. }
  82. }
  83.  
  84. writeln!(
  85. std::io::stderr(),
  86. "Usage: sexy_primes [low [high [seg_size(kb)]]]"
  87. ).unwrap();
  88. std::process::exit(1);
  89. }
  90.  
  91. fn simple_sieve(mut high: usize) -> Vec<u32> {
  92. // x where x: odd and (x+2)^2 > high and x^2 < high
  93. high = (sqrt(high) - 1) | 1;
  94. let mut pvec = vec![false; (high + 1)/2];
  95. let mut primes = vec![];
  96. let n = high >> 1;
  97. let mut i = 3;
  98. while i*i <= high {
  99. if !pvec[i >> 1] {
  100. primes.push(i as u32);
  101. let mut j = (i*i) >> 1;
  102. while j <= n {
  103. pvec[j] = true;
  104. j += i;
  105. }
  106. }
  107. i += 2;
  108. }
  109. i >>= 1;
  110. while i <= n {
  111. if !pvec[i] {
  112. primes.push(((i << 1) | 1) as u32);
  113. }
  114. i += 1;
  115. }
  116. primes
  117. }
  118.  
  119. fn sqrt(n: usize) -> usize {
  120. let (mut r1, mut r) = (n, n + 1);
  121. while r1 < r {
  122. r = r1;
  123. r1 = (r1 + n/r1) >> 1
  124. }
  125. r
  126. }
  127.  
  128. struct Bvec {
  129. v: Vec<u8>
  130. }
  131. impl Bvec {
  132. fn new(val: bool, s: usize) -> Self {
  133. let valu8 = if val { 255 } else { 0 };
  134. Bvec { v: vec![valu8; (s >> 3) + if (s & 7) == 0 { 0 } else { 1 } ] }
  135. }
  136. #[inline(always)]
  137. fn get(&self, index: usize) -> bool {
  138. self.v[index >> 3] & 1 << (index & 7) != 0
  139. }
  140. #[inline(always)]
  141. fn set(&mut self, mut index: usize, val: bool) {
  142. let bitpos = 1 << (index & 7);
  143. index >>= 3;
  144. if val {
  145. self.v[index] |= bitpos;
  146. } else {
  147. self.v[index] &= !bitpos;
  148. }
  149. }
  150. }
  151.  
  152. struct PrimesIter<'a> {
  153. sieve_index: usize,
  154. base: usize,
  155. low: usize,
  156. high: usize,
  157. sieve: &'a [u8],
  158. lookup_table: &'a Vec<Vec<u8>>,
  159. lookup_table_cur: &'a Vec<u8>,
  160. lookup_table_cur_index: usize,
  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.lookup_table_cur_index >= self.lookup_table_cur.len() {
  167. if self.sieve_index >= self.sieve.len() {
  168. return None;
  169. }
  170. self.lookup_table_cur = &self.lookup_table[self.sieve[self.sieve_index] as usize];
  171. self.lookup_table_cur_index = 0;
  172. self.base = self.sieve_index*16 + self.low;
  173. self.sieve_index += 1;
  174. }
  175. let prime = self.base + self.lookup_table_cur[self.lookup_table_cur_index] as usize;
  176. self.lookup_table_cur_index += 1;
  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, lookup_table: &'a Vec<Vec<u8>>) -> Self {
  186. PrimesIter { sieve_index: 0, base: 0, low, high, sieve: &sieve.v, lookup_table,
  187. lookup_table_cur: &lookup_table[0], lookup_table_cur_index: 8 }
  188. }
  189. fn lookup_table_gen() -> Vec<Vec<u8>> {
  190. let mut t = vec![vec![]; 256];
  191. for i in 0..256 {
  192. for j in 0..8 {
  193. if !i & 1 << j != 0 {
  194. t[i].push((2*j) as u8);
  195. }
  196. }
  197. }
  198. t
  199. }
  200. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement