use super::Vector;
pub fn vec_rms_scaled_diff(u: &Vector, v: &Vector, abs_tol: f64, rel_tol: f64) -> f64 {
let n = v.dim();
assert!(u.dim() == n);
if n == 0 {
return 0.0;
}
let mut sum = 0.0;
for i in 0..n {
let sci = abs_tol + rel_tol * f64::max(f64::abs(u[i]), f64::abs(v[i]));
let diff = u[i] - v[i];
sum += diff * diff / (sci * sci);
}
f64::sqrt(sum / (n as f64))
}
#[cfg(test)]
mod tests {
use super::{vec_rms_scaled_diff, Vector};
use crate::approx_eq;
#[test]
fn vec_rms_scaled_diff_works() {
let empty = Vector::new(0);
assert_eq!(vec_rms_scaled_diff(&empty, &empty, 1.0, 1.0), 0.0);
let abs_tol = 1.0;
let rel_tol = 1.0;
let u = Vector::from(&[3.0, 1.0, 2.0]);
let v = Vector::from(&[-2.0, 0.0, 3.0]);
let rms = vec_rms_scaled_diff(&u, &v, abs_tol, rel_tol);
approx_eq(rms, f64::sqrt(5.0 / 8.0), 1e-15);
let abs_tol = 0.1;
let rel_tol = 0.25;
let rms = vec_rms_scaled_diff(&u, &v, abs_tol, rel_tol);
approx_eq(rms, 3.8362057850464972, 1e-15);
}
}