refined 0.3.1

Simple refinement types; parse, don't validate!
Documentation
use core::{marker::PhantomData, ops::Mul};

use crate::{boundable::*, Predicate, Refinement};

use super::*;

impl<
        const A: usize,
        Type: unsigned::UnsignedBoundable + Mul<Output = Type>,
        B: UnsignedMax<Type> + Predicate<Type>,
    > Mul<Refinement<Type, B>> for Refinement<Type, unsigned::LessThan<A>>
where
    Refinement<Type, unsigned::LessThan<{ (A - 1) * B::UMAX + 1 }>>: Sized,
{
    type Output = Refinement<Type, unsigned::LessThan<{ (A - 1) * B::UMAX + 1 }>>;

    fn mul(self, rhs: Refinement<Type, B>) -> Self::Output {
        Refinement(self.0 * rhs.0, PhantomData)
    }
}

impl<
        const A: usize,
        Type: unsigned::UnsignedBoundable + Mul<Output = Type>,
        B: UnsignedMax<Type> + Predicate<Type>,
    > Mul<Refinement<Type, B>> for Refinement<Type, unsigned::LessThanEqual<A>>
where
    Refinement<Type, unsigned::LessThanEqual<{ A * B::UMAX }>>: Sized,
{
    type Output = Refinement<Type, unsigned::LessThanEqual<{ A * B::UMAX }>>;

    fn mul(self, rhs: Refinement<Type, B>) -> Self::Output {
        Refinement(self.0 * rhs.0, PhantomData)
    }
}

impl<
        const A: usize,
        Type: unsigned::UnsignedBoundable + Mul<Output = Type>,
        B: UnsignedMin<Type> + Predicate<Type>,
    > Mul<Refinement<Type, B>> for Refinement<Type, unsigned::GreaterThan<A>>
where
    Refinement<Type, unsigned::GreaterThan<{ (A + 1) * B::UMIN - 1 }>>: Sized,
{
    type Output = Refinement<Type, unsigned::GreaterThan<{ (A + 1) * B::UMIN - 1 }>>;

    fn mul(self, rhs: Refinement<Type, B>) -> Self::Output {
        Refinement(self.0 * rhs.0, PhantomData)
    }
}

impl<
        const A: usize,
        Type: unsigned::UnsignedBoundable + Mul<Output = Type>,
        B: UnsignedMin<Type> + Predicate<Type>,
    > Mul<Refinement<Type, B>> for Refinement<Type, unsigned::GreaterThanEqual<A>>
where
    Refinement<Type, unsigned::GreaterThanEqual<{ A * B::UMIN }>>: Sized,
{
    type Output = Refinement<Type, unsigned::GreaterThanEqual<{ A * B::UMIN }>>;

    fn mul(self, rhs: Refinement<Type, B>) -> Self::Output {
        Refinement(self.0 * rhs.0, PhantomData)
    }
}

impl<
        const MIN: usize,
        const MAX: usize,
        Type: unsigned::UnsignedBoundable + Mul<Output = Type>,
        B: UnsignedMinMax<Type> + Predicate<Type>,
    > Mul<Refinement<Type, B>> for Refinement<Type, unsigned::OpenInterval<MIN, MAX>>
where
    Refinement<
        Type,
        unsigned::OpenInterval<{ (MIN + 1) * B::UMIN - 1 }, { (MAX - 1) * B::UMAX + 1 }>,
    >: Sized,
{
    type Output = Refinement<
        Type,
        unsigned::OpenInterval<{ (MIN + 1) * B::UMIN - 1 }, { (MAX - 1) * B::UMAX + 1 }>,
    >;

    fn mul(self, rhs: Refinement<Type, B>) -> Self::Output {
        Refinement(self.0 * rhs.0, PhantomData)
    }
}

impl<
        const MIN: usize,
        const MAX: usize,
        Type: unsigned::UnsignedBoundable + Mul<Output = Type>,
        B: UnsignedMinMax<Type> + Predicate<Type>,
    > Mul<Refinement<Type, B>> for Refinement<Type, unsigned::ClosedInterval<MIN, MAX>>
