152{
154
161 }
162
164
165 std::vector<double> chronological(view.rbegin(), view.rend());
166 std::span<const double> ordered(chronological);
167
171
172 const double mean = std::accumulate(chronological.begin(), chronological.end(), 0.0) /
static_cast<double>(chronological.size());
174
175 const auto n = static_cast<double>(chronological.size());
176 double sum_x = 0.0;
177 for (size_t i = 0; i < chronological.size(); ++i)
178 sum_x += static_cast<double>(i);
179 const double mean_x = sum_x / n;
180 const double intercept =
mean - slope * mean_x;
181 const auto newest_x = static_cast<double>(chronological.size() - 1);
183
184 const double first = chronological.front();
185 const double last = chronological.back();
186 const auto span_n = static_cast<double>(chronological.size() - 1);
187
188 double residual_sq_sum = 0.0;
189 for (size_t i = 0; i < chronological.size(); ++i) {
190 const double t = static_cast<double>(i) / span_n;
191 const double trend_value = first + t * (last - first);
192 const double residual = chronological[i] - trend_value;
193 residual_sq_sum += residual * residual;
194 }
195
196 const double residual_var = (chronological.size() > 2)
197 ? residual_sq_sum / static_cast<double>(chronological.size() - 2)
198 : 0.0;
199
202
204}
static double trend_slope(std::span< const double > samples) noexcept
Linear trend slope across a span.
static double trend_explained_ratio(std::span< const double > samples) noexcept
Fraction of a span's variance attributable to its linear trend.
Memory::HistoryBuffer< double > m_history
std::span< T > linearized_view()
Get mutable linearized view of entire history.
void push(const T &value)
Push new value to front of history.
double mean(const std::vector< double > &data)
Calculate mean of single-channel data.
double trend_explained_ratio