use std::fs;
use std::io::{self, BufWriter, Write};
use std::path::Path;
pub fn write_csv<P: AsRef<Path>>(path: P, headers: &[&str], rows: &[Vec<f64>]) -> io::Result<()> {
let file = fs::File::create(path)?;
let mut w = BufWriter::new(file);
writeln!(w, "{}", headers.join(","))?;
for row in rows {
let line: Vec<String> = row.iter().map(|v| format!("{:.8e}", v)).collect();
writeln!(w, "{}", line.join(","))?;
}
w.flush()
}
pub fn write_dat<P: AsRef<Path>>(
path: P,
comment: &str,
columns: &[&str],
rows: &[Vec<f64>],
) -> io::Result<()> {
let file = fs::File::create(path)?;
let mut w = BufWriter::new(file);
writeln!(w, "# {}", comment)?;
writeln!(w, "# {}", columns.join("\t"))?;
for row in rows {
let line: Vec<String> = row.iter().map(|v| format!("{:.8e}", v)).collect();
writeln!(w, "{}", line.join("\t"))?;
}
w.flush()
}
pub fn ensure_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
fs::create_dir_all(path)
}
pub fn format_si(value: f64) -> String {
let prefixes = [
(1e24, "Y"),
(1e21, "Z"),
(1e18, "E"),
(1e15, "P"),
(1e12, "T"),
(1e9, "G"),
(1e6, "M"),
(1e3, "k"),
(1.0, ""),
(1e-3, "m"),
(1e-6, "μ"),
(1e-9, "n"),
(1e-12, "p"),
];
let abs_val = value.abs();
for &(threshold, prefix) in &prefixes {
if abs_val >= threshold {
return format!("{:.3} {}", value / threshold, prefix);
}
}
format!("{:.3e}", value)
}