I tried hard to come up with a function template computing a sliding average. A sliding average over data \$x_1, x_2, \dots, x_n\$ with window length \$k \leq n\$ is a sequence \$y_1, y_2, \dots, y_{n - k + 1}\$, where $$y_i = \frac{1}{k}\sum_{j = 0}^{k - 1} x_{i + j}.$$
Here is my attempt:
mymath.h
#ifndef MYMATH_H
#define MYMATH_H
#include <iterator>
#include <sstream>
#include <stdexcept>
template<typename ForwardIterator, typename OutputIterator>
void sliding_average(ForwardIterator begin,
ForwardIterator end,
OutputIterator output,
size_t window_length)
{
if (window_length == 0)
{
std::stringstream ss;
ss << "Bad window_length: ";
ss << window_length;
throw std::runtime_error{ss.str()};
}
using T = typename std::iterator_traits<ForwardIterator>::value_type;
ForwardIterator finger = begin;
T sum {};
size_t count = 0;
while (finger != end and count < window_length)
{
sum += *finger++;
count++;
}
if (count < window_length)
{
std::stringstream ss;
ss << "The length of the range (";
ss << count;
ss << ") is too short. Must be at least ";
ss << window_length;
throw std::runtime_error{ss.str()};
}
*output++ = sum / window_length;
ForwardIterator window_tail = begin;
while (finger != end)
{
sum -= *window_tail++;
sum += *finger++;
*output++ = sum / window_length;
}
}
#endif // MYMATH_H
main.cpp
#include "mymath.h"
#include <iostream>
#include <iterator>
using std::cout;
using std::endl;
using std::begin;
using std::end;
int main(int argc, const char * argv[]) {
float input[15];
for (size_t i = 0; i < 15; ++i)
{
input[i] = i + 1;
}
float output[11];
sliding_average(begin(input), end(input), begin(output), 5);
for (auto& a : output)
{
cout << a << " ";
}
cout << endl;
return 0;
}
Critique request
I would like to receive comments regarding how to make my implementation more generic, and how to make it more idiomatic. Other comments are welcome as well.