macro_rules! get_sderivative2 {
($f:ident, $func_name:ident) => { ... };
($f:ident, $func_name:ident, $param_type:ty) => { ... };
}Expand description
Get a function that returns the second derivative of the provided univariate, scalar-valued function.
The second derivative is computed using forward-mode automatic differentiation.
§Arguments
f- Univariate, scalar-valued function, $f:\mathbb{R}\to\mathbb{R}$.func_name- Name of the function that will return the second derivative of $f(x)$ at any point $x\in\mathbb{R}$.param_type(optional) - Type of the extra runtime parameterpthat is passed tof. Defaults to[f64](implying thatfacceptsp: &[f64]).
§Warning
f cannot be defined as closure. It must be defined as a function.
§Note
The function produced by this macro will perform 1 evaluation of $f(x)$ to evaluate its second derivative.
§Examples
§Basic Example
Compute the second derivative of
$$f(x)=x^{3}$$
at $x=2$, and compare the result to the true result of $f’’(2)=12$.
use linalg_traits::Scalar;
use numtest::*;
use numdiff::{get_sderivative2, HyperDual};
// Define the function, f(x).
fn f<S: Scalar>(x: S, _p: &[f64]) -> S {
x.powi(3)
}
// Parameter vector (empty for this example).
let p = [];
// Autogenerate the function "d2f" that can be used to compute the second derivative of f(x) at
// any point x.
get_sderivative2!(f, d2f);
// Compute the second derivative of f(x) at the evaluation point, x = 2.
let d2f_at_2: f64 = d2f(2.0, &p);
// Check the accuracy of the second derivative.
assert_equal_to_decimal!(d2f_at_2, 12.0, 16);§Example Passing Runtime Parameters
Compute the second derivative of a parameterized function
$$f(x)=ax^{2}+bx+c$$
where $a$, $b$, and $c$ are runtime parameters. Compare the result against the true second derivative of
$$f’’(x)=2a$$
use linalg_traits::Scalar;
use numtest::*;
use numdiff::{get_sderivative2, HyperDual};
// Define the function, f(x).
fn f<S: Scalar>(x: S, p: &[f64]) -> S {
let a = S::new(p[0]);
let b = S::new(p[1]);
let c = S::new(p[2]);
a * x.powi(2) + b * x + c
}
// Parameter vector.
let a = 2.5;
let b = -1.3;
let c = 4.7;
let p = [a, b, c];
// Autogenerate the second derivative function.
get_sderivative2!(f, d2f);
// True second derivative function.
let d2f_true = |_x: f64| 2.0 * a;
// Compute the second derivative at x = 1.0 using both the automatically generated second
// derivative function and the true second derivative function, and compare the results.
let d2f_at_1: f64 = d2f(1.0, &p);
let d2f_at_1_true: f64 = d2f_true(1.0);
assert_eq!(d2f_at_1, d2f_at_1_true);§Example Passing Custom Parameter Types
Use a custom parameter struct instead of f64 values.
use linalg_traits::Scalar;
use numtest::*;
use numdiff::{get_sderivative2, HyperDual};
struct Data {
a: f64,
b: f64,
c: f64,
}
// Define the function, f(x).
fn f<S: Scalar>(x: S, p: &Data) -> S {
let a = S::new(p.a);
let b = S::new(p.b);
let c = S::new(p.c);
a * x.powi(2) + b * x + c
}
// Runtime parameter struct.
let p = Data {
a: 2.5,
b: -1.3,
c: 4.7,
};
// Autogenerate the second derivative function, telling the macro to expect a runtime parameter
// of type `&Data`.
get_sderivative2!(f, d2f, Data);
// True second derivative function.
let d2f_true = |_x: f64| 2.0 * p.a;
// Compute the second derivative at x = 1.0 using both the automatically generated second
// derivative function and the true second derivative function, and compare the results.
let x0 = 1.0;
let d2f_eval: f64 = d2f(x0, &p);
let d2f_eval_true: f64 = d2f_true(x0);
assert_equal_to_decimal!(d2f_eval, d2f_eval_true, 15);