Skip to content

Commit 3463417

Browse files
committed
Add a trait to tie together compile-time and runtime number of dimensions
1 parent 5056ef8 commit 3463417

File tree

3 files changed

+154
-46
lines changed

3 files changed

+154
-46
lines changed

src/dimension/dimension_trait.rs

Lines changed: 29 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ use super::conversion::Convert;
1717
use super::ops::DimAdd;
1818
use super::{stride_offset, stride_offset_checked};
1919
use crate::itertools::{enumerate, zip};
20-
#[cfg(feature = "unstable")]
2120
use crate::layout::dimensionality::*;
21+
use crate::layout::ranked::Ranked;
2222
use crate::IntoDimension;
2323
use crate::RemoveAxis;
2424
use crate::{ArrayView1, ArrayViewMut1};
@@ -61,6 +61,7 @@ pub trait Dimension:
6161
+ DimAdd<Ix0, Output = Self>
6262
+ DimAdd<Ix1, Output = <Self as Dimension>::Larger>
6363
+ DimAdd<IxDyn, Output = IxDyn>
64+
+ Ranked
6465
{
6566
/// For fixed-size dimension representations (e.g. `Ix2`), this should be
6667
/// `Some(ndim)`, and for variable-size dimension representations (e.g.
@@ -78,12 +79,11 @@ pub trait Dimension:
7879
/// Next larger dimension
7980
type Larger: Dimension + RemoveAxis;
8081

81-
/// The dimensionality of the type, under the new, unstable API.
82-
#[cfg(feature = "unstable")]
83-
type Rank: Dimensionality;
84-
8582
/// Returns the number of dimensions (number of axes).
86-
fn ndim(&self) -> usize;
83+
fn ndim(&self) -> usize
84+
{
85+
self.rank()
86+
}
8787

8888
/// Convert the dimension into a pattern matching friendly value.
8989
fn into_pattern(self) -> Self::Pattern;
@@ -420,21 +420,26 @@ macro_rules! impl_insert_axis_array(
420420
);
421421
);
422422

