use crate::*;
use numpy::{PyArray, PyReadonlyArrayDyn, PyReadwriteArrayDyn};
use pyo3::exceptions::PyTypeError;
use pyo3::prelude::*;
#[pyclass(name = "HyperHyperDual64")]
#[derive(Clone)]
pub struct PyHyperHyperDual64(HyperHyperDual64);
#[pymethods]
#[expect(clippy::too_many_arguments)]
impl PyHyperHyperDual64 {
#[new]
fn new(
re: f64,
eps1: f64,
eps2: f64,
eps3: f64,
eps1eps2: f64,
eps1eps3: f64,
eps2eps3: f64,
eps1eps2eps3: f64,
) -> Self {
HyperHyperDual::new(
re,
eps1,
eps2,
eps3,
eps1eps2,
eps1eps3,
eps2eps3,
eps1eps2eps3,
)
.into()
}
#[getter]
fn get_first_derivative(&self) -> (f64, f64, f64) {
(self.0.eps1, self.0.eps2, self.0.eps3)
}
#[getter]
fn get_second_derivative(&self) -> (f64, f64, f64) {
(self.0.eps1eps2, self.0.eps1eps3, self.0.eps2eps3)
}
#[getter]
fn get_third_derivative(&self) -> f64 {
self.0.eps1eps2eps3
}
}
impl_dual_num!(PyHyperHyperDual64, HyperHyperDual64, f64);
#[pyfunction]
#[expect(clippy::type_complexity)]
pub fn third_partial_derivative(
f: &Bound<'_, PyAny>,
x: f64,
y: f64,
z: f64,
) -> PyResult<(f64, f64, f64, f64, f64, f64, f64, f64)> {
let g = |(x, y, z)| {
let res = f.call1((
PyHyperHyperDual64::from(x),
PyHyperHyperDual64::from(y),
PyHyperHyperDual64::from(z),
))?;
if let Ok(res) = res.extract::<PyHyperHyperDual64>() {
Ok(res.0)
} else {
Err(PyErr::new::<PyTypeError, _>(
"argument 'f' must return a scalar.".to_string(),
))
}
};
crate::third_partial_derivative(g, (x, y, z))
}
#[pyfunction]
#[expect(clippy::type_complexity)]
pub fn third_partial_derivative_vec(
f: &Bound<'_, PyAny>,
x: Vec<f64>,
i: usize,
j: usize,
k: usize,
) -> PyResult<(f64, f64, f64, f64, f64, f64, f64, f64)> {
let g = |x: &[_]| {
let x: Vec<_> = x.iter().map(|&x| PyHyperHyperDual64::from(x)).collect();
let res = f.call1((x,))?;
if let Ok(res) = res.extract::<PyHyperHyperDual64>() {
Ok(res.0)
} else {
Err(PyErr::new::<PyTypeError, _>(
"argument 'f' must return a scalar.".to_string(),
))
}
};
crate::third_partial_derivative_vec(g, &x, i, j, k)
}