numdiff 0.11.2

Numerical differentiation via forward-mode automatic differentiation and finite difference approximations.
Documentation
use crate::HyperDual;
use linalg_traits::{RealField, Vector};

/// Trait to create a vector of hyper-dual numbers.
pub trait HyperDualVector<R, V>
where
    R: RealField,
    V: Vector<R>,
{
    /// Convert this vector of scalars to a vector of hyper-dual numbers.
    ///
    /// # Returns
    ///
    /// A copy of this vector with each element converted to a hyper-dual number (with `ε1`, `ε2`,
    /// and `ε1ε2` coefficients equal to `0.0`).
    fn to_hyper_dual_vector(self) -> V::VectorT<HyperDual>;
}

impl<R, V> HyperDualVector<R, V> for V
where
    R: RealField,
    V: Vector<R>,
{
    fn to_hyper_dual_vector(self) -> V::VectorT<HyperDual> {
        let mut vec_hyper_dual = V::VectorT::new_with_length(self.len());
        for i in 0..self.len() {
            vec_hyper_dual[i] = HyperDual::new(self[i].into(), 0.0, 0.0, 0.0);
        }
        vec_hyper_dual
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[cfg(feature = "nalgebra")]
    use nalgebra::{SVector, dvector};
    #[cfg(feature = "ndarray")]
    use ndarray::array;

    #[test]
    fn test_vec() {
        let vec = vec![1.0, 2.0, 3.0];
        assert_eq!(
            vec.to_hyper_dual_vector(),
            vec![
                HyperDual::new(1.0, 0.0, 0.0, 0.0),
                HyperDual::new(2.0, 0.0, 0.0, 0.0),
                HyperDual::new(3.0, 0.0, 0.0, 0.0)
            ]
        );
    }

    #[test]
    #[cfg(feature = "nalgebra")]
    fn test_nalgebra_dvector() {
        let vec = dvector![1.0, 2.0, 3.0];
        assert_eq!(
            vec.to_hyper_dual_vector(),
            dvector![
                HyperDual::new(1.0, 0.0, 0.0, 0.0),
                HyperDual::new(2.0, 0.0, 0.0, 0.0),
                HyperDual::new(3.0, 0.0, 0.0, 0.0)
            ]
        );
    }

    #[test]
    #[cfg(feature = "nalgebra")]
    fn test_nalgebra_svector() {
        let vec = SVector::<f64, 3>::from_row_slice(&[1.0, 2.0, 3.0]);
        assert_eq!(
            vec.to_hyper_dual_vector(),
            SVector::<HyperDual, 3>::from_row_slice(&[
                HyperDual::new(1.0, 0.0, 0.0, 0.0),
                HyperDual::new(2.0, 0.0, 0.0, 0.0),
                HyperDual::new(3.0, 0.0, 0.0, 0.0)
            ])
        );
    }

    #[test]
    #[cfg(feature = "ndarray")]
    fn test_ndarray_array1() {
        let vec = array![1.0, 2.0, 3.0];
        assert_eq!(
            vec.to_hyper_dual_vector(),
            array![
                HyperDual::new(1.0, 0.0, 0.0, 0.0),
                HyperDual::new(2.0, 0.0, 0.0, 0.0),
                HyperDual::new(3.0, 0.0, 0.0, 0.0)
            ]
        );
    }
}