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(1_000_000_000)),
- args.next().unwrap_or(Ok(2_000_000_000)),
- args.next().unwrap_or(Ok(128)),) {
- println!("S15: Finding sexy primes with args {} {} {}", low, high, seg_size_kb, );
- 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;
- 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!("{} of {} primes are sexy", sexy_count, nprimes);
- 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;
- 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
- }
- 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];
- for i in 0..sieve_primes.len() {
- let p = unsafe { *sieve_primes.get_unchecked(i) as usize };
- let mut j = p*p;
- if j > high {
- break;
- }
- if j < low {
- j += (low - 1 - j + p*2)/2/p*p*2;
- }
- j = (j - low) >> 1;
- while j < n {
- unsafe { *sieve_seg.get_unchecked_mut(j) = true };
- j += p;
- }
- }
- 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