Skip to content

Improving slicing (or viewing?) #7

Open
@grothesque

Description

@grothesque

Here is a NumPy demonstration of what I mean with slicing:

>>> import numpy as np
>>> a = np.arange(16).reshape((2,)*4)
>>> a[1, :, :, :]
array([[[ 8,  9],
        [10, 11]],

       [[12, 13],
        [14, 15]]])
>>> a[1, ...]
array([[[ 8,  9],
        [10, 11]],

       [[12, 13],
        [14, 15]]])
>>> a[:, 1, ...]
array([[[ 4,  5],
        [ 6,  7]],

       [[12, 13],
        [14, 15]]])
>>> a[:, 1, ..., np.newaxis]
array([[[[ 4],
         [ 5]],

        [[ 6],
         [ 7]]],


       [[[12],
         [13]],

        [[14],
         [15]]]])

Mdarray provides something similar through the methods tensor, view, and view_mut of Slice. There is an equivalent of Python's : (the various ranges that implement DimIndex), but as far as I can see there is no equivalent of .../ellipsis or np.newaxis (which is actually just an alternative name for None).

One conceptual difference that I see compared to NumPy (and also Rust's ndarray: https://docs.rs/ndarray/latest/ndarray/macro.s.html) is that the view operations never take the index as a single argument, but always as a bunch of individual arguments. An appropriate trait exists (ViewIndex), but it is only used internally. This approach simplifies the syntax (are there other reasons for it?), but I note the following limitations:

  • There seems to be no easy way (without rather arcane macro use) to wrap view and friends inside an API. Let's say that I'd like to write a function that internally calls view in some customizable way. I can pass in an argument that implements ViewIndex, but there is no way to "apply" this argument (in the functional programming sense) to the view method. (This is not a hypothetical problem. I'm working on a library where I'd like to be able to deal with such ViewIndex implementing objects.)

  • view does not work for dynamic rank arrays (and is limited to six dimensions).

  • Having an ellipsis equivalent would be nice, especially for dynamic rank.

  • Having a newaxis equivalent might be nice, if it doesn't complicate things too much.

Does the author of mdarray think that these issues are worth addressing? Perhaps a possible solution could use the following elements? (This is not a complete design, just some ideas.)

  • Modify view and friends to take a single argument of a type that implements ViewIndex. Not sure if the trait ViewIndex is (or can be made) general enough so that static rank

  • Perhaps provide a macro (in the spirit of ndarray's) if the syntax would be unwieldy.

  • Add an ellipsis type (or reuse something else as it) and implement DimIndex for it.

As far as I can tell currently there is no way to further slice a Slice if the number of dimensions is dynamic. I think that this would be necessary for dynamic dimensions to become truly useful.

One possible way would be to introduce a structure similar to ndarray's SliceInfo along with "dynamic" variants of the methods tensor, view, and view_mut.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions