diff --git a/src/aliases.rs b/src/aliases.rs index 5df0c95ec..7bcafe47b 100644 --- a/src/aliases.rs +++ b/src/aliases.rs @@ -4,6 +4,13 @@ use crate::dimension::Dim; use crate::{ArcArray, Array, ArrayView, ArrayViewMut, Ix, IxDynImpl}; +/// Create a static-dimensional index +#[allow(non_snake_case)] +#[inline(always)] +pub fn IxD(ix: [Ix; D]) -> IxD +{ + Dim::new(ix) +} /// Create a zero-dimensional index #[allow(non_snake_case)] #[inline(always)] @@ -62,6 +69,19 @@ pub fn IxDyn(ix: &[Ix]) -> IxDyn Dim(ix) } +impl IxD +{ + /// Create a static-dimensional index, repeating a single index value + #[inline(always)] + pub fn repeating(i: Ix) -> Self { + Dim::new([i; D]) + } +} + +/// static-dimensional +/// +/// Static generic to create arrays of any supported dimensionality (up to 6) +pub type IxD = Dim<[Ix; D]>; /// zero-dimensionial pub type Ix0 = Dim<[Ix; 0]>; /// one-dimensional diff --git a/src/dimension/broadcast.rs b/src/dimension/broadcast.rs index d277cfea2..53f9415dd 100644 --- a/src/dimension/broadcast.rs +++ b/src/dimension/broadcast.rs @@ -1,5 +1,5 @@ use crate::error::*; -use crate::{Dimension, Ix0, Ix1, Ix2, Ix3, Ix4, Ix5, Ix6, IxDyn}; +use crate::{Dimension, IxD, Ix0, Ix1, Ix2, Ix3, Ix4, Ix5, Ix6, IxDyn}; /// Calculate the common shape for a pair of array shapes, that they can be broadcasted /// to. Return an error if the shapes are not compatible. @@ -48,6 +48,20 @@ impl DimMax for D type Output = D; } +/// Any static type dimension can be broadcast to a dynamic dimension +impl DimMax for IxD +where IxD: Dimension +{ + type Output = IxDyn; +} + +/// Any static type dimension can be broadcast to a dynamic dimension +impl DimMax> for IxDyn +where IxD: Dimension +{ + type Output = IxDyn; +} + macro_rules! impl_broadcast_distinct_fixed { ($smaller:ty, $larger:ty) => { impl DimMax<$larger> for $smaller { @@ -81,13 +95,6 @@ impl_broadcast_distinct_fixed!(Ix3, Ix6); impl_broadcast_distinct_fixed!(Ix4, Ix5); impl_broadcast_distinct_fixed!(Ix4, Ix6); impl_broadcast_distinct_fixed!(Ix5, Ix6); -impl_broadcast_distinct_fixed!(Ix0, IxDyn); -impl_broadcast_distinct_fixed!(Ix1, IxDyn); -impl_broadcast_distinct_fixed!(Ix2, IxDyn); -impl_broadcast_distinct_fixed!(Ix3, IxDyn); -impl_broadcast_distinct_fixed!(Ix4, IxDyn); -impl_broadcast_distinct_fixed!(Ix5, IxDyn); -impl_broadcast_distinct_fixed!(Ix6, IxDyn); #[cfg(test)] #[cfg(feature = "std")] diff --git a/src/dimension/conversion.rs b/src/dimension/conversion.rs index 0cf2e1296..fa74db5c9 100644 --- a/src/dimension/conversion.rs +++ b/src/dimension/conversion.rs @@ -87,6 +87,53 @@ impl IntoDimension for Vec } } +impl IntoDimension for [Ix; D] +where Dim<[Ix; D]> : Dimension +{ + type Dim = Dim<[Ix; D]>; + #[inline(always)] + fn into_dimension(self) -> Self::Dim + { + Dim::new(self) + } +} + +impl Index for Dim<[Ix; D]> +where Dim<[Ix; D]>: Dimension +{ + type Output = usize; + #[inline(always)] + fn index(&self, index: usize) -> &Self::Output + { + &self.ix()[index] + } +} + +impl IndexMut for Dim<[Ix; D]> +where Dim<[Ix; D]>: Dimension +{ + #[inline(always)] + fn index_mut(&mut self, index: usize) -> &mut Self::Output + { + &mut self.ixm()[index] + } +} + +impl Zero for Dim<[Ix; D]> +where Dim<[Ix; D]>: Dimension +{ + #[inline] + fn zero() -> Self + { + Self::repeating(0) + } + + fn is_zero(&self) -> bool + { + self.slice().iter().all(|x| *x == 0) + } +} + pub trait Convert { type To; @@ -117,12 +164,6 @@ macro_rules! array_expr { ); } -macro_rules! array_zero { - ([] $($index:tt)*) => ( - [$(sub!($index 0), )*] - ); -} - macro_rules! tuple_to_array { ([] $($n:tt)*) => { $( @@ -134,14 +175,6 @@ macro_rules! tuple_to_array { } } - impl IntoDimension for [Ix; $n] { - type Dim = Dim<[Ix; $n]>; - #[inline(always)] - fn into_dimension(self) -> Self::Dim { - Dim::new(self) - } - } - impl IntoDimension for index!(tuple_type [Ix] $n) { type Dim = Dim<[Ix; $n]>; #[inline(always)] @@ -150,31 +183,6 @@ macro_rules! tuple_to_array { } } - impl Index for Dim<[Ix; $n]> { - type Output = usize; - #[inline(always)] - fn index(&self, index: usize) -> &Self::Output { - &self.ix()[index] - } - } - - impl IndexMut for Dim<[Ix; $n]> { - #[inline(always)] - fn index_mut(&mut self, index: usize) -> &mut Self::Output { - &mut self.ixm()[index] - } - } - - impl Zero for Dim<[Ix; $n]> { - #[inline] - fn zero() -> Self { - Dim::new(index!(array_zero [] $n)) - } - fn is_zero(&self) -> bool { - self.slice().iter().all(|x| *x == 0) - } - } - )* }; } diff --git a/src/prelude.rs b/src/prelude.rs index acf39da1a..908e3c1c2 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -42,7 +42,7 @@ pub use crate::{ }; #[doc(no_inline)] -pub use crate::{Ix0, Ix1, Ix2, Ix3, Ix4, Ix5, Ix6, IxDyn}; +pub use crate::{IxD, Ix0, Ix1, Ix2, Ix3, Ix4, Ix5, Ix6, IxDyn}; #[doc(no_inline)] pub use crate::{arr0, arr1, arr2, aview0, aview1, aview2, aview_mut1}; diff --git a/tests/ixd.rs b/tests/ixd.rs new file mode 100644 index 000000000..b06acd536 --- /dev/null +++ b/tests/ixd.rs @@ -0,0 +1,36 @@ +#![allow( + clippy::many_single_char_names, clippy::deref_addrof, clippy::unreadable_literal, clippy::many_single_char_names, + clippy::float_cmp +)] + +use ndarray::Array; +use ndarray::IxD; +use ndarray::Ix2; + +#[test] +fn test_ixd() +{ + // Check that IxD creats a static index based on the provided array size + let mut a = Array::zeros(IxD([2, 3])); + assert_eq!(a.raw_dim(), Ix2(2, 3)); + + assert_eq!(a[(1, 1)], 0.); + + a[(1, 1)] = 3.; + assert_eq!(a[(1, 1)], 3.); + + // Wrong index dimension is caught by the type checker + // a[(1, 1, 1)] = 4.; +} + +#[test] +fn test_ixd_repeating() +{ + // Check that repeating creates an array of a specified dimension + let mut a = Array::zeros(IxD::<2>::repeating(2)); + assert_eq!(a.raw_dim(), Ix2(2, 2)); + + a[(1, 1)] = 2.; + assert_eq!(a[(1, 1)], 2.); +} +