Skip to main content

axiolid_curve_evaluate_contract/
interval.rs

1//! A certified enclosure of a distance (#294).
2
3use axiolid_core::Scalar;
4
5/// A distance certified to lie in `[lower, upper]`: what
6/// [`CurveEvaluator::path_joint_distances`](crate::CurveEvaluator::path_joint_distances)
7/// returns for each joint of a curve path.
8///
9/// The bounds are a proof, not an estimate: the true value lies between
10/// them. A distance read from stored data alone (a line's, a circle's, a
11/// sum of stored lengths) is a point interval, `lower == upper`.
12#[non_exhaustive]
13#[derive(Debug, Clone, Copy, PartialEq)]
14pub struct DistanceInterval {
15    /// The largest value the distance is certified not to be below.
16    pub lower: Scalar,
17    /// The smallest value the distance is certified not to exceed.
18    pub upper: Scalar,
19}
20
21impl DistanceInterval {
22    /// The interval `[lower, upper]`. Nothing is checked here; a provider
23    /// returns `lower <= upper`, both finite.
24    #[must_use]
25    pub const fn new(lower: Scalar, upper: Scalar) -> Self {
26        Self { lower, upper }
27    }
28
29    /// The point interval `[value, value]`: a distance known exactly.
30    #[must_use]
31    pub const fn point(value: Scalar) -> Self {
32        Self::new(value, value)
33    }
34
35    /// `upper - lower`.
36    #[must_use]
37    pub fn width(&self) -> Scalar {
38        self.upper - self.lower
39    }
40
41    /// The midpoint, `(lower + upper) / 2`.
42    #[must_use]
43    pub fn midpoint(&self) -> Scalar {
44        0.5 * (self.lower + self.upper)
45    }
46
47    /// Whether `value` lies in `[lower, upper]`.
48    #[must_use]
49    pub fn contains(&self, value: Scalar) -> bool {
50        self.lower <= value && value <= self.upper
51    }
52
53    /// Whether the two intervals share a point, their ends included:
54    /// whether a distance certified to `self` can lie in `other` (#305).
55    #[must_use]
56    pub fn meets(&self, other: &Self) -> bool {
57        self.lower <= other.upper && other.lower <= self.upper
58    }
59
60    /// Whether it is a point interval.
61    #[must_use]
62    pub fn is_point(&self) -> bool {
63        self.lower == self.upper
64    }
65}