Direct access to Shape

Open
#592 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
35/100
Issue type
Feature
Clarity
Mostly clear
Activity status
Stale
Tech stack
rust
Domain
data

Research direction

Start by reading ArrayBase::dim, raw_dim, as_slice, and as_slice_memory_order, then trace the Shape and ShapeBuilder APIs referenced in the issue. Done means callers can directly obtain an array's Shape and determine row-major, column-major, or non-contiguous layout without relying on the workaround shown.

Written by the indexing model from the issue text.

Description

I have this code, which takes a matrix and tries to create a matrix with similar specifications, i.e. a matrix with the same Shape. Unfortunately, this turns out to be more complicated then I hoped, because I don't have an easy way to check the memory layout of my matrix.

The reasons are:

  1. I don't have direct access to Shape, but only to Dim::Pattern (via ArrayBase::dim) or Dim (via ArrayBase::raw_dim). If I could get the Shape from an array, I could pass it to the various methods that accept a T: ShapeBuilder.
  2. There is no way to check if a matrix is in column major or row major form. Similarly, there is no way to check if a Shape is for column or row major form.

The only workaround that I see and am using, is to call as_slice and as_slice_memory_order on my array. If the first call returns an Option, I know I am in row major form. If it returns None but as_slice_memory_order returns an Option, I know I am in column major form. Both of these methods of course depend on the current specific implementation in ndarray.

It would be nice to have a more direct check for the memory layout. This is important when writing methods that call blas or lapack functions.

See the code below for reference.

fn from_matrix<S>(a: &ArrayBase<S, Ix2>) -> Result<Self>
    where S: Data<Elem = f64>
{
    use cblas::Layout::*;
    let dim = a.dim();
    let shape = match utils::get_layout(a) {
        Some(ColumnMajor) => dim.f(),
        Some(RowMajor) => dim.into_shape(),
        None => Err(Error::NonContiguous)?,
    };
                                                         
    Self::from_shape(shape)
}

fn from_shape<T>(shape: T) -> Result<Self>
    where T: ShapeBuilder<Dim = Ix2>,
{
    // Unfortunately we cannot check the shape itself to see if it's
    // in ColumnMajor or RowMajor layout. So we need to first construct
    // an array and then check that.
    let shape = shape.into_shape();
    let q = Array2::zeros(shape);
    let memory_layout = match get_layout(&q) {
        Some(layout) => layout,
        None => Err(Error::NonContiguous)?,
    };
    let r = q.clone();
    Ok(ClassicalGramSchmidt {
        q,
        r,
        memory_layout,
    })
}

fn get_layout<S, T, D>(a: &ArrayBase<S, D>) -> Option<cblas::Layout>
    where S: Data<Elem=T>,
          D: Dimension
{
    if let Some(_) = a.as_slice() {
        Some(cblas::Layout::RowMajor)
    } else if let Some(_) = a.as_slice_memory_order() {
        Some(cblas::Layout::ColumnMajor)
    } else {
        None
    }
}
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

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from rust-ndarray/ndarray

All issues in rust-ndarray/ndarray

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.