wiki-rajchman-measure.rs
2.4 kB · rust · 81 lines
1use mrlycore::errors::Result;2use mrlyfig::{ink, plot, save, Board, Frame};3use std::f64::consts::PI;45const TOP: usize = 243;6const DEPTH: u32 = 40;7const WIDTH: f64 = 0.1;8const STEPS: usize = 4096;910fn main() -> Result<()> {11 let mut board = Board::square();12 let frame = board.frame(0.08);13 let gap = frame.h * 0.08;14 let half = (frame.h - gap) / 2.0;15 let upper = Frame::new(frame.x, frame.y, frame.w, half);16 let lower = Frame::new(frame.x, frame.y + half + gap, frame.w, half);1718 let cantor: Vec<f64> = (1..=TOP).map(|n| cantor(n as f64)).collect();19 let bump: Vec<f64> = (1..=TOP).map(|n| bump(n as f64)).collect();2021 let powers: Vec<usize> = (0..)22 .map(|k| 3usize.pow(k))23 .take_while(|&p| p <= TOP)24 .collect();25 let ceiling = cantor[0];26 for &p in &powers {27 assert!((cantor[p - 1] - ceiling).abs() < 1e-9);28 }29 assert_eq!(powers.len(), 6);30 assert!(cantor.iter().all(|&v| v <= ceiling + 1e-9));31 assert!(bump[0] > 0.9);32 assert!(bump[40..].iter().all(|&v| v < 0.01));3334 comb(&mut board, upper, &cantor, ceiling, &powers);35 comb(&mut board, lower, &bump, ceiling.max(bump[0]), &[]);36 plot::axis(&mut board, upper, ink::line());37 plot::axis(&mut board, lower, ink::line());38 save("wiki-rajchman-measure", &board)?;39 Ok(())40}4142fn comb(board: &mut Board, frame: Frame, values: &[f64], peak: f64, lit: &[usize]) {43 let slot = frame.w / values.len() as f64;44 let pad = slot * 0.2;45 for (i, &v) in values.iter().enumerate() {46 let h = frame.h * v / peak;47 let color = if lit.contains(&(i + 1)) {48 ink::yellow()49 } else {50 ink::blue()51 };52 board.rect(53 frame.x + i as f64 * slot + pad,54 frame.y + frame.h - h,55 slot - 2.0 * pad,56 h,57 color,58 );59 }60}6162fn cantor(t: f64) -> f64 {63 (1..=DEPTH)64 .map(|k| (2.0 * PI * t / 3f64.powi(k as i32)).cos().abs())65 .product()66}6768fn bump(n: f64) -> f64 {69 let mut re = 0.0;70 let mut im = 0.0;71 let mut mass = 0.0;72 for i in 0..STEPS {73 let u = (i as f64 + 0.5) / STEPS as f64;74 let w = (-1.0 / (u * (1.0 - u))).exp();75 let x = 0.5 + WIDTH * (u - 0.5);76 re += w * (2.0 * PI * n * x).cos();77 im += w * (2.0 * PI * n * x).sin();78 mass += w;79 }80 re.hypot(im) / mass81}