sigma_types/
positive.rs

1//! Positive terms (defined by comparison to zero).
2
3use {
4    crate::{Sigma, Test, Zero},
5    core::{fmt, marker::PhantomData},
6};
7
8/// A term expected to be positive was not.
9#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
10pub struct NotPositive<'i, Input: fmt::Debug + PartialOrd + Zero>(&'i Input);
11
12impl<Input: fmt::Debug + PartialOrd + Zero> fmt::Display for NotPositive<'_, Input> {
13    #[inline]
14    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
15        #![expect(
16            clippy::use_debug,
17            reason = "Intentional and informative, not just forgotten print-debugging"
18        )]
19
20        let Self(z) = *self;
21        write!(f, "{z:#?} <= {:#?}", Input::ZERO)
22    }
23}
24
25/// Positive terms (defined by comparison to zero).
26pub type Positive<Input> = Sigma<Input, PositiveInvariant<Input>>;
27
28/// Positive terms (defined by comparison to zero).
29#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
30pub struct PositiveInvariant<Input: fmt::Debug + PartialOrd + Zero>(PhantomData<Input>);
31
32impl<Input: fmt::Debug + PartialOrd + Zero> Test<Input, 1> for PositiveInvariant<Input> {
33    const ADJECTIVE: &str = "positive";
34    type Error<'i>
35        = NotPositive<'i, Input>
36    where
37        Input: 'i;
38
39    #[inline(always)]
40    fn test([input]: [&Input; 1]) -> Result<(), Self::Error<'_>> {
41        if *input > Input::ZERO {
42            Ok(())
43        } else {
44            Err(NotPositive(input))
45        }
46    }
47}