use crate::network::node::Node;
use core::ops;
use alloc::boxed::Box;
use core::any::Any;
pub struct Differentiate {}
impl Differentiate {
pub fn new<T>() -> Node<T>
where T: Copy + ops::Sub<Output=T> + 'static + Default
{
let storage = Box::new(T::default()) as Box<dyn Any>;
Node::new(storage, |data_input, data_buffer,
output| {
let (inputs, max_len) = data_input;
let last_val: &mut T = data_buffer.downcast_mut::<T>().unwrap();
output.clear();
inputs.into_iter().take(1).into_iter().for_each(|data| {
data.into_iter().take(max_len).into_iter().for_each(|v| {
let diff_result = *v - *last_val;
output.push(diff_result);
*last_val = *v;
})
})
})
}
}
#[cfg(test)]
mod tests {
use crate::operations::math::differentiate::Differentiate;
use alloc::vec::Vec;
#[test]
fn test_differentiate_constant() {
let mut div = Differentiate::new();
let mut input = Vec::new();
input.push(&[1.0][..]);
div.process((input, 1));
let mut input = Vec::new();
input.push(&[1.0][..]);
div.process((input, 1));
let mut input = Vec::new();
input.push(&[1.0][..]);
div.process((input, 1));
assert_eq!(div.poll(), &[0.0][..]);
}
#[test]
fn test_differentiate_slope() {
let mut div = Differentiate::new();
let mut input = Vec::new();
input.push(&[3.0][..]);
div.process((input, 1));
let mut input = Vec::new();
input.push(&[2.0][..]);
div.process((input, 1));
let mut input = Vec::new();
input.push(&[1.0][..]);
div.process((input, 1));
assert_eq!(div.poll(), &[-1.0][..]);
}
#[test]
fn test_long_slice() {
let mut div = Differentiate::new();
let mut input = Vec::new();
input.push(&[3.0, 2.0, 1.0][..]);
div.process((input, 3));
assert_eq!(div.poll(), &[3.0, -1.0, -1.0][..]);
}
}