- used `syn::parse_quote!` instead of constructing `syn` structs directly. unsurprisingly, makes a world of difference! - code is, like, 1k lines shorter now - moved tests into dedicated crate - tweaked the tests even more, to represent complete lack of dependency on external crates
114 lines
3.1 KiB
Rust
114 lines
3.1 KiB
Rust
#![allow(missing_docs)]
|
|
|
|
use nacfahi::{fit, models::basic::Constant};
|
|
|
|
#[test]
|
|
fn custom_lavmar() {
|
|
use approx::assert_ulps_ne;
|
|
use nacfahi::{models::basic::Exponent, *};
|
|
|
|
// some data, presumably 2x + 1
|
|
let x = [1.0, 2.0, 3.0, 4.0, 5.0];
|
|
let y = [3.0, 5.0, 7.0, 9.0, 11.0];
|
|
|
|
// fitting model: a * exp(-b*x)
|
|
let mut line = Exponent { a: 0.0, b: 0.0 };
|
|
|
|
// custom very impatient lavmar instance
|
|
let lavmar = LevenbergMarquardt::new().with_patience(1);
|
|
|
|
// patience too low, proceed to fail the fit :3
|
|
let report = fit!(&mut line, x, y, minimizer = lavmar);
|
|
|
|
// expect to stop because of patience
|
|
assert_eq!(
|
|
report.termination,
|
|
TerminationReason::LostPatience,
|
|
"Approximation should stop because of patience"
|
|
);
|
|
|
|
// no reason to assume this, but oh well
|
|
assert_ulps_ne!(line.a, 2.0);
|
|
assert_ulps_ne!(line.b, 1.0);
|
|
|
|
// since we use different model, let's check that it's still able to fit, eventually:
|
|
line.a = 0.0;
|
|
line.b = 0.0;
|
|
|
|
// do the fit! (again)
|
|
let report = fit!(&mut line, x, y);
|
|
|
|
// check that approximation is successful
|
|
assert!(
|
|
report.termination.was_successful(),
|
|
"Approximation should be successful"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn custom_weight() {
|
|
use nacfahi::{models::basic::Linear, *};
|
|
|
|
// some data, presumably 2x + 1
|
|
let x = [1.0, 2.0, 3.0, 4.0, 5.0];
|
|
let y = [3.0, 5.0, 7.0, 9.0, 11.0];
|
|
|
|
// fitting model: a*x + b
|
|
let mut line = Linear { a: 0.0, b: 0.0 };
|
|
|
|
// custom weight function, really breaking the fit
|
|
let weight = |x: f64, y: f64| x.powi(206_265) % y / y.ln();
|
|
|
|
// proceed to fail the fit, because omg what is this weight function
|
|
let report = fit!(&mut line, x, y, weights = weight);
|
|
|
|
// expect to stop because of some bad reason, idk
|
|
assert!(
|
|
!report.termination.was_successful(),
|
|
"Approximation should fail because of silly weight function"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn custom_lavmar_weight() {
|
|
use nacfahi::{models::basic::Linear, *};
|
|
|
|
// some data, presumably 2x + 1
|
|
let x = [1.0, 2.0, 3.0, 4.0, 5.0];
|
|
let y = [3.0, 5.0, 7.0, 9.0, 11.0];
|
|
|
|
// fitting model: a*x + b
|
|
let mut line = Linear { a: 0.0, b: 0.0 };
|
|
|
|
// custom very impatient lavmar instance
|
|
let lavmar = LevenbergMarquardt::new().with_patience(1);
|
|
|
|
// custom weight function, really breaking the fit
|
|
let weight = |x: f64, y: f64| x.powi(206_265) % y / y.ln();
|
|
|
|
let _report = fit!(&mut line, x, y, weights = weight, minimizer = lavmar);
|
|
|
|
let _report = fit!(&mut line, x, y, minimizer = lavmar, weights = weight);
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic = "Weight function panic"]
|
|
fn weight_function_respected() {
|
|
let x = [0.0];
|
|
let y = [1.0];
|
|
let mut model = Constant { c: 0.0 };
|
|
let weights = |_: f64, _: f64| panic!("Weight function panic");
|
|
|
|
let _ = fit!(&mut model, x, y, weights = weights);
|
|
}
|
|
|
|
#[test]
|
|
fn default_weights_unused() {
|
|
let x = [0.0];
|
|
let y = [1.0];
|
|
let mut model = Constant { c: 0.0 };
|
|
#[allow(unused)]
|
|
let default_weights = |_: f64, _: f64| panic!("Weight function panic");
|
|
|
|
let _ = fit!(&mut model, x, y, weights = default_weights);
|
|
}
|