= Moving Sum

include::../common.adoc[]

== Overview

The moving sum involves adding a specified number of values in a sequence of data points —the moving sum window. The window moves through the data one point at a time as new samples arrive, and at each step, the sum of the data points within the window is calculated. Instead of calculating the sum of all elements in the window each time, an efficient scheme keeps a continuous total and subtracts the last element that will fall off the window when a new sample arrives.

image::moving-sum.svg[alt="Moving Sum", width=500px, align=center, title="Moving Sum"]

When data is pushed into a moving sum, the element indices are shifted by one position to accommodate the incoming data. This logical shifting ensures that the newest data is stored in the first index (index 0), while the oldest data is pushed out of the buffer. The physical location of data does not actually change, only the indices.

`basic_moving_sum` is a template class representing moving sums with provision for specifying the element type, `T`. Integers are typically faster than floating point and are not prone to round-off errors. It is implemented internally using a ring buffer. Refer to {ring_buffer}.

== Include

```c++
#include <q/fx/moving_sum.hpp>
```

== Declaration

```c++
template <typename T>
struct basic_moving_sum
{
   using value_type = T;

                  basic_moving_sum(std::size_t max_size);
                  basic_moving_sum(duration d, float sps);

   value_type     operator()(value_type s);
   value_type     operator()() const;

   value_type     sum() const;
   std::size_t    size() const;
   void           resize(std::size_t size, bool update = false);
   void           resize(duration d, float sps, bool update = false);
   void           clear();
   void           fill(T val);
};

using moving_sum = basic_moving_sum<float>;
```

== Expressions

=== Notation

`T`                  :: Element type, e.g. `float`.
`ms_type`            :: A `basic_moving_sum<T>` type.
`ms`, `a`, `b`       :: Objects of type `basic_moving_sum<T>`.
`s`, `val`           :: Objects of type `ms_type::value_type`.
`size`               :: Object of type `std::size_t`.
`d`                  :: Object of type `duration`.
`sps`                :: Floating point value representing samples per second.
`a [, b, c, d]`      :: Required `a`, optional `b, c, d`.

=== Type Construction

[cols="1,1"]
|===
| Expression            | Semantics

| `basic_moving_sum<T>` | Instantiate a `basic_moving_sum` type given `T`,
                          the element type, e.g. `float`.
| `moving_sum`          | Pre declared `basic_moving_sum<float>` type.

|===

=== Type Accessors

[cols="1,1"]
|===
| Expression                     | Semantics

| `ms_type::value_type`          | Get the underlying element type.
|===


=== Constructors and Assignment

[cols="1,1"]
|===
| Expression                  | Semantics

| `ms_type(size)`             | Construct a `basic_moving_sum` with specified window
                                `size` in samples.
| `ms_type(d, sps)`           | Construct a `basic_moving_sum` with window size
                                specified by `d` and `sps` (`duration` and sample rate).
| `ms_type(ms)`               | Copy construct from `ms_type ms`.
| `a = b`                     | Assign `b` to `a`.
|===

NOTE: C++ brace initialization may also be used.

=== Function Call

[cols="1,1,1"]
|===
| Expression      | Semantics                                  | Return Type

| `ms()`          | Return the current sum.                    | `ms_type::value_type`
| `ms(s)`         | Add a new sample and calculate the
                    current sum.                               | `ms_type::value_type`
|===

=== Accessors

[cols="1,1,1"]
|===
| Expression         | Semantics                            | Return Type

| `ms.sum()`         | Return the current sum.              | `ms_type::value_type`
| `ms.size()`        | Return the window size (in samples). | `std::size_t`
|===

=== Mutators

[cols="1,1"]
|===
| Expression                     | Semantics

| `ms.resize(size [, update])`   | Resize the moving sum window to the number
                                   of samples specified by the 'size' parameter.
                                   If `update=true`, the sum is recalculated.
                                   if `update=false`, the contents are cleared.
                                   Default: `update=false`.
| `ms.resize(d, sps [, update])` | Resize the moving sum with window size
                                   specified by `d` and `sps` (`duration` and sample rate).
                                   If `update=true`, the sum is recalculated.
                                   if `update=false`, the contents are cleared.
                                   Default: `update=false`.
| `ms.clear()`                   | Clear the moving window to zero.
| `ms.fill(val)`                 | Fill the moving window with `val`, and update
                                   the sum accordingly.
|===

NOTE: `basic_moving_sum` can be resized as long as the new size does not exceed the original size (at construction time). When resizing with `update=true`, when downsizing, the oldest elements are subtracted from the sum. When upsizing, the older elements are added to the sum, otherwise, if `update=false`, the contents are cleared.

