vderivative

Function vderivative 

Source
pub fn vderivative<V>(f: &impl Fn(f64) -> V, x0: f64, h: Option<f64>) -> V
where V: Vector<f64>,
Expand description

Derivative of a univariate, vector-valued function using the forward difference approximation.

§Arguments

  • f - Univariate, vector-valued function, $\mathbf{f}:\mathbb{R}\to\mathbb{R}^{m}$.
  • x0 - Evaluation point, $x_{0}\in\mathbb{R}$.
  • h - Relative step size, $h\in\mathbb{R}$. Defaults to SQRT_EPS.

§Returns

Derivative of $\mathbf{f}$ with respect to $x$, evaluated at $x=x_{0}$.

$$\frac{d\mathbf{f}}{dx}\bigg\rvert_{x=x_{0}}\in\mathbb{R}^{m}$$

§Note

This function performs 2 evaluations of $f(x)$.

§Example

Approximate the derivative of

$$f(t)=\begin{bmatrix}\sin{t}\\\cos{t}\end{bmatrix}$$

at $t=1$, and compare the result to the true result of

$$\frac{d\mathbf{f}}{dt}\bigg\rvert_{t=1}=\begin{bmatrix}\cos{(1)}\\-\sin{(1)}\end{bmatrix}$$

§Using standard vectors
use numtest::*;

use numdiff::forward_difference::vderivative;

// Define the function, f(t).
let f = |t: f64| vec![t.sin(), t.cos()];

// Approximate the derivative of f(t) at the evaluation point.
let df: Vec<f64> = vderivative(&f, 1.0, None);

// True derivative of f(t) at the evaluation point.
let df_true: Vec<f64> = vec![1.0_f64.cos(), -1.0_f64.sin()];

// Check the accuracy of the derivative approximation.
assert_arrays_equal_to_decimal!(df, df_true, 8);
§Using other vector types

We can also use other types of vectors, such as nalgebra::SVector, nalgebra::DVector, ndarray::Array1, faer::Mat, or any other type of vector that implements the linalg_traits::Vector trait.

use faer::Mat;
use linalg_traits::Vector;  // to provide from_slice method for faer::Mat
use nalgebra::{dvector, DVector, SVector};
use ndarray::{array, Array1};
use numtest::*;

use numdiff::forward_difference::vderivative;

let df_true: Vec<f64> = vec![1.0_f64.cos(), -1.0_f64.sin()];

// nalgebra::DVector
let f_dvector = |t: f64| dvector![t.sin(), t.cos()];
let df_dvector: DVector<f64> = vderivative(&f_dvector, 1.0, None);
assert_arrays_equal_to_decimal!(df_dvector, df_true, 8);

// nalgebra::SVector
let f_svector = |t: f64| SVector::<f64, 2>::from_row_slice(&[t.sin(), t.cos()]);
let df_svector: SVector<f64, 2> = vderivative(&f_svector, 1.0, None);
assert_arrays_equal_to_decimal!(df_svector, df_true, 8);

// ndarray::Array1
let f_array1 = |t: f64| array![t.sin(), t.cos()];
let df_array1: Array1<f64> = vderivative(&f_array1, 1.0, None);
assert_arrays_equal_to_decimal!(df_array1, df_true, 8);

// faer::Mat
let f_mat = |t: f64| Mat::from_slice(&[t.sin(), t.cos()]);
let df_mat: Mat<f64> = vderivative(&f_mat, 1.0, None);
assert_arrays_equal_to_decimal!(df_mat.as_slice(), df_true, 8);
§Modifying the relative step size

We can also modify the relative step size. Choosing a coarser relative step size, we get a worse approximation.

use numtest::*;

use numdiff::forward_difference::vderivative;

let f = |t: f64| vec![t.sin(), t.cos()];

let df: Vec<f64> = vderivative(&f, 1.0, Some(0.001));
let df_true: Vec<f64> = vec![1.0_f64.cos(), -1.0_f64.sin()];

assert_arrays_equal_to_decimal!(df, df_true, 3);