423+
impl<const N: usize> Ranked for Dim<[Ix; N]>
424+
where NDim<N>: Dimensionality // Limit us to < 12, since Rank must impl Dimensionality
425+
{
426+
type Rank = NDim<N>;
427+
428+
#[inline]
429+
fn rank(&self) -> usize
430+
{
431+
N
432+
}
433+
}
434+
423435
impl Dimension for Dim<[Ix; 0]>
424436
{
425437
const NDIM: Option<usize> = Some(0);
426438
type Pattern = ();
427439
type Smaller = Self;
428440
type Larger = Ix1;
429-
#[cfg(feature = "unstable")]
430-
type Rank = D0;
431441
// empty product is 1 -> size is 1
432442
#[inline]
433-
fn ndim(&self) -> usize
434-
{
435-
0
436-
}
437-
#[inline]
438443
fn slice(&self) -> &[Ix]
439444
{
440445
&[]
@@ -478,13 +483,6 @@ impl Dimension for Dim<[Ix; 1]>
478483
type Pattern = Ix;
479484
type Smaller = Ix0;
480485
type Larger = Ix2;
481-
#[cfg(feature = "unstable")]
482-
type Rank = D1;
483-
#[inline]
484-
fn ndim(&self) -> usize
485-
{
486-
1
487-
}
488486
#[inline]
489487
fn slice(&self) -> &[Ix]
490488
{
@@ -613,13 +611,6 @@ impl Dimension for Dim<[Ix; 2]>
613611
type Pattern = (Ix, Ix);
614612
type Smaller = Ix1;
615613
type Larger = Ix3;
616-
#[cfg(feature = "unstable")]
617-
type Rank = D2;
618-
#[inline]
619-
fn ndim(&self) -> usize
620-
{
621-
2
622-
}
623614
#[inline]
624615
fn into_pattern(self) -> Self::Pattern
625616
{
@@ -790,13 +781,6 @@ impl Dimension for Dim<[Ix; 3]>
790781
type Pattern = (Ix, Ix, Ix);
791782
type Smaller = Ix2;
792783
type Larger = Ix4;
793-
#[cfg(feature = "unstable")]
794-
type Rank = D3;
795-
#[inline]
796-
fn ndim(&self) -> usize
797-
{
798-
3
799-
}
800784
#[inline]
801785
fn into_pattern(self) -> Self::Pattern
802786
{
@@ -924,10 +908,6 @@ macro_rules! large_dim {
924908
type Pattern = $pattern;
925909
type Smaller = Dim<[Ix; $n - 1]>;
926910
type Larger = $larger;
927-
#[cfg(feature = "unstable")]
928-
type Rank = NDim<$n>;
929-
#[inline]
930-
fn ndim(&self) -> usize { $n }
931911
#[inline]
932912
fn into_pattern(self) -> Self::Pattern {
933913
self.ix().convert()
@@ -968,6 +948,17 @@ large_dim!(6, Ix6, (Ix, Ix, Ix, Ix, Ix, Ix), IxDyn, {
968948
}
969949
});
970950

951+
impl Ranked for IxDyn
952+
{
953+
type Rank = DDyn;
954+
955+
#[inline]
956+
fn rank(&self) -> usize
957+
{
958+
self.ix().len()
959+
}
960+
}
961+
971962
/// IxDyn is a "dynamic" index, pretty hard to use when indexing,
972963
/// and memory wasteful, but it allows an arbitrary and dynamic number of axes.
973964
impl Dimension for IxDyn
@@ -976,13 +967,6 @@ impl Dimension for IxDyn
976967
type Pattern = Self;
977968
type Smaller = Self;
978969
type Larger = Self;
979-
#[cfg(feature = "unstable")]
980-
type Rank = DDyn;
981-
#[inline]
982-
fn ndim(&self) -> usize
983-
{
984-
self.ix().len()
985-
}
986970
#[inline]
987971
fn slice(&self) -> &[Ix]
988972
{

src/layout/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
//! flexible and expressive layout representations.
1010
1111
mod bitset;
12-
#[cfg(feature = "unstable")]
1312
pub mod dimensionality;
13+
pub mod ranked;
1414

1515
#[allow(deprecated)]
1616
pub use bitset::{Layout, LayoutBitset};

src/layout/ranked.rs

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
//! Unified trait for type- and runtime-level array rank.
2+
//!
3+
//! This module defines the [`Ranked`] trait, which bridges compile-time and runtime representations
4+
//! of array dimensionality. It enables generic code to query the number of dimensions (rank) of an
5+
//! array, whether known statically (via [`Dimensionality`]) or only at runtime. Blanket
6+
//! implementations are provided for common pointer and container types.
7+
8+
use crate::layout::dimensionality::{Dimensionality, D1};
9+
10+
/// A trait to unify type- and runtime-level number of dimensions.
11+
///
12+
/// The [`Dimensionality`] trait captures array rank at the type level; however it
13+
/// is limited at runtime. If the `Dimensionality` is dynamic (i.e., [`DDyn`][DDyn])
14+
/// then the dimensionality cannot be known at compile time. This trait unifies type-
15+
/// and runtime-level dimensionality by providing:
16+
/// 1. An associated type, [`Rank`][Rank], with type-level dimensionality
17+
/// 2. A function, [`ndim`][ndim], that can give the dimensionality at runtime.
18+
///
19+
/// [DDyn]: crate::layout::dimensionality::DDyn
20+
/// [Rank]: Ranked::Rank
21+
/// [ndim]: Ranked::ndim
22+
/// [N]: Dimensionality::N
23+
pub trait Ranked
24+
{
25+
/// The compile-time rank of the type; can be [`DDyn`][DDyn] if unknown.
26+
///
27+
/// [DDyn]: crate::layout::dimensionality::DDyn
28+
type Rank: Dimensionality;
29+
30+
/// The runtime number of dimensions of the type.
31+
fn rank(&self) -> usize;
32+
}
33+
34+
mod blanket_impls
35+
{
36+
use super::*;
37+
use alloc::rc::Rc;
38+
use alloc::sync::Arc;
39+
40+
impl<T> Ranked for &T
41+
where T: Ranked
42+
{
43+
type Rank = T::Rank;
44+
45+
fn rank(&self) -> usize
46+
{
47+
(*self).rank()
48+
}
49+
}
50+
51+
impl<T> Ranked for &mut T
52+
where T: Ranked
53+
{
54+
type Rank = T::Rank;
55+
56+
fn rank(&self) -> usize
57+
{
58+
(**self).rank()
59+
}
60+
}
61+
62+
impl<T> Ranked for Arc<T>
63+
where T: Ranked
64+
{
65+
type Rank = T::Rank;
66+
67+
fn rank(&self) -> usize
68+
{
69+
(**self).rank()
70+
}
71+
}
72+
73+
impl<T> Ranked for Rc<T>
74+
where T: Ranked
75+
{
76+
type Rank = T::Rank;
77+
78+
fn rank(&self) -> usize
79+
{
80+
(**self).rank()
81+
}
82+
}
83+
84+
impl<T> Ranked for Box<T>
85+
where T: Ranked
86+
{
87+
type Rank = T::Rank;
88+
89+
fn rank(&self) -> usize
90+
{
91+
(**self).rank()
92+
}
93+
}
94+
}
95+
96+
impl<T> Ranked for [T]
97+
{
98+
type Rank = D1;
99+
100+
fn rank(&self) -> usize
101+
{
102+
1
103+
}
104+
}
105+
106+
impl<T> Ranked for Vec<T>
107+
{
108+
type Rank = D1;
109+
110+
fn rank(&self) -> usize
111+
{
112+
1
113+
}
114+
}
115+
116+
impl<T, const N: usize> Ranked for [T; N]
117+
{
118+
type Rank = D1;
119+
120+
fn rank(&self) -> usize
121+
{
122+
1
123+
}
124+
}

0 commit comments

Comments
 (0)