dendritic_ndarray/ops/
aggregate.rs1use crate::ops::unary::UnaryOps;
2use crate::ops::scalar::ScalarOps;
3use crate::ndarray::NDArray;
4
5pub trait AggregateOps {
6 fn avg(&self) -> f64;
7 fn length(&self) -> f64;
8 fn square(&self) -> Result<NDArray<f64>, String>;
9 fn sum(&self) -> Result<NDArray<f64>, String>;
10 fn abs(&self) -> Result<NDArray<f64>, String>;
11 fn sort(&self) -> Vec<f64>;
12 fn unique(&self) -> Vec<f64>;
13 fn mean(&self, axis: usize) -> Result<Vec<f64>, String>;
14 fn stdev(&self, axis: usize) -> Result<Vec<f64>, String>;
15 fn stdev_sample(&self, axis: usize) -> Result<Vec<f64>, String>;
16}
17
18
19impl AggregateOps for NDArray<f64> {
20
21 fn avg(&self) -> f64 {
23 let sum: f64 = self.values().iter().sum();
24 sum / self.size() as f64
25 }
26
27 fn length(&self) -> f64 {
29 let mut sum: f64 = 0.0;
30 for index in 0..self.size() {
31 let value = self.values()[index];
32 let raised = value.powf(2.0);
33 sum += raised;
34 }
35
36 sum.sqrt()
37 }
38
39
40 fn square(&self) -> Result<NDArray<f64>, String> {
42
43 let mut result = NDArray::new(self.shape().values()).unwrap();
44 for index in 0..self.size() {
45 let value = self.values()[index];
46 let raised = value.powf(2.0);
47 let _ = result.set_idx(index, raised);
48 }
49
50 Ok(result)
51 }
52
53
54 fn sum(&self) -> Result<NDArray<f64>, String> {
56
57 let sum_val = self.values().iter().sum();
58 let result = NDArray::array(
59 vec![1, 1],
60 vec![sum_val]
61 ).unwrap();
62
63 Ok(result)
64
65 }
66
67
68 fn abs(&self) -> Result<NDArray<f64>, String> {
70
71 let abs: Vec<f64> = self.values().into_iter().map(
72 |val| val.abs()
73 ).collect();
74
75 let result = NDArray::array(
76 self.shape().values(), abs
77 ).unwrap();
78
79 Ok(result)
80 }
81
82
83 fn sort(&self) -> Vec<f64> {
85 let mut values = self.values().clone();
86 values.sort_by(|a, b| a.partial_cmp(b).unwrap());
87 values.to_vec()
88 }
89
90
91 fn unique(&self) -> Vec<f64> {
93 let mut values = self.values().clone();
94 values.sort_by(|a, b| a.partial_cmp(b).unwrap());
95 values.dedup();
96 values.to_vec()
97 }
98
99
100 fn mean(&self, axis: usize) -> Result<Vec<f64>, String> {
102
103 let mut results: Vec<f64> = Vec::new();
104 let shape_axis = self.shape().dim(axis);
105 for item in 0..shape_axis {
106 let axis_vals = self.axis(axis, item).unwrap();
107 let sum_vals: f64 = axis_vals.values().iter().sum();
108 let avg: f64 = sum_vals / axis_vals.values().len() as f64;
109 results.push(avg);
110 }
111
112 Ok(results)
113 }
114
115 fn stdev(&self, axis: usize) -> Result<Vec<f64>, String> {
117
118 if axis >= self.shape().values().len() {
119 let msg = "stdev: Axis too large for current array";
120 return Err(msg.to_string());
121 }
122
123 let mut results: Vec<f64> = Vec::new();
124 let mean_axis = self.mean(axis).unwrap();
125 let shape_axis = self.shape().dim(axis);
126 for shape in 0..shape_axis {
127 let axis_vals = self.axis(axis, shape).unwrap();
128 let mean_axis_val = mean_axis[shape];
129 let subtract_mean = axis_vals.scalar_subtract(mean_axis_val).unwrap();
130 let squared = subtract_mean.norm(2).unwrap();
131 let sum: f64 = squared.values().iter().sum();
132 let avg = sum / axis_vals.size() as f64;
133 results.push(avg.sqrt());
134 }
135
136 Ok(results)
137 }
138
139
140 fn stdev_sample(&self, axis: usize) -> Result<Vec<f64>, String> {
142
143 if axis >= self.shape().values().len() {
144 let msg = "stdev sample: Axis too large for current array";
145 return Err(msg.to_string());
146 }
147
148 let mut results: Vec<f64> = Vec::new();
149 let mean_axis = self.mean(axis).unwrap();
150 let shape_axis = self.shape().dim(axis);
151 for shape in 0..shape_axis {
152 let axis_vals = self.axis(axis, shape).unwrap();
153 let mean_axis_val = mean_axis[shape];
154 let subtract_mean = axis_vals.scalar_subtract(mean_axis_val).unwrap();
155 let squared = subtract_mean.norm(2).unwrap();
156 let sum: f64 = squared.values().iter().sum();
157 let avg = sum / (axis_vals.size() - 1) as f64;
158 results.push(avg.sqrt());
159 }
160
161 Ok(results)
162 }
163
164
165}