demo-echo.rs
3.2 kB · rust · 108 lines
1use mrlycore::errors::Result;2use mrlyfig::{ink, plot, save, Board, Frame};3use mrlynum::design;45const BASE: u64 = 10;6const DIGITS: [u64; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8];7const DEPTH: usize = 5;8const SAMPLES: usize = 4096;9const FLOOR: usize = 101;10const BAND: (f64, f64) = (4.0, 60.0);11const THRESHOLD: f64 = 8.0;1213fn column(board: &mut Board, frame: Frame, x: f64, thick: f64, color: mrlycore::Color, dash: f64) {14 if dash <= 0.0 {15 board.segment((x, frame.y), (x, frame.y + frame.h), thick, color);16 return;17 }18 let mut y = frame.y;19 while y < frame.y + frame.h {20 let end = (y + dash).min(frame.y + frame.h);21 board.segment((x, y), (x, end), thick, color);22 y = end + dash * 0.8;23 }24}2526fn main() -> Result<()> {27 let values = design::elements(BASE, &DIGITS, DEPTH);28 let mu = design::mobius_of(&values);29 let running = design::meter(&mu);30 assert_eq!(values.len(), 59048);31 assert_eq!(running[values.len() - 1], 201);3233 let alpha = (DIGITS.len() as f64).ln() / (BASE as f64).ln();34 let logx = design::log_grid(&values, SAMPLES);35 let series = design::resample(&values, &running, alpha / 2.0, &logx);36 let (gamma, power) = design::spectrum(&logx, &series);37 let score = design::score(&power, FLOOR);38 let found = design::peaks(&gamma, &score, BAND, THRESHOLD);39 let bin = gamma[1];40 let zeros: Vec<f64> = design::ZETA_ORDINATES41 .iter()42 .copied()43 .filter(|g| *g > BAND.0 && *g < BAND.1)44 .collect();45 let lattice: Vec<f64> = design::pole_lattice(BASE, BAND.1)46 .into_iter()47 .filter(|g| *g > BAND.0)48 .collect();49 assert_eq!(found.len(), 5);50 assert_eq!(zeros.len(), 13);51 assert_eq!(lattice.len(), 20);52 assert_eq!(53 found54 .iter()55 .filter(|&&at| design::nearest(gamma[at], &zeros) <= bin)56 .count(),57 558 );5960 let mut board = Board::square();61 let frame = board.frame(0.08);62 let peak = found63 .iter()64 .map(|&at| score[at])65 .fold(0.0f64, |top, value| top.max(value));66 let x = |g: f64| frame.x + frame.w * (g - BAND.0) / (BAND.1 - BAND.0);67 let y = |v: f64| frame.y + frame.h * (1.0 - (v / peak).clamp(0.0, 1.0).sqrt());6869 for line in &lattice {70 column(71 &mut board,72 frame,73 x(*line),74 3.0,75 ink::fade(ink::pink(), 0.34),76 13.0,77 );78 }79 for zero in &zeros {80 column(81 &mut board,82 frame,83 x(*zero),84 7.0,85 ink::fade(ink::yellow(), 0.46),86 0.0,87 );88 }89 plot::baseline(&mut board, frame, ink::line());90 for at in 0..gamma.len() {91 if gamma[at] <= BAND.0 || gamma[at] >= BAND.1 {92 continue;93 }94 board.segment(95 (x(gamma[at]), frame.y + frame.h),96 (x(gamma[at]), y(score[at])),97 4.0,98 ink::blue(),99 );100 }101 let crowns: Vec<(f64, f64)> = found102 .iter()103 .map(|&at| (x(gamma[at]), y(score[at])))104 .collect();105 plot::dots(&mut board, &crowns, 11.0, ink::yellow());106 save("demo-echo", &board)?;107 Ok(())108}