use crate::iters::{SIMDIterator, SIMDIterable, SIMDObject, UnsafeIterator, SIMDSized};
use crate::vecs::{Packed, Packable};
#[macro_export] macro_rules! tuplify {
(1, $i:expr) => { ($i) };
(2, $i:expr) => { ($i, $i) };
(3, $i:expr) => { ($i, $i, $i) };
(4, $i:expr) => { ($i, $i, $i, $i) };
(5, $i:expr) => { ($i, $i, $i, $i, $i) };
(6, $i:expr) => { ($i, $i, $i, $i, $i, $i) };
(7, $i:expr) => { ($i, $i, $i, $i, $i, $i, $i) };
(8, $i:expr) => { ($i, $i, $i, $i, $i, $i, $i, $i) };
(9, $i:expr) => { ($i, $i, $i, $i, $i, $i, $i, $i, $i) };
(10, $i:expr) => { ($i, $i, $i, $i, $i, $i, $i, $i, $i, $i) };
(11, $i:expr) => { ($i, $i, $i, $i, $i, $i, $i, $i, $i, $i, $i) };
(12, $i:expr) => { ($i, $i, $i, $i, $i, $i, $i, $i, $i, $i, $i, $i) };
}
pub struct Zip<T> {
iters: T
}
pub struct SIMDZipMap<I, F> where I : SIMDZippedIterator {
iter: I,
func: F,
}
pub trait IntoSIMDZip : Sized {
fn zip(self) -> Zip<Self>;
}
pub trait SIMDZippedObject : Sized {
type Scalars;
type Vectors;
fn width(&self) -> usize;
fn size(&self) -> usize;
}
pub trait SIMDZippedIterable : SIMDZippedObject + ExactSizeIterator<Item = <Self as SIMDZippedObject>::Vectors> {
fn scalar_pos(&self) -> usize;
#[inline(always)]
fn vector_pos(&self) -> usize {
self.scalar_pos() / self.width()
}
#[inline(always)]
fn scalar_len(&self) -> usize {
<Self as ExactSizeIterator>::len(self)
}
#[inline(always)]
fn vector_len(&self) -> usize {
self.scalar_len() / self.width()
}
fn advance(&mut self, amount: usize);
#[inline(always)]
fn finalize(&mut self) {
let end = self.scalar_len() - self.scalar_pos();
self.advance(end);
}
fn default(&self) -> Self::Vectors;
}
pub trait SIMDZippedIterator : SIMDZippedIterable {
fn end(&mut self) -> Option<(Self::Vectors, usize)>;
#[inline(always)]
fn simd_map<A, B, F>(self, func: F) -> SIMDZipMap<Self, F>
where F : FnMut(Self::Vectors) -> A, A : Packed<Scalar = B>, B : Packable {
SIMDZipMap {
iter: self,
func: func,
}
}
#[inline(always)]
fn simd_do_each<F>(&mut self, mut func: F)
where F : FnMut(Self::Vectors) -> () {
while let Some(v) = self.next() {
func(v);
}
if let Some((v, _)) = self.end() {
func(v);
}
}
#[inline(always)]
fn simd_reduce<A, F>(&mut self, mut start: A, mut func: F) -> A
where F : FnMut(A, Self::Vectors) -> A {
while let Some(v) = self.next() {
start = func(start, v);
}
if let Some((v, _)) = self.end() {
start = func(start, v);
}
start
}
}
macro_rules! impl_iter_zip {
(($($a:tt),*), ($($b:tt),*), ($($n:tt),*)) => (
impl<$($a),*> IntoSIMDZip for ($($a),*) where $($a : SIMDIterator + UnsafeIterator),* {
#[inline(always)]
fn zip(self) -> Zip<Self> {
if $(self.0.len() != self.$n.len())||* {
panic!("You can only zip iterators of the same length.");
}
Zip { iters: self }
}
}
impl<$($a),*> ExactSizeIterator for Zip<($($a),*)>
where $($a : SIMDIterator + UnsafeIterator),* {
#[inline(always)]
fn len(&self) -> usize {
self.iters.0.len()
}
}
impl<$($a),*> Iterator for Zip<($($a),*)>
where $($a : SIMDIterator + UnsafeIterator),* {
type Item = ($(<$a as Iterator>::Item),*);
#[inline(always)]
fn next(&mut self) -> Option<<Self as SIMDZippedObject>::Vectors> {
let pos = self.iters.0.scalar_pos();
self.iters.0.next().map(|v| unsafe {
(v, $(self.iters.$n.next_unchecked(pos)),*)
})
}
}
impl<$($a),*> SIMDZippedObject for Zip<($($a),*)>
where $($a : SIMDIterator + UnsafeIterator),* {
type Vectors = ($($a::Vector),*);
type Scalars = ($($a::Scalar),*);
#[inline(always)]
fn width(&self) -> usize {
self.iters.0.width()
}
#[inline(always)]
fn size(&self) -> usize {
self.iters.0.size()
}
}
impl<$($a),*> SIMDZippedIterator for Zip<($($a),*)>
where $($a : SIMDIterator + UnsafeIterator),* {
#[inline(always)]
fn end(&mut self) -> Option<(Self::Vectors, usize)> {
let pos = self.iters.0.scalar_pos();
self.iters.0.end().map(|(v, n)| unsafe {
((v, $(self.iters.$n.end_unchecked(pos, n)),*), n)
})
}
}
impl<$($a),*> SIMDZippedIterable for Zip<($($a),*)>
where $($a : SIMDIterator + UnsafeIterator),* {
#[inline(always)]
fn scalar_pos(&self) -> usize {
self.iters.0.scalar_pos()
}
#[inline(always)]
fn advance(&mut self, amount: usize) {
self.iters.0.advance(amount);
}
#[inline(always)]
fn default(&self) -> Self::Vectors {
(self.iters.0.default(), $(self.iters.$n.default()),*)
}
}
);
}
impl<I, F, A> Iterator for SIMDZipMap<I, F>
where I : SIMDZippedIterator, F : FnMut(I::Vectors) -> A, A : Packed {
type Item = A;
#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(&mut self.func)
}
}
impl<I, F, A> ExactSizeIterator for SIMDZipMap<I, F>
where I : SIMDZippedIterator, F : FnMut(I::Vectors) -> A, A : Packed {
#[inline(always)]
fn len(&self) -> usize {
self.iter.len()
}
}
impl<I, F, A> SIMDObject for SIMDZipMap<I, F>
where I : SIMDZippedIterator, F : FnMut(I::Vectors) -> A, A : Packed {
type Vector = A;
type Scalar = A::Scalar;
}
impl<I, F, A> SIMDSized for SIMDZipMap<I, F>
where I : SIMDZippedIterator, F : FnMut(I::Vectors) -> A, A : Packed {
#[inline(always)]
fn scalar_len(&self) -> usize {
self.iter.scalar_len()
}
#[inline(always)]
fn vector_len(&self) -> usize {
self.iter.vector_len()
}
}
impl<I, F, A> SIMDIterable for SIMDZipMap<I, F>
where I : SIMDZippedIterator, F : FnMut(I::Vectors) -> A, A : Packed {
#[inline(always)]
fn scalar_pos(&self) -> usize {
self.iter.scalar_pos()
}
#[inline(always)]
fn advance(&mut self, amount: usize) {
self.iter.advance(amount)
}
#[inline(always)]
fn default(&self) -> Self::Vector {
<Self::Vector as Packed>::default()
}
}
impl<I, F, A> SIMDIterator for SIMDZipMap<I, F>
where I : SIMDZippedIterator, F : FnMut(I::Vectors) -> A, A : Packed {
#[inline(always)]
fn end(&mut self) -> Option<(Self::Vector, usize)> {
let (v, n) = self.iter.end()?;
let nr = n * self.iter.size() / self.size();
Some(((self.func)(v), nr))
}
}
impl_iter_zip!((A, B),
(AA, BB),
(1));
impl_iter_zip!((A, B, C),
(AA, BB, CC),
(1, 2));
impl_iter_zip!((A, B, C, D),
(AA, BB, CC, DD),
(1, 2, 3));
impl_iter_zip!((A, B, C, D, E),
(AA, BB, CC, DD, EE),
(1, 2, 3, 4));
impl_iter_zip!((A, B, C, D, E, F),
(AA, BB, CC, DD, EE, FF),
(1, 2, 3, 4, 5));
impl_iter_zip!((A, B, C, D, E, F, G),
(AA, BB, CC, DD, EE, FF, GG),
(1, 2, 3, 4, 5, 6));
impl_iter_zip!((A, B, C, D, E, F, G, H),
(AA, BB, CC, DD, EE, FF, GG, HH),
(1, 2, 3, 4, 5, 6, 7));
impl_iter_zip!((A, B, C, D, E, F, G, H, I),
(AA, BB, CC, DD, EE, FF, GG, HH, II),
(1, 2, 3, 4, 5, 6, 7, 8));
impl_iter_zip!((A, B, C, D, E, F, G, H, I, J),
(AA, BB, CC, DD, EE, FF, GG, HH, II, JJ),
(1, 2, 3, 4, 5, 6, 7, 8, 9));
impl_iter_zip!((A, B, C, D, E, F, G, H, I, J, K),
(AA, BB, CC, DD, EE, FF, GG, HH, II, JJ, KK),
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
impl_iter_zip!((A, B, C, D, E, F, G, H, I, J, K, L),
(AA, BB, CC, DD, EE, FF, GG, HH, II, JJ, KK, LL),
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11));
impl_iter_zip!((A, B, C, D, E, F, G, H, I, J, K, L, M),
(AA, BB, CC, DD, EE, FF, GG, HH, II, JJ, KK, LL, MM),
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12));