modes.rs

3.6 kB · rust · 107 lines

1use mrlydemo::modes::*;2use mrlydemo::two::two_grid;3use std::f64::consts::TAU;45fn direct(6    code: &str,7    number: usize,8    level: usize,9    base: usize,10    t1: usize,11    t2: usize,12) -> (f64, f64) {13    let grid = two_grid(code, number, level, 0, base).unwrap();14    let span = grid.width as usize;15    let (mut re, mut im) = (0.0, 0.0);16    for x1 in 0..span {17        for x2 in 0..span {18            if grid.types[x1 * span + x2] == 0 {19                continue;20            }21            let angle = TAU * ((t1 * x1 + t2 * x2) % span) as f64 / span as f64;22            re += angle.cos();23            im += angle.sin();24        }25    }26    (re, im)27}2829fn gap(code: &str, number: usize, level: usize, base: usize) -> f64 {30    let span = number.pow(level as u32);31    let mass = f64::from(32        two_grid(code, number, 1, 0, base)33            .unwrap()34            .types35            .iter()36            .map(|&b| u32::from(b != 0))37            .sum::<u32>(),38    )39    .powi(level as i32);40    let field = modes_field(code, number, level, base).unwrap();41    assert_eq!(field.len(), span * span);42    let mut worst: f64 = 0.0;43    for t1 in 0..span {44        for t2 in 0..span {45            let (re, im) = direct(code, number, level, base, t1, t2);46            let read = modes_value(code, number, level, base, t1, t2).unwrap();47            worst = worst.max((read[0] - re).abs());48            worst = worst.max((read[1] - im).abs());49            worst = worst.max((read[2] - re.hypot(im) / mass).abs());50            worst = worst.max((f64::from(field[t1 * span + t2]) - re.hypot(im) / mass).abs());51        }52    }53    worst54}5556#[test]57fn the_product_formula_is_the_masks_transform() {58    assert!(gap("7", 2, 3, 2) < 1e-6);59    assert!(gap("9", 2, 3, 2) < 1e-6);60    assert!(gap("495", 3, 2, 3) < 1e-6);61    assert!(gap("127", 3, 2, 3) < 1e-6);62}6364#[test]65fn the_modes_exports_answer() {66    let gasket = modes_field("7", 2, 3, 2).unwrap();67    let carpet = modes_field("495", 3, 2, 3).unwrap();68    let runner = modes_field("127", 3, 2, 3).unwrap();69    let top = |field: &[f32]| format!("{:.6}", field[1..].iter().copied().fold(f32::MIN, f32::max));70    assert_eq!(format!("{},{}", gasket.len(), carpet.len()), "64,81");71    assert_eq!(format!("{},{}", gasket[0], carpet[0]), "1,1");72    assert_eq!(format!("{:.6}", gasket[1]), "0.231717");73    assert_eq!(top(&gasket), "0.333333");74    assert_eq!(format!("{:.6}", carpet[1]), "0.103067");75    assert_eq!(top(&carpet), "0.125000");76    assert_eq!(format!("{:.6}", runner[9]), "0.253018");77    assert_eq!(top(&runner), "0.285714");7879    assert_eq!(modes_large("9", 2, 3, 2, 0.5).unwrap(), 8);80    assert_eq!(modes_large("7", 2, 3, 2, 0.25).unwrap(), 4);81    assert_eq!(modes_large("495", 3, 2, 3, 0.1).unwrap(), 13);82    assert_eq!(modes_large("127", 3, 2, 3, 0.1).unwrap(), 17);83    assert_eq!(modes_large("495", 3, 5, 3, 0.1).unwrap(), 25);8485    let one = modes_value("495", 3, 2, 3, 1, 1).unwrap();86    assert_eq!(87        format!("{:.6},{:.6},{:.6}", one[0], one[1], one[2]),88        "-4.145430,3.478429,0.084554"89    );90    let two = modes_value("127", 3, 2, 3, 1, 2).unwrap();91    assert_eq!(92        format!("{:.6},{:.6},{:.6}", two[0], two[1], two[2]),93        "3.145430,-1.508813,0.071196"94    );9596    let mode = modes_pattern("495", 3, 2, 3, 1, 2).unwrap();97    assert_eq!(format!("{},{}", mode.len(), mode[0]), "81,1");98    assert_eq!(modes_digits("495", 3, 3).unwrap(), 8);99    assert_eq!(modes_digits("127", 3, 3).unwrap(), 7);100    assert_eq!(modes_digits("7", 2, 2).unwrap(), 3);101}102103#[test]104fn the_torus_is_capped_and_the_empty_design_refused() {105    assert!(modes_field("495", 3, 6, 3).is_err());106    assert!(modes_field("0", 3, 2, 3).is_err());107}