Plan for dimension types

オープン
#519 コメント 7 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

評価

難易度
5/5
見積もり時間
1週間以上
初心者へのやさしさ
20/100
issue の種類
リファクタリング
明瞭さ
説明が足りない
活発さ
停滞
技術スタック
rust
領域
data

調査の方向性

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.

索引モデルが issue の本文から書いたものです。

説明

I've been thinking about the dimension types for a while. Two things I don't like about the current implementation are that:

  1. Strides are represented as usize and have to be converted to isize every time they're used. This is error-prone and confusing.
  2. 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?

主要言語
Rust
スター
4.3k
フォーク
391
PR マージ指標
30日以内にマージされた PR はありません

コントリビューションガイド

このリポジトリのコントリビューションガイドは索引されていません

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

rust-ndarray/ndarray のほかの issue

rust-ndarray/ndarray の issue をすべて見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。