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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
use core::ops::{Neg, Sub};
use num::{Float, Num};
use std::ops::{Add, AddAssign};
/// Returns a n-tau vector containing the time series lagged by tau.
///
/// # Arguments
///
/// * `&x` - Reference to input vector slice of length n.
/// * `tau` - Lag.
///
/// # Returns
///
/// * Output vector of length n-tau.
///
/// # Example
///
/// ```
/// use arima::util;
/// let x = [-4, -9, 20, 23, -18, 6];
/// assert_eq!(util::lag(&x, 2), &[20, 23, -18, 6]);
/// ```
pub fn lag<T: Num + Copy>(x: &[T], tau: u32) -> Vec<T> {
let mut y: Vec<T> = Vec::new();
assert!(tau < x.len() as u32);
for a in x.iter().skip(tau as usize) {
y.push(*a);
}
y
}
/// Returns a n-1 vector containing the pairwise difference x_t - x_t-1.
///
/// # Arguments
///
/// * `&x` - Reference to input vector slice of length n.
/// * `d` - Number of differences to be taken.
///
/// # Returns
///
/// * Output vector of length n-1.
///
/// # Example
///
/// ```
/// use arima::util;
/// let x = [1, 2, 3];
/// assert_eq!(util::diff(&x, 1), &[1, 1])
/// ```
pub fn diff<T: Num + Copy + Neg<Output = T> + Sub>(x: &[T], d: usize) -> Vec<T> {
let mut y: Vec<T> = x.to_vec();
let len = y.len();
for s in 0..d {
for i in 1..len - s {
// we iterate backwards through the vector to avoid cloning
y[len - i] = y[len - i] - y[len - i - 1];
}
}
y.drain(0..d);
y
}
/// Returns a n-1 vector containing the pairwise difference of log(x_t) - log(x_t-1).
///
/// # Arguments
///
/// * `&x` - Reference to input vector slice of length n.
///
/// # Returns
///
/// * Output vector of length n-1.
///
/// # Example
///
/// ```
/// use arima::util;
/// let x = [1.0, 4.0, 6.0];
/// let y = util::diff_log(&x);
/// assert!(y[0] - 1.3862944 < 1.0e-7);
/// assert!(y[1] - 0.4054651 < 1.0e-7);
/// ```
pub fn diff_log<T: Float>(x: &[T]) -> Vec<T> {
let mut y: Vec<T> = x.to_vec();
let len = y.len();
y[len - 1] = y[len - 1].ln();
for i in 1..len {
// we iterate backwards through the vector to avoid re-calculation of ln()
y[len - i - 1] = y[len - i - 1].ln();
y[len - i] = y[len - i] - y[len - i - 1];
}
y.drain(0..1);
y
}
/// Calculate the cumulative sum of a vector.
///
/// # Arguments
///
/// * `&x` - Reference to input vector slice of length n.
///
/// # Returns
///
/// * Output vector of length n containing the cumulated values.
///
/// # Example
///
/// ```
/// use arima::util;
/// let x = [1, 2, 3];
/// assert_eq!(util::cumsum(&x), &[1, 3, 6]);
/// ```
pub fn cumsum<T: Num + Add + AddAssign + Copy + From<u8>>(x: &[T]) -> Vec<T> {
let mut y: Vec<T> = Vec::new();
if x.len() < 2 {
y.push(From::from(0));
return y;
}
y.push(x[0]);
for i in 1..x.len() {
y.push(y[i - 1] + x[i]);
}
y
}
/// Calculate the inverse difference of a vector.
///
/// # Arguments
///
/// * `&x` - Reference to input vector slice of length n.
/// * `d` - How often the inverse differences should be applied.
///
/// # Returns
///
/// * Output vector of length n+d containing the inversed values. The first d values are zero.
///
/// # Example
///
/// ```
/// use arima::util;
/// let x = [1, 1, 1, 1, 1];
/// let y = util::diffinv(&x, 1);
/// assert_eq!(y, &[0, 1, 2, 3, 4, 5]);
///
/// let z = util::diff(&y, 1);
/// assert_eq!(z, x);
/// ```
pub fn diffinv<T: Num + Add + AddAssign + Copy + From<u8>>(x: &[T], d: usize) -> Vec<T> {
let zero = From::from(0);
// x vector with d leading zeros
let mut cum: Vec<T> = [&vec![zero; d], x].concat().to_vec();
// build cumulative sum d times
for _ in 0..d {
cum = cumsum(&cum);
}
cum
}
/// Calculate the mean of a vector.
///
/// # Arguments
///
/// * `&x` - Vector of length n to calculate the mean for.
///
/// # Returns
///
/// * Output vector containing the mean sum(x)/.
///
/// # Example
///
/// ```
/// use arima::util;
/// let x = [2, 3, 4, 5, 6];
/// let y = util::mean(&x);
/// assert_eq!(y, 4);
/// ```
pub fn mean<T: Num + Copy + Add<T, Output = T> + From<i32>>(x: &[T]) -> T {
let zero: T = From::from(0_i32);
let n: T = From::from(x.len() as i32);
x.iter().fold(zero, |sum, &item| sum + item) / n
}
/// Center vector, i.e. remove the mean from each element. Returns a tuple containing the
/// centered vector and the mean.
///
/// # Arguments
///
/// * `&x` - Vector of length n to be centered.
///
/// # Returns
///
/// * Tuple of (y, mean) where y is the centered vector and mean is the mean.
///
/// # Example
///
/// ```
/// use arima::util;
/// let x = [2, 3, 4, 5, 6];
/// let (y, m) = util::center(&x);
/// assert_eq!(y, [-2, -1, 0, 1, 2]);
/// assert_eq!(m, 4);
/// ```
pub fn center<T: Num + Copy + Add + AddAssign + Copy + From<i32>>(x: &[T]) -> (Vec<T>, T) {
let m = mean(x);
(x.iter().map(|&x| x - m).collect(), m)
}