use cartan_core::Real;
use rand::Rng;
use rand_distr::{Distribution, StandardNormal};
use crate::error::StochasticError;
use crate::frame::OrthonormalFrame;
use crate::sde::{stratonovich_step, StratonovichDevelopment};
#[derive(Debug, Clone)]
pub struct DevelopmentPath<M: cartan_core::Manifold> {
pub path: Vec<M::Point>,
pub final_frame: OrthonormalFrame<M>,
}
pub fn stochastic_development<M: StratonovichDevelopment, R: Rng + ?Sized>(
manifold: &M,
p0: &M::Point,
frame0: OrthonormalFrame<M>,
n_steps: usize,
dt: Real,
rng: &mut R,
tol: Real,
) -> Result<DevelopmentPath<M>, StochasticError>
where
StandardNormal: Distribution<Real>,
{
let n = manifold.dim();
let mut path: Vec<M::Point> = Vec::with_capacity(n_steps + 1);
path.push(p0.clone());
let mut p = p0.clone();
let mut frame = frame0;
let mut dw = vec![0.0_f64; n];
for _ in 0..n_steps {
for w in dw.iter_mut() {
*w = StandardNormal.sample(rng);
}
let (p_next, frame_next) = stratonovich_step(manifold, &p, &frame, &dw, dt, tol)?;
path.push(p_next.clone());
p = p_next;
frame = frame_next;
}
Ok(DevelopmentPath { path, final_frame: frame })
}