granite_reckoner/
lib.rs

1//! # Granite Reckoner
2//!
3//! `granite_reckoner` is a simple calculator enabling basic aggregations on Vec<T> in the specified number of threads. Works for all Rust's built-in numeric types.
4//!  Returns "None" for overflows and non-comparable data.
5//!  As for the primitives, the error propagates accordingly for high multiplicities.
6
7use std::marker::PhantomData;
8pub mod constants;
9
10mod aggregator;
11mod column_data;
12mod tools;
13mod traits;
14
15use crate::column_data::ColumnData;
16use crate::traits::NumericType;
17
18/// Data wrapper without any data yet.
19pub struct EmptyColumn<T: NumericType<T>> {
20    phantom: PhantomData<T>,
21}
22
23/// Data wrapper populated with values.
24pub struct Column<T: NumericType<T>> {
25    data: ColumnData<T>,
26}
27
28impl<T: NumericType<T>> EmptyColumn<T> {
29    pub fn add_data(self, container: Vec<T>) -> Column<T> {
30        Column {
31            data: ColumnData::<T>::new(container),
32        }
33    }
34}
35
36impl<T: NumericType<T>> Column<T> {
37    pub fn new() -> EmptyColumn<T> {
38        EmptyColumn::<T> {
39            phantom: PhantomData,
40        }
41    }
42    /// Sums x
43    pub fn sum(&self) -> Option<T> {
44        aggregator::sum(&self.data, constants::NUMBER_OF_NODES)
45    }
46    /// Sums x^2
47    pub fn sum_x2(&self) -> Option<T> {
48        aggregator::sum_x2(&self.data, constants::NUMBER_OF_NODES)
49    }
50
51    /// Moment-I (pop. Average)
52    pub fn moment_i(&self) -> Option<f64> {
53        aggregator::moment_i(&self.data, constants::NUMBER_OF_NODES)
54    }
55
56    /// Moment-II
57    pub fn moment_ii(&self) -> Option<f64> {
58        aggregator::moment_ii(&self.data, constants::NUMBER_OF_NODES)
59    }
60
61    /// Sample Variance. (Square of the sample standard deviation).
62    pub fn variance(&self) -> Option<f64> {
63        aggregator::variance(&self.data, constants::NUMBER_OF_NODES)
64    }
65
66    /// Sample Standard Deviation.
67    pub fn stddev(&self) -> Option<f64> {
68        aggregator::stddev(&self.data, constants::NUMBER_OF_NODES)
69    }
70
71    pub fn min(&self) -> Option<T> {
72        aggregator::min(&self.data, constants::NUMBER_OF_NODES)
73    }
74
75    pub fn max(&self) -> Option<T> {
76        aggregator::max(&self.data, constants::NUMBER_OF_NODES)
77    }
78
79    pub fn count(&self) -> Option<usize> {
80        // O(1) complexity
81        aggregator::count(&self.data)
82    }
83
84    pub fn print(&self) {
85        println!("{:?}", &self);
86    }
87
88    pub fn sum_t(&self, number_of_threads: usize) -> Option<T> {
89        if number_of_threads < 1 || number_of_threads > constants::NUMBER_OF_NODES {
90            println!("The number of threads must be in range: (1..=constants::NUMBER_OF_NODES)");
91            return None;
92        }
93        aggregator::sum(&self.data, number_of_threads)
94    }
95
96    pub fn sum_x2_t(&self, number_of_threads: usize) -> Option<T> {
97        if number_of_threads < 1 || number_of_threads > constants::NUMBER_OF_NODES {
98            println!("The number of threads must be in range: (1..=constants::NUMBER_OF_NODES)");
99            return None;
100        }
101        aggregator::sum_x2(&self.data, number_of_threads)
102    }
103
104    pub fn moment_i_t(&self, number_of_threads: usize) -> Option<f64> {
105        if number_of_threads < 1 || number_of_threads > constants::NUMBER_OF_NODES {
106            println!("The number of threads must be in range: (1..=constants::NUMBER_OF_NODES)");
107            return None;
108        }
109        aggregator::moment_i(&self.data, number_of_threads)
110    }
111
112    pub fn moment_ii_t(&self, number_of_threads: usize) -> Option<f64> {
113        if number_of_threads < 1 || number_of_threads > constants::NUMBER_OF_NODES {
114            println!("The number of threads must be in range: (1..=constants::NUMBER_OF_NODES)");
115            return None;
116        }
117        aggregator::moment_ii(&self.data, number_of_threads)
118    }
119
120    pub fn variance_t(&self, number_of_threads: usize) -> Option<f64> {
121        if number_of_threads < 1 || number_of_threads > constants::NUMBER_OF_NODES {
122            println!("The number of threads must be in range: (1..=constants::NUMBER_OF_NODES)");
123            return None;
124        }
125        aggregator::variance(&self.data, number_of_threads)
126    }
127
128    pub fn stddev_t(&self, number_of_threads: usize) -> Option<f64> {
129        if number_of_threads < 1 || number_of_threads > constants::NUMBER_OF_NODES {
130            println!("The number of threads must be in range: (1..=constants::NUMBER_OF_NODES)");
131            return None;
132        }
133        aggregator::stddev(&self.data, number_of_threads)
134    }
135
136    pub fn min_t(&self, number_of_threads: usize) -> Option<T> {
137        if number_of_threads < 1 || number_of_threads > constants::NUMBER_OF_NODES {
138            println!("The number of threads must be in range: (1..=constants::NUMBER_OF_NODES)");
139            return None;
140        }
141        aggregator::min(&self.data, number_of_threads)
142    }
143
144    pub fn max_t(&self, number_of_threads: usize) -> Option<T> {
145        if number_of_threads < 1 || number_of_threads > constants::NUMBER_OF_NODES {
146            println!("The number of threads must be in range: (1..=constants::NUMBER_OF_NODES)");
147            return None;
148        }
149        aggregator::max(&self.data, number_of_threads)
150    }
151
152    // just to preserve the interface consistency
153    pub fn count_t(&self, number_of_threads: usize) -> Option<usize> {
154        if number_of_threads < 1 || number_of_threads > constants::NUMBER_OF_NODES {
155            println!("The number of threads must be in range: (1..=constants::NUMBER_OF_NODES)");
156            return None;
157        }
158        // O(1) complexity
159        aggregator::count(&self.data)
160    }
161}