diff -r 962c8e346ab9 -r 4e80fb049dca src/bisection_tree/aggregator.rs --- a/src/bisection_tree/aggregator.rs Sun Apr 27 15:45:40 2025 -0500 +++ b/src/bisection_tree/aggregator.rs Sun Apr 27 15:56:43 2025 -0500 @@ -2,8 +2,7 @@ Aggregation / summarisation of information in branches of bisection trees. */ -use crate::instance::Instance; -use crate::sets::Set; +pub use crate::bounds::Bounds; use crate::types::*; /// Trait for aggregating information about a branch of a [bisection tree][super::BT]. @@ -56,144 +55,6 @@ } } -/// Upper and lower bounds on an `F`-valued function. -#[derive(Copy, Clone, Debug)] -pub struct Bounds( - /// Lower bound - pub F, - /// Upper bound - pub F, -); - -impl Bounds { - /// Returns the lower bound - #[inline] - pub fn lower(&self) -> F { - self.0 - } - - /// Returns the upper bound - #[inline] - pub fn upper(&self) -> F { - self.1 - } -} - -impl Bounds { - /// Returns a uniform bound. - /// - /// This is maximum over the absolute values of the upper and lower bound. - #[inline] - pub fn uniform(&self) -> F { - let &Bounds(lower, upper) = self; - lower.abs().max(upper.abs()) - } - - /// Construct a bounds, making sure `lower` bound is less than `upper` - #[inline] - pub fn corrected(lower: F, upper: F) -> Self { - if lower <= upper { - Bounds(lower, upper) - } else { - Bounds(upper, lower) - } - } - - /// Refine the lower bound - #[inline] - pub fn refine_lower(&self, lower: F) -> Self { - let &Bounds(l, u) = self; - debug_assert!(l <= u); - Bounds(l.max(lower), u.max(lower)) - } - - /// Refine the lower bound - #[inline] - pub fn refine_upper(&self, upper: F) -> Self { - let &Bounds(l, u) = self; - debug_assert!(l <= u); - Bounds(l.min(upper), u.min(upper)) - } -} - -impl<'a, F: Float> std::ops::Add for Bounds { - type Output = Self; - #[inline] - fn add(self, Bounds(l2, u2): Self) -> Self::Output { - let Bounds(l1, u1) = self; - debug_assert!(l1 <= u1 && l2 <= u2); - Bounds(l1 + l2, u1 + u2) - } -} - -impl<'a, F: Float> std::ops::Mul for Bounds { - type Output = Self; - #[inline] - fn mul(self, Bounds(l2, u2): Self) -> Self::Output { - let Bounds(l1, u1) = self; - debug_assert!(l1 <= u1 && l2 <= u2); - let a = l1 * l2; - let b = u1 * u2; - // The order may flip when negative numbers are involved, so need min/max - Bounds(a.min(b), a.max(b)) - } -} - -impl std::iter::Product for Bounds { - #[inline] - fn product(mut iter: I) -> Self - where - I: Iterator, - { - match iter.next() { - None => Bounds(F::ZERO, F::ZERO), - Some(init) => iter.fold(init, |a, b| a * b), - } - } -} - -impl Set for Bounds { - fn contains>(&self, item: I) -> bool { - let v = item.own(); - let &Bounds(l, u) = self; - debug_assert!(l <= u); - l <= v && v <= u - } -} - -impl Bounds { - /// Calculate a common bound (glb, lub) for two bounds. - #[inline] - pub fn common(&self, &Bounds(l2, u2): &Self) -> Self { - let &Bounds(l1, u1) = self; - debug_assert!(l1 <= u1 && l2 <= u2); - Bounds(l1.min(l2), u1.max(u2)) - } - - /// Indicates whether `Self` is a superset of the argument bound. - #[inline] - pub fn superset(&self, &Bounds(l2, u2): &Self) -> bool { - let &Bounds(l1, u1) = self; - debug_assert!(l1 <= u1 && l2 <= u2); - l1 <= l2 && u2 <= u1 - } - - /// Returns the greatest bound contained by both argument bounds, if one exists. - #[inline] - pub fn glb(&self, &Bounds(l2, u2): &Self) -> Option { - let &Bounds(l1, u1) = self; - debug_assert!(l1 <= u1 && l2 <= u2); - let l = l1.max(l2); - let u = u1.min(u2); - debug_assert!(l <= u); - if l < u { - Some(Bounds(l, u)) - } else { - None - } - } -} - impl Aggregator for Bounds { #[inline] fn aggregate(&mut self, aggregates: I)