sciforge 0.0.3

A comprehensive scientific computing library in pure Rust with zero dependencies
Documentation
use sciforge::benchmark::decode::decode;
use sciforge::benchmark::engine::bench;
use sciforge::benchmark::export::{Entry, export};
use sciforge::benchmark::report::generate;
use sciforge::hub::prelude::constants::elements;
use std::fs;
use std::path::Path;

fn grid_position(e: &elements::Element) -> (Option<u8>, Option<u8>) {
    let z = e.atomic_number;
    match z {
        57..=71 => (Some(9), Some((z - 57 + 4) as u8)),
        89..=103 => (Some(10), Some((z - 89 + 4) as u8)),
        _ => (Some(e.period as u8), e.group.map(|g| g as u8)),
    }
}

fn main() {
    let dir = Path::new("output/examples/periodic_table");
    fs::create_dir_all(dir).unwrap();
    let all = elements::all();

    let precisions = ["f32", "f64"];
    let iters_choices: [u64; 3] = [1000, 5000, 10000];

    let experiments: Vec<String> = all
        .iter()
        .map(|e| format!("{}_{}_benchmark", e.symbol, e.name))
        .collect();

    let mass_strs: Vec<String> = all.iter().map(|e| format!("{}", e.atomic_mass)).collect();

    let mut metrics_store: Vec<(String, String, _)> = Vec::with_capacity(all.len());

    for (idx, e) in all.iter().enumerate() {
        let prec = precisions[idx % 2];
        let iters = iters_choices[idx % 3];
        let z = e.atomic_number;
        let m = bench(&experiments[idx], prec, iters, move || {
            let mut v = z as u64;
            for i in 0..(z as u64 * 10) {
                v = v.wrapping_mul(6364136223846793005).wrapping_add(i);
            }
            v
        });
        let result_str = format!(
            "Z={} | {} ({}) | {} u | {} | {}",
            e.atomic_number, e.symbol, e.name, e.atomic_mass, e.category, e.electron_configuration
        );
        let label = format!("{:03}_{}", e.atomic_number, e.symbol);
        let r = generate(&m, &result_str);
        assert!(r.csv.starts_with("experiment_name"));
        assert!(r.html.starts_with("<!DOCTYPE html>"));
        metrics_store.push((label, result_str, m));
    }

    let entries: Vec<Entry<'_>> = metrics_store
        .iter()
        .enumerate()
        .map(|(idx, (label, result, m))| {
            let e = &all[idx];
            let (row, col) = grid_position(e);
            Entry {
                metrics: m,
                result: result.as_str(),
                label: label.as_str(),
                tags: vec![
                    ("category", e.category),
                    ("symbol", e.symbol),
                    ("name", e.name),
                    ("config", e.electron_configuration),
                    ("mass", mass_strs[idx].as_str()),
                ],
                grid_row: row,
                grid_col: col,
            }
        })
        .collect();

    let summary = export(
        "Periodic Table of Elements \u{2014} Data from IUPAC, 2024 edition",
        &entries,
        dir,
    )
    .unwrap();
    assert!(summary.files_written > 0);

    let bmk_dir = dir.join("bmk");
    let last_bmk = fs::read(bmk_dir.join("periodic_table.bmk")).unwrap();
    let view = decode(&last_bmk).unwrap();
    assert!(!view.experiment_name.is_empty());
}