bachelor/bachelorarbeit/src/gq_storage.rs

90 lines
2.8 KiB
Rust

//! This module writes and reads roots and weights of gauss-quad into files, using a dedicated file format.
//! The format works as follows: One u64 is written, indicating the n of the roots and weights that follow
//! (thereby hinting at the number of floats that are following before the next u64, which is 2*n). This is repeated for
//! arbitrary n.
#![allow(dead_code)]
use std::{
fs::File,
io::{self, BufReader, BufWriter, Read, Seek, SeekFrom, Write},
};
use gauss_quad::GaussLegendre;
/// Writes roots and weights of gauss-quad into a file at `filepath`. params contains roots and weights for multiple n.
pub fn serialize(filepath: &str, params: Vec<(Vec<f64>, Vec<f64>)>) -> io::Result<()> {
let file = File::create(filepath)?;
let mut file = BufWriter::new(file);
for (roots, weights) in params.iter() {
file.write_all(&u64::try_from(roots.len()).unwrap().to_le_bytes())?;
for root in roots {
file.write_all(&root.to_bits().to_le_bytes())?;
}
for weight in weights {
file.write_all(&weight.to_bits().to_le_bytes())?;
}
}
Ok(())
}
pub fn deserialize<R: Read + Seek>(
reader: &mut R,
filter: impl Fn(u64) -> bool,
) -> io::Result<Vec<(Vec<f64>, Vec<f64>)>> {
let mut buf = [0u8; 8];
let mut values = Vec::new();
'outer: loop {
let res = reader.read(&mut buf)?;
if res < 8 {
break;
}
let n = u64::from_le_bytes(buf);
// skips stored floats for n that should not be stored
if !filter(n) {
reader
.seek(SeekFrom::Current(i64::try_from(2 * n * 8).unwrap()))
.unwrap();
continue;
}
// Stores roots and weights into values Vec
let mut roots = Vec::new();
for _ in 0..n {
let res = reader.read(&mut buf)?;
if res < 8 {
break 'outer;
}
roots.push(f64::from_bits(u64::from_le_bytes(buf)));
}
let mut weights = Vec::new();
for _ in 0..n {
let res = reader.read(&mut buf)?;
if res < 8 {
break 'outer;
}
weights.push(f64::from_bits(u64::from_le_bytes(buf)));
}
values.push((roots, weights));
}
Ok(values)
}
pub fn fill_with_gauss_quad(n_values: Vec<u64>) -> std::io::Result<()> {
let mut params = Vec::new();
for i in n_values {
let gq = GaussLegendre::init(usize::try_from(i).unwrap());
params.push((gq.nodes, gq.weights));
}
serialize("./gauss_quad_lut.morello", params).unwrap();
let file = File::open("./gauss_quad_lut.morello")?;
let mut file = BufReader::new(file);
let res = deserialize(&mut file, |_| true);
println!("{:?}", res);
Ok(())
}