wiki-famous-formulas.rs

3.4 kB · rust · 108 lines

1use mrlycore::errors::Result;2use mrlycore::Color;3use mrlyfig::{ink, plot, save, Board, Frame};4use mrlynum::formulas;5use mrlynum::series::EULER;6use std::f64::consts::{E, PI};78const TOP: usize = 2000;9const FLOOR: usize = 2;10const SAMPLES: usize = 240;11const DECADES: f64 = 4.5;12const LEFT: f64 = FLOOR as f64;13const RIGHT: f64 = TOP as f64;1415fn ladder() -> Vec<usize> {16    let (lo, hi) = ((FLOOR as f64).ln(), (TOP as f64).ln());17    let mut out: Vec<usize> = Vec::with_capacity(SAMPLES);18    for k in 0..SAMPLES {19        let step = lo + (hi - lo) * k as f64 / (SAMPLES - 1) as f64;20        let at = step.exp().round() as usize;21        if out.last() != Some(&at) {22            out.push(at);23        }24    }25    out26}2728fn place(panel: Frame, at: f64, gauge: f64) -> Option<(f64, f64)> {29    if gauge <= 0.0 {30        return None;31    }32    let across = (at.log10() - LEFT.log10()) / (RIGHT.log10() - LEFT.log10());33    let drop = (-gauge.log10()).clamp(0.0, DECADES) / DECADES;34    Some((panel.x + panel.w * across, panel.y + panel.h * drop))35}3637fn trace(panel: Frame, rungs: &[usize], gauge: impl Fn(usize) -> f64) -> Vec<(f64, f64)> {38    rungs39        .iter()40        .filter_map(|&m| place(panel, m as f64, gauge(m)))41        .collect()42}4344fn chaser(board: &mut Board, panel: Frame, rungs: &[usize], partial: fn(usize) -> f64, limit: f64) {45    let path = trace(panel, rungs, |m| (partial(m) - limit).abs() / limit);46    board.polyline(&path, 2.6, ink::blue());47}4849fn stage(board: &mut Board, panel: Frame, path: &[(f64, f64)], color: Color) {50    board.polyline(path, 2.6, color);51    plot::axis(board, panel, ink::line());52}5354fn main() -> Result<()> {55    let rungs = ladder();56    let mut board = Board::square();57    let frame = board.frame(0.08);58    let mut panels: Vec<Frame> = Vec::new();59    for row in frame.rows(2) {60        for cell in row.cols(4) {61            panels.push(Frame::new(62                cell.x + cell.w * 0.04,63                cell.y + cell.h * 0.09,64                cell.w * 0.92,65                cell.h * 0.82,66            ));67        }68    }69    assert_eq!(panels.len(), 8);7071    chaser(&mut board, panels[0], &rungs, formulas::wallis, PI / 2.0);72    chaser(&mut board, panels[1], &rungs, formulas::leibniz, PI / 4.0);73    chaser(&mut board, panels[2], &rungs, formulas::basel, PI * PI / 6.0);74    chaser(&mut board, panels[3], &rungs, formulas::e_partial, E);75    chaser(76        &mut board,77        panels[4],78        &rungs,79        formulas::euler_gamma_partial,80        EULER,81    );82    for panel in &panels[..5] {83        plot::axis(&mut board, *panel, ink::line());84    }8586    let counted = trace(panels[5], &rungs, |m| {87        let li = formulas::li(m as f64);88        (formulas::prime_count(m) as f64 - li).abs() / li89    });90    stage(&mut board, panels[5], &counted, ink::yellow());9192    let comet = trace(panels[6], &rungs, |m| 1.0 / formulas::goldbach(2 * m) as f64);93    stage(&mut board, panels[6], &comet, ink::yellow());9495    let meter = trace(panels[7], &rungs, |m| {96        formulas::mertens(m).unsigned_abs() as f64 / (m as f64).sqrt()97    });98    plot::dots(&mut board, &meter, 2.4, ink::orange());99    plot::axis(&mut board, panels[7], ink::line());100101    assert_eq!(rungs.first().copied(), Some(FLOOR));102    assert_eq!(rungs.last().copied(), Some(TOP));103    assert_eq!(counted.len(), rungs.len());104    assert_eq!(comet.len(), rungs.len());105    assert!(meter.len() < rungs.len());106    save("wiki-famous-formulas", &board)?;107    Ok(())108}