use crate::{Domain, domain::SDomain};
use nalgebra::{
DefaultAllocator, Dim, OVector, RealField, SVector, Scalar, U1, VectorView,
allocator::Allocator,
};
use serde::{Deserialize, Serialize};
#[allow(missing_docs)]
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(bound(serialize = "OVector<SDomain<T>, D>: Serialize"))]
#[serde(bound(deserialize = "OVector<SDomain<T>, D>: Deserialize<'de>"))]
pub struct MDomain<T, D>(OVector<SDomain<T>, D>)
where
T: Scalar,
D: Dim,
DefaultAllocator: Allocator<D>;
impl<T, D> MDomain<T, D>
where
T: Scalar,
D: Dim,
DefaultAllocator: Allocator<D>,
{
pub fn new(domains: OVector<SDomain<T>, D>) -> Self {
Self(domains)
}
pub fn unbounded(ndim: usize) -> Self {
Self(OVector::from_element_generic(
D::from_usize(ndim),
U1,
SDomain::Unbounded,
))
}
}
impl<T, D> Domain<T, D> for MDomain<T, D>
where
T: PartialOrd + Scalar + Send + Sync,
D: Dim,
DefaultAllocator: Allocator<D>,
<DefaultAllocator as Allocator<D>>::Buffer<SDomain<T>>: Send + Sync,
{
fn clip<RStride: Dim, CStride: Dim>(
&self,
sample: &VectorView<T, D, RStride, CStride>,
) -> OVector<T, D> {
(&self).clip(sample)
}
fn contains<RStride: Dim, CStride: Dim>(
&self,
sample: &VectorView<T, D, RStride, CStride>,
) -> bool {
(&self).contains(sample)
}
fn maximum_values(&self) -> Option<OVector<T, D>> {
(&self).maximum_values()
}
fn minimum_values(&self) -> Option<OVector<T, D>> {
(&self).minimum_values()
}
fn size(&self) -> OVector<Option<T>, D>
where
T: RealField,
{
(&self).size()
}
}
impl<T, D> Domain<T, D> for &MDomain<T, D>
where
T: PartialOrd + Scalar + Send + Sync,
D: Dim,
DefaultAllocator: Allocator<D>,
<DefaultAllocator as Allocator<D>>::Buffer<SDomain<T>>: Send + Sync,
{
fn clip<RStride: Dim, CStride: Dim>(
&self,
sample: &VectorView<T, D, RStride, CStride>,
) -> OVector<T, D> {
OVector::from_iterator_generic(
sample.shape_generic().0,
U1,
self.0.iter().enumerate().map(|(i, sdom)| {
Domain::<T, U1>::clip::<U1, U1>(sdom, &SVector::from([sample[i].clone()]).as_view())
[0]
.clone()
}),
)
}
fn contains<RStride: Dim, CStride: Dim>(
&self,
sample: &VectorView<T, D, RStride, CStride>,
) -> bool {
self.0.iter().zip(sample).fold(true, |acc, (sdom, value)| {
acc & Domain::<T, U1>::contains::<U1, U1>(
sdom,
&SVector::from([value.clone()]).as_view(),
)
})
}
fn maximum_values(&self) -> Option<OVector<T, D>> {
Some(OVector::from_iterator_generic(
self.0.shape_generic().0,
U1,
self.0
.iter()
.map(|sdom| Domain::<T, U1>::maximum_values(sdom).unwrap()[0].clone()),
))
}
fn minimum_values(&self) -> Option<OVector<T, D>> {
Some(OVector::from_iterator_generic(
self.0.shape_generic().0,
U1,
self.0
.iter()
.map(|sdom| Domain::<T, U1>::minimum_values(sdom).unwrap()[0].clone()),
))
}
fn size(&self) -> OVector<Option<T>, D>
where
T: RealField,
{
OVector::from_iterator_generic(
self.0.shape_generic().0,
U1,
self.0
.iter()
.map(|sdom| Domain::<T, U1>::size(sdom)[0].clone()),
)
}
}