research-mobius.rs
2.0 kB · rust · 70 lines
1use mrlycore::errors::Result;2use mrlyfig::{ink, plot, save, Board};3use mrlynum::factor::mobius;45const LENGTH: u32 = 16;6const STEPS: usize = 1 << LENGTH;7const DRAWN: usize = 4096;89fn spread(index: usize) -> usize {10 let mut value = 0usize;11 for bit in 0..LENGTH {12 if index >> bit & 1 == 1 {13 value += 4usize.pow(bit);14 }15 }16 value17}1819fn walks() -> (Vec<f64>, Vec<f64>) {20 let mut low = Vec::with_capacity(STEPS + 1);21 let mut high = Vec::with_capacity(STEPS + 1);22 let (mut a, mut b) = (0i64, 0i64);23 low.push(0.0);24 high.push(0.0);25 for index in 0..STEPS {26 let value = spread(index);27 a += mobius(value) as i64;28 b += mobius(2 * value) as i64;29 assert_eq!(b, -a);30 low.push(a as f64);31 high.push(b as f64);32 }33 (low, high)34}3536fn main() -> Result<()> {37 let (low, high) = walks();38 let reach = (STEPS as f64).sqrt();39 let peak = low.iter().fold(0.0f64, |m, v| m.max(v.abs()));40 assert!(peak < reach);4142 let mut board = Board::square();43 let frame = board.frame(0.08);44 let at = |index: f64, meter: f64| {45 (46 frame.x + frame.w * index / STEPS as f64,47 frame.y + frame.h * (0.5 - meter / (2.0 * reach)),48 )49 };50 board.segment(at(0.0, 0.0), at(STEPS as f64, 0.0), 1.6, ink::line());51 plot::axis(&mut board, frame, ink::line());52 for sign in [1.0f64, -1.0] {53 let envelope: Vec<(f64, f64)> = (0..=DRAWN)54 .map(|k| {55 let index = STEPS as f64 * k as f64 / DRAWN as f64;56 at(index, sign * index.sqrt())57 })58 .collect();59 board.polyline(&envelope, 2.0, ink::fade(ink::dim(), 0.75));60 }61 let stride = STEPS / DRAWN;62 for (walk, color) in [(&low, ink::blue()), (&high, ink::orange())] {63 let trace: Vec<(f64, f64)> = (0..=DRAWN)64 .map(|k| at((k * stride) as f64, walk[k * stride]))65 .collect();66 board.polyline(&trace, 2.4, color);67 }68 save("research-mobius", &board)?;69 Ok(())70}