The formula for getting the average of several numbers is of course well known:
And this formula can easily be used to get the average of chrono::duration
s:
template <class Rep0, class Period0>
auto
sum(const std::chrono::duration<Rep0, Period0>& d0)
{
return d0;
}
template <class Rep0, class Period0, class ...Rep, class ...Period>
auto
sum(const std::chrono::duration<Rep0, Period0>& d0,
const std::chrono::duration<Rep, Period>& ...d)
{
return d0 + sum(d...);
}
template <class ...Rep, class ...Period>
auto
avg(const std::chrono::duration<Rep, Period>& ...d)
{
return sum(d...) / static_cast<std::common_type_t<Rep...>>(sizeof...(d));
}
But chrono::time_point
s can't be added to one another. How can I average time_point
s?
It helps to start out with the assumption that you can add time_point
s, and then manipulate the formula to eliminate those additions:
First separate out t1 from the sum:
Next both add and subtract t1:
Factor and rearrange:
And then, since you are subtracting t1 the same number of times as you are summing, you can include that into the sum:
Now you are summing duration
s instead of time_point
s! As we already have a function to sum duration
s, averaging time_point
s can easily build on that:
template <class Clock, class Duration0, class ...Duration>
auto
avg(const std::chrono::time_point<Clock, Duration0>& t0,
const std::chrono::time_point<Clock, Duration>& ...t)
{
constexpr auto N =
static_cast<std::common_type_t<typename Duration0::rep,
typename Duration::rep...>>(1 + sizeof...(t));
return t0 + sum((t - t0)...) / N;
}
Averaging a single time_point
is a special case since sum
of duration
s does not handle summing zero duration
s (what would be the units?). So an overload for that case is easily added:
template <class Clock, class Duration0>
auto
avg(const std::chrono::time_point<Clock, Duration0>& t0)
{
return t0;
}
This is written in C++14. It can be coded in C++11, using the trailing return type declaration syntax, which is more verbose, but completely doable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With