Plan for dimension types
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 20/100
Research direction
Start by reading the existing Dimension and ArrayBase implementations, then compare how Ix2 and IxDyn currently represent shapes and strides. The proposal requires agreement on the associated-type design, conversion traits, and type-level operations before implementation; completion would include resolving the related dimension issues and validating the affected API.
Written by the indexing model from the issue text.
Description
I've been thinking about the dimension types for a while. Two things I don't like about the current implementation are that:
- Strides are represented as
usizeand have to be converted toisizeevery time they're used. This is error-prone and confusing. - It seems a little weird that the dimension type itself (instead of an associated type) has a representation. For example, "2-D" doesn't necessary imply a specific representation to me.
What I'd like to do is something like the following:
pub trait Dimension
where
for<'a> Into<Self::OwnedUsize> for &'a Self::BorrowedUsize,
for<'a> Into<Self::OwnedIsize> for &'a Self::BorrowedIsize,
{
type OwnedUsize: AsRef<Self::BorrowedUsize> + AsMut<Self::BorrowedUsize> + AsRef<[usize]> + AsMut<[usize]>;
type BorrowedUsize: ?Sized + AsRef<[usize]> + AsMut<[usize]>;
type OwnedIsize: AsRef<Self::BorrowedIsize> + AsMut<Self::BorrowedIsize> + AsRef<[isize]> + AsMut<[isize]>;
type BorrowedIsize: ?Sized + AsRef<[isize]> + AsMut<[isize]>;
}
pub struct Ix2;
pub struct IxDyn;
impl Dimension for Ix2 {
type OwnedUsize = [usize; 2];
type BorrowedUsize = [usize; 2];
type OwnedIsize = [isize; 2];
type BorrowedIsize = [isize; 2];
}
impl Dimension for IxDyn {
type OwnedUsize = IxDynImpl<usize>;
type BorrowedUsize = [usize];
type OwnedIsize = IxDynImpl<isize>;
type BorrowedIsize = [isize];
}
pub trait IntoDimOwnedUsize {
type Dim: Dimension;
fn into_dim_owned_usize(self) -> Self::Dim::OwnedUsize;
}
pub trait AsDimBorrowedUsize {
type Dim: Dimension;
fn as_dim_borrowed_usize(&self) -> &Self::Dim::BorrowedUsize;
}
pub trait IntoDimOwnedIsize { ... }
pub trait AsDimBorrowedIsize { ... }
pub struct ArrayBase<S, D>
where
S: Data,
{
data: S,
ptr: *mut S::Elem,
dim: D::OwnedUsize,
strides: D::OwnedIsize,
}
impl<A, S, D> ArrayBase<S, D>
where
S: Data<Elem = A>,
D: Dimension,
{
pub fn shape(&self) -> &D::BorrowedUsize {
// ...
}
pub fn strides(&self) -> &D::BorrowedIsize {
// ...
}
}
Once Rust has generic associated types, we can simplify this to:
pub trait Dimension
where
for<'a, T: Clone> Into<Self::Owned<T>> for &'a Self::Borrowed,
{
type Owned<T>: AsRef<Self::Borrowed<T>> + AsMut<Self::Borrowed<T>> + AsRef<[T]> + AsMut<[T]>;
type Borrowed<T>>: ?Sized + AsRef<[T]> + AsMut<[T]>;
}
pub struct Ix2;
pub struct IxDyn;
impl Dimension for Ix2 {
type Owned<T> = [T; 2];
type Borrowed<T> = [T; 2];
}
impl Dimension for IxDyn {
type Owned<T> = IxDynImpl<T>;
type Borrowed<T> = [T];
}
pub trait IntoDimOwned<T> {
type Dim: Dimension;
fn into_dim_owned(self) -> Self::Dim::Owned<T>;
}
pub trait AsDimBorrowed<T> {
type Dim: Dimension;
fn as_dim_borrowed(&self) -> &Self::Dim::Borrowed<T>;
}
pub struct ArrayBase<S, D>
where
S: Data,
{
data: S,
ptr: *mut S::Elem,
dim: D::Owned<usize>,
strides: D::Owned<isize>,
}
impl<A, S, D> ArrayBase<S, D>
where
S: Data<Elem = A>,
D: Dimension,
{
pub fn shape(&self) -> &D::Borrowed<usize> {
// ...
}
pub fn strides(&self) -> &D::Borrowed<isize> {
// ...
}
}
I'd also add various type-level arithmetic operations on the dimension types, which are necessary for things like co-broadcasting (trait PartialOrdDim) and fold_axes (trait SubDim).
We can also add Shape<T>, Strides<T>, and Index<T> thin wrapper types.
This approach would resolve things like #489 and this comment on #367.
Thoughts?
- Dominant language
- Rust
- Stars
- 4.3k
- Forks
- 391
- PR merge metrics
- No merged PRs in 30d
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from rust-ndarray/ndarray
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
rust-ndarray/ndarray#1612 · 1 comment ·
-
Difficulty 4/5 3-5 days Newbie friendliness 48/100
rust-ndarray/ndarray#1617 · 1 comment ·
-
bug good first issue
Difficulty 3/5 1-2 days Newbie friendliness 68/100
rust-ndarray/ndarray#1615 · 1 comment ·
-
Difficulty 4/5 3-5 days Newbie friendliness 48/100
rust-ndarray/ndarray#1610 ·
-
Difficulty 3/5 1-2 days Newbie friendliness 72/100
rust-ndarray/ndarray#1609 ·
All issues in rust-ndarray/ndarray
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
kwakseongjae/auto-hwp#319 ·
-
area:cli bug filter-quality good first issue priority:medium
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
-
Difficulty 1/5 Under an hour Newbie friendliness 72/100
bevyengine/bevy#25861 ·
-
comp-datalake
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
ClickHouse/ClickHouse#121222 ·
-
enhancement remote
Difficulty 2/5 1-3 hours Newbie friendliness 68/100