sigma_types/
finite.rs

1//! Finite types (e.g. for floating points, not `NaN`, infinite, etc.).
2
3use {
4    crate::{Sigma, Test},
5    core::{fmt, marker::PhantomData},
6};
7
8/// Types that can represent infinite values.
9pub trait CanBeInfinite {
10    /// Check that this value is finite (i.e. not infinite, `NaN`, etc).
11    fn check_finite(&self) -> bool;
12}
13
14/// Finite terms (e.g. for floating points, not `NaN`, infinite, etc.).
15pub type Finite<Input> = Sigma<Input, FiniteInvariant<Input>>;
16
17/// Finite terms (e.g. for floating points, not `NaN`, infinite, etc.).
18#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
19pub struct FiniteInvariant<Input: fmt::Debug + CanBeInfinite>(PhantomData<Input>);
20
21impl<Input: fmt::Debug + CanBeInfinite> Test<Input, 1> for FiniteInvariant<Input> {
22    const ADJECTIVE: &str = "finite";
23    type Error<'i>
24        = NotFinite
25    where
26        Input: 'i;
27
28    #[inline(always)]
29    fn test([input]: [&Input; 1]) -> Result<(), Self::Error<'_>> {
30        if input.check_finite() {
31            Ok(())
32        } else {
33            Err(NotFinite)
34        }
35    }
36}
37
38/// A term expected to be finite was not.
39#[non_exhaustive]
40#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
41pub struct NotFinite;
42
43impl fmt::Display for NotFinite {
44    #[inline]
45    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46        write!(f, "`CanBeInfinite::check_finite(..)` returned `false`")
47    }
48}
49
50impl CanBeInfinite for f32 {
51    #[inline(always)]
52    fn check_finite(&self) -> bool {
53        self.is_finite()
54    }
55}
56
57impl CanBeInfinite for f64 {
58    #[inline(always)]
59    fn check_finite(&self) -> bool {
60        self.is_finite()
61    }
62}