use crate::DType;
use numr::autograd::DualTensor;
use numr::error::Result;
use numr::runtime::Runtime;
use numr::tensor::Tensor;
use crate::integrate::error::IntegrateResult;
use crate::integrate::ode::{
BDFOptions, BVPOptions, DAEOptions, DAEResultTensor, LSODAOptions, RadauOptions,
SymplecticOptions,
};
use crate::integrate::{ODEOptions, ODEResultTensor};
use super::{
BVPResult, MonteCarloOptions, MonteCarloResult, NQuadOptions, QMCOptions, QuadOptions,
QuadResult, RombergOptions, SymplecticResult, TanhSinhOptions,
};
pub trait IntegrationAlgorithms<R: Runtime<DType = DType>> {
fn trapezoid(&self, y: &Tensor<R>, x: &Tensor<R>) -> Result<Tensor<R>>;
fn trapezoid_uniform(&self, y: &Tensor<R>, dx: f64) -> Result<Tensor<R>>;
fn cumulative_trapezoid(
&self,
y: &Tensor<R>,
x: Option<&Tensor<R>>,
dx: f64,
) -> Result<Tensor<R>>;
fn simpson(&self, y: &Tensor<R>, x: Option<&Tensor<R>>, dx: f64) -> Result<Tensor<R>>;
fn fixed_quad<F>(&self, f: F, a: f64, b: f64, n: usize) -> Result<Tensor<R>>
where
F: Fn(&Tensor<R>) -> Result<Tensor<R>>;
fn quad<F>(&self, f: F, a: f64, b: f64, options: &QuadOptions) -> Result<QuadResult<R>>
where
F: Fn(&Tensor<R>) -> Result<Tensor<R>>;
fn romberg<F>(&self, f: F, a: f64, b: f64, options: &RombergOptions) -> Result<QuadResult<R>>
where
F: Fn(&Tensor<R>) -> Result<Tensor<R>>;
fn solve_ivp<F>(
&self,
f: F,
t_span: [f64; 2],
y0: &Tensor<R>,
options: &ODEOptions,
) -> IntegrateResult<ODEResultTensor<R>>
where
F: Fn(&Tensor<R>, &Tensor<R>) -> Result<Tensor<R>>;
fn tanh_sinh<F>(
&self,
f: F,
a: f64,
b: f64,
options: &TanhSinhOptions,
) -> Result<QuadResult<R>>
where
F: Fn(&Tensor<R>) -> Result<Tensor<R>>;
fn monte_carlo<F>(
&self,
f: F,
bounds: &[(f64, f64)],
options: &MonteCarloOptions,
) -> Result<MonteCarloResult<R>>
where
F: Fn(&Tensor<R>) -> Result<Tensor<R>>;
fn qmc_quad<F>(
&self,
f: F,
bounds: &[(f64, f64)],
options: &QMCOptions,
) -> Result<QuadResult<R>>
where
F: Fn(&Tensor<R>) -> Result<Tensor<R>>;
fn dblquad<F, G, H>(
&self,
f: F,
a: f64,
b: f64,
gfun: G,
hfun: H,
options: &NQuadOptions,
) -> Result<QuadResult<R>>
where
F: Fn(&Tensor<R>, &Tensor<R>) -> Result<Tensor<R>>,
G: Fn(f64) -> f64,
H: Fn(f64) -> f64;
fn nquad<F>(
&self,
f: F,
bounds: &[(f64, f64)],
options: &NQuadOptions,
) -> Result<QuadResult<R>>
where
F: Fn(&Tensor<R>) -> Result<Tensor<R>>;
fn solve_ivp_bdf<F>(
&self,
f: F,
t_span: [f64; 2],
y0: &Tensor<R>,
options: &ODEOptions,
bdf_options: &BDFOptions<R>,
) -> IntegrateResult<ODEResultTensor<R>>
where
F: Fn(&DualTensor<R>, &DualTensor<R>, &Self) -> Result<DualTensor<R>>;
fn solve_ivp_radau<F>(
&self,
f: F,
t_span: [f64; 2],
y0: &Tensor<R>,
options: &ODEOptions,
radau_options: &RadauOptions<R>,
) -> IntegrateResult<ODEResultTensor<R>>
where
F: Fn(&DualTensor<R>, &DualTensor<R>, &Self) -> Result<DualTensor<R>>;
fn solve_ivp_lsoda<F>(
&self,
f: F,
t_span: [f64; 2],
y0: &Tensor<R>,
options: &ODEOptions,
lsoda_options: &LSODAOptions,
) -> IntegrateResult<ODEResultTensor<R>>
where
F: Fn(&DualTensor<R>, &DualTensor<R>, &Self) -> Result<DualTensor<R>>;
fn solve_bvp<F, BC>(
&self,
f: F,
bc: BC,
x: &Tensor<R>,
y: &Tensor<R>,
options: &BVPOptions,
) -> IntegrateResult<BVPResult<R>>
where
F: Fn(&Tensor<R>, &Tensor<R>) -> Result<Tensor<R>>,
BC: Fn(&Tensor<R>, &Tensor<R>) -> Result<Tensor<R>>;
fn verlet<F>(
&self,
force: F,
t_span: [f64; 2],
q0: &Tensor<R>,
p0: &Tensor<R>,
options: &SymplecticOptions,
) -> IntegrateResult<SymplecticResult<R>>
where
F: Fn(&Tensor<R>) -> Result<Tensor<R>>;
fn leapfrog<F>(
&self,
force: F,
t_span: [f64; 2],
q0: &Tensor<R>,
p0: &Tensor<R>,
options: &SymplecticOptions,
) -> IntegrateResult<SymplecticResult<R>>
where
F: Fn(&Tensor<R>) -> Result<Tensor<R>>;
fn solve_dae<F>(
&self,
f: F,
t_span: [f64; 2],
y0: &Tensor<R>,
yp0: &Tensor<R>,
options: &ODEOptions,
dae_options: &DAEOptions<R>,
) -> IntegrateResult<DAEResultTensor<R>>
where
F: Fn(&DualTensor<R>, &DualTensor<R>, &DualTensor<R>, &Self) -> Result<DualTensor<R>>;
}