From 2ea5d90ea6e1eb1c0ff61a62ac421109f992eaa8 Mon Sep 17 00:00:00 2001 From: thatcomputerguy0101 Date: Sat, 11 May 2024 19:30:15 -0400 Subject: [PATCH 1/5] Add generic initializers for statically-dimensioned array types --- src/aliases.rs | 21 ++++++++++ src/dimension/conversion.rs | 79 ++++++++++++++++++------------------- 2 files changed, 60 insertions(+), 40 deletions(-) diff --git a/src/aliases.rs b/src/aliases.rs index 5df0c95ec..c85347edc 100644 --- a/src/aliases.rs +++ b/src/aliases.rs @@ -62,6 +62,23 @@ pub fn IxDyn(ix: &[Ix]) -> IxDyn Dim(ix) } +/// Create a static-dimensional index +#[allow(non_snake_case)] +#[inline(always)] +pub fn IxD(ix: [Ix; D]) -> IxD { + Dim::new(ix) +} + +impl IxD { + /// Create a static-dimensional index, repeating a single index value + #[allow(non_snake_case)] + #[inline(always)] + pub fn repeating(i: Ix) -> Self { + Dim::new([i; D]) + } +} + + /// zero-dimensionial pub type Ix0 = Dim<[Ix; 0]>; /// one-dimensional @@ -105,6 +122,10 @@ pub type Ix6 = Dim<[Ix; 6]>; /// let arrays = vec![a, b]; /// ``` pub type IxDyn = Dim; +/// static-dimensional +/// +/// Static generic to create arrays of any dimensionality up to 6 +pub type IxD = Dim<[Ix; D]>; /// zero-dimensional array pub type Array0 = Array; diff --git a/src/dimension/conversion.rs b/src/dimension/conversion.rs index 0cf2e1296..53c507e78 100644 --- a/src/dimension/conversion.rs +++ b/src/dimension/conversion.rs @@ -13,7 +13,7 @@ use alloc::vec::Vec; use num_traits::Zero; use std::ops::{Index, IndexMut}; -use crate::{Dim, Dimension, Ix, Ix1, IxDyn, IxDynImpl}; +use crate::{Dim, Dimension, Ix, Ix1, IxD, IxDyn, IxDynImpl}; /// $m: macro callback /// $m is called with $arg and then the indices corresponding to the size argument @@ -87,6 +87,44 @@ 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 { + IxD::repeating(0) + } + + fn is_zero(&self) -> bool { + self.slice().iter().all(|x| *x == 0) + } +} + pub trait Convert { type To; @@ -117,12 +155,6 @@ macro_rules! array_expr { ); } -macro_rules! array_zero { - ([] $($index:tt)*) => ( - [$(sub!($index 0), )*] - ); -} - macro_rules! tuple_to_array { ([] $($n:tt)*) => { $( @@ -134,14 +166,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 +174,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) - } - } - )* }; } From 32ff2da80ea26d37fa1be333ba5a3856d8d68117 Mon Sep 17 00:00:00 2001 From: thatcomputerguy0101 Date: Sun, 12 May 2024 14:01:02 -0400 Subject: [PATCH 2/5] Formatting convention adjustments --- src/dimension/conversion.rs | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/dimension/conversion.rs b/src/dimension/conversion.rs index 53c507e78..fa74db5c9 100644 --- a/src/dimension/conversion.rs +++ b/src/dimension/conversion.rs @@ -13,7 +13,7 @@ use alloc::vec::Vec; use num_traits::Zero; use std::ops::{Index, IndexMut}; -use crate::{Dim, Dimension, Ix, Ix1, IxD, IxDyn, IxDynImpl}; +use crate::{Dim, Dimension, Ix, Ix1, IxDyn, IxDynImpl}; /// $m: macro callback /// $m is called with $arg and then the indices corresponding to the size argument @@ -88,39 +88,48 @@ impl IntoDimension for Vec } impl IntoDimension for [Ix; D] -where Dim<[Ix; D]> : Dimension { +where Dim<[Ix; D]> : Dimension +{ type Dim = Dim<[Ix; D]>; #[inline(always)] - fn into_dimension(self) -> Self::Dim { + fn into_dimension(self) -> Self::Dim + { Dim::new(self) } } impl Index for Dim<[Ix; D]> -where Dim<[Ix; D]>: Dimension { +where Dim<[Ix; D]>: Dimension +{ type Output = usize; #[inline(always)] - fn index(&self, index: usize) -> &Self::Output { + fn index(&self, index: usize) -> &Self::Output + { &self.ix()[index] } } impl IndexMut for Dim<[Ix; D]> -where Dim<[Ix; D]>: Dimension { +where Dim<[Ix; D]>: Dimension +{ #[inline(always)] - fn index_mut(&mut self, index: usize) -> &mut Self::Output { + 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 { +where Dim<[Ix; D]>: Dimension +{ #[inline] - fn zero() -> Self { - IxD::repeating(0) + fn zero() -> Self + { + Self::repeating(0) } - fn is_zero(&self) -> bool { + fn is_zero(&self) -> bool + { self.slice().iter().all(|x| *x == 0) } } From ccdb221337fe056c3b2da080596aad783fca35f8 Mon Sep 17 00:00:00 2001 From: thatcomputerguy0101 Date: Sat, 6 Jul 2024 10:25:05 -0400 Subject: [PATCH 3/5] Index-related format tweaks --- src/aliases.rs | 27 +++++++++++++-------------- src/prelude.rs | 2 +- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/aliases.rs b/src/aliases.rs index c85347edc..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,23 +69,19 @@ pub fn IxDyn(ix: &[Ix]) -> IxDyn Dim(ix) } -/// Create a static-dimensional index -#[allow(non_snake_case)] -#[inline(always)] -pub fn IxD(ix: [Ix; D]) -> IxD { - Dim::new(ix) -} - -impl IxD { +impl IxD +{ /// Create a static-dimensional index, repeating a single index value - #[allow(non_snake_case)] #[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 @@ -122,10 +125,6 @@ pub type Ix6 = Dim<[Ix; 6]>; /// let arrays = vec![a, b]; /// ``` pub type IxDyn = Dim; -/// static-dimensional -/// -/// Static generic to create arrays of any dimensionality up to 6 -pub type IxD = Dim<[Ix; D]>; /// zero-dimensional array pub type Array0 = Array; 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}; From 9b0598ef59082f4036d2e35740ca766d4af1e33b Mon Sep 17 00:00:00 2001 From: thatcomputerguy0101 Date: Sat, 6 Jul 2024 10:26:05 -0400 Subject: [PATCH 4/5] Unified static-dynamic max dimension --- src/dimension/broadcast.rs | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) 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")] From 789ecef1f6edccc0d160e44919ffaf1d6698afbc Mon Sep 17 00:00:00 2001 From: thatcomputerguy0101 Date: Fri, 19 Jul 2024 00:56:09 -0400 Subject: [PATCH 5/5] Generic static index intialization tests --- tests/ixd.rs | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 tests/ixd.rs 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.); +} +