Mon, 01 Sep 2025 20:55:34 -0500
lots of space changes
/*! Aggregation / summarisation of information in branches of bisection trees. */ pub use crate::bounds::Bounds; use crate::types::*; /// Trait for aggregating information about a branch of a [bisection tree][super::BT]. /// /// Currently [`Bounds`] is the only provided aggregator. /// It keeps track of upper and lower bounds of a function representeed by the `BT` by /// summing [`Bounds`] produced by [`LocalAnalysis`][super::support::LocalAnalysis] of the /// [`Support`][super::support::Support]s of the data stored in the tree. /// For the `Bounds` aggregator: /// * [`Self::aggregate`] sums input bounds to the current bound. This provides a conservative /// estimate of the upper and lower bounds of a sum of functions. /// * [`Self::summarise`] takes the maximum of the input bounds. This calculates the bounds /// of a function on a greater domain from bounds on subdomains /// (in practise [`Cube`][crate::sets::Cube]s). /// pub trait Aggregator: Clone + Sync + Send + 'static + std::fmt::Debug { /// Aggregate a new data to current state. fn aggregate<I>(&mut self, aggregates: I) where I: Iterator<Item = Self>; /// Summarise several other aggregators, resetting current state. fn summarise<'a, I>(&'a mut self, aggregates: I) where I: Iterator<Item = &'a Self>; /// Create a new “empty” aggregate data. fn new() -> Self; } /// An [`Aggregator`] that doesn't aggregate anything. #[derive(Clone, Debug)] pub struct NullAggregator; impl Aggregator for NullAggregator { fn aggregate<I>(&mut self, _aggregates: I) where I: Iterator<Item = Self>, { } fn summarise<'a, I>(&'a mut self, _aggregates: I) where I: Iterator<Item = &'a Self>, { } fn new() -> Self { NullAggregator } } impl<F: Float> Aggregator for Bounds<F> { #[inline] fn aggregate<I>(&mut self, aggregates: I) where I: Iterator<Item = Self>, { *self = aggregates.fold(*self, |a, b| a + b); } #[inline] fn summarise<'a, I>(&'a mut self, mut aggregates: I) where I: Iterator<Item = &'a Self>, { *self = match aggregates.next() { None => Bounds(F::ZERO, F::ZERO), // No parts in this cube; the function is zero Some(&bounds) => aggregates.fold(bounds, |a, b| a.common(b)), } } #[inline] fn new() -> Self { Bounds(F::ZERO, F::ZERO) } }