You can implement the moving average by iterating over each element of the input array, slicing that array over a subrange determined by the input window parameter, and applying the general average function to that slice, as shown in the following listing.
Listing 5.19 Calculating moving average of a real array x over window w
pure function moving_average(x, w) result(res)
real, intent(in) :: x(:)
integer, intent(in) :: w
real :: res(size(x)) ❶
integer :: i, i1
do i = 1, size(x) ❷
i1 = max(i-w, 1) ❸
res(i) = average(x(i1:i)) ❹
end do
end function moving_average
❸ Start and end indices, limited to not exceed bounds of x
❹ Computes the average over the subrange
Notice that inside the loop, I use the built-in functions min and max to limit the subrange from exceeding the bounds of the array x. For a standard deviation function over an equivalent window, we’d just replace average(x(i1:i)) with std(x(i1:i)). You can find these functions in src/mod_arrays.f 90.