where
    Refinement<Type, unsigned::ClosedInterval<{ MIN * B::UMIN }, { MAX * B::UMAX }>>: Sized,
{
    type Output = Refinement<Type, unsigned::ClosedInterval<{ MIN * B::UMIN }, { MAX * B::UMAX }>>;

    fn mul(self, rhs: Refinement<Type, B>) -> Self::Output {
        Refinement(self.0 * rhs.0, PhantomData)
    }
}

impl<
        const MIN: usize,
        const MAX: usize,
        Type: unsigned::UnsignedBoundable + Mul<Output = Type>,
        B: UnsignedMinMax<Type> + Predicate<Type>,
    > Mul<Refinement<Type, B>> for Refinement<Type, unsigned::OpenClosedInterval<MIN, MAX>>
where
    Refinement<Type, unsigned::OpenClosedInterval<{ (MIN + 1) * B::UMIN - 1 }, { MAX * B::UMAX }>>:
        Sized,
{
    type Output = Refinement<
        Type,
        unsigned::OpenClosedInterval<{ (MIN + 1) * B::UMIN - 1 }, { MAX * B::UMAX }>,
    >;

    fn mul(self, rhs: Refinement<Type, B>) -> Self::Output {
        Refinement(self.0 * rhs.0, PhantomData)
    }
}

impl<
        const MIN: usize,
        const MAX: usize,
        Type: unsigned::UnsignedBoundable + Mul<Output = Type>,
        B: UnsignedMinMax<Type> + Predicate<Type>,
    > Mul<Refinement<Type, B>> for Refinement<Type, unsigned::ClosedOpenInterval<MIN, MAX>>
where
    Refinement<Type, unsigned::ClosedOpenInterval<{ MIN * B::UMIN }, { (MAX - 1) * B::UMAX + 1 }>>:
        Sized,
{
    type Output = Refinement<
        Type,
        unsigned::ClosedOpenInterval<{ MIN * B::UMIN }, { (MAX - 1) * B::UMAX + 1 }>,
    >;

    fn mul(self, rhs: Refinement<Type, B>) -> Self::Output {
        Refinement(self.0 * rhs.0, PhantomData)
    }
}

#[cfg(test)]
mod unsigned_tests {
    use super::*;
    use crate::prelude::*;

    #[test]
    fn test_lt_mul_lt() {
        let a = Refinement::<u8, unsigned::LessThan<10>>::refine(9).unwrap();
        let b = Refinement::<u8, unsigned::LessThan<10>>::refine(9).unwrap();
        let c: Refinement<u8, unsigned::LessThan<82>> = a * b;
        assert_eq!(*c, 81);
    }

    #[test]
    fn test_lte_mul_lte() {
        let a = Refinement::<u8, unsigned::LessThanEqual<10>>::refine(6).unwrap();
        let b = Refinement::<u8, unsigned::LessThanEqual<10>>::refine(3).unwrap();
        let c: Refinement<u8, unsigned::LessThanEqual<100>> = a * b;
        assert_eq!(*c, 18);
    }

    #[test]
    fn test_lte_mul_lt() {
        let a = Refinement::<u8, unsigned::LessThanEqual<10>>::refine(6).unwrap();
        let b = Refinement::<u8, unsigned::LessThan<11>>::refine(3).unwrap();
        let c: Refinement<u8, unsigned::LessThanEqual<100>> = a * b;
        assert_eq!(*c, 18);
    }

    #[test]
    fn test_gt_mul_gt() {
        let a = Refinement::<u8, unsigned::GreaterThan<10>>::refine(11).unwrap();
        let b = Refinement::<u8, unsigned::GreaterThan<10>>::refine(11).unwrap();
        let c: Refinement<u8, unsigned::GreaterThan<120>> = a * b;
        assert_eq!(*c, 121);
    }

    #[test]
    fn test_gt_mul_gte() {
        let a = Refinement::<u8, unsigned::GreaterThan<10>>::refine(11).unwrap();
        let b = Refinement::<u8, unsigned::GreaterThanEqual<3>>::refine(3).unwrap();
        let c: Refinement<u8, unsigned::GreaterThan<32>> = a * b;
        assert_eq!(*c, 33);
    }

