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
use array_to_complex_mut;
use numbers::*;
use super::super::{Vector, DspVec, ToSliceMut, Domain, NumberSpace, MetaData};

/// A trait to calculate the diff (1st derivative in a discrete number space) or cumulative sum
/// (integral  in a discrete number space).
pub trait DiffSumOps {
    /// Calculates the delta of each elements to its previous element. This will decrease
    /// the vector length by one point.
    ///
    /// # Example
    ///
    /// # Example
    ///
    /// ```
    /// use basic_dsp_vector::*;
    /// let mut vector = vec!(2.0, 3.0, 2.0, 6.0).to_real_time_vec();
    /// vector.diff();
    /// assert_eq!([1.0, -1.0, 4.0], vector[..]);
    /// let mut vector = vec!(2.0, 2.0, 3.0, 3.0, 5.0, 5.0).to_complex_time_vec();
    /// vector.diff();
    /// assert_eq!([1.0, 1.0, 2.0, 2.0], vector[..]);
    /// ```
    fn diff(&mut self);

    /// Calculates the delta of each elements to its previous element. The first element
    /// will remain unchanged.
    ///
    /// # Example
    ///
    /// ```
    /// use basic_dsp_vector::*;
    /// let mut vector = vec!(2.0, 3.0, 2.0, 6.0).to_real_time_vec();
    /// vector.diff_with_start();
    /// assert_eq!([2.0, 1.0, -1.0, 4.0], vector[..]);
    /// let mut vector = vec!(2.0, 2.0, 3.0, 3.0, 5.0, 5.0).to_complex_time_vec();
    /// vector.diff_with_start();
    /// assert_eq!([2.0, 2.0, 1.0, 1.0, 2.0, 2.0], vector[..]);
    /// ```
    fn diff_with_start(&mut self);

    /// Calculates the cumulative sum of all elements. This operation undoes the
    /// `diff_with_start`operation.
    ///
    /// # Example
    ///
    /// ```
    /// use basic_dsp_vector::*;
    /// let mut vector = vec!(2.0, 1.0, -1.0, 4.0).to_real_time_vec();
    /// vector.cum_sum();
    /// assert_eq!([2.0, 3.0, 2.0, 6.0], vector[..]);
    /// ```
    fn cum_sum(&mut self);
}

impl<S, T, N, D> DiffSumOps for DspVec<S, T, N, D>
    where S: ToSliceMut<T>,
          T: RealNumber,
          N: NumberSpace,
          D: Domain
{
    fn diff(&mut self) {
        let is_complex = self.is_complex();
        let step = if is_complex { 2 } else { 1 };
        let len = self.len();
        self.valid_len -= step;
        let data = self.data.to_slice_mut();

        if is_complex {
            let data = array_to_complex_mut(data);
            for j in 0..len / 2 - 1 {
                unsafe {
                    let b = *data.get_unchecked(j + 1);
                    let a = data.get_unchecked_mut(j);
                    *a = b - *a;
                }
            }
        } else {
            for j in 0..len - 1 {
                unsafe {
                    let b = *data.get_unchecked(j + 1);
                    let a = data.get_unchecked_mut(j);
                    *a = b - *a;
                }
            }
        }
    }

    fn diff_with_start(&mut self) {
        let is_complex = self.is_complex();
        let len = self.len();
        if len == 0 {
            return;
        }

        let data = self.data.to_slice_mut();

        if is_complex {
            let data = array_to_complex_mut(data);
            let mut temp = data[0];
            for n in &mut data[1..len / 2] {
                let diff = *n - temp;
                temp = *n;
                *n = diff;
            }
        } else {
            let mut temp = data[0];
            for n in &mut data[1..len] {
                let diff = *n - temp;
                temp = *n;
                *n = diff;
            }
        }
    }

    fn cum_sum(&mut self) {
        let data_length = self.len();
        let mut i = 0;
        let mut j = if self.is_complex() { 2 } else { 1 };

        let data = self.data.to_slice_mut();
        while j < data_length {
            data[j] = data[j] + data[i];
            i += 1;
            j += 1;
        }
    }
}