Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add generic initializers for statically-dimensioned array types #1385

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/aliases.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -62,6 +69,19 @@ pub fn IxDyn(ix: &[Ix]) -> IxDyn
Dim(ix)
}

impl<const D: usize> IxD<D>
{
/// 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<const D: usize> = Dim<[Ix; D]>;
/// zero-dimensionial
pub type Ix0 = Dim<[Ix; 0]>;
/// one-dimensional
Expand Down
23 changes: 15 additions & 8 deletions src/dimension/broadcast.rs
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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")]
Expand Down
86 changes: 47 additions & 39 deletions src/dimension/conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,53 @@ 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
{
Self::repeating(0)
}

fn is_zero(&self) -> bool
{
self.slice().iter().all(|x| *x == 0)
}
}

pub trait Convert
{
type To;
Expand Down Expand Up @@ -117,12 +164,6 @@ macro_rules! array_expr {
);
}

macro_rules! array_zero {
([] $($index:tt)*) => (
[$(sub!($index 0), )*]
);
}

macro_rules! tuple_to_array {
([] $($n:tt)*) => {
$(
Expand All @@ -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)]
Expand All @@ -150,31 +183,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)
}
}

)*
};
}
Expand Down
2 changes: 1 addition & 1 deletion src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down
36 changes: 36 additions & 0 deletions tests/ixd.rs
Original file line number Diff line number Diff line change
@@ -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.);
}