1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
//! Variance (Var(X))
//!
//! Measure of dispersion between values.
//!
//! # Formula
//!
//! Var(X) = ∑\[(x - μ)^2\]
//!
//! where:
//!
//! * `x` is the current value in a set.
//! * `μ` is the mean of the set.
//! * `∑` is the sum.
use crate::traits::{AsValue, Next, Period, Value};
use crate::{Buffer, Num, TAError};
/// Variance (Var(X))
///
/// Measure of dispersion between values.
///
/// # Formula
///
/// Var(X) = ∑\[(x - μ)^2\]
///
/// where:
///
/// * `x` is the current value in a set.
/// * `μ` is the mean of the set.
/// * `∑` is the sum.
#[derive(Debug)]
pub struct Variance {
/// Size of the period (window) in which data is looked at.
period: usize,
/// Var(X)'s current value.
value: Num,
/// Holds all of the current period's values.
buffer: Buffer,
/// Labels it as sample or population.
is_sample: bool,
}
impl Variance {
/// Creates a new Var(X) with the supplied period and initial data.
///
/// Required: The initial data must be at least of equal size/length or greater than the period.
///
/// # Arguments
///
/// * `period` - Size of the period / window used.
/// * `data` - Array of values to create the Var(X) from.
/// * `is_sample` - If the data is a Sample or Population, default should be True.
pub fn new(period: usize, data: &[Num], is_sample: bool) -> Result<Self, TAError> {
// Make sure we have enough data.
if data.len() < period {
return Err(TAError::InvalidData(String::from(
"not enough data for period provided",
)));
}
// Build the buffer from the data provided.
let buffer: Buffer = match Buffer::from_array(period, data) {
Ok(value) => value,
Err(error) => return Err(error),
};
Ok(Self {
period,
value: buffer.variance(is_sample),
buffer,
is_sample,
})
}
/// Indicates either sample or population being used.
pub fn is_sample(&self) -> bool {
self.is_sample
}
}
impl Period for Variance {
/// Period (window) for the samples.
fn period(&self) -> usize {
self.period
}
}
impl Value for Variance {
/// Current and most recent value calculated.
fn value(&self) -> Num {
self.value
}
}
impl Next<Num> for Variance {
/// Value for the next Variance.
type Output = Num;
/// Supply an additional value to recalculate a new Var(X).
///
/// # Arguments
///
/// * `value` - New value to add to period.
fn next(&mut self, value: Num) -> Self::Output {
// Rotate the buffer.
self.buffer.shift(value);
// Calculate the new Var(X).
self.value = self.buffer.variance(self.is_sample());
self.value
}
}
impl<T> Next<T> for Variance
where
T: AsValue,
{
/// Value for the next Variance.
type Output = Num;
/// Supply an additional value to recalculate a new Variance.
///
/// # Arguments
///
/// * `value` - New value to add to period.
fn next(&mut self, value: T) -> Self::Output {
self.next(value.as_value())
}
}