8ece9c3f439dc7eaf2e23f3962e816fec42e829a
6 // Filter [time-]series by replacing all values by the moving average of values
7 // centered around current one. Border values are averaged with available data.
9 // @param M_ A real matrix of size LxD
10 // @param w_ The (odd) number of values to average
12 // @return The filtered matrix, of same size as the input
13 SEXP
filterMA(SEXP M_
, SEXP w_
)
15 int L
= INTEGER(getAttrib(M_
, R_DimSymbol
))[0],
16 D
= INTEGER(getAttrib(M_
, R_DimSymbol
))[1],
17 w
= INTEGER_VALUE(w_
),
20 nt
; //number of terms in the current sum (max: w)
22 cs
, //current sum (max: w terms)
23 left
; //leftward term in the current moving sum
25 SEXP fM_
; //the filtered result
26 PROTECT(fM_
= allocMatrix(REALSXP
, L
, D
));
27 double* fM
= REAL(fM_
); //pointer to the encapsulated vector
29 // NOTE: unused loop parameter: shifting at the end of the loop is more efficient
30 for (int col
=D
-1; col
>=0; col
--)
36 for (i
=half_w
; i
>=0; i
--)
40 for (i
=0; i
<half_w
; i
++)
42 fM
[i
] = cs
/ nt
; //(partial) moving average at current index i
47 // Middle: now nt == w, i == half_w
48 for (; i
<L
-half_w
-1; i
++)
50 fM
[i
] = cs
/ w
; //moving average at current index i
51 cs
= cs
- left
+ M
[i
+half_w
+1]; //remove oldest items, add next
52 left
= M
[i
-half_w
+1]; //update first value for next iteration
55 // (Last "fully averaged" index +) Right border
58 fM
[i
] = cs
/ nt
; //(partial) moving average at current index i
63 // Shift by L == increment column index by 1 (storage per column)