1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
/// Asserts that derivatives have approximately equal values
///
/// # Input
///
/// * `dfdx: f64` -- derivative of f with respect to x at a given x
/// * `at_x: f64` -- location for the derivative of f(x, {arguments}) w.r.t x
/// * `f: fn(f64, &A) -> f64` -- function `f(x: f64, args: &A)`
/// * `tol: f64` -- Error tolerance such that `|dfdx - dfdx_num| < tol`
///
/// # Examples
///
/// ## Accepts small error
///
/// ```
/// # #[macro_use] extern crate russell_chk;
/// # fn main() {
/// struct Arguments {}
/// let f = |x: f64, _: &mut Arguments| -x;
/// let args = &mut Arguments {};
/// let at_x = 8.0;
/// let dfdx = -1.01;
/// assert_deriv_approx_eq!(dfdx, at_x, f, args, 1e-2);
/// # }
/// ```
///
/// ## Panics due to tighter tolerance
///
/// ```should_panic
/// # #[macro_use] extern crate russell_chk;
/// # fn main() {
/// struct Arguments {}
/// let f = |x: f64, _: &mut Arguments| -x;
/// let args = &mut Arguments {};
/// let at_x = 8.0;
/// let dfdx = -1.01;
/// assert_deriv_approx_eq!(dfdx, at_x, f, args, 1e-3);
/// # }
/// ```
#[macro_export]
macro_rules! assert_deriv_approx_eq {
($dfdx:expr, $at_x:expr, $f:expr, $args:expr, $tol:expr) => {{
let dfdx_num = $crate::deriv_central5($at_x, $f, $args);
assert!(
(($dfdx - dfdx_num) as f64).abs() < $tol,
"assert derivative failed: `(dfdx != dfdx_num)` \
(dfdx: `{:?}`, dfdx_num: `{:?}`, expect diff: `{:?}`, real diff: `{:?}`)",
$dfdx,
dfdx_num,
$tol,
(($dfdx - dfdx_num) as f64).abs()
);
}};
}
#[cfg(test)]
mod tests {
struct Arguments {}
#[test]
#[should_panic(expected = "assert derivative failed: `(dfdx != dfdx_num)`")]
fn panics_on_different_deriv() {
let f = |x: f64, _: &mut Arguments| x * x / 2.0;
let args = &mut Arguments {};
let at_x = 1.5;
let dfdx = 1.51;
assert_deriv_approx_eq!(dfdx, at_x, f, args, 1e-2);
}
#[test]
fn accepts_approx_equal_deriv() {
let f = |x: f64, _: &mut Arguments| x * x / 2.0;
let args = &mut Arguments {};
let at_x = 1.5;
let dfdx = 1.501;
assert_deriv_approx_eq!(dfdx, at_x, f, args, 1e-2);
assert_deriv_approx_eq!(dfdx, at_x, f, args, 1e-2);
}
}