use crate::index::{IndexList, UniqueIndexList};
use paradis_core::Bounds;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct IndexZip<A, B>(A, B);
impl<A, B> IndexZip<A, B>
where
A: IndexList,
B: IndexList,
{
pub fn new(a: A, b: B) -> Self {
assert_eq!(
a.num_indices(),
b.num_indices(),
"IndexZip requires the number of indices to be equal in the zipped index sets"
);
Self(a, b)
}
}
unsafe impl<A, B> IndexList for IndexZip<A, B>
where
A: IndexList,
B: IndexList,
{
type Index = (A::Index, B::Index);
const ALWAYS_BOUNDED: bool = A::ALWAYS_BOUNDED && B::ALWAYS_BOUNDED;
unsafe fn get_index_unchecked(&self, loc: usize) -> Self::Index {
unsafe {
(
self.0.get_index_unchecked(loc),
self.1.get_index_unchecked(loc),
)
}
}
fn num_indices(&self) -> usize {
debug_assert_eq!(self.0.num_indices(), self.1.num_indices());
self.0.num_indices()
}
fn bounds(&self) -> Option<Bounds<Self::Index>> {
self.0.bounds().zip(self.1.bounds()).map(|(a, b)| a.zip(b))
}
}
unsafe impl<A, B> UniqueIndexList for IndexZip<A, B>
where
A: UniqueIndexList,
B: IndexList,
{
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct IndexAZip<A, B>(A, B);
impl<A, B> IndexAZip<A, B>
where
A: IndexList,
B: IndexList,
{
pub fn new(a: A, b: B) -> Self {
assert_eq!(
a.num_indices(),
b.num_indices(),
"IndexAZip requires the number of indices to be equal in the zipped index sets"
);
Self(a, b)
}
}
unsafe impl<A, B> IndexList for IndexAZip<A, B>
where
A: IndexList,
B: IndexList,
{
type Index = (A::Index, B::Index);
const ALWAYS_BOUNDED: bool = A::ALWAYS_BOUNDED && B::ALWAYS_BOUNDED;
unsafe fn get_index_unchecked(&self, loc: usize) -> Self::Index {
unsafe {
(
self.0.get_index_unchecked(loc),
self.1.get_index_unchecked(loc),
)
}
}
fn num_indices(&self) -> usize {
debug_assert_eq!(self.0.num_indices(), self.1.num_indices());
self.0.num_indices()
}
fn bounds(&self) -> Option<Bounds<Self::Index>> {
self.0.bounds().zip(self.1.bounds()).map(|(a, b)| a.zip(b))
}
}
unsafe impl<A, B> UniqueIndexList for IndexAZip<A, B>
where
A: IndexList,
B: UniqueIndexList,
{
}