From 2ea5d90ea6e1eb1c0ff61a62ac421109f992eaa8 Mon Sep 17 00:00:00 2001
From: thatcomputerguy0101 <thatcomputerguy0101@gmail.com>
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<const D: usize>(ix: [Ix; D]) -> IxD<D> {
+    Dim::new(ix)
+}
+
+impl<const D: usize> IxD<D> {
+    /// 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<IxDynImpl>;
+/// static-dimensional
+/// 
+/// Static generic to create arrays of any dimensionality up to 6
+pub type IxD<const D: usize> = Dim<[Ix; D]>;
 
 /// zero-dimensional array
 pub type Array0<A> = Array<A, Ix0>;
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<Ix>
     }
 }
 
+impl<const D: usize> 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<const D: usize> Index<usize> 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<const D: usize> IndexMut<usize> 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<const D: usize> 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<usize> for Dim<[Ix; $n]> {
-            type Output = usize;
-            #[inline(always)]
-            fn index(&self, index: usize) -> &Self::Output {
-                &self.ix()[index]
-            }
-        }
-
-        impl IndexMut<usize> 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 <thatcomputerguy0101@gmail.com>
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<Ix>
 }
 
 impl<const D: usize> 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<const D: usize> Index<usize> 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<const D: usize> IndexMut<usize> 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<const D: usize> 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 <thatcomputerguy0101@gmail.com>
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<const D: usize>(ix: [Ix; D]) -> IxD<D>
+{
+    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<const D: usize>(ix: [Ix; D]) -> IxD<D> {
-    Dim::new(ix)
-}
-
-impl<const D: usize> IxD<D> {
+impl<const D: usize> IxD<D>
+{
     /// 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<const D: usize> = 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<IxDynImpl>;
-/// static-dimensional
-/// 
-/// Static generic to create arrays of any dimensionality up to 6
-pub type IxD<const D: usize> = Dim<[Ix; D]>;
 
 /// zero-dimensional array
 pub type Array0<A> = Array<A, Ix0>;
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 <thatcomputerguy0101@gmail.com>
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<D: Dimension> DimMax<D> for D
     type Output = D;
 }
 
+/// Any static type dimension can be broadcast to a dynamic dimension
+impl<const D: usize> DimMax<IxDyn> for IxD<D>
+where IxD<D>: Dimension
+{
+    type Output = IxDyn;
+}
+
+/// Any static type dimension can be broadcast to a dynamic dimension
+impl<const D: usize> DimMax<IxD<D>> for IxDyn
+where IxD<D>: 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 <thatcomputerguy0101@gmail.com>
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.);
+}
+