use nalgebra::{
allocator::Allocator,
storage::{Storage, StorageMut},
DefaultAllocator, IsContiguous, OVector, Vector,
};
use super::{
base::{Problem, ProblemError},
domain::Domain,
};
pub trait System: Problem {
fn eval<Sx, Sfx>(
&self,
x: &Vector<Self::Scalar, Self::Dim, Sx>,
fx: &mut Vector<Self::Scalar, Self::Dim, Sfx>,
) -> Result<(), ProblemError>
where
Sx: Storage<Self::Scalar, Self::Dim> + IsContiguous,
Sfx: StorageMut<Self::Scalar, Self::Dim>;
}
pub struct RepulsiveSystem<'f, F: System>
where
DefaultAllocator: Allocator<F::Scalar, F::Dim>,
{
f: &'f F,
archive: Vec<OVector<F::Scalar, F::Dim>>,
}
impl<'f, F: System> RepulsiveSystem<'f, F>
where
DefaultAllocator: Allocator<F::Scalar, F::Dim>,
{
pub fn new(f: &'f F) -> Self {
Self {
f,
archive: Vec::new(),
}
}
pub fn push(&mut self, root: OVector<F::Scalar, F::Dim>) {
self.archive.push(root);
}
pub fn len(&self) -> usize {
self.archive.len()
}
pub fn is_empty(&self) -> bool {
self.archive.is_empty()
}
pub fn unpack(self) -> Vec<OVector<F::Scalar, F::Dim>> {
self.archive
}
}
impl<'f, F: System> Problem for RepulsiveSystem<'f, F>
where
DefaultAllocator: Allocator<F::Scalar, F::Dim>,
{
type Scalar = F::Scalar;
type Dim = F::Dim;
fn dim(&self) -> Self::Dim {
self.f.dim()
}
fn domain(&self) -> Domain<Self::Scalar> {
self.f.domain()
}
}
impl<'f, F: System> System for RepulsiveSystem<'f, F>
where
DefaultAllocator: Allocator<F::Scalar, F::Dim>,
{
fn eval<Sx, Sfx>(
&self,
x: &Vector<Self::Scalar, Self::Dim, Sx>,
fx: &mut Vector<Self::Scalar, Self::Dim, Sfx>,
) -> Result<(), ProblemError>
where
Sx: Storage<Self::Scalar, Self::Dim> + IsContiguous,
Sfx: StorageMut<Self::Scalar, Self::Dim>,
{
self.f.eval(x, fx)
}
}