diff --git a/include/plot/data/minmax_pyramid.hpp b/include/plot/data/minmax_pyramid.hpp index d632b20..6b65439 100644 --- a/include/plot/data/minmax_pyramid.hpp +++ b/include/plot/data/minmax_pyramid.hpp @@ -28,9 +28,6 @@ inline constexpr u32 kBucket = 64; /// buckets; a range with partial edge buckets would silently pull in samples /// outside the range. Every query here is therefore bucket-grained and named /// *_buckets, and exact range queries live on Series, which owns the raw samples. -/// reduce() is the one non-*_buckets query: it is the *covering* aggregate over -/// the level-0 buckets that [begin, end) touches. Use it to ask which buckets a -/// range spans, never to measure a range. class MinMaxPyramid { public: MinMaxPyramid() { add_level(); } @@ -55,11 +52,6 @@ class MinMaxPyramid { f64 sum_buckets(u64 begin, u64 end) const; /// Sum of squares of the samples in those same whole buckets. f64 sumsq_buckets(u64 begin, u64 end) const; - - /// Min/max over the covering level-0 buckets: every bucket that holds a sample - /// of [begin, end). Exact only when the range is bucket-aligned. - Range reduce(u64 begin, u64 end) const; - /// Pyramid level whose buckets hold about `samples_per_pixel` samples, for a /// window of `n` samples: 0 when a pixel covers at most one bucket. Clamped to /// the levels that exist, to levels with more than one bucket, and to levels diff --git a/src/data/minmax_pyramid.cpp b/src/data/minmax_pyramid.cpp index 0e9d6ce..573e13e 100644 --- a/src/data/minmax_pyramid.cpp +++ b/src/data/minmax_pyramid.cpp @@ -221,15 +221,6 @@ f64 MinMaxPyramid::sumsq_buckets(u64 begin, u64 end) const { return total; } -Range MinMaxPyramid::reduce(u64 begin, u64 end) const { - const u64 e = std::min(end, size_); - const u64 b = std::min(begin, e); - if (e <= b) return Range{0.0, 0.0}; - const u64 b0 = b / kBucket; // first bucket holding a sample - const u64 b1 = (e - 1) / kBucket + 1; // one past the last one - return fold_range(*this, b0, b1); -} - u32 MinMaxPyramid::level_for(u64 n, f64 samples_per_pixel) const { // The ratio test also rejects NaN, and the clamp keeps a huge (or infinite) // samples-per-pixel from making the floor-to-u32 conversion ill-formed. diff --git a/tests/test_minmax_pyramid.cpp b/tests/test_minmax_pyramid.cpp index 605081e..46a3af1 100644 --- a/tests/test_minmax_pyramid.cpp +++ b/tests/test_minmax_pyramid.cpp @@ -103,7 +103,13 @@ PLOT_TEST(pyramid_clear_and_rebuild) { PLOT_CHECK(p.level_count() <= 1); p.append(7.0f); PLOT_CHECK(p.size() == 1); - PLOT_CHECK_NEAR(p.reduce(0, 1).max, 7.0, 1e-6); + // A pyramid can only answer exactly for whole buckets, so complete the first + // bucket and ask the bucket-grained query for its extrema. + for (u32 i = 1; i < kBucket; ++i) p.append(1.0f); + PLOT_CHECK(p.size() == kBucket); + PLOT_CHECK(p.level(0).size() == 1); + PLOT_CHECK_NEAR(p.reduce_buckets(0, kBucket).max, 7.0, 1e-6); + PLOT_CHECK_NEAR(p.reduce_buckets(0, kBucket).min, 1.0, 1e-6); } PLOT_TEST(pyramid_cover_cost_is_logarithmic_for_unaligned_starts) { diff --git a/tests/test_series.cpp b/tests/test_series.cpp index 1b15a29..abfc519 100644 --- a/tests/test_series.cpp +++ b/tests/test_series.cpp @@ -29,7 +29,7 @@ PLOT_TEST(stream_series_acquire_publishes_snapshot) { s.acquire(); PLOT_CHECK(s.size() == 100); // Pyramid must track the published samples. - PLOT_CHECK_NEAR(s.pyramid().reduce(0, 100).max, 99.0, 1e-4); + PLOT_CHECK_NEAR(s.reduce(0, 100).max, 99.0, 1e-4); for (int i = 100; i < 250; ++i) s.push(f32(i)); s.acquire(); PLOT_CHECK(s.size() == 250);