computation-types 0.0.0

Types for abstract mathematical computation
Documentation
pub use paste;

#[macro_export]
macro_rules! impl_core_ops {
    ( $ty:ident $( < $( $gen:ident ),* > )? ) => {
        impl_core_ops!(@impl Add for $ty $( < $( $gen ),* > )?);
        impl_core_ops!(@impl Sub for $ty $( < $( $gen ),* > )?);
        impl_core_ops!(@impl Mul for $ty $( < $( $gen ),* > )?);
        impl_core_ops!(@impl Div for $ty $( < $( $gen ),* > )?);

        impl $( < $( $gen ),* > )? core::ops::Neg for $ty $( < $( $gen ),* > )?
        where
            Self: Computation,
            $crate::math::Neg<Self>: $crate::Computation,
        {
            type Output = $crate::math::Neg<Self>;

            fn neg(self) -> Self::Output {
                <Self as $crate::Computation>::neg(self)
            }
        }
    };
    ( @impl $op:ident for $ty:ident $( < $( $gen:ident ),* > )? ) => {
        $crate::macros::paste::paste! {
            impl<Rhs, $( $( $gen ),* )?> core::ops::$op<Rhs> for $ty $( < $( $gen ),* > )?
            where
                Self: Computation,
                $crate::math::$op<Self, Rhs>: $crate::Computation,
            {
                type Output = $crate::math::$op<Self, Rhs>;

                fn [<$op:lower>](self, rhs: Rhs) -> Self::Output {
                    <Self as $crate::Computation>::[<$op:lower>](self, rhs)
                }
            }
        }
    };
}

#[macro_export]
macro_rules! impl_display_for_inline_binary {
    ( $op:ident, $inline:literal ) => {
        impl<A, B> core::fmt::Display for $op<A, B>
        where
            Self: $crate::Computation,
            A: core::fmt::Display,
            B: core::fmt::Display,
        {
            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
                write!(f, "({} {} {})", self.0, $inline, self.1)
            }
        }
    };
}

#[macro_export]
macro_rules! impl_computation_fn_for_unary {
    ( $op:ident ) => {
        impl<A> ComputationFn for $op<A>
        where
            Self: Computation,
            A: ComputationFn,
            $op<A::Filled>: Computation,
        {
            type Filled = $op<A::Filled>;

            fn fill(self, named_args: NamedArgs) -> Self::Filled {
                $op(self.0.fill(named_args))
            }

            fn arg_names(&self) -> $crate::Names {
                self.0.arg_names()
            }
        }
    };
}

#[macro_export]
macro_rules! impl_computation_fn_for_binary {
    ( $op:ident ) => {
        impl<A, B> ComputationFn for $op<A, B>
        where
            Self: Computation,
            A: ComputationFn,
            B: ComputationFn,
            $op<A::Filled, B::Filled>: Computation,
        {
            type Filled = $op<A::Filled, B::Filled>;

            fn fill(self, named_args: NamedArgs) -> Self::Filled {
                let (args_0, args_1) = named_args
                    .partition(&self.0.arg_names(), &self.1.arg_names())
                    .unwrap_or_else(|e| panic!("{}", e));
                $op(self.0.fill(args_0), self.1.fill(args_1))
            }

            fn arg_names(&self) -> $crate::Names {
                self.0.arg_names().union(self.1.arg_names())
            }
        }
    };
}