    #[test]
    fn test_gte_mul_gte() {
        let a = Refinement::<u8, unsigned::GreaterThanEqual<10>>::refine(12).unwrap();
        let b = Refinement::<u8, unsigned::GreaterThanEqual<3>>::refine(3).unwrap();
        let c: Refinement<u8, unsigned::GreaterThanEqual<30>> = a * b;
        assert_eq!(*c, 36);
    }

    #[test]
    fn test_gte_mul_gt() {
        let a = Refinement::<u8, unsigned::GreaterThanEqual<12>>::refine(15).unwrap();
        let b = Refinement::<u8, unsigned::GreaterThan<3>>::refine(4).unwrap();
        let c: Refinement<u8, unsigned::GreaterThanEqual<48>> = a * b;
        assert_eq!(*c, 60);
    }

    #[test]
    fn test_open_closed_interval_mul() {
        let a = Refinement::<u8, unsigned::OpenClosedInterval<15, 20>>::refine(18).unwrap();
        let b = Refinement::<u8, unsigned::OpenClosedInterval<3, 6>>::refine(6).unwrap();
        let c: Refinement<u8, unsigned::OpenClosedInterval<63, 120>> = a * b;
        assert_eq!(*c, 108);
    }

    #[test]
    fn test_closed_open_interval_mul() {
        let a = Refinement::<u16, unsigned::ClosedOpenInterval<50, 100>>::refine(99).unwrap();
        let b = Refinement::<u16, unsigned::ClosedOpenInterval<5, 10>>::refine(9).unwrap();
        let c: Refinement<u16, unsigned::ClosedOpenInterval<250, 892>> = a * b;
        assert_eq!(*c, 891);
    }

    #[test]
    fn test_open_interval_mul() {
        let a = Refinement::<u8, unsigned::OpenInterval<15, 30>>::refine(18).unwrap();
        let b = Refinement::<u8, unsigned::OpenInterval<3, 6>>::refine(5).unwrap();
        let c: Refinement<u8, unsigned::OpenInterval<63, 146>> = a * b;
        assert_eq!(*c, 90);
    }

    #[test]
    fn test_closed_interval_mul() {
        let a = Refinement::<u8, unsigned::ClosedInterval<15, 50>>::refine(30).unwrap();
        let b = Refinement::<u8, unsigned::ClosedInterval<3, 6>>::refine(6).unwrap();
        let c: Refinement<u8, unsigned::ClosedInterval<45, 300>> = a * b;
        assert_eq!(*c, 180);
    }
}

impl<
        const MIN: isize,
        const MAX: isize,
        Type: signed::SignedBoundable + Mul<Output = Type>,
        B: SignedMinMax<Type> + Predicate<Type>,
    > Mul<Refinement<Type, B>> for Refinement<Type, signed::OpenInterval<MIN, MAX>>
where
    Refinement<
        Type,
        signed::OpenInterval<
            { min_mul(MIN + 1, MAX - 1, B::UMIN, B::UMAX) - 1 },
            { max_mul(MIN + 1, MAX - 1, B::UMIN, B::UMAX) + 1 },
        >,
    >: Sized,
{
    type Output = Refinement<
        Type,
        signed::OpenInterval<
            { min_mul(MIN + 1, MAX - 1, B::UMIN, B::UMAX) - 1 },
            { max_mul(MIN + 1, MAX - 1, B::UMIN, B::UMAX) + 1 },
        >,
    >;

    fn mul(self, rhs: Refinement<Type, B>) -> Self::Output {
        Refinement(self.0 * rhs.0, PhantomData)
    }
}

impl<
        const MIN: isize,
        const MAX: isize,
        Type: signed::SignedBoundable + Mul<Output = Type>,
        B: SignedMinMax<Type> + Predicate<Type>,
    > Mul<Refinement<Type, B>> for Refinement<Type, signed::ClosedInterval<MIN, MAX>>
