formulas.rs

4.4 kB · rust · 134 lines

1use crate::Fault;2use mrlycore::json;3use mrlynum::formulas;4use mrlynum::series::EULER;5use std::f64::consts::{E, PI};6use wasm_bindgen::prelude::*;78const FLOOR: usize = 2;9const REACH: usize = 2000;10const STOPS: usize = 400;1112fn depth(n: usize) -> Result<usize, Fault> {13    if !(FLOOR..=REACH).contains(&n) {14        return Err(Fault::new(format!(15            "the depth must be between {FLOOR} and {REACH}."16        )));17    }18    Ok(n)19}2021fn drift(value: f64, limit: f64) -> f64 {22    (value - limit).abs() / limit.abs()23}2425fn reading(kind: &str, m: usize) -> Result<(f64, f64, f64), Fault> {26    let x = m as f64;27    Ok(match kind {28        "wallis" => {29            let v = formulas::wallis(m);30            (x, v, drift(v, PI / 2.0))31        }32        "leibniz" => {33            let v = formulas::leibniz(m);34            (x, v, drift(v, PI / 4.0))35        }36        "basel" => {37            let v = formulas::basel(m);38            (x, v, drift(v, PI * PI / 6.0))39        }40        "gamma" => {41            let v = formulas::euler_gamma_partial(m);42            (x, v, drift(v, EULER))43        }44        "e" => {45            let v = formulas::e_partial(m);46            (x, v, drift(v, E))47        }48        "primes" => {49            let v = formulas::prime_count(m) as f64;50            (x, v, drift(v, formulas::li(x)))51        }52        "goldbach" => {53            let v = formulas::goldbach(2 * m) as f64;54            (2.0 * x, v, 1.0 / v)55        }56        "mertens" => {57            let v = formulas::mertens(m) as f64;58            (x, v, v.abs() / x.sqrt())59        }60        _ => return Err(Fault::new(format!("no formula is named {kind:?}."))),61    })62}6364/// Reads the eight elementary systems at the depth n: the constants pi, e and gamma the crate holds, then each system's partial, its target, the gap and the gap against the target, with the prime count beside li and n over ln n, the Goldbach partition count of two n beside the smallest partition count of any even number up to it, and the Mertens sum beside the square root of n, as JSON.65#[wasm_bindgen]66pub fn formulas_read(n: usize) -> Result<String, Fault> {67    let n = depth(n)?;68    let card = |value: f64, limit: f64| {69        json!({70            "value": value,71            "limit": limit,72            "error": (value - limit).abs(),73            "rel": drift(value, limit),74        })75    };76    let count = formulas::prime_count(n);77    let li = formulas::li(n as f64);78    let record = formulas::goldbach_record(2 * n);79    let pairs = record.last().copied().unwrap_or(0);80    let least = record.iter().copied().min().unwrap_or(0);81    let sum = formulas::mertens(n);82    let root = (n as f64).sqrt();83    Ok(json!({84        "n": n,85        "constants": { "pi": PI, "e": E, "gamma": EULER },86        "cards": {87            "wallis": card(formulas::wallis(n), PI / 2.0),88            "leibniz": card(formulas::leibniz(n), PI / 4.0),89            "basel": card(formulas::basel(n), PI * PI / 6.0),90            "gamma": card(formulas::euler_gamma_partial(n), EULER),91            "e": card(formulas::e_partial(n), E),92            "primes": {93                "value": count,94                "li": li,95                "ratio": n as f64 / (n as f64).ln(),96                "gauge": count as f64 / li,97                "rel": drift(count as f64, li),98            },99            "goldbach": {100                "even": 2 * n,101                "value": pairs,102                "floor": least,103                "rel": 1.0 / pairs as f64,104            },105            "mertens": {106                "value": sum,107                "root": root,108                "rel": (sum as f64).abs() / root,109            },110        },111    })112    .to_string())113}114115/// Walks one of the eight systems from the floor up to n at the count of stops and returns each stop as its point on the number line, the partial there and the normalised gap it stands at, three numbers a stop, so the approach can be drawn.116#[wasm_bindgen]117pub fn formulas_walk(kind: &str, n: usize, stops: usize) -> Result<Vec<f64>, Fault> {118    let n = depth(n)?;119    if !(2..=STOPS).contains(&stops) {120        return Err(Fault::new(format!(121            "the stops must be between 2 and {STOPS}."122        )));123    }124    let stops = stops.min(n - FLOOR + 1).max(2);125    let mut out = Vec::with_capacity(stops * 3);126    for k in 0..stops {127        let at = FLOOR + (n - FLOOR) * k / (stops - 1);128        let (x, value, gauge) = reading(kind, at)?;129        out.push(x);130        out.push(value);131        out.push(gauge);132    }133    Ok(out)134}