use crate::linear_algebra::Matrix;
use crate::numerical_derivative::autodiff::AutoDiffMulti;
use crate::numerical_derivative::derivator::DerivatorMultiVariable;
use crate::scalar::{Numeric, ScalarFnN};
use crate::utils::error_codes::CalcError;
pub struct Hessian<D: DerivatorMultiVariable = AutoDiffMulti> {
derivator: D,
}
impl<D: DerivatorMultiVariable + Default> Default for Hessian<D> {
fn default() -> Self {
Hessian {
derivator: D::default(),
}
}
}
impl<D: DerivatorMultiVariable> Hessian<D> {
pub fn from_derivator(derivator: D) -> Self {
Hessian { derivator }
}
pub fn get<F: ScalarFnN<NUM_VARS>, const NUM_VARS: usize>(
&self,
function: &F,
vector_of_points: &[D::Scalar; NUM_VARS],
) -> Result<[[D::Scalar; NUM_VARS]; NUM_VARS], CalcError> {
let mut result: Matrix<NUM_VARS, NUM_VARS, D::Scalar> =
Matrix::from_fn(|_, _| <D::Scalar as Numeric>::NAN);
for row_index in 0..NUM_VARS {
for col_index in 0..NUM_VARS {
if result[(row_index, col_index)].is_nan() {
result[(row_index, col_index)] = self.derivator.get_double_partial(
function,
&[row_index, col_index],
vector_of_points,
)?;
result[(col_index, row_index)] = result[(row_index, col_index)];
}
}
}
Ok(result.into_array())
}
}