Advertisement
Guest User

Untitled

a guest
Sep 17th, 2019
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.72 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. #[inline(always)]
  35. fn set_true(v: &mut [u8], mut index: usize) {
  36. let bitpos = 1 << (index & 7);
  37. index >>= 3;
  38. v[index] |= bitpos;
  39. }
  40. }
  41.  
  42. struct SimpleSieve {
  43. primes: Vec<u32>,
  44. }
  45. impl SimpleSieve {
  46. fn new(high: usize) -> Self {
  47. assert_eq!(high | 1, high);
  48. let mut pvec = vec![false; (high + 1)/2];
  49. let mut primes = vec![];
  50. let n = high >> 1;
  51. let mut i = 3;
  52. while i*i <= high {
  53. if !pvec[i >> 1] {
  54. primes.push(i as u32);
  55. let mut j = (i*i) >> 1;
  56. while j <= n {
  57. pvec[j] = true;
  58. j += i;
  59. }
  60. }
  61. i += 2;
  62. }
  63. i >>= 1;
  64. while i <= n {
  65. if !pvec[i] {
  66. primes.push(((i << 1) | 1) as u32);
  67. }
  68. i += 1;
  69. }
  70. //dbg!(primes.len());
  71. SimpleSieve { primes, }
  72. }
  73. }
  74.  
  75. struct SieveSlice<'a> {
  76. low: usize,
  77. high: usize,
  78. bslice: &'a mut [u8],
  79. }
  80. impl<'a> SieveSlice<'a> {
  81. fn new(low: usize, high: usize, bslice: &'a mut [u8]) -> Self {
  82. // assert_eq!(low | 1, low);
  83. // assert_eq!(high | 1, high);
  84. SieveSlice { low, high, bslice }
  85. }
  86. fn find(&mut self, sieve: &SimpleSieve) {
  87. let low = self.low;
  88. let high = self.high;
  89. if low <= 1 {
  90. Bvec::set_true(self.bslice, 0);
  91. }
  92.  
  93. let n = (high - low) >> 1;
  94. for i in 0..sieve.primes.len() {
  95. let p = sieve.primes[i] as usize;
  96. let mut j = p*p;
  97. if j > high {
  98. break;
  99. }
  100. if j < low {
  101. j += (low - 1 - j + p*2)/2/p*p*2;
  102. }
  103. j = (j - low) >> 1;
  104. while j <= n {
  105. Bvec::set_true(self.bslice, j);
  106. j += p;
  107. }
  108. }
  109. }
  110. }
  111.  
  112. use rayon::prelude::*;
  113. struct Primes {
  114. low: usize,
  115. high: usize,
  116. sieve_seg: Bvec,
  117. lookup_table: Vec<Vec<u8>>,
  118. }
  119. impl Primes {
  120. fn new(mut low: usize, mut high: usize, mut seg_size_kb: usize) -> Option<Self> {
  121. // lowest odd >= low
  122. low |= 1;
  123. if low > high {
  124. return None;
  125. }
  126. // highest odd <= high
  127. high = (high - 1) | 1;
  128. // x where x: odd and (x+2)^2 > high and x^2 < high
  129. let ss_high = (sqrt(high) - 1) | 1;
  130.  
  131. let sieve = SimpleSieve::new(ss_high);
  132. let mut sieve_seg = Bvec::new(false, (high + 2 - low)/2);
  133. println!("prime sieve size in KB = {}", sieve_seg.v.len()/1024);
  134.  
  135. seg_size_kb = seg_size_kb.next_power_of_two();
  136. // 1024kb, 8 bit bytes, track odds only
  137. let seg_nprimes = seg_size_kb*1024*8*2;
  138.  
  139. let mut segments = vec!();
  140. let mut seg_low = low;
  141. //dbg!(low, ss_high, seg_low, high, seg_size_kb, seg_nprimes, );
  142. for bslice in sieve_seg.v.chunks_mut(seg_size_kb*1024) {
  143. let mut seg_high = seg_low + seg_nprimes - 2;
  144. if seg_high > high {
  145. seg_high = high;
  146. }
  147. segments.push(SieveSlice::new(seg_low, seg_high, bslice));
  148. seg_low += seg_nprimes;
  149. }
  150. //dbg!(segments[0].bslice.len(), segments.len());
  151.  
  152. segments.par_iter_mut().for_each(|seg| seg.find(&sieve));
  153. Some(Primes { low, high, sieve_seg, lookup_table: Primes::lookup_table_gen() })
  154. }
  155. #[inline(always)]
  156. fn is_prime(&self, index: usize) -> bool {
  157. !self.sieve_seg.get((index - self.low) >> 1)
  158. }
  159. fn lookup_table_gen() -> Vec<Vec<u8>> {
  160. let mut t = vec![vec![]; 256];
  161. for i in 0..256 {
  162. for j in 0..8 {
  163. if !i & 1 << j != 0 {
  164. t[i].push((2*j) as u8);
  165. }
  166. }
  167. }
  168. t
  169. }
  170. }
  171.  
  172. struct PrimesIter<'a> {
  173. sieve_index: usize,
  174. base: usize,
  175. low: usize,
  176. high: usize,
  177. sieve: &'a [u8],
  178. lookup_table: &'a Vec<Vec<u8>>,
  179. lookup_table_cur: &'a Vec<u8>,
  180. lookup_table_cur_index: usize,
  181. }
  182. impl<'a> Iterator for PrimesIter<'a> {
  183. type Item = usize;
  184. #[inline(always)]
  185. fn next(&mut self) -> Option<Self::Item> {
  186. while self.lookup_table_cur_index >= self.lookup_table_cur.len() {
  187. if self.sieve_index >= self.sieve.len() {
  188. return None;
  189. }
  190. self.lookup_table_cur = &self.lookup_table[self.sieve[self.sieve_index] as usize];
  191. self.lookup_table_cur_index = 0;
  192. self.base = self.sieve_index*16 + self.low;
  193. self.sieve_index += 1;
  194. }
  195. let prime = self.base + self.lookup_table_cur[self.lookup_table_cur_index] as usize;
  196. self.lookup_table_cur_index += 1;
  197. if prime <= self.high {
  198. Some(prime)
  199. } else {
  200. None
  201. }
  202. }
  203. }
  204. impl<'a> IntoIterator for &'a Primes {
  205. type Item = usize;
  206. type IntoIter = PrimesIter<'a>;
  207. fn into_iter(self) -> Self::IntoIter {
  208. PrimesIter { sieve_index: 0, base: 0, low: self.low, high: self.high, sieve: &self.sieve_seg.v,
  209. lookup_table: &self.lookup_table, lookup_table_cur: &self.lookup_table[0], lookup_table_cur_index: 8 }
  210. }
  211. }
  212. impl Primes {
  213. fn seg_into_iter(&self, sieve_low_index: usize, sieve_high_index: usize) -> PrimesIter {
  214. let mut high = sieve_high_index*16 + self.low;
  215. if high > self.high {
  216. high = self.high;
  217. }
  218. let low = sieve_low_index*16 + self.low;
  219. PrimesIter { sieve_index: sieve_low_index, base: 0, low: 0, high, sieve: &self.sieve_seg.v,
  220. lookup_table: &self.lookup_table, lookup_table_cur: &self.lookup_table[0], lookup_table_cur_index: 8 }
  221. }
  222. }
  223.  
  224. use time::PreciseTime;
  225. use std::io::Write;
  226. fn main() {
  227. let mut args = std::env::args()
  228. .skip(1)
  229. .map(|a| a
  230. .split('_')
  231. .fold("".to_string(), |a, s| a + s)
  232. .parse::<usize>());
  233.  
  234. if args.len() <= 3 {
  235. if let (Ok(low), Ok(high), Ok(seg_size_kb), ) = (
  236. args.next().unwrap_or(Ok(1_000_000_000)),
  237. args.next().unwrap_or(Ok(2_000_000_000)),
  238. args.next().unwrap_or(Ok(128)),) {
  239. println!("S11: Finding sexy primes with args {} {} {}", low, high, seg_size_kb, );
  240. let start = PreciseTime::now();
  241. if let Some(primes) = Primes::new(low, high + 6, seg_size_kb) {
  242. let end = PreciseTime::now();
  243. println!("done generating primes in {:.2} secs...", start.to(end).num_milliseconds() as f64 / 1000.0);
  244. let mut count = 0;
  245. let mut nprimes: usize = if high >= 2 && low <= 2 { /*print!("{} ", 2);*/ 1 } else { 0 };
  246.  
  247. // let seg_size_kb = seg_size_kb.next_power_of_two();
  248. // // 1024kb, 8 bit bytes, track odds only
  249. // let seg_nprimes = seg_size_kb*1024*8*2;
  250.  
  251. // let mut segments = vec!();
  252. // let mut seg_low = low;
  253. // for bslice in primes.sieve_seg.v.chunks_mut(seg_size_kb*1024) {
  254. // let mut seg_high = seg_low + seg_nprimes - 2;
  255. // if seg_high > high {
  256. // seg_high = high;
  257. // }
  258. // segments.push(SieveSlice::new(seg_low, seg_high, bslice));
  259. // seg_low += seg_nprimes;
  260. // }
  261.  
  262. // segments.par_iter_mut().for_each(|seg| seg.find(&sieve));
  263. // Some(Primes { low, high, sieve_seg, lookup_table: Primes::lookup_table_gen() })
  264.  
  265. for p in primes.into_iter() {
  266. if p > primes.high - 6 {
  267. break;
  268. }
  269. nprimes += 1;
  270. // if p < 200 { print!("{} ", p); }
  271. if primes.is_prime(p + 6) {
  272. //println!("sexy: {}, {}", p, p + 6);
  273. count += 1;
  274. }
  275. }
  276. println!("\n{} of {} primes are sexy", count, nprimes);
  277. return;
  278. }
  279. }
  280. }
  281.  
  282. writeln!(
  283. std::io::stderr(),
  284. "Usage: sexy_primes low high seg_size(kb)"
  285. ).unwrap();
  286. std::process::exit(1);
  287. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement