diff --git a/russell_lab/README.md b/russell_lab/README.md index b0ec1778..3aff616a 100644 --- a/russell_lab/README.md +++ b/russell_lab/README.md @@ -500,13 +500,14 @@ roots = │ 0.5162732673126048 │ └ ┘ f @ roots = - 1.84e-8 - -1.51e-8 - -2.40e-8 - 9.53e-9 - -1.16e-8 - -5.80e-9 - +┌ ┐ +│ 1.84E-08 │ +│ -1.51E-08 │ +│ -2.40E-08 │ +│ 9.53E-09 │ +│ -1.16E-08 │ +│ -5.80E-09 │ +└ ┘ refined roots = ┌ ┐ │ 0.04109147155278252 │ @@ -517,12 +518,14 @@ refined roots = │ 0.5162732665558162 │ └ ┘ f @ refined roots = - 6.66e-16 --2.22e-16 --2.22e-16 - 1.33e-15 - 4.44e-16 --2.22e-16 +┌ ┐ +│ 6.66E-16 │ +│ -2.22E-16 │ +│ -2.22E-16 │ +│ 1.33E-15 │ +│ 4.44E-16 │ +│ -2.22E-16 │ +└ ┘ ``` The function and the roots are illustrated in the figure below. diff --git a/russell_lab/examples/algo_multi_root_solver_cheby.rs b/russell_lab/examples/algo_multi_root_solver_cheby.rs index 28f27b26..ecd0d60f 100644 --- a/russell_lab/examples/algo_multi_root_solver_cheby.rs +++ b/russell_lab/examples/algo_multi_root_solver_cheby.rs @@ -1,7 +1,6 @@ use plotpy::{Curve, Legend, Plot}; use russell_lab::math::PI; use russell_lab::*; -use std::fmt::Write; fn main() -> Result<(), StrError> { // function @@ -22,14 +21,14 @@ fn main() -> Result<(), StrError> { let roots = Vector::from(&solver.chebyshev(&interp)?); let f_at_roots = roots.get_mapped(|x| f(x, args).unwrap()); println!("roots =\n{}", roots); - println!("f @ roots =\n{}", print_vec_exp(&f_at_roots)); + println!("f @ roots =\n{}", vec_fmt_scientific(&f_at_roots, 2)); // polish the roots let mut roots_refined = roots.clone(); solver.refine(roots_refined.as_mut_data(), xa, xb, args, f)?; let f_at_roots_refined = roots_refined.get_mapped(|x| f(x, args).unwrap()); println!("refined roots =\n{}", roots_refined); - println!("f @ refined roots =\n{}", print_vec_exp(&f_at_roots_refined)); + println!("f @ refined roots =\n{}", vec_fmt_scientific(&f_at_roots_refined, 2)); // plot the results let nstation = 301; @@ -81,11 +80,3 @@ fn main() -> Result<(), StrError> { .unwrap(); Ok(()) } - -fn print_vec_exp(v: &Vector) -> String { - let mut buf = String::new(); - for x in v { - writeln!(&mut buf, "{:>9.2e}", x).unwrap(); - } - buf -} diff --git a/russell_lab/src/vector/mod.rs b/russell_lab/src/vector/mod.rs index e20f2fdf..b66548bf 100644 --- a/russell_lab/src/vector/mod.rs +++ b/russell_lab/src/vector/mod.rs @@ -14,6 +14,7 @@ mod vec_add; mod vec_all_finite; mod vec_approx_eq; mod vec_copy; +mod vec_fmt_scientific; mod vec_inner; mod vec_max_abs_diff; mod vec_max_scaled; @@ -35,6 +36,7 @@ pub use crate::vector::vec_add::*; pub use crate::vector::vec_all_finite::*; pub use crate::vector::vec_approx_eq::*; pub use crate::vector::vec_copy::*; +pub use crate::vector::vec_fmt_scientific::*; pub use crate::vector::vec_inner::*; pub use crate::vector::vec_max_abs_diff::*; pub use crate::vector::vec_max_scaled::*; diff --git a/russell_lab/src/vector/vec_fmt_scientific.rs b/russell_lab/src/vector/vec_fmt_scientific.rs new file mode 100644 index 00000000..a7144204 --- /dev/null +++ b/russell_lab/src/vector/vec_fmt_scientific.rs @@ -0,0 +1,70 @@ +use super::Vector; +use crate::format_scientific; +use std::cmp; +use std::fmt::Write; + +pub fn vec_fmt_scientific(u: &Vector, precision: usize) -> String { + let mut result = String::new(); + let f = &mut result; + // handle empty vector + if u.dim() == 0 { + write!(f, "[]").unwrap(); + return result; + } + // find largest width + let mut width = 0; + let mut buf = String::new(); + for i in 0..u.dim() { + write!(&mut buf, "{:.1$e}", u[i], precision).unwrap(); + let _ = buf.split_off(buf.find('e').unwrap()); + width = cmp::max(buf.chars().count(), width); + buf.clear(); + } + width += 4; + // draw vector + width += 1; + write!(f, "┌{:1$}┐\n", " ", width + 1).unwrap(); + for i in 0..u.dim() { + if i > 0 { + write!(f, " │\n").unwrap(); + } + write!(f, "│").unwrap(); + write!(f, "{}", format_scientific(u[i], width, precision)).unwrap(); + } + write!(f, " │\n").unwrap(); + write!(f, "└{:1$}┘", " ", width + 1).unwrap(); + result +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#[cfg(test)] +mod tests { + use super::vec_fmt_scientific; + use crate::Vector; + + #[test] + fn vec_fmt_scientific_works() { + let u = Vector::from(&[1.012444, 200.034123, 1e-8]); + println!("{}", vec_fmt_scientific(&u, 3)); + assert_eq!( + vec_fmt_scientific(&u, 3), + "┌ ┐\n\ + │ 1.012E+00 │\n\ + │ 2.000E+02 │\n\ + │ 1.000E-08 │\n\ + └ ┘" + ); + + let u = Vector::from(&[1.012444, 200.034123, 1e+8]); + println!("{}", vec_fmt_scientific(&u, 4)); + assert_eq!( + vec_fmt_scientific(&u, 4), + "┌ ┐\n\ + │ 1.0124E+00 │\n\ + │ 2.0003E+02 │\n\ + │ 1.0000E+08 │\n\ + └ ┘" + ); + } +}