hyperdual/
differentials.rs

1use crate::OHyperdual;
2
3use super::Float;
4use na::{allocator::Allocator, DefaultAllocator};
5use na::{Dim, DimName, OMatrix, OVector, SMatrix, SVector};
6use {Dual, DualN, One, Scalar, Zero};
7
8/// Evaluates the function using dual numbers to get the partial derivative at the input point
9#[inline]
10pub fn differentiate<T: Copy + Scalar + One, F>(x: T, f: F) -> T
11where
12    F: Fn(Dual<T>) -> Dual<T>,
13{
14    f(Dual::new(x, T::one())).dual()
15}
16
17// Extracts Jacobian matrix and function value from a vector of dual numbers
18#[inline]
19pub fn extract_jacobian_and_result<T: Scalar + Zero + Float, const DIM_IN: usize, const DIM_OUT: usize, const DIM_HYPER: usize>(
20    fx_dual: &SVector<DualN<T, DIM_HYPER>, DIM_OUT>,
21) -> (SVector<T, DIM_OUT>, SMatrix<T, DIM_OUT, DIM_IN>) {
22    let fx = super::vector_from_hyperspace(fx_dual);
23    let mut grad = SMatrix::<T, DIM_OUT, DIM_IN>::zeros();
24
25    for i in 0..DIM_OUT {
26        for j in 0..DIM_IN {
27            grad[(i, j)] = fx_dual[i][j + 1];
28        }
29    }
30    (fx, grad)
31}
32
33// Extracts Jacobian matrix and function value from a vector of dual numbers
34#[inline]
35pub fn extract_jacobian_and_result_owned<T: Scalar + Zero + Float, DimIn: Dim + DimName, DimOut: Dim + DimName, DimHyper: Dim + DimName>(
36    fx_dual: &OVector<OHyperdual<T, DimHyper>, DimOut>,
37) -> (OVector<T, DimOut>, OMatrix<T, DimOut, DimIn>)
38where
39    DefaultAllocator: Allocator<DimIn> + Allocator<DimOut> + Allocator<DimOut, DimIn> + Allocator<DimOut> + Allocator<DimHyper>,
40    <DefaultAllocator as Allocator<DimHyper>>::Buffer<T>: Copy,
41{
42    let fx = super::ovector_from_hyperspace(fx_dual);
43    let mut grad = OMatrix::<T, DimOut, DimIn>::zeros();
44
45    for i in 0..DimOut::dim() {
46        for j in 0..DimIn::dim() {
47            grad[(i, j)] = fx_dual[i][j + 1];
48        }
49    }
50    (fx, grad)
51}