array_trait/array_nd.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
use super::*;
/// A trait for N-dimensional arrays with depth up to 64.
///
/// The associated constants [DIMENSIONS](ArrayNd::DIMENSIONS) and [FLAT_LENGTH](ArrayNd::FLAT_LENGTH) vary depending on the chosen depth.
///
/// The assiciated type [ItemNd](ArrayNd::ItemNd) represents the innermost type given a chosen depth.
///
/// # Examples
///
/// ```rust
/// #![feature(generic_const_exprs)]
///
/// use array_trait::*;
///
/// type Mat2x3 = [[i8; 3]; 2];
///
/// /// The number of dimensions
/// const DEPTH: usize = 2;
///
/// // `FLAT_LENGTH` is the combined length if the N-dimensional array was flattened,
/// // i.e. the product of the lengths of each dimension.
/// assert_eq!(<Mat2x3 as ArrayNd<DEPTH>>::FLAT_LENGTH, 6);
///
/// // `DIMENSIONS` contains the lengths of each dimension ordered outermost to innermost.
/// assert_eq!(<Mat2x3 as ArrayNd<DEPTH>>::DIMENSIONS, [2, 3]);
/// ```
pub trait ArrayNd<const DEPTH: usize>: Array
{
/// The dimensions of the n-dimensional containing the lengths of each level of array from outermost to innermost
const DIMENSIONS: [usize; DEPTH];
/// The product of the lengths of each dimension.
const FLAT_LENGTH: usize;
type ItemNd;
}
macro_rules! count {
() => {0};
($a:ident) => {1};
($a:ident $($b:ident)+) => {1 $(+ count!($b))+};
}
macro_rules! flat_len {
() => {0};
($a:ident $($b:ident)*) => {$a $(* $b)*}
}
macro_rules! nd {
($t:ty;) => {
$t
};
($t:ty; $a:ident) => {
[$t; $a]
};
($t:ty; $a:ident $($b:ident)+) => {
[nd!{$t; $($b)+}; $a]
};
}
macro_rules! impl_nd_array {
($a:ident $($($b:ident)+)?) => {
impl<T, const $a: usize $($(, const $b: usize)+)?> /*const*/ ArrayNd<{count!{$a $($($b)+)?}}> for nd!{T; $a $($($b)+)?}
{
const DIMENSIONS: [usize; count!{$a $($($b)+)?}] = [$a $($(, $b)+)?];
const FLAT_LENGTH: usize = flat_len!{$a $($($b)+)?};
type ItemNd = T;
}
$(impl_nd_array!($($b)+);)?
};
}
mod r#impl
{
use super::*;
impl_nd_array!(
_0 _1 _2 _3 _4 _5 _6 _7 _8 _9 _10 _11 _12 _13 _14 _15 _16
_17 _18 _19 _20 _21 _22 _23 _24 _25 _26 _27 _28 _29 _30 _31 _32
_33 _34 _35 _36 _37 _38 _39 _40 _41 _42 _43 _44 _45 _46 _47 _48
_49 _50 _51 _52 _53 _54 _55 _56 _57 _58 _59 _60 _61 _62 _63 _64
);
}
/*
_65 _66 _67 _68 _69 _70 _71 _72 _73 _74 _75 _76 _77 _78 _79 _80
_81 _82 _83 _84 _85 _86 _87 _88 _89 _90 _91 _92 _93 _94 _95 _96
_97 _98 _99 _100 _101 _102 _103 _104 _105 _106 _107 _108 _109 _110 _111 _112
_113 _114 _115 _116 _117 _118 _119 _120 _121 _122 _123 _124 _125 _126 _127 _128
*/
#[cfg(test)]
mod test
{
#[test]
fn test()
{
use crate::*;
type Mat2x3 = [[i8; 3]; 2];
/// The number of dimensions
const DEPTH: usize = 2;
// `FLAT_LENGTH` is the combined length if the N-dimensional array was flattened
assert_eq!(<Mat2x3 as ArrayNd<DEPTH>>::FLAT_LENGTH, 6);
// `DIMENSIONS` contains the lengths of each dimension ordered outermost to innermost.
assert_eq!(<Mat2x3 as ArrayNd<DEPTH>>::DIMENSIONS, [2, 3]);
}
}