use std::collections::VecDeque;
use std::convert;
use std::ops;
use std::time::Duration;
use std::vec::Vec;
use image::{ImageBuffer, Pixel, Primitive};
use rayon::prelude::*;
pub trait Average<Div, Result = Self> {
fn add(&self, rhs: &Self) -> Result;
fn sub(&self, rhs: &Self) -> Result;
fn div(&self, rhs: &Div) -> Result;
}
pub trait AverageMut<Div, Result = Self>: Average<Div, Result> {
fn add_assign(&mut self, rhs: &Self);
fn sub_assign(&mut self, rhs: &Self);
}
macro_rules! average_primitive {
($primitive:tt) => {
impl<Div> Average<Div> for $primitive
where
Div: convert::Into<$primitive> + Copy,
{
fn add(&self, rhs: &Self) -> Self {
self + rhs
}
fn sub(&self, rhs: &Self) -> Self {
self - rhs
}
fn div(&self, rhs: &Div) -> Self {
let divisor: $primitive = Into::<$primitive>::into(*rhs);
self / divisor
}
}
impl<Div> AverageMut<Div> for $primitive
where
Div: convert::Into<$primitive> + Copy,
{
fn add_assign(&mut self, rhs: &Self) {
*self += *rhs;
}
fn sub_assign(&mut self, rhs: &Self) {
*self -= rhs;
}
}
};
}
average_primitive!(f32);
average_primitive!(f64);
average_primitive!(u8);
average_primitive!(u16);
average_primitive!(u32);
impl Average<u16> for Duration {
fn add(&self, rhs: &Self) -> Self {
*self + *rhs
}
fn sub(&self, rhs: &Self) -> Self {
*self - *rhs
}
fn div(&self, rhs: &u16) -> Self {
*self / *rhs as u32
}
}
impl AverageMut<u16> for Duration {
fn add_assign(&mut self, rhs: &Self) {
*self += *rhs
}
fn sub_assign(&mut self, rhs: &Self) {
*self -= *rhs
}
}
macro_rules! average_container {
($typ:ty, $inner_typ:ty, $return_typ:ty) => {
impl<Div> Average<Div, $return_typ> for $typ
where
Div: convert::Into<$inner_typ> + Copy
{
fn add(&self, other: &Self) -> $return_typ {
assert!(self.len() == other.len(), "The two collections must be the same length to average");
self.par_iter().zip(other.par_iter()).map(|(lhs, rhs)| *lhs + *rhs).collect()
}
fn sub(&self, other: &Self) -> $return_typ {
assert!(self.len() == other.len(), "The two collections must be the same length to average");
self.par_iter().zip(other.par_iter()).map(|(lhs, rhs)| *lhs - *rhs).collect()
}
fn div(&self, rhs: &Div) -> $return_typ {
let divisor: $inner_typ = Into::<$inner_typ>::into(*rhs);
self.par_iter().map(|lhs| *lhs / divisor).collect()
}
}
};
($typ:ty, $inner_typ:ty) => {
average_container!($typ, $inner_typ, Self);
};
(generic $typ:ty, $return_typ:ty) => {
impl<T, Div> Average<Div, $return_typ> for $typ
where
T: Primitive + ops::AddAssign + ops::SubAssign + Send + Sync,
Div: convert::Into<T> + Copy
{
fn add(&self, other: &Self) -> $return_typ {
assert!(self.len() == other.len(), "The two collections must be the same length to average");
self.par_iter().zip(other.par_iter()).map(|(lhs, rhs)| *lhs + *rhs).collect()
}
fn sub(&self, other: &Self) -> $return_typ {
assert!(self.len() == other.len(), "The two collections must be the same length to average");
self.par_iter().zip(other.par_iter()).map(|(lhs, rhs)| *lhs - *rhs).collect()
}
fn div(&self, rhs: &Div) -> $return_typ {
let divisor: T = Into::<T>::into(*rhs);
self.par_iter().map(|lhs| *lhs / divisor).collect()
}
}
};
(generic $typ:ty) => {
average_container!(generic $typ, Self);
};
}
macro_rules! average_mut_container {
($typ:ty, $inner_typ:ty, $return_typ:ty) => {
impl<Div> AverageMut<Div, $return_typ> for $typ
where
Div: convert::Into<$inner_typ> + Copy
{
fn add_assign(&mut self, other: &Self) {
assert!(self.len() == other.len(), "The two collections must be the same length to average");
self
.par_iter_mut()
.zip(other.par_iter())
.for_each(|(lhs, rhs)| *lhs += *rhs)
}
fn sub_assign(&mut self, other: &Self) {
assert!(self.len() == other.len(), "The two collections must be the same length to average");
self
.par_iter_mut()
.zip(other.par_iter())
.for_each(|(lhs, rhs)| *lhs -= *rhs)
}
}
};
($typ:ty, $inner_typ:ty) => {
average_mut_container!($typ, $inner_typ, Self);
};
(generic $typ:ty, $return_typ:ty) => {
impl<T, Div> AverageMut<Div, $return_typ> for $typ
where
T: Primitive + ops::AddAssign + ops::SubAssign + Send + Sync,
Div: convert::Into<T> + Copy
{
fn add_assign(&mut self, other: &Self) {
self
.par_iter_mut()
.zip(other.par_iter())
.for_each(|(lhs, rhs)| *lhs += *rhs)
}
fn sub_assign(&mut self, other: &Self) {
self
.par_iter_mut()
.zip(other.par_iter())
.for_each(|(lhs, rhs)| *lhs -= *rhs)
}
}
};
(generic $typ:ty) => {
average_mut_container!(generic $typ, Self);
};
}
average_container!(generic Vec<T>);
average_mut_container!(generic Vec<T>);
average_container!(generic[T], Vec<T>);
average_mut_container!(generic[T], Vec<T>);
impl<Div, Px, Co> Average<Div> for ImageBuffer<Px, Co>
where
Px: Pixel + 'static,
<Px as Pixel>::Subpixel: 'static,
Co: ops::Deref<Target = [Px::Subpixel]> + Average<Div>,
{
fn add(&self, rhs: &Self) -> Self {
let new_raw = self.as_raw().add(rhs.as_raw());
ImageBuffer::from_raw(self.width(), self.height(), new_raw)
.expect("An identically sized Vec to work as an image")
}
fn sub(&self, rhs: &Self) -> Self {
let new_raw = self.as_raw().sub(rhs.as_raw());
ImageBuffer::from_raw(self.width(), self.height(), new_raw)
.expect("An identically sized Vec to work as an image")
}
fn div(&self, rhs: &Div) -> Self {
let new_raw = self.as_raw().div(rhs);
ImageBuffer::from_raw(self.width(), self.height(), new_raw)
.expect("An identically sized Vec to work as an image")
}
}
pub trait Filter<T> {
fn update(&mut self, new_value: T) -> T {
self.push(new_value);
self.current_value()
.expect("There to be a value as we just pushed one")
}
fn push(&mut self, new_value: T);
fn current_value(&self) -> Option<T>;
}
#[derive(Clone, Debug)]
pub struct MovingAverage<T, const N: usize> {
frames: VecDeque<T>,
sums: Option<T>,
}
impl<T, const N: usize> MovingAverage<T, N> {
pub fn new() -> Self {
Self {
frames: VecDeque::with_capacity(N),
sums: None,
}
}
}
impl<T, const N: usize> Default for MovingAverage<T, N> {
fn default() -> Self {
Self::new()
}
}
impl<T, const N: usize> Filter<T> for MovingAverage<T, N>
where
T: AverageMut<u16> + Clone,
{
fn push(&mut self, new_value: T) {
if self.frames.len() >= N {
if let Some(old_frame) = self.frames.pop_front() {
if let Some(sums) = &mut self.sums {
sums.sub_assign(&old_frame);
}
}
}
match &mut self.sums {
Some(sums) => sums.add_assign(&new_value),
None => {
self.sums.replace(new_value.clone());
}
}
self.frames.push_back(new_value);
}
fn current_value(&self) -> Option<T> {
let num_frames = self.frames.len() as u16;
self.sums.as_ref().map(|sums| sums.clone().div(&num_frames))
}
}
impl<T, const N: usize> PartialEq for MovingAverage<T, N>
where
T: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.frames == other.frames
}
}
impl<T, const N: usize> Eq for MovingAverage<T, N> where T: Eq {}