Skip to content

Instantly share code, notes, and snippets.

@pacmancoder
Last active October 23, 2018 22:08
Show Gist options
  • Save pacmancoder/0ee33123c021ee9c2b38f185d225f19c to your computer and use it in GitHub Desktop.
Save pacmancoder/0ee33123c021ee9c2b38f185d225f19c to your computer and use it in GitHub Desktop.
[Rust] Overlaying Slices iterator PoC
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);
}
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