use crate::frame::Frame; use crate::matrix::{Axis, BoolMatrix, BoolOps, FloatMatrix, SeriesOps}; // Macro to delegate method calls to self.matrix() macro_rules! delegate_to_matrix { ($($method_name:ident -> $return_type:ty),* $(,)?) => { $( fn $method_name(&self) -> $return_type { self.matrix().$method_name() } )* }; } impl SeriesOps for Frame { #[allow(unused_mut)] fn apply_axis(&self, axis: Axis, mut f: F) -> Vec where F: FnMut(&[f64]) -> U, { self.matrix().apply_axis(axis, f) } delegate_to_matrix!( sum_vertical -> Vec, sum_horizontal -> Vec, prod_horizontal -> Vec, prod_vertical -> Vec, cumsum_horizontal -> FloatMatrix, cumsum_vertical -> FloatMatrix, count_nan_vertical -> Vec, count_nan_horizontal -> Vec, is_nan -> BoolMatrix ); } impl BoolOps for Frame { fn apply_axis(&self, axis: Axis, f: F) -> Vec where F: FnMut(&[bool]) -> U, { self.matrix().apply_axis(axis, f) } delegate_to_matrix!( any_vertical -> Vec, any_horizontal -> Vec, all_vertical -> Vec, all_horizontal -> Vec, count_vertical -> Vec, count_horizontal -> Vec, any -> bool, all -> bool, count -> usize ); } // use crate::frame::Frame; // use crate::matrix::{Axis, SeriesOps, FloatMatrix, BoolMatrix}; // impl SeriesOps for Frame { // fn apply_axis(&self, axis: Axis, mut f: F) -> Vec // where // F: FnMut(&[f64]) -> U, // { // self.matrix().apply_axis(axis, f) // } // fn sum_vertical(&self) -> Vec { // self.matrix().sum_vertical() // } // fn sum_horizontal(&self) -> Vec { // self.matrix().sum_horizontal() // } // fn prod_horizontal(&self) -> Vec { // self.matrix().prod_horizontal() // } // fn prod_vertical(&self) -> Vec { // self.matrix().prod_vertical() // } // fn cumsum_horizontal(&self) -> FloatMatrix { // self.matrix().cumsum_horizontal() // } // fn cumsum_vertical(&self) -> FloatMatrix { // self.matrix().cumsum_vertical() // } // fn count_nan_vertical(&self) -> Vec { // self.matrix().count_nan_vertical() // } // fn count_nan_horizontal(&self) -> Vec { // self.matrix().count_nan_horizontal() // } // fn is_nan(&self) -> BoolMatrix { // self.matrix().is_nan() // } // } #[cfg(test)] mod tests { use super::*; use crate::matrix::Matrix; #[test] fn test_series_ops() { let col_names = vec!["A".to_string(), "B".to_string()]; let frame = Frame::new( Matrix::from_cols(vec![vec![1.0, 2.0], vec![3.0, 4.0]]), col_names, None, ); assert_eq!(frame.sum_vertical(), frame.matrix().sum_vertical()); assert_eq!(frame.sum_horizontal(), frame.matrix().sum_horizontal()); assert_eq!(frame.prod_horizontal(), frame.matrix().prod_horizontal()); assert_eq!(frame.prod_vertical(), frame.matrix().prod_vertical()); assert_eq!( frame.cumsum_horizontal(), frame.matrix().cumsum_horizontal() ); assert_eq!(frame.cumsum_vertical(), frame.matrix().cumsum_vertical()); assert_eq!( frame.count_nan_vertical(), frame.matrix().count_nan_vertical() ); assert_eq!( frame.count_nan_horizontal(), frame.matrix().count_nan_horizontal() ); assert_eq!(frame.is_nan(), frame.matrix().is_nan()); assert_eq!(frame.apply_axis(Axis::Row, |x| x[0] + x[1]), vec![4.0, 6.0]); } #[test] fn test_bool_ops() { let col_names = vec!["A".to_string(), "B".to_string()]; let frame = Frame::new( Matrix::from_cols(vec![vec![true, false], vec![false, true]]), col_names, None, ); assert_eq!(frame.any_vertical(), vec![true, true]); assert_eq!(frame.any_horizontal(), vec![true, true]); assert_eq!(frame.all_horizontal(), vec![false, false]); assert_eq!(frame.all_vertical(), vec![false, false]); assert_eq!(frame.count_vertical(), vec![1, 1]); assert_eq!(frame.count_horizontal(), vec![1, 1]); assert_eq!(frame.any(), true); assert_eq!(frame.all(), false); assert_eq!(frame.count(), 2); assert_eq!( frame.apply_axis(Axis::Row, |x| x[0] && x[1]), vec![false, false] ); } }