main.rs

2.7 kB · rust · 85 lines

1mod census;2mod design;3mod terms;45use design::Design;67fn run_terms(design: &Design, top: u32, threads: usize) {8    let stored = terms::stored(design);9    let delta = design.density();10    println!(11        "{} k {} delta {:.6} live domain n <= {}",12        design.name, design.fill, delta, top13    );14    let mut last_gap = 0.0;15    let mut agree = true;16    for term in terms::terms(design, top, threads) {17        let ratio = term.value as f64 / (design.fill as f64).powi(term.level as i32);18        let gap = ratio - delta;19        let kept = stored20            .iter()21            .find(|(n, _)| *n == term.level)22            .map(|(_, v)| *v);23        let tag = match kept {24            Some(v) if v == term.value => "stored",25            Some(_) => "DIFFERS",26            None => "fresh",27        };28        agree &= tag != "DIFFERS";29        println!(30            "n {:2} A {:>26} A/k^n {:.6} gap {:+.2e} halving {:.2} {:.1}s {}",31            term.level,32            term.value,33            ratio,34            gap,35            if last_gap != 0.0 { gap / last_gap } else { 0.0 },36            term.seconds,37            tag38        );39        last_gap = gap;40    }41    for (n, v) in stored.iter().filter(|(n, _)| *n > top) {42        let gap = *v as f64 / (design.fill as f64).powi(*n as i32) - delta;43        println!("n {:2} A {:>26} gap {:+.2e} stored only", n, v, gap);44    }45    let brute_top = match design.dimension {46        3 => 5,47        _ => 8,48    };49    let brute: Vec<u64> = (1..=brute_top).map(|n| terms::brute(design, n)).collect();50    let matches = brute.iter().enumerate().all(|(i, b)| {51        stored52            .iter()53            .any(|(n, v)| *n as usize == i + 1 && *v == *b as i128)54    });55    println!(56        "{} live terms agree with stored {}, brute force to n = {} agrees {}",57        design.name, agree, brute_top, matches58    );59}6061fn main() {62    let args: Vec<String> = std::env::args().skip(1).collect();63    let threads = std::thread::available_parallelism()64        .map(|n| n.get())65        .unwrap_or(8);66    match args.first().map(String::as_str) {67        Some("terms") => {68            let design = Design::named(&args[1]).expect("carpet, menger or vicsek");69            run_terms(design, args[2].parse().expect("top level"), threads);70        }71        Some("census") => {72            for level in args[1..].iter().map(|a| a.parse().expect("level")) {73                census::report(level, level == 13);74            }75        }76        _ => {77            run_terms(&design::CARPET, 18, threads);78            run_terms(&design::MENGER, 16, threads);79            run_terms(&design::VICSEK, 18, threads);80            for level in 13..=16 {81                census::report(level, level == 13);82            }83        }84    }85}