use crate::utils::access;
use crate::value::Value;
use crate::{config::Config, vec_wrapper::VecWrapper};
use rayon::{
iter::{
FromParallelIterator, IntoParallelIterator, IntoParallelRefIterator,
},
slice::Iter,
vec::IntoIter,
};
use serde_derive::{Deserialize, Serialize};
use std::{iter::FromIterator, ops::Index};
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct Schedule<T>(Vec<Config<T>>);
pub type IntegralSchedule = Schedule<i32>;
pub type FractionalSchedule = Schedule<f64>;
impl<'a, T> Schedule<T>
where
T: Value<'a>,
{
pub fn new(x: Vec<Config<T>>) -> Schedule<T> {
Schedule(x)
}
pub fn empty() -> Schedule<T> {
Schedule(vec![])
}
pub fn repeat(x: Config<T>, t: i32) -> Schedule<T> {
Schedule(vec![x; t as usize])
}
pub fn is_empty(&self) -> bool {
self.t_end() == 0
}
pub fn t_end(&self) -> i32 {
self.0.len() as i32
}
pub fn now(&self) -> Config<T> {
self[self.0.len() - 1].clone()
}
pub fn now_with_default(&self, default: Config<T>) -> Config<T> {
if self.is_empty() {
default
} else {
self[self.0.len() - 1].clone()
}
}
pub fn get(&self, t: i32) -> Option<&Config<T>> {
access(&self.0, t)
}
pub fn shift(&mut self, x: Config<T>) {
self.0.insert(0, x)
}
pub fn push(&mut self, x: Config<T>) {
self.0.push(x)
}
pub fn extend(&self, x: Config<T>) -> Schedule<T> {
Schedule([&self.0[..], &[x]].concat())
}
pub fn to_vec(&self) -> Vec<Vec<T>> {
self.0.iter().map(|x| x.to_vec()).collect()
}
pub fn from_raw(d: i32, w: i32, raw_xs: &[T]) -> Schedule<T> {
assert_eq!(
raw_xs.len() as i32,
Schedule::<T>::raw_encoding_len(d, w),
"length of raw encoding does not match expected length"
);
Schedule::new(
(0..w as usize)
.into_iter()
.map(|t| {
let i = d as usize * t;
Config::new(raw_xs[i..i + d as usize].to_vec())
})
.collect(),
)
}
pub fn build_raw(w: i32, x: &Config<T>) -> Vec<T> {
let raw_xs: Vec<T> = (0..w as usize)
.into_iter()
.flat_map(|_| x.iter().cloned())
.collect();
assert_eq!(
raw_xs.len() as i32,
Schedule::<T>::raw_encoding_len(x.d(), w),
"length of raw encoding does not match expected length"
);
raw_xs
}
pub fn raw_encoding_len(d: i32, w: i32) -> i32 {
d * w
}
}
impl<'a, T> Index<usize> for Schedule<T>
where
T: Value<'a>,
{
type Output = Config<T>;
fn index(&self, t: usize) -> &Config<T> {
assert!(
t < self.0.len(),
"argument must denote one of {} time steps, is {}",
self.0.len(),
t + 1
);
&self.0[t]
}
}
impl<'a, T> VecWrapper for Schedule<T>
where
T: Value<'a>,
{
type Item = Config<T>;
fn to_vec(&self) -> &Vec<Self::Item> {
&self.0
}
}
impl<'a, T> FromIterator<Config<T>> for Schedule<T>
where
T: Value<'a>,
{
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = Config<T>>,
{
Schedule::new(Vec::<Config<T>>::from_iter(iter))
}
}
impl<'a, T> FromParallelIterator<Config<T>> for Schedule<T>
where
T: Value<'a>,
{
fn from_par_iter<I>(iter: I) -> Self
where
I: IntoParallelIterator<Item = Config<T>>,
{
Schedule::new(Vec::<Config<T>>::from_par_iter(iter))
}
}
impl<'a, 'b, T> IntoParallelIterator for &'a Schedule<T>
where
T: Value<'b>,
{
type Item = &'a Config<T>;
type Iter = Iter<'a, Config<T>>;
fn into_par_iter(self) -> Self::Iter {
self.0.par_iter()
}
}
impl<'a, T> IntoParallelIterator for Schedule<T>
where
T: Value<'a>,
{
type Item = Config<T>;
type Iter = IntoIter<Config<T>>;
fn into_par_iter(self) -> Self::Iter {
self.0.into_par_iter()
}
}