where
    Refinement<
        Type,
        signed::ClosedInterval<
            { min_mul(MIN, MAX, B::UMIN, B::UMAX) },
            { max_mul(MIN, MAX, B::UMIN, B::UMAX) },
        >,
    >: Sized,
{
    type Output = Refinement<
        Type,
        signed::ClosedInterval<
            { min_mul(MIN, MAX, B::UMIN, B::UMAX) },
            { max_mul(MIN, MAX, B::UMIN, B::UMAX) },
        >,
    >;

    fn mul(self, rhs: Refinement<Type, B>) -> Self::Output {
        Refinement(self.0 * rhs.0, PhantomData)
    }
}

impl<
        const MIN: isize,
        const MAX: isize,
        Type: signed::SignedBoundable + Mul<Output = Type>,
        B: SignedMinMax<Type> + Predicate<Type>,
    > Mul<Refinement<Type, B>> for Refinement<Type, signed::OpenClosedInterval<MIN, MAX>>
where
    Refinement<
        Type,
        signed::OpenClosedInterval<
            { min_mul(MIN + 1, MAX, B::UMIN, B::UMAX) - 1 },
            { max_mul(MIN + 1, MAX, B::UMIN, B::UMAX) },
        >,
    >: Sized,
{
    type Output = Refinement<
        Type,
        signed::OpenClosedInterval<
            { min_mul(MIN + 1, MAX, B::UMIN, B::UMAX) - 1 },
            { max_mul(MIN + 1, MAX, B::UMIN, B::UMAX) },
        >,
    >;

    fn mul(self, rhs: Refinement<Type, B>) -> Self::Output {
        Refinement(self.0 * rhs.0, PhantomData)
    }
}

impl<
        const MIN: isize,
        const MAX: isize,
        Type: signed::SignedBoundable + Mul<Output = Type>,
        B: SignedMinMax<Type> + Predicate<Type>,
    > Mul<Refinement<Type, B>> for Refinement<Type, signed::ClosedOpenInterval<MIN, MAX>>
where
    Refinement<
        Type,
        signed::ClosedOpenInterval<
            { min_mul(MIN, MAX - 1, B::UMIN, B::UMAX) },
            { max_mul(MIN, MAX - 1, B::UMIN, B::UMAX) + 1 },
        >,
    >: Sized,
{
    type Output = Refinement<
        Type,
        signed::ClosedOpenInterval<
            { min_mul(MIN, MAX - 1, B::UMIN, B::UMAX) },
            { max_mul(MIN, MAX - 1, B::UMIN, B::UMAX) + 1 },
        >,
    >;

    fn mul(self, rhs: Refinement<Type, B>) -> Self::Output {
        Refinement(self.0 * rhs.0, PhantomData)
    }
}

#[cfg(test)]
mod signed_tests {
    use super::*;
    use crate::prelude::*;

    #[test]
    fn test_open_closed_interval_mul() {
        let a = Refinement::<i8, signed::OpenClosedInterval<15, 20>>::refine(20).unwrap();
        let b = Refinement::<i8, signed::OpenClosedInterval<-6, -3>>::refine(-5).unwrap();
        let c: Refinement<i8, signed::OpenClosedInterval<-101, -48>> = a * b;
        assert_eq!(*c, -100);
    }

    #[test]
    fn test_closed_open_interval_mul() {
        let a = Refinement::<i16, signed::ClosedOpenInterval<-50, 100>>::refine(99).unwrap();
        let b = Refinement::<i16, signed::ClosedOpenInterval<5, 10>>::refine(9).unwrap();
        let c: Refinement<i16, signed::ClosedOpenInterval<-450, 892>> = a * b;
        assert_eq!(*c, 891);
    }

    #[test]
    fn test_open_interval_mul() {
        let a = Refinement::<i8, signed::OpenInterval<15, 30>>::refine(16).unwrap();
        let b = Refinement::<i8, signed::OpenInterval<-13, -6>>::refine(-7).unwrap();
        let c: Refinement<i8, signed::OpenInterval<-349, -111>> = a * b;
        assert_eq!(*c, -112);
    }

    #[test]
    fn test_closed_interval_mul() {
        let a = Refinement::<i16, signed::ClosedInterval<15, 50>>::refine(30).unwrap();
        let b = Refinement::<i16, signed::ClosedInterval<3, 6>>::refine(6).unwrap();
        let c: Refinement<i16, signed::ClosedInterval<45, 300>> = a * b;
        assert_eq!(*c, 180);
    }
}