//! A type-level array of type-level numbers. //! //! It is not very featureful right now, and should be considered a work in progress. use core::ops::{Add, Div, Mul, Sub}; use super::*; /// The terminating type for type arrays. #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug)] pub struct ATerm; impl TypeArray for ATerm {} /// `TArr` is a type that acts as an array of types. It is defined similarly to `UInt`, only its /// values can be more than bits, and it is designed to act as an array. So you can only add two if /// they have the same number of elements, for example. /// /// This array is only really designed to contain `Integer` types. If you use it with others, you /// may find it lacking functionality. #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug)] pub struct TArr { first: V, rest: A, } impl TypeArray for TArr {} /// Create a new type-level arrray. Only usable on Rust 1.13.0 or newer. /// /// There's not a whole lot you can do with it right now. /// /// # Example /// ```rust /// #[macro_use] /// extern crate typenum; /// use typenum::consts::*; /// /// type Array = tarr![P3, N4, Z0, P38]; /// # fn main() { let _: Array; } #[macro_export] macro_rules! tarr { () => ( $crate::ATerm ); ($n:ty) => ( $crate::TArr<$n, $crate::ATerm> ); ($n:ty,) => ( $crate::TArr<$n, $crate::ATerm> ); ($n:ty, $($tail:ty),+) => ( $crate::TArr<$n, tarr![$($tail),+]> ); ($n:ty, $($tail:ty),+,) => ( $crate::TArr<$n, tarr![$($tail),+]> ); } // --------------------------------------------------------------------------------------- // Length /// Length of `ATerm` by itself is 0 impl Len for ATerm { type Output = U0; #[inline] fn len(&self) -> Self::Output { UTerm } } /// Size of a `TypeArray` impl Len for TArr where A: Len, Length: Add, Sum, B1>: Unsigned, { type Output = Add1>; #[inline] fn len(&self) -> Self::Output { self.rest.len() + B1 } } // --------------------------------------------------------------------------------------- // Add arrays // Note that two arrays are only addable if they are the same length. impl Add for ATerm { type Output = ATerm; #[inline] fn add(self, _: ATerm) -> Self::Output { ATerm } } impl Add> for TArr where Al: Add, Vl: Add, { type Output = TArr, Sum>; #[inline] fn add(self, rhs: TArr) -> Self::Output { TArr { first: self.first + rhs.first, rest: self.rest + rhs.rest, } } } // --------------------------------------------------------------------------------------- // Subtract arrays // Note that two arrays are only subtractable if they are the same length. impl Sub for ATerm { type Output = ATerm; #[inline] fn sub(self, _: ATerm) -> Self::Output { ATerm } } impl Sub> for TArr where Vl: Sub, Al: Sub, { type Output = TArr, Diff>; #[inline] fn sub(self, rhs: TArr) -> Self::Output { TArr { first: self.first - rhs.first, rest: self.rest - rhs.rest, } } } // --------------------------------------------------------------------------------------- // Multiply an array by a scalar impl Mul for ATerm { type Output = ATerm; #[inline] fn mul(self, _: Rhs) -> Self::Output { ATerm } } impl Mul for TArr where V: Mul, A: Mul, Rhs: Copy, { type Output = TArr, Prod>; #[inline] fn mul(self, rhs: Rhs) -> Self::Output { TArr { first: self.first * rhs, rest: self.rest * rhs, } } } impl Mul for Z0 { type Output = ATerm; #[inline] fn mul(self, _: ATerm) -> Self::Output { ATerm } } impl Mul for PInt where U: Unsigned + NonZero, { type Output = ATerm; #[inline] fn mul(self, _: ATerm) -> Self::Output { ATerm } } impl Mul for NInt where U: Unsigned + NonZero, { type Output = ATerm; #[inline] fn mul(self, _: ATerm) -> Self::Output { ATerm } } impl Mul> for Z0 where Z0: Mul, { type Output = TArr>; #[inline] fn mul(self, rhs: TArr) -> Self::Output { TArr { first: Z0, rest: self * rhs.rest, } } } impl Mul> for PInt where U: Unsigned + NonZero, PInt: Mul + Mul, { type Output = TArr, V>, Prod, A>>; #[inline] fn mul(self, rhs: TArr) -> Self::Output { TArr { first: self * rhs.first, rest: self * rhs.rest, } } } impl Mul> for NInt where U: Unsigned + NonZero, NInt: Mul + Mul, { type Output = TArr, V>, Prod, A>>; #[inline] fn mul(self, rhs: TArr) -> Self::Output { TArr { first: self * rhs.first, rest: self * rhs.rest, } } } // --------------------------------------------------------------------------------------- // Divide an array by a scalar impl Div for ATerm { type Output = ATerm; #[inline] fn div(self, _: Rhs) -> Self::Output { ATerm } } impl Div for TArr where V: Div, A: Div, Rhs: Copy, { type Output = TArr, Quot>; #[inline] fn div(self, rhs: Rhs) -> Self::Output { TArr { first: self.first / rhs, rest: self.rest / rhs, } } } // --------------------------------------------------------------------------------------- // Partial Divide an array by a scalar impl PartialDiv for ATerm { type Output = ATerm; #[inline] fn partial_div(self, _: Rhs) -> Self::Output { ATerm } } impl PartialDiv for TArr where V: PartialDiv, A: PartialDiv, Rhs: Copy, { type Output = TArr, PartialQuot>; #[inline] fn partial_div(self, rhs: Rhs) -> Self::Output { TArr { first: self.first.partial_div(rhs), rest: self.rest.partial_div(rhs), } } } // --------------------------------------------------------------------------------------- // Modulo an array by a scalar use core::ops::Rem; impl Rem for ATerm { type Output = ATerm; #[inline] fn rem(self, _: Rhs) -> Self::Output { ATerm } } impl Rem for TArr where V: Rem, A: Rem, Rhs: Copy, { type Output = TArr, Mod>; #[inline] fn rem(self, rhs: Rhs) -> Self::Output { TArr { first: self.first % rhs, rest: self.rest % rhs, } } } // --------------------------------------------------------------------------------------- // Negate an array use core::ops::Neg; impl Neg for ATerm { type Output = ATerm; #[inline] fn neg(self) -> Self::Output { ATerm } } impl Neg for TArr where V: Neg, A: Neg, { type Output = TArr, Negate>; #[inline] fn neg(self) -> Self::Output { TArr { first: -self.first, rest: -self.rest, } } }