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}