Files
plotter/src/plot/measure.cpp
T
Martino Ferrari ed3a8ce645 licence: MIT LICENSE and SPDX identifiers in every first-party file
The repository had no licence at all, so every source was all-rights-reserved
by default. Add the verbatim MIT text at LICENSE (Copyright (c) 2026 Martino
Ferrari) and a two-line SPDX header to each of the 113 first-party sources --
48 include/plot, 26 src, 10 adapters, 5 examples, 21 tests, 3 tools -- so the
grant travels with each file rather than relying on the root document alone.

Scripts keep their shebang on line 1; the SPDX lines follow it. Genuinely
vendored code is untouched: third_party/stb_truetype.h carries no header of
ours. src/render/embedded_mono_font.cpp is generated, so tools/fonts/gen_atlas.py
emit() now writes the two lines into its header comment and the file was
regenerated -- gen_atlas.py --check passes and the regeneration adds only those
comment lines to the previously committed file.

README's provenance section now states MIT and links LICENSE.

No code, test or public API change.
2026-09-28 22:13:40 +02:00

47 lines
1.6 KiB
C++

// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: 2026 Martino Ferrari
#include <plot/plot/measure.hpp>
#include <cmath>
namespace plot {
Measurement Measure::evaluate(const data::Series& s, u64 begin, u64 end) {
Measurement m;
// Both guards run before any query, so an empty, inverted or out-of-range
// interval returns an invalid result without touching the series.
if (end <= begin || end > s.size()) return m;
// Exact extremes and sums come from Series -- never from the pyramid's
// *_buckets forms, which answer in whole buckets only and would drop up to two
// partial edge buckets, silently returning wrong extrema and sums for any
// interval that is not bucket-aligned. Each query here is O(kBucket) worst
// case, so a measurement never scales with series length.
const Range extremes = s.reduce(begin, end);
const f64 total = s.sum(begin, end);
const f64 squared = s.sumsq(begin, end);
const f64 n = static_cast<f64>(end - begin);
const f64 step = s.dx();
m.ymin = extremes.min;
m.ymax = extremes.max;
m.mean = total / n;
m.rms = std::sqrt(squared / n);
m.integral = total * step; // left-Riemann sum: see the note in measure.hpp
if (end - begin >= 2) {
// First and last sample of the interval: a single-sample query reduces to
// that sample's value, and costs the same O(kBucket) as any other.
const f64 first = s.reduce(begin, begin + 1).min;
const f64 last = s.reduce(end - 1, end).min;
m.dy = last - first;
m.dx = static_cast<f64>(end - 1 - begin) * step;
m.slope = m.dx != 0.0 ? m.dy / m.dx : 0.0;
}
m.valid = true;
return m;
}
} // namespace plot