Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* author Bill Wood */
- use rayon::prelude::*;
- use std::io::Write;
- fn main() {
- let mut args = std::env::args()
- .skip(1)
- .map(|a| a
- .split('_')
- .fold("".to_string(), |a, s| a + s)
- .parse::<usize>());
- if args.len() <= 3 {
- if let (Ok(mut low), Ok(mut high), Ok(seg_size_kb), ) = (
- args.next().unwrap_or(Ok(0)),
- args.next().unwrap_or(Ok(200)),
- args.next().unwrap_or(Ok(128)),) {
- println!("S15: Finding sexy primes with args {} {} {}", low, high, seg_size_kb, );
- let count_two = if low <= 2 && high >= 2 { 1 } else { 0 };
- low = if low < 3 { 3 } else { low | 1 }; // lowest odd >= low
- high = (high - 1) | 1; // highest odd <= high
- // find sieving primes
- let sieve_primes = simple_sieve(high);
- // prepare for parallel segment sieve
- let mut candidates_per_seg = seg_size_kb*1024*2;
- while (high - low)/candidates_per_seg > 100_000_000 { // increase seg size to reduce mem usage
- candidates_per_seg *= 2;
- }
- dbg!(candidates_per_seg/1024/2);
- let segs: Vec<(usize, usize)> = { low..=high }
- .step_by(candidates_per_seg)
- .map(|seg_low| {
- let seg_high = seg_low + candidates_per_seg - 2;
- (seg_low, if seg_high > high { high } else { seg_high } + 6)
- })
- .collect();
- // do parallel segment sieve
- let (sexy_count, nprimes) =
- segs.into_par_iter()
- .map(|(low, high)| {
- // sieve this segment
- let sieve_seg = seg_sieve(low, high, &sieve_primes);
- // find sexy primes in this segment
- let (mut sexy_count, mut nprimes) = (0_usize, 0_usize);
- for p in 0..sieve_seg.len() - 6/2 {
- if unsafe { !sieve_seg.get_unchecked(p) } {
- nprimes += 1;
- // print!("{} ", (p << 1) + low);
- if unsafe { !sieve_seg.get_unchecked(p + 6/2) } {
- sexy_count += 1;
- }
- }
- }
- (sexy_count, nprimes)
- })
- .reduce(|| (0, 0),
- |a, b| (a.0 + b.0, a.1 + b.1));
- println!("\n{} of {} primes are sexy", sexy_count, nprimes + count_two);
- return;
- }
- }
- writeln!(std::io::stderr(), "Usage: sexy_primes [low [high [seg_size_kb]]]").unwrap();
- std::process::exit(1);
- }
- fn simple_sieve(mut high: usize) -> Vec<u32> {
- // x where x: odd and (x+2)^2 > high and x^2 < high
- high = (sqrt(high) - 1) | 1;
- dbg!(high);
- let mut pvec = vec![false; (high + 1)/2];
- let mut primes = vec![];
- let n = high >> 1;
- let mut i = 3;
- while i*i <= high {
- if unsafe { !pvec.get_unchecked(i >> 1) } {
- primes.push(i as u32);
- let mut j = (i*i) >> 1;
- while j <= n {
- unsafe { *pvec.get_unchecked_mut(j) = true };
- j += i;
- }
- }
- i += 2;
- }
- i >>= 1;
- while i <= n {
- if unsafe { !pvec.get_unchecked(i) } {
- primes.push(((i << 1) | 1) as u32);
- }
- i += 1;
- }
- primes
- }
- /*
- 2 3 5 7
- 3
- 5 *
- 7 *
- 9 x
- 11 *
- 13
- 15 x x
- 17
- 19
- 21 x x
- 23
- 25 x
- 27 x
- 29
- 31
- 33 x
- 35 x x
- 37 *
- 39 x
- 41
- 43
- 45 x x
- 47
- 49 x
- 51 x
- 53
- 55 x
- 57 x
- 59
- 61
- 63 x x
- 65 x
- 67 *
- 69 x
- 71
- 73
- 75 x x
- 77 x
- 79
- 81 x
- 83
- 85 x
- 87 x
- 89
- 91 x
- 93 x
- 95 x
- 97 *
- 99 x
- 101
- 103
- 105 x x x
- */
- const WHEEL: [usize; 2] = [ 1, 2 ];
- const K: usize = 3;
- // const WHEEL: [usize; 8] = [ 4/2, 2/2, 4/2, 2/2, 4/2, 6/2, 2/2, 6/2 ];
- // const K: usize = 5;
- // const WHEEL: [usize; 48] = [ 2/2, 4/2, 2/2, 4/2, 6/2, 2/2, 6/2, 4/2, 2/2, 4/2, 6/2, 6/2, 2/2, 6/2, 4/2, 2/2, 6/2, 4/2, 6/2, 8/2, 4/2, 2/2, 4/2, 2/2, 4/2, 8/2, 6/2, 4/2, 6/2, 2/2, 4/2, 6/2, 2/2, 6/2, 6/2, 4/2, 2/2, 4/2, 6/2, 2/2, 6/2, 4/2, 2/2, 4/2, 2/2, 10/2, 2/2, 10/2 ];
- // const K: usize = 7;
- fn seg_sieve(low: usize, high: usize, sieve_primes: &Vec<u32>) -> Vec<bool> {
- let n = (high + 2 - low) >> 1;
- let mut sieve_seg = vec![false; n];
- let mut wheel_index;
- for p in sieve_primes {
- let p = *p as usize;
- let mut j = p*p;
- if j > high {
- break;
- }
- if j < low {
- // j = low - 1 + p - (low - 1)%p;
- // j += (low - 1 - j + p*2)/2/p*p*2;
- j = p*(((low - 1)/p + 1) | 1);
- }
- j = (j - low) >> 1;
- if p <= K {
- while j < n {
- unsafe { *sieve_seg.get_unchecked_mut(j) = true };
- j += p;
- }
- } else {
- dbg!(p);
- while ((j << 1) + low) % K != 0 && j < n {
- dbg!((j << 1) + low);
- unsafe { *sieve_seg.get_unchecked_mut(j) = true };
- j += p;
- }
- dbg!((j << 1) + low);
- j += p;
- dbg!();
- wheel_index = 0;
- while j < n {
- dbg!((j << 1) + low);
- unsafe { *sieve_seg.get_unchecked_mut(j) = true };
- j += p*WHEEL[wheel_index];
- wheel_index = if wheel_index == WHEEL.len() - 1 { 0 } else { wheel_index + 1 };
- }
- }
- }
- sieve_seg
- }
- fn sqrt(n: usize) -> usize {
- let (mut r1, mut r) = (n, n + 1);
- while r1 < r {
- r = r1;
- r1 = (r1 + n/r1) >> 1
- }
- r
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement