46 std::span<const double>
a, std::span<const double>
b)
noexcept
48 if (
a.size() !=
b.size() ||
a.size() < 2)
51 const size_t n =
a.size();
54 for (
size_t i = 0; i < n; ++i) {
58 mean_a /=
static_cast<double>(n);
59 mean_b /=
static_cast<double>(n);
64 for (
size_t i = 0; i < n; ++i) {
65 const double da =
a[i] - mean_a;
66 const double db =
b[i] - mean_b;
72 const double denom = std::sqrt(var_a * var_b);
76 return std::clamp(cov / denom, -1.0, 1.0);
112 std::span<const double>
a, std::span<const double>
b,
long lag)
noexcept
114 const auto na =
static_cast<long>(
a.size());
115 const auto nb =
static_cast<long>(
b.size());
117 const long start_a = std::max(0L, -lag);
118 const long start_b = std::max(0L, lag);
119 const long overlap = std::min(na - start_a, nb - start_b);
125 a.subspan(
static_cast<size_t>(start_a),
static_cast<size_t>(overlap)),
126 b.subspan(
static_cast<size_t>(start_b),
static_cast<size_t>(overlap)));
156 std::span<const double>
a, std::span<const double>
b,
long max_lag)
noexcept
159 for (
long lag = -max_lag; lag <= max_lag; ++lag) {
161 if (std::abs(r) > std::abs(best.
strength)) {
193 std::span<const double>
a, std::span<const double>
b,
double dt)
noexcept
195 const size_t n =
a.size();
196 if (n !=
b.size() || n < 2 || dt <= 0.0)
199 std::vector<double> separation(n);
200 for (
size_t i = 0; i < n; ++i)
201 separation[i] = std::abs(
a[i] -
b[i]);
228 std::span<
const std::span<const double>> streams)
noexcept
230 const size_t n = streams.size();
236 for (
size_t i = 0; i < n; ++i) {
237 for (
size_t j = i + 1; j < n; ++j) {
243 return (pairs > 0) ? (acc /
static_cast<double>(pairs)) : 0.0;
static double trend_slope(std::span< const double > samples) noexcept
Linear trend slope across a span.
double relation_at_lag(std::span< const double > a, std::span< const double > b, long lag) noexcept
Correlation between two spans at a single fixed lag.
double correlation(std::span< const double > a, std::span< const double > b) noexcept
Pearson correlation between two equal-length windows.
LagRelation relation_lag(std::span< const double > a, std::span< const double > b, long max_lag) noexcept
Search a bounded lag range for the offset at which two streams correlate most strongly.
double coherence(std::span< const std::span< const double > > streams) noexcept
How tightly a set of streams move together.
double approach_rate(std::span< const double > a, std::span< const double > b, double dt) noexcept
Rate at which two streams approach or separate.
double strength
Correlation at that lag, in -1..1. Near zero means no relation.
long lag
Samples b is offset from a; positive means b lags a.
A candidate offset between two streams and how strongly the windows support it.