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}