Advertisement
Guest User

Untitled

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