use crate::rational_sequences::{RationalSequence, rational_sequence_reduce};
use core::ops::Index;
impl<T: Eq> Index<usize> for RationalSequence<T> {
type Output = T;
#[inline]
fn index(&self, i: usize) -> &T {
self.get(i).unwrap()
}
}
impl<T: Eq> RationalSequence<T> {
pub fn get(&self, i: usize) -> Option<&T> {
let non_repeating_len = self.non_repeating.len();
if i < non_repeating_len {
Some(&self.non_repeating[i])
} else if self.repeating.is_empty() {
None
} else {
Some(&self.repeating[(i - non_repeating_len) % self.repeating.len()])
}
}
}
impl<T: Clone + Eq> RationalSequence<T> {
pub fn mutate<F: FnOnce(&mut T) -> U, U>(&mut self, i: usize, f: F) -> U {
let non_repeating_len = self.non_repeating.len();
let result = if i < non_repeating_len {
f(&mut self.non_repeating[i])
} else if self.repeating.is_empty() {
panic!("index out of bounds");
} else {
let repeating_len = self.repeating.len();
let extra = i - non_repeating_len + 1;
self.non_repeating
.extend(self.repeating.iter().cycle().take(extra).cloned());
self.repeating.rotate_left(extra % repeating_len);
f(&mut self.non_repeating[i])
};
rational_sequence_reduce(&mut self.non_repeating, &mut self.repeating);
result
}
}