Last active
October 23, 2018 22:08
-
-
Save pacmancoder/0ee33123c021ee9c2b38f185d225f19c to your computer and use it in GitHub Desktop.
[Rust] Overlaying Slices iterator PoC
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extern crate rayon; | |
use rayon::prelude::*; | |
struct State<'a> | |
{ | |
first: &'a [usize], | |
other: &'a mut [usize], | |
value: Option<(&'a [usize], &'a mut [usize], &'a [usize])>, | |
} | |
impl<'a> State<'a> { | |
fn from_vector(vec: &'a mut Vec<usize>, step: usize) -> Self { | |
let (vec_first, vec_other) = vec.split_at_mut(step); | |
State { | |
first: vec_first, | |
other: vec_other, | |
value: None, | |
} | |
} | |
fn next(self) -> State<'a> | |
{ | |
if self.other.len() == 0 { | |
return State{ value: None, ..self}; | |
} | |
let (middle, temp) = self.other.split_at_mut(self.first.len()); | |
let (right, other) = temp.split_at_mut(self.first.len()); | |
State { | |
first: right, | |
other: other, | |
value: Some((self.first, middle, right)), | |
} | |
} | |
fn value(&mut self) -> Option<(&'a [usize], &'a mut [usize], &'a [usize])> | |
{ | |
self.value.take() | |
} | |
} | |
struct PartialOverlappingIterator<'a> | |
{ | |
state: Option<State<'a>>, | |
} | |
impl<'a> PartialOverlappingIterator<'a> | |
{ | |
pub fn make(vec: &'a mut Vec<usize>, step: usize) -> PartialOverlappingIterator<'a> { | |
PartialOverlappingIterator { | |
state: Some(State::from_vector(vec, step)), | |
} | |
} | |
} | |
impl<'a> Iterator for PartialOverlappingIterator<'a> | |
{ | |
type Item = (&'a [usize], &'a mut [usize], &'a [usize]); | |
fn next(&mut self) -> Option<Self::Item> | |
{ | |
let new_state = self.state.take().unwrap().next(); | |
self.state = Some(new_state); | |
self.state.as_mut().unwrap().value() | |
} | |
} | |
fn main() { | |
let mut arr = vec![1_usize, 2, 3, 4, 5]; | |
{ | |
PartialOverlappingIterator::make(&mut arr, 1).par_bridge().count(); | |
} | |
println!("{:?}", arr); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::mem; | |
pub struct DoubleOverlappedChunksIterator<'a, T> | |
where T: 'a | |
{ | |
prev_left: &'a [T], | |
next_left: &'a [T], | |
next_middle: &'a mut [T], | |
next_right: &'a [T], | |
remainder: &'a mut [T], | |
} | |
impl<'a, T> DoubleOverlappedChunksIterator<'a, T> | |
{ | |
pub fn from_slice(slice: &'a mut [T], step: usize) -> DoubleOverlappedChunksIterator<'a, T> | |
{ | |
if slice.len() < step * 2{ | |
// valid, but no elements will be generated by iterator | |
return DoubleOverlappedChunksIterator { | |
prev_left: &[], | |
next_left: &[], | |
next_middle: &mut [], | |
next_right: & [], | |
remainder: &mut [], | |
} | |
} | |
let (next_left, remainder) = slice.split_at_mut(step); | |
if remainder.len() <= step { | |
return DoubleOverlappedChunksIterator { | |
prev_left: &[], | |
next_left, | |
next_middle: remainder, | |
next_right: & [], | |
remainder: &mut [], | |
} | |
} | |
let (next_middle, remainder) = remainder.split_at_mut(step); | |
if remainder.len() <= step { | |
return DoubleOverlappedChunksIterator { | |
prev_left: &[], | |
next_left, | |
next_middle, | |
next_right: remainder, | |
remainder: &mut [], | |
} | |
} | |
let (next_right, remainder) = remainder.split_at_mut(step); | |
DoubleOverlappedChunksIterator { | |
prev_left: &[], | |
next_left, | |
next_middle, | |
next_right, | |
remainder, | |
} | |
} | |
} | |
impl<'a, T> Iterator for DoubleOverlappedChunksIterator<'a, T> | |
{ | |
// |(&trace)|(&mut _)|(&left)|(&mut middle)|(&right)|(&mut _)|(&aim) | |
type Item = (&'a[T], &'a [T], &'a mut [T], &'a [T], &'a[T]); | |
fn next(&mut self) -> Option<Self::Item> | |
{ | |
let step = self.next_left.len(); | |
if self.next_middle.len() == 0 { | |
return None; | |
} | |
let mut remainder : &'a mut[T] = &mut[]; | |
mem::swap(&mut self.remainder, &mut remainder); | |
let (next_next_middle, remainder) = if remainder.len() <= step { | |
let mut empty : &'a mut[T] = &mut[]; | |
(remainder, empty) | |
} else { | |
remainder.split_at_mut(step) | |
}; | |
let (next_next_right, remainder) = if remainder.len() <= step { | |
let mut empty : &'a mut[T] = &mut[]; | |
(remainder, empty) | |
} else { | |
remainder.split_at_mut(step) | |
}; | |
let mut next_middle : &'a mut[T] = &mut[]; | |
mem::swap(&mut self.next_middle, &mut next_middle); | |
let result = (self.prev_left, self.next_left, next_middle, self.next_right, &*next_next_right); | |
self.prev_left = self.next_left; | |
self.next_left = self.next_right; | |
self.next_right = next_next_right; | |
self.next_middle = next_next_middle; | |
self.remainder = remainder; | |
Some(result) | |
} | |
} | |
#[cfg(test)] | |
mod test | |
{ | |
use super::*; | |
#[test] | |
fn not_enough_chunks_test() | |
{ | |
let mut v = vec!(1u8); | |
let mut it = DoubleOverlappedChunksIterator::from_slice(&mut v, 1); | |
match it.next() { | |
Some(_) => { panic!("Should not generate elements!"); } | |
None => {} | |
}; | |
} | |
#[test] | |
fn minimal_chunks_test() | |
{ | |
let mut v = vec!(1u8, 2, 3, 4); | |
let mut it = DoubleOverlappedChunksIterator::from_slice(&mut v, 2); | |
match it.next() { | |
Some((trace, left, middle, right, aim)) => { | |
assert_eq!(trace, &[]); | |
assert_eq!(left, &[1u8, 2]); | |
assert_eq!(middle, &[3u8, 4]); | |
assert_eq!(right, &[]); | |
assert_eq!(aim, &[]); | |
} | |
None => { panic!("Should generate elements!"); } | |
}; | |
assert!(it.next().is_none()); | |
} | |
#[test] | |
fn normal_chunks_test() | |
{ | |
let mut v = vec!(1u8, 2, 3); | |
let mut it = DoubleOverlappedChunksIterator::from_slice(&mut v, 1); | |
match it.next() { | |
Some((trace, left, middle, right, aim)) => { | |
assert_eq!(trace, &[]); | |
assert_eq!(left, &[1u8]); | |
assert_eq!(middle, &[2u8]); | |
assert_eq!(right, &[3u8]); | |
assert_eq!(aim, &[]); | |
} | |
None => { panic!("Should generate elements!"); } | |
}; | |
assert!(it.next().is_none()); | |
} | |
#[test] | |
fn two_iterations_test() | |
{ | |
let mut v = vec!(1u8, 2, 3, 4, 5); | |
let mut it = DoubleOverlappedChunksIterator::from_slice(&mut v, 1); | |
match it.next() { | |
Some((trace, left, middle, right, aim)) => { | |
assert_eq!(trace, &[]); | |
assert_eq!(left, &[1u8]); | |
assert_eq!(middle, &[2u8]); | |
assert_eq!(right, &[3u8]); | |
assert_eq!(aim, &[5u8]); | |
} | |
None => { panic!("Should generate elements!"); } | |
}; | |
match it.next() { | |
Some((trace, left, middle, right, aim)) => { | |
assert_eq!(trace, &[1u8]); | |
assert_eq!(left, &[3u8]); | |
assert_eq!(middle, &[4u8]); | |
assert_eq!(right, &[5u8]); | |
assert_eq!(aim, &[]); | |
} | |
None => { panic!("Should generate elements!"); } | |
}; | |
assert!(it.next().is_none()); | |
} | |
#[test] | |
fn three_iterations_test() | |
{ | |
let mut v = vec!(1u8, 2, 3, 4, 5, 6); | |
let mut it = DoubleOverlappedChunksIterator::from_slice(&mut v, 1); | |
match it.next() { | |
Some((trace, left, middle, right, aim)) => { | |
assert_eq!(trace, &[]); | |
assert_eq!(left, &[1u8]); | |
assert_eq!(middle, &[2u8]); | |
assert_eq!(right, &[3u8]); | |
assert_eq!(aim, &[5u8]); | |
} | |
None => { panic!("Should generate elements!"); } | |
}; | |
match it.next() { | |
Some((trace, left, middle, right, aim)) => { | |
assert_eq!(trace, &[1u8]); | |
assert_eq!(left, &[3u8]); | |
assert_eq!(middle, &[4u8]); | |
assert_eq!(right, &[5u8]); | |
assert_eq!(aim, &[]); | |
} | |
None => { panic!("Should generate elements!"); } | |
}; | |
match it.next() { | |
Some((trace, left, middle, right, aim)) => { | |
assert_eq!(trace, &[3u8]); | |
assert_eq!(left, &[5u8]); | |
assert_eq!(middle, &[6u8]); | |
assert_eq!(right, &[]); | |
assert_eq!(aim, &[]); | |
} | |
None => { panic!("Should generate elements!"); } | |
}; | |
assert!(it.next().is_none()); | |
} | |
#[test] | |
fn pointer_equality_test() | |
{ | |
let mut v = vec!(1u8, 2, 3, 4, 5, 6, 7); | |
{ | |
let mut it = DoubleOverlappedChunksIterator::from_slice(&mut v, 1); | |
let (_t, l1, m1, r1, a1) = it.next().unwrap(); | |
let (t2, l2, m2, r2, a2) = it.next().unwrap(); | |
let (t3, l3, m3, r3, _a) = it.next().unwrap(); | |
m1[0] = 0; | |
m2[0] = 1; | |
m3[0] = 2; | |
assert_eq!(l1.as_ptr(), t2.as_ptr()); | |
assert_eq!(r1.as_ptr(), l2.as_ptr()); | |
assert_eq!(a1.as_ptr(), r2.as_ptr()); | |
assert_eq!(l2.as_ptr(), t3.as_ptr()); | |
assert_eq!(r2.as_ptr(), l3.as_ptr()); | |
assert_eq!(a2.as_ptr(), r3.as_ptr()); | |
assert!(it.next().is_none()); | |
} | |
assert_eq!(v, &[1u8, 0, 3, 1, 5, 2, 7]) | |
} | |
} | |
fn main() { | |
println!("Hello, world!"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment