use crate::{format_nanoseconds, Stopwatch};
use std::fmt::{self, Write};
pub(crate) const UNINITIALIZED: f64 = f64::INFINITY;
pub type NoArgs = u8;
#[derive(Clone, Copy, Debug)]
pub struct Stats {
pub n_function: usize,
pub n_jacobian: usize,
pub n_iterations: usize,
pub error_estimate: f64,
pub nanos_total: u128,
pub(crate) sw_total: Stopwatch,
}
#[derive(Clone, Copy, Debug)]
pub struct Bracket {
pub a: f64,
pub b: f64,
pub fa: f64,
pub fb: f64,
pub xo: f64,
pub fxo: f64,
}
impl Stats {
pub fn new() -> Stats {
Stats {
n_function: 0,
n_jacobian: 0,
n_iterations: 0,
error_estimate: UNINITIALIZED,
nanos_total: 0,
sw_total: Stopwatch::new(),
}
}
pub(crate) fn stop_sw_total(&mut self) {
self.nanos_total = self.sw_total.stop();
}
pub fn summary(&self) -> String {
let mut buffer = String::new();
let est_err = if self.error_estimate == UNINITIALIZED {
"unavailable".to_string()
} else {
format!("{:.2e}", self.error_estimate)
};
write!(
&mut buffer,
"Number of function evaluations = {}\n\
Number of Jacobian evaluations = {}\n\
Number of iterations = {}\n\
Error estimate = {}",
self.n_function, self.n_jacobian, self.n_iterations, est_err
)
.unwrap();
buffer
}
}
impl fmt::Display for Stats {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}\n\
Total computation time = {}",
self.summary(),
format_nanoseconds(self.nanos_total),
)
.unwrap();
Ok(())
}
}
impl fmt::Display for Bracket {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"lower bound: a = {}\n\
root/optimum: xo = {}\n\
upper bound: b = {}\n\
function @ a: f(a) = {}\n\
function @ root/optimum: f(xo) = {}\n\
function @ b: f(b) = {}",
self.a, self.xo, self.b, self.fa, self.fxo, self.fb
)
.unwrap();
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::{Bracket, Stats};
#[test]
fn stats_summary_and_display_work() {
let stats = Stats::new();
assert_eq!(
format!("{}", stats),
"Number of function evaluations = 0\n\
Number of Jacobian evaluations = 0\n\
Number of iterations = 0\n\
Error estimate = unavailable\n\
Total computation time = 0ns"
);
}
#[test]
fn bracket_display_works() {
let bracket = Bracket {
a: 1.0,
xo: 2.0,
b: 3.0,
fa: 4.0,
fxo: 5.0,
fb: 6.0,
};
assert_eq!(
format!("{}", bracket),
"lower bound: a = 1\n\
root/optimum: xo = 2\n\
upper bound: b = 3\n\
function @ a: f(a) = 4\n\
function @ root/optimum: f(xo) = 5\n\
function @ b: f(b) = 6",
);
}
}