normalize_interval/
raw_interval.rs

1// Copyright 2024 Skylor R. Schermer.
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8////////////////////////////////////////////////////////////////////////////////
9//! Non-normalizing interval type.
10////////////////////////////////////////////////////////////////////////////////
11
12// Internal library imports.
13use crate::bound::Bound;
14
15// External library imports.
16#[cfg(feature="serde")] use serde::Deserialize;
17#[cfg(feature="serde")] use serde::Serialize;
18use few::Few;
19
20// Standard library imports.
21use std::cmp::Ordering;
22use std::str::FromStr;
23
24
25////////////////////////////////////////////////////////////////////////////////
26// RawInterval<T>
27////////////////////////////////////////////////////////////////////////////////
28/// A contiguous interval of the type T. Used to implement the internal state of
29/// `Interval`.
30/// 
31/// [`Interval`]: interval/struct.Interval.html
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
33#[cfg_attr(feature="serde", derive(Deserialize, Serialize))]
34pub enum RawInterval<T> {
35    /// An interval containing no points.
36    Empty,
37    /// An interval containing only the given point.
38    Point(T),
39    /// An interval containing all points between two given points, excluding
40    /// them both.
41    Open(T, T),
42    /// An interval containing all points between two given points, including
43    /// the greater of the two.
44    LeftOpen(T, T),
45    /// An interval containing all points between two given points, including
46    /// the lesser of the two.
47    RightOpen(T, T),
48    /// An interval containing all points between two given points, including
49    /// them both.
50    Closed(T, T),
51    /// An interval containing all points less than the given point.
52    UpTo(T),
53    /// An interval containing all points greater than the given point.
54    UpFrom(T),
55    /// An interval containing the given point and all points less than it.
56    To(T),
57    /// An interval containing the given point and all points greater than it.
58    From(T),
59    /// An interval containing all points.
60    Full,
61}
62
63impl<T> RawInterval<T> {
64    // Queries
65    ////////////////////////////////////////////////////////////////////////////
66
67    /// Returns `true` if the interval is [`Empty`].
68    ///
69    /// [`Empty`]: #variant.Empty
70    pub fn is_empty(&self) -> bool {
71        matches!(self, Self::Empty)
72    }
73
74    /// Returns `true` if the interval is [`Full`].
75    ///
76    /// [`Full`]: #variant.Full
77    pub fn is_full(&self) -> bool {
78        matches!(self, Self::Full)
79    }
80
81    /// Writes the `RawInterval` to the given [`Formatter`] using a specified
82    /// function to write the interval's boundary points.
83    ///
84    /// [`Formatter`]: std::fmt::Formatter
85    pub fn write_fmt_with<F>(&self,
86        f: &mut std::fmt::Formatter<'_>,
87        write_fn: F)
88        -> Result<(), std::fmt::Error> 
89        where F: Fn(&T, &mut std::fmt::Formatter<'_>) 
90            -> Result<(), std::fmt::Error> 
91    {
92        use RawInterval::*;
93        match *self {
94            Empty => write!(f, "Ø"),
95            Point(ref p) => write_fn(p, f),
96            Open(ref l, ref r) => {
97                write!(f, "(")?;
98                write_fn(l, f)?;
99                write!(f, ",")?;
100                write_fn(r, f)?;
101                write!(f, ")")
102            },
103            LeftOpen(ref l, ref r) => {
104                write!(f, "(")?;
105                write_fn(l, f)?;
106                write!(f, ",")?;
107                write_fn(r, f)?;
108                write!(f, "]")
109            },
110            RightOpen(ref l, ref r) => {
111                write!(f, "[")?;
112                write_fn(l, f)?;
113                write!(f, ",")?;
114                write_fn(r, f)?;
115                write!(f, ")")
116            },
117            Closed(ref l, ref r) => {
118                write!(f, "[")?;
119                write_fn(l, f)?;
120                write!(f, ",")?;
121                write_fn(r, f)?;
122                write!(f, "]")
123            },
124            UpTo(ref p) => {
125                write!(f, "(-∞,")?;
126                write_fn(p, f)?;
127                write!(f, ")")
128            },
129            UpFrom(ref p) => {
130                write!(f, "(")?;
131                write_fn(p, f)?;
132                write!(f, ",∞)")
133            },
134            To(ref p) => {
135                write!(f, "(-∞,")?;
136                write_fn(p, f)?;
137                write!(f, "]")
138            },
139            From(ref p) => {
140                write!(f, "[")?;
141                write_fn(p, f)?;
142                write!(f, ",∞)")
143            },
144            Full => write!(f, "(-∞,∞)"),
145        }
146    }
147}
148
149impl<T> RawInterval<T> where T: Ord {
150    // Constructors
151    ////////////////////////////////////////////////////////////////////////////
152    
153    /// Constructs a new interval from the given [`Bound`]s. If the right bound
154    /// point is less than the left bound point, an [`Empty`] interval will be 
155    /// returned.
156    /// 
157    /// [`Bound`]: bound/enum.Bound.html
158    /// [`Empty`]: #variant.Empty
159    pub fn new(lower: Bound<T>, upper: Bound<T>) -> Self {
160        use Bound::*;
161        use RawInterval::*;
162        match (lower, upper) {
163            (Include(l), Include(u)) => Self::closed(l, u),
164            (Include(l), Exclude(u)) => Self::right_open(l, u),
165            (Include(l), Infinite)   => From(l),
166            (Exclude(l), Include(u)) => Self::left_open(l, u),
167            (Exclude(l), Exclude(u)) => Self::open(l, u),
168            (Exclude(l), Infinite)   => UpFrom(l),
169            (Infinite,   Include(u)) => To(u),
170            (Infinite,   Exclude(u)) => UpTo(u),
171            (Infinite,   Infinite)   => Full,
172        }
173    }
174
175    /// Constructs a new [`Open`] interval from the given points. If the upper
176    /// point is less than the lower point, an [`Empty`] `RawInterval` will be
177    /// returned.
178    ///
179    /// [`Open`]: #variant.Open
180    /// [`Empty`]: #variant.Empty
181    pub fn open(lower: T, upper: T) -> Self {
182        use RawInterval::*;
183        match T::cmp(&lower, &upper) {
184            Ordering::Less => Open(lower, upper),
185            _              => Empty,
186        }
187    }
188    
189    /// Constructs a new [`LeftOpen`] interval from the given points. If the
190    /// upper bound point is less than the lower bound point, an [`Empty`]
191    /// `RawInterval` will be returned.
192    ///
193    /// [`LeftOpen`]: #variant.LeftOpen
194    /// [`Empty`]: #variant.Empty
195    pub fn left_open(lower: T, upper: T) -> Self {
196        use RawInterval::*;
197        match T::cmp(&lower, &upper) {
198            Ordering::Less    => LeftOpen(lower, upper),
199            Ordering::Equal   => Point(upper),
200            Ordering::Greater => Empty,
201        }
202    }
203    
204    /// Constructs a new [`RightOpen`] interval from the given points. If the
205    /// upper bound point is less than the lower bound point, an [`Empty`]
206    /// `RawInterval` will be returned.
207    ///
208    /// [`RightOpen`]: #variant.RightOpen
209    /// [`Empty`]: #variant.Empty
210    pub fn right_open(lower: T, upper: T) -> Self {
211        use RawInterval::*;
212        match T::cmp(&lower, &upper) {
213            Ordering::Less    => RightOpen(lower, upper),
214            Ordering::Equal   => Point(lower),
215            Ordering::Greater => Empty,
216        }
217    }
218    
219    /// Constructs a new [`Closed`] interval from the given points. If the
220    /// upper bound point is less than the lower bound point, an [`Empty`]
221    /// `RawInterval` will be returned.
222    ///
223    /// [`Closed`]: #variant.Closed
224    /// [`Empty`]: #variant.Empty
225    pub fn closed(lower: T, upper: T) -> Self {
226        use RawInterval::*;
227        match T::cmp(&lower, &upper) {
228            Ordering::Less    => Closed(lower, upper),
229            Ordering::Equal   => Point(lower),
230            Ordering::Greater => Empty,
231        }
232    }
233
234    // Queries
235    ////////////////////////////////////////////////////////////////////////////
236
237    /// Returns `true` if the interval contains the given point.
238    pub fn contains(&self, point: &T) -> bool {
239        use RawInterval::*;
240        match *self {
241            Empty                   => false,
242            Point(ref p)            => point == p,
243            Open(ref l, ref r)      => point > l && point < r,
244            LeftOpen(ref l, ref r)  => point > l && point <= r,
245            RightOpen(ref l, ref r) => point >= l && point < r,
246            Closed(ref l, ref r)    => point >= l && point <= r,
247            UpTo(ref p)             => point < p,
248            UpFrom(ref p)           => point > p,
249            To(ref p)               => point <= p,
250            From(ref p)             => point >= p,
251            Full                    => true,
252        }
253    }
254
255    /// Parses a `RawInterval` from a string using the specified function to
256    /// parse the interval's boundary points.
257    pub fn from_str_with<F, E>(s: &str, read_fn: F)
258        -> Result<Self, IntervalParseError<E>>
259        where F: Fn(&str) -> Result<T, E> 
260    {
261        use RawInterval::*;
262        // Parse empty interval.
263        if s.starts_with("Ø") { return Ok(Empty); }
264        // Parse point interval.
265        if let Ok(p) = read_fn(s) { return Ok(Point(p)); }
266
267        let (x, y) = s.split_once(',')
268            .ok_or(IntervalParseError::InvalidInterval)?;
269
270        let lb = if x.starts_with("(-∞") { 
271            Bound::Infinite
272        } else if let Some(res) = x.strip_prefix('(') {
273            Bound::Exclude(read_fn(res)
274                .map_err(|e| IntervalParseError::InvalidValue(e))?)
275        } else if let Some(res) = x.strip_prefix('[') {
276            Bound::Include(read_fn(res)
277                .map_err(|e| IntervalParseError::InvalidValue(e))?)
278        } else {
279            return Err(IntervalParseError::InvalidInterval);
280        };
281
282        let ub = if y.ends_with("∞)") { 
283            Bound::Infinite
284        } else if y.ends_with(')') {
285            let end = y.len() - 1;
286            Bound::Exclude(read_fn(&y[..end])
287                .map_err(|e| IntervalParseError::InvalidValue(e))?)
288        } else if y.ends_with(']') {
289            let end = y.len() - 1;
290            Bound::Include(read_fn(&y[..end])
291                .map_err(|e| IntervalParseError::InvalidValue(e))?)
292        } else {
293            return Err(IntervalParseError::InvalidInterval);
294        };
295
296        Ok(Self::new(lb, ub))
297    }
298}
299
300impl<T> RawInterval<T> where T: Clone {
301    // Bound accessors
302    ////////////////////////////////////////////////////////////////////////////
303
304    /// Returns the lower and upper bound of the interval, or `None` if the
305    /// interval is empty.
306    pub fn bounds(&self) -> Option<(Bound<T>, Bound<T>)> {
307        use Bound::*;
308        use RawInterval::*;
309        Some(match *self {
310            Empty                   => return None,
311            Point(ref p)            => (Include(p.clone()), Include(p.clone())),
312            Open(ref l, ref r)      => (Exclude(l.clone()), Exclude(r.clone())),
313            LeftOpen(ref l, ref r)  => (Exclude(l.clone()), Include(r.clone())),
314            RightOpen(ref l, ref r) => (Include(l.clone()), Exclude(r.clone())),
315            Closed(ref l, ref r)    => (Include(l.clone()), Include(r.clone())),
316            UpTo(ref p)             => (Infinite, Exclude(p.clone())),
317            UpFrom(ref p)           => (Exclude(p.clone()), Infinite),
318            To(ref p)               => (Infinite, Include(p.clone())),
319            From(ref p)             => (Include(p.clone()), Infinite),
320            Full                    => (Infinite, Infinite),
321        })
322    }
323
324    /// Returns the lower bound of the interval, or `None` if the interval is
325    /// empty.
326    pub fn lower_bound(&self) -> Option<Bound<T>> {
327        use Bound::*;
328        use RawInterval::*;
329        Some(match *self {
330            Empty               => return None,
331            Point(ref p)        => Include(p.clone()),
332            Open(ref l, _)      => Exclude(l.clone()),
333            LeftOpen(ref l, _)  => Exclude(l.clone()),
334            RightOpen(ref l, _) => Include(l.clone()),
335            Closed(ref l, _)    => Include(l.clone()),
336            UpTo(_)             => Infinite,
337            UpFrom(ref p)       => Exclude(p.clone()),
338            To(_)               => Infinite,
339            From(ref p)         => Include(p.clone()),
340            Full                => Infinite,
341        })
342    }
343    
344    /// Returns the upper bound of the interval, or `None` if the interval is
345    /// empty.
346    pub fn upper_bound(&self) -> Option<Bound<T>> {
347        use Bound::*;
348        use RawInterval::*;
349        Some(match *self {
350            Empty               => return None,
351            Point(ref p)        => Include(p.clone()),
352            Open(_, ref r)      => Exclude(r.clone()),
353            LeftOpen(_, ref r)  => Include(r.clone()),
354            RightOpen(_, ref r) => Exclude(r.clone()),
355            Closed(_, ref r)    => Include(r.clone()),
356            UpTo(ref p)         => Exclude(p.clone()),
357            UpFrom(_)           => Infinite,
358            To(ref p)           => Include(p.clone()),
359            From(_)             => Infinite,
360            Full                => Infinite,
361        })
362    }
363
364    /// Returns the greatest lower bound of the interval, if it exists.
365    pub fn infimum(&self) -> Option<T> {
366        use Bound::*;
367        match self.lower_bound() {
368            Some(Include(ref b)) => Some(b.clone()),
369            Some(Exclude(ref b)) => Some(b.clone()),
370            _ => None,
371        }
372    }
373    
374    /// Returns the least upper bound of the interval, if it exists.
375    pub fn supremum(&self) -> Option<T> {
376        use Bound::*;
377        match self.upper_bound() {
378            Some(Include(ref b)) => Some(b.clone()),
379            Some(Exclude(ref b)) => Some(b.clone()),
380            _ => None,
381        }
382    }
383
384    /// Returns the greatest lower bound and least upper bound of the interval,
385    /// if they both exist.
386    pub fn extrema(&self) -> Option<(T, T)> {
387        match (self.infimum(), self.supremum()) {
388            (Some(l), Some(u)) => Some((l, u)),
389            _ => None,
390        }
391    }
392}
393
394impl<T> RawInterval<T> where T: Clone + std::ops::Sub<T> {
395    /// Returns the width of the interval, if it is bounded.
396    pub fn width(&self) -> Option<T::Output> {
397        self.extrema().map(|(l, r)| r - l)
398    }
399}
400
401impl<T> RawInterval<T> where T: Ord + Clone {
402    // Set comparisons
403    ////////////////////////////////////////////////////////////////////////////
404    
405    /// Returns `true` if the interval overlaps the given interval.
406    pub fn intersects(&self, other: &Self) -> bool {
407        !self.intersect(other).is_empty()
408    }
409
410    /// Returns `true` if the given intervals share any boundary points.
411    pub fn is_adjacent_to(&self, other: &Self) -> bool {
412        let a = match (self.lower_bound(), other.upper_bound()) {
413            (Some(lb), Some(ub)) => lb.is_union_adjacent_to(&ub),
414            _ => false,
415
416        };
417        let b = match (self.upper_bound(), other.lower_bound()) {
418            (Some(ub), Some(lb)) => lb.is_union_adjacent_to(&ub),
419            _ => false,
420        };
421        a || b
422    }
423
424    // Set operations
425    ////////////////////////////////////////////////////////////////////////////
426
427    /// Returns a `Vec` of `RawInterval`s containing all of the points not in
428    /// the interval.
429    pub fn complement(&self) -> impl Iterator<Item=Self> {
430        use RawInterval::*;
431        match *self {
432            Empty                   => Few::One(Full),
433            Point(ref p)            => Few::Two(UpTo(p.clone()), UpFrom(p.clone())),
434            Open(ref l, ref r)      => Few::Two(To(l.clone()), From(r.clone())),
435            LeftOpen(ref l, ref r)  => Few::Two(To(l.clone()), UpFrom(r.clone())),
436            RightOpen(ref l, ref r) => Few::Two(UpTo(l.clone()), From(r.clone())),
437            Closed(ref l, ref r)    => Few::Two(UpTo(l.clone()), UpFrom(r.clone())),
438            UpTo(ref p)             => Few::One(From(p.clone())),
439            UpFrom(ref p)           => Few::One(To(p.clone())),
440            To(ref p)               => Few::One(UpFrom(p.clone())),
441            From(ref p)             => Few::One(UpTo(p.clone())),
442            Full                    => Few::Zero,
443        }
444    }
445
446    /// Returns the largest interval whose points are all contained entirely
447    /// within this interval and the given interval.
448    #[must_use]
449    pub fn intersect(&self, other: &Self) -> Self {
450        let lb = match (self.lower_bound(), other.lower_bound()) {
451            (Some(a), Some(b)) => a.greatest_intersect(&b),
452            _                  => return Self::Empty, // Either Empty.
453        };
454
455        let ub = match (self.upper_bound(), other.upper_bound()) {
456            (Some(a), Some(b)) => a.least_intersect(&b),
457            _                  => return Self::Empty, // Either Empty.
458        };
459
460        if lb.as_ref() == ub.as_ref() && 
461            ((lb.is_inclusive() && ub.is_exclusive()) ||
462             (lb.is_exclusive() && ub.is_inclusive()))
463        {
464            Self::Empty
465        } else {
466            Self::new(lb, ub)
467        }
468    }
469    
470    /// Returns a `Vec` of `RawInterval`s containing all of the points 
471    /// contained within this interval and the given interval., `vec![a, b]`);
472    pub fn union(&self, other: &Self) -> impl Iterator<Item=Self> {
473        match (self.is_empty(), other.is_empty()) {
474            (true,  true)  => Few::Zero,
475            (true,  false) => Few::One(other.clone()),
476            (false, true)  => Few::One(self.clone()),
477            (false, false) => {
478                // if self.lb > other.ub || other.lb < self.ub
479                if self.intersects(other) || self .is_adjacent_to(other) {
480                    Few::One(self.enclose(other))
481                } else {
482                    Few::Two(self.clone(), other.clone())
483                }
484            },
485        }
486    }
487    
488    /// Returns a `Vec` of `RawInterval`s containing all of the points
489    /// contained within this interval that are not in the given interval.
490    pub fn minus(&self, other: &Self) -> impl Iterator<Item=Self> {
491        other.complement()
492            .map(|i| self.intersect(&i))
493            .filter(|i| !i.is_empty())
494            .collect::<Vec<_>>()
495            .into_iter()
496    }
497    
498    /// Returns the smallest interval that contains all of the points contained
499    /// within this interval and the given interval.
500    #[must_use]
501    pub fn enclose(&self, other: &Self) -> Self {
502        let lb = match (self.lower_bound(), other.lower_bound()) {
503            (Some(a), Some(b)) => a.least_union(&b),
504            (Some(a), None)    => a,
505            (None,    Some(b)) => b,
506            (None,    None)    => return Self::Empty, // Both Empty.
507        };
508
509        let ub = match (self.upper_bound(), other.upper_bound()) {
510            (Some(a), Some(b)) => a.greatest_union(&b),
511            (Some(a), None)    => a,
512            (None,    Some(b)) => b,
513            (None,    None)    => return Self::Empty, // Both Empty.
514        };
515
516        Self::new(lb, ub)
517    }
518
519    /// Returns the smallest closed interval that contains all of the points
520    /// contained within the interval.
521    #[must_use]
522    pub fn closure(&self) -> Self {
523        use RawInterval::*;
524        match self {
525            Open(l, r)      => Closed(l.clone(), r.clone()),
526            LeftOpen(l, r)  => Closed(l.clone(), r.clone()),
527            RightOpen(l, r) => Closed(l.clone(), r.clone()),
528            UpTo(r)         => To(r.clone()),
529            UpFrom(l)       => From(l.clone()),
530            _               => self.clone(),
531        }
532    }
533
534    // Bulk set operations
535    ////////////////////////////////////////////////////////////////////////////
536
537    /// Returns the interval enclosing all of the given intervals.
538    #[must_use]
539    pub fn enclose_all<I>(intervals: I) -> Self
540        where I: Iterator<Item=Self>
541    {
542        intervals.fold(Self::Full, |acc, i| acc.enclose(&i))
543    }
544
545    /// Returns the intersection of all of the given intervals.
546    #[must_use]
547    pub fn intersect_all<I>(intervals: I) -> Self
548        where I: Iterator<Item=Self>
549    {
550        intervals.fold(Self::Full, |acc, i| acc.intersect(&i))
551    }
552
553    /// Returns the union of all of the given intervals.
554    #[allow(clippy::option_if_let_else)] // False positive.
555    pub fn union_all<I>(intervals: I) -> impl Iterator<Item=Self>
556        where I: Iterator<Item=Self>
557    {
558        // TODO: Consider using selection/disjunction map. It may be faster.
559        let mut it = intervals.filter(|i| !i.is_empty());
560   
561        // Get first interval.
562        if let Some(start) = it.next() {
563            // Fold over remaining intervals.
564            it.fold(vec![start], |mut prev, next| {
565                // Early exit for full interval.
566                if next == Self::Full {
567                    return vec![Self::Full];
568                }
569                let mut append = true;
570                for item in &mut prev {
571                    if item.intersects(&next) || item .is_adjacent_to(&next) {
572                        *item = item.enclose(&next);
573                        append = false;
574                        break;
575                    }
576                }
577                if append {prev.push(next);}
578                prev
579            })
580        } else {
581           Vec::new()
582        }.into_iter()
583    }
584}
585
586// Display using interval notation.
587impl<T> std::fmt::Display for RawInterval<T> where T: std::fmt::Display {
588    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
589        self.write_fmt_with(f, |p, f| write!(f, "{}", p))
590    }
591}
592
593impl<T> FromStr for RawInterval<T> where T: Ord + FromStr {
594    type Err = IntervalParseError<T::Err>;
595
596    fn from_str(s: &str) -> Result<Self, Self::Err> {
597        Self::from_str_with(s, T::from_str)
598    }
599}
600
601/// Error type returned by failure to parse a `RawInterval`.
602#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
603pub enum IntervalParseError<E> {
604    /// An error occurred during the interval parse.
605    InvalidInterval,
606    /// An error occurred during a value parse.
607    InvalidValue(E),
608}
609
610
611impl<T> std::fmt::Binary for RawInterval<T>
612    where T: std::fmt::Binary
613{
614    fn fmt(&self, f: &mut std::fmt::Formatter<'_>)
615        -> Result<(), std::fmt::Error>
616    {
617        self.write_fmt_with(f, |p, f| std::fmt::Binary::fmt(p, f))
618    }
619}
620
621impl<T> std::fmt::Octal for RawInterval<T>
622    where T: std::fmt::Octal
623{
624    fn fmt(&self, f: &mut std::fmt::Formatter<'_>)
625        -> Result<(), std::fmt::Error>
626    {
627        self.write_fmt_with(f, |p, f| std::fmt::Octal::fmt(p, f))
628    }
629}
630
631impl<T> std::fmt::LowerHex for RawInterval<T>
632    where T: std::fmt::LowerHex
633{
634    fn fmt(&self, f: &mut std::fmt::Formatter<'_>)
635        -> Result<(), std::fmt::Error>
636    {
637        self.write_fmt_with(f, |p, f| std::fmt::LowerHex::fmt(p, f))
638    }
639}
640
641impl<T> std::fmt::UpperHex for RawInterval<T>
642    where T: std::fmt::UpperHex
643{
644    fn fmt(&self, f: &mut std::fmt::Formatter<'_>)
645        -> Result<(), std::fmt::Error>
646    {
647        self.write_fmt_with(f, |p, f| std::fmt::UpperHex::fmt(p, f))
648    }
649}
650
651
652impl<T> std::fmt::LowerExp for RawInterval<T>
653    where T: std::fmt::LowerExp
654{
655    fn fmt(&self, f: &mut std::fmt::Formatter<'_>)
656        -> Result<(), std::fmt::Error>
657    {
658        self.write_fmt_with(f, |p, f| std::fmt::LowerExp::fmt(p, f))
659    }
660}
661
662impl<T> std::fmt::UpperExp for RawInterval<T>
663    where T: std::fmt::UpperExp
664{
665    fn fmt(&self, f: &mut std::fmt::Formatter<'_>)
666        -> Result<(), std::fmt::Error>
667    {
668        self.write_fmt_with(f, |p, f| std::fmt::UpperExp::fmt(p, f))
669    }
670}
671
672impl<T> std::fmt::Pointer for RawInterval<T>
673    where T: std::fmt::Pointer
674{
675    fn fmt(&self, f: &mut std::fmt::Formatter<'_>)
676        -> Result<(), std::fmt::Error>
677    {
678        self.write_fmt_with(f, |p, f| std::fmt::Pointer::fmt(p, f))
679    }
680}