prime.rs

4.4 kB · rust · 132 lines

1use crate::{Fault, Grid};2use mrlycore::json;3use mrlylab::moire::pairs;4use mrlynum::prime;5use wasm_bindgen::prelude::*;67const SHEET: usize = 400;8const STONES: u64 = 1_000_000_000_000;9const TOP: usize = 1_000_000;10const SCALE: usize = 999;1112/// The sieve of Eratosthenes taken one prime at a time: each byte says who struck the number.13#[wasm_bindgen]14pub struct Sieve(prime::Sieve);1516#[wasm_bindgen]17impl Sieve {18    /// Starts a sieve over zero through the limit, at most four hundred.19    #[wasm_bindgen(constructor)]20    pub fn new(limit: usize) -> Result<Sieve, Fault> {21        if limit > SHEET {22            return Err(Fault::new(format!("the sheet holds {SHEET} numbers.")));23        }24        Ok(Sieve(prime::Sieve::new(limit)))25    }26    /// Uses the next prime and returns it, zero once the sieve is done.27    pub fn step(&mut self) -> u32 {28        self.0.step() as u3229    }30    /// Runs the sieve to the end.31    pub fn finish(&mut self) {32        self.0.finish();33    }34    /// Returns whether every number is settled.35    pub fn done(&self) -> bool {36        self.0.done()37    }38    /// Returns the type of every number from zero: zero untouched, one prime, and one past the rank of the prime that struck it.39    pub fn types(&self) -> Vec<u8> {40        self.0.types().to_vec()41    }42    /// Returns the count of numbers marked prime so far.43    pub fn count(&self) -> u32 {44        self.0.count() as u3245    }46    /// Returns the count of numbers the last step struck.47    pub fn struck(&self) -> u32 {48        self.0.struck() as u3249    }50    /// Returns the count of primes used so far.51    pub fn rank(&self) -> u32 {52        self.0.rank() as u3253    }54    /// Lays the numbers from one out in rows of the given width as a grid, one on the primes.55    pub fn grid(&self, columns: usize) -> Result<Grid, Fault> {56        if columns == 0 {57            return Err(Fault::new("a row needs a width."));58        }59        let types = &self.0.types()[1..];60        let height = types.len().div_ceil(columns);61        let mut cells = vec![0u8; columns * height];62        for (cell, &t) in cells.iter_mut().zip(types) {63            *cell = u8::from(t == 1);64        }65        Ok(Grid {66            width: columns as u32,67            height: height as u32,68            types: cells,69        })70    }71}7273/// Reads a number of stones up to a million million: its prime factors as pairs, whether it is prime, and every rectangle as a pair of sides, as JSON.74#[wasm_bindgen]75pub fn factor(number: &str) -> Result<String, Fault> {76    let number: u64 = number77        .trim()78        .parse()79        .map_err(|_| Fault::new(format!("{number:?} is not a whole number.")))?;80    if number > STONES {81        return Err(Fault::new(format!("the pile holds {STONES} stones.")));82    }83    let pile = prime::pile(number);84    Ok(json!({85        "n": pile.number,86        "factors": pile.factors,87        "prime": pile.prime,88        "rectangles": pile.rectangles,89    })90    .to_string())91}9293/// Reads the prime count against x over ln x and li at evenly spaced x up to the top, a million at most, in at most the given count of bins, as JSON columns.94#[wasm_bindgen]95pub fn prime_chart(top: usize, bins: usize) -> Result<String, Fault> {96    if top > TOP {97        return Err(Fault::new(format!("the chart counts to {TOP}.")));98    }99    let readings = prime::chart(top, bins.min(1000));100    let column = |pick: fn(&prime::Reading) -> f64| readings.iter().map(pick).collect::<Vec<f64>>();101    Ok(json!({102        "x": readings.iter().map(|r| r.x).collect::<Vec<usize>>(),103        "pi": readings.iter().map(|r| r.pi).collect::<Vec<usize>>(),104        "ratio": column(|r| r.ratio),105        "li": column(|r| r.li),106    })107    .to_string())108}109110/// Returns the smallest prime at or above the number.111#[wasm_bindgen]112pub fn prime_from(number: u32) -> u32 {113    prime::prime_from(number as usize) as u32114}115116/// Puts an odd scale on trial against every earlier odd scale of the flat carpet stack: the scales, the exact correlation with each, the largest and where, and whether the row is clear, as JSON.117#[wasm_bindgen]118pub fn carpet_witness(scale: usize) -> Result<String, Fault> {119    if scale > SCALE {120        return Err(Fault::new(format!("the stack reaches scale {SCALE}.")));121    }122    let trial = pairs::witness(scale)?;123    Ok(json!({124        "n": trial.scale,125        "scales": trial.scales,126        "row": trial.row,127        "max": trial.max,128        "at": trial.at,129        "prime": trial.prime,130    })131    .to_string())132}