1 //! A type-level array of type-level numbers. 2 //! 3 //! It is not very featureful right now, and should be considered a work in progress. 4 5 use core::ops::{Add, Div, Mul, Sub}; 6 7 use super::*; 8 9 /// The terminating type for type arrays. 10 #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug)] 11 pub struct ATerm; 12 13 impl TypeArray for ATerm {} 14 15 /// `TArr` is a type that acts as an array of types. It is defined similarly to `UInt`, only its 16 /// values can be more than bits, and it is designed to act as an array. So you can only add two if 17 /// they have the same number of elements, for example. 18 /// 19 /// This array is only really designed to contain `Integer` types. If you use it with others, you 20 /// may find it lacking functionality. 21 #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug)] 22 pub struct TArr<V, A> { 23 first: V, 24 rest: A, 25 } 26 27 impl<V, A> TypeArray for TArr<V, A> {} 28 29 /// Create a new type-level arrray. Only usable on Rust 1.13.0 or newer. 30 /// 31 /// There's not a whole lot you can do with it right now. 32 /// 33 /// # Example 34 /// ```rust 35 /// #[macro_use] 36 /// extern crate typenum; 37 /// use typenum::consts::*; 38 /// 39 /// type Array = tarr![P3, N4, Z0, P38]; 40 /// # fn main() { let _: Array; } 41 #[macro_export] 42 macro_rules! tarr { 43 () => ( $crate::ATerm ); 44 ($n:ty) => ( $crate::TArr<$n, $crate::ATerm> ); 45 ($n:ty,) => ( $crate::TArr<$n, $crate::ATerm> ); 46 ($n:ty, $($tail:ty),+) => ( $crate::TArr<$n, tarr![$($tail),+]> ); 47 ($n:ty, $($tail:ty),+,) => ( $crate::TArr<$n, tarr![$($tail),+]> ); 48 } 49 50 // --------------------------------------------------------------------------------------- 51 // Length 52 53 /// Length of `ATerm` by itself is 0 54 impl Len for ATerm { 55 type Output = U0; 56 #[inline] len(&self) -> Self::Output57 fn len(&self) -> Self::Output { 58 UTerm 59 } 60 } 61 62 /// Size of a `TypeArray` 63 impl<V, A> Len for TArr<V, A> 64 where 65 A: Len, 66 Length<A>: Add<B1>, 67 Sum<Length<A>, B1>: Unsigned, 68 { 69 type Output = Add1<Length<A>>; 70 #[inline] len(&self) -> Self::Output71 fn len(&self) -> Self::Output { 72 self.rest.len() + B1 73 } 74 } 75 76 // --------------------------------------------------------------------------------------- 77 // Add arrays 78 // Note that two arrays are only addable if they are the same length. 79 80 impl Add<ATerm> for ATerm { 81 type Output = ATerm; 82 #[inline] add(self, _: ATerm) -> Self::Output83 fn add(self, _: ATerm) -> Self::Output { 84 ATerm 85 } 86 } 87 88 impl<Al, Vl, Ar, Vr> Add<TArr<Vr, Ar>> for TArr<Vl, Al> 89 where 90 Al: Add<Ar>, 91 Vl: Add<Vr>, 92 { 93 type Output = TArr<Sum<Vl, Vr>, Sum<Al, Ar>>; 94 #[inline] add(self, rhs: TArr<Vr, Ar>) -> Self::Output95 fn add(self, rhs: TArr<Vr, Ar>) -> Self::Output { 96 TArr { 97 first: self.first + rhs.first, 98 rest: self.rest + rhs.rest, 99 } 100 } 101 } 102 103 // --------------------------------------------------------------------------------------- 104 // Subtract arrays 105 // Note that two arrays are only subtractable if they are the same length. 106 107 impl Sub<ATerm> for ATerm { 108 type Output = ATerm; 109 #[inline] sub(self, _: ATerm) -> Self::Output110 fn sub(self, _: ATerm) -> Self::Output { 111 ATerm 112 } 113 } 114 115 impl<Vl, Al, Vr, Ar> Sub<TArr<Vr, Ar>> for TArr<Vl, Al> 116 where 117 Vl: Sub<Vr>, 118 Al: Sub<Ar>, 119 { 120 type Output = TArr<Diff<Vl, Vr>, Diff<Al, Ar>>; 121 #[inline] sub(self, rhs: TArr<Vr, Ar>) -> Self::Output122 fn sub(self, rhs: TArr<Vr, Ar>) -> Self::Output { 123 TArr { 124 first: self.first - rhs.first, 125 rest: self.rest - rhs.rest, 126 } 127 } 128 } 129 130 // --------------------------------------------------------------------------------------- 131 // Multiply an array by a scalar 132 133 impl<Rhs> Mul<Rhs> for ATerm { 134 type Output = ATerm; 135 #[inline] mul(self, _: Rhs) -> Self::Output136 fn mul(self, _: Rhs) -> Self::Output { 137 ATerm 138 } 139 } 140 141 impl<V, A, Rhs> Mul<Rhs> for TArr<V, A> 142 where 143 V: Mul<Rhs>, 144 A: Mul<Rhs>, 145 Rhs: Copy, 146 { 147 type Output = TArr<Prod<V, Rhs>, Prod<A, Rhs>>; 148 #[inline] mul(self, rhs: Rhs) -> Self::Output149 fn mul(self, rhs: Rhs) -> Self::Output { 150 TArr { 151 first: self.first * rhs, 152 rest: self.rest * rhs, 153 } 154 } 155 } 156 157 impl Mul<ATerm> for Z0 { 158 type Output = ATerm; 159 #[inline] mul(self, _: ATerm) -> Self::Output160 fn mul(self, _: ATerm) -> Self::Output { 161 ATerm 162 } 163 } 164 165 impl<U> Mul<ATerm> for PInt<U> 166 where 167 U: Unsigned + NonZero, 168 { 169 type Output = ATerm; 170 #[inline] mul(self, _: ATerm) -> Self::Output171 fn mul(self, _: ATerm) -> Self::Output { 172 ATerm 173 } 174 } 175 176 impl<U> Mul<ATerm> for NInt<U> 177 where 178 U: Unsigned + NonZero, 179 { 180 type Output = ATerm; 181 #[inline] mul(self, _: ATerm) -> Self::Output182 fn mul(self, _: ATerm) -> Self::Output { 183 ATerm 184 } 185 } 186 187 impl<V, A> Mul<TArr<V, A>> for Z0 188 where 189 Z0: Mul<A>, 190 { 191 type Output = TArr<Z0, Prod<Z0, A>>; 192 #[inline] mul(self, rhs: TArr<V, A>) -> Self::Output193 fn mul(self, rhs: TArr<V, A>) -> Self::Output { 194 TArr { 195 first: Z0, 196 rest: self * rhs.rest, 197 } 198 } 199 } 200 201 impl<V, A, U> Mul<TArr<V, A>> for PInt<U> 202 where 203 U: Unsigned + NonZero, 204 PInt<U>: Mul<A> + Mul<V>, 205 { 206 type Output = TArr<Prod<PInt<U>, V>, Prod<PInt<U>, A>>; 207 #[inline] mul(self, rhs: TArr<V, A>) -> Self::Output208 fn mul(self, rhs: TArr<V, A>) -> Self::Output { 209 TArr { 210 first: self * rhs.first, 211 rest: self * rhs.rest, 212 } 213 } 214 } 215 216 impl<V, A, U> Mul<TArr<V, A>> for NInt<U> 217 where 218 U: Unsigned + NonZero, 219 NInt<U>: Mul<A> + Mul<V>, 220 { 221 type Output = TArr<Prod<NInt<U>, V>, Prod<NInt<U>, A>>; 222 #[inline] mul(self, rhs: TArr<V, A>) -> Self::Output223 fn mul(self, rhs: TArr<V, A>) -> Self::Output { 224 TArr { 225 first: self * rhs.first, 226 rest: self * rhs.rest, 227 } 228 } 229 } 230 231 // --------------------------------------------------------------------------------------- 232 // Divide an array by a scalar 233 234 impl<Rhs> Div<Rhs> for ATerm { 235 type Output = ATerm; 236 #[inline] div(self, _: Rhs) -> Self::Output237 fn div(self, _: Rhs) -> Self::Output { 238 ATerm 239 } 240 } 241 242 impl<V, A, Rhs> Div<Rhs> for TArr<V, A> 243 where 244 V: Div<Rhs>, 245 A: Div<Rhs>, 246 Rhs: Copy, 247 { 248 type Output = TArr<Quot<V, Rhs>, Quot<A, Rhs>>; 249 #[inline] div(self, rhs: Rhs) -> Self::Output250 fn div(self, rhs: Rhs) -> Self::Output { 251 TArr { 252 first: self.first / rhs, 253 rest: self.rest / rhs, 254 } 255 } 256 } 257 258 // --------------------------------------------------------------------------------------- 259 // Partial Divide an array by a scalar 260 261 impl<Rhs> PartialDiv<Rhs> for ATerm { 262 type Output = ATerm; 263 #[inline] partial_div(self, _: Rhs) -> Self::Output264 fn partial_div(self, _: Rhs) -> Self::Output { 265 ATerm 266 } 267 } 268 269 impl<V, A, Rhs> PartialDiv<Rhs> for TArr<V, A> 270 where 271 V: PartialDiv<Rhs>, 272 A: PartialDiv<Rhs>, 273 Rhs: Copy, 274 { 275 type Output = TArr<PartialQuot<V, Rhs>, PartialQuot<A, Rhs>>; 276 #[inline] partial_div(self, rhs: Rhs) -> Self::Output277 fn partial_div(self, rhs: Rhs) -> Self::Output { 278 TArr { 279 first: self.first.partial_div(rhs), 280 rest: self.rest.partial_div(rhs), 281 } 282 } 283 } 284 285 // --------------------------------------------------------------------------------------- 286 // Modulo an array by a scalar 287 use core::ops::Rem; 288 289 impl<Rhs> Rem<Rhs> for ATerm { 290 type Output = ATerm; 291 #[inline] rem(self, _: Rhs) -> Self::Output292 fn rem(self, _: Rhs) -> Self::Output { 293 ATerm 294 } 295 } 296 297 impl<V, A, Rhs> Rem<Rhs> for TArr<V, A> 298 where 299 V: Rem<Rhs>, 300 A: Rem<Rhs>, 301 Rhs: Copy, 302 { 303 type Output = TArr<Mod<V, Rhs>, Mod<A, Rhs>>; 304 #[inline] rem(self, rhs: Rhs) -> Self::Output305 fn rem(self, rhs: Rhs) -> Self::Output { 306 TArr { 307 first: self.first % rhs, 308 rest: self.rest % rhs, 309 } 310 } 311 } 312 313 // --------------------------------------------------------------------------------------- 314 // Negate an array 315 use core::ops::Neg; 316 317 impl Neg for ATerm { 318 type Output = ATerm; 319 #[inline] neg(self) -> Self::Output320 fn neg(self) -> Self::Output { 321 ATerm 322 } 323 } 324 325 impl<V, A> Neg for TArr<V, A> 326 where 327 V: Neg, 328 A: Neg, 329 { 330 type Output = TArr<Negate<V>, Negate<A>>; 331 #[inline] neg(self) -> Self::Output332 fn neg(self) -> Self::Output { 333 TArr { 334 first: -self.first, 335 rest: -self.rest, 336 } 337 } 338 } 339