LayoutRef in ndarray - Rust

pub struct LayoutRef<A, D>(/* private fields */);
Expand description

A reference to the layout of an n-dimensional array.

This type can be used to read and write to the layout of an array; that is to say, its shape and strides. It does not provide any read or write access to the array’s underlying data. It is generic on two types: D, its dimensionality, and A, the element type of its data.

§Example

Say we wanted to write a function that provides the aspect ratio of any 2D array: the ratio of its width (number of columns) to its height (number of rows). We would write that as follows:

use ndarray::{LayoutRef2, array};

fn aspect_ratio<T, A>(layout: &T) -> (usize, usize)
where T: AsRef<LayoutRef2<A>> + ?Sized
{
    let layout = layout.as_ref();
    (layout.ncols(), layout.nrows())
}

let arr = array![[1, 2], [3, 4]];
assert_eq!(aspect_ratio(&arr), (2, 2));

Similarly, new traits that provide functions that only depend on or alter the layout of an array should do so via a blanket implementation. Lets write a trait that both provides the aspect ratio and lets users cut down arrays to a desired aspect ratio. For simplicity, we’ll panic if the user provides an aspect ratio where either element is larger than the array’s size.

use ndarray::{LayoutRef2, array, s};

trait Ratioable<A> {
    fn aspect_ratio(&self) -> (usize, usize)
    where Self: AsRef<LayoutRef2<A>>;

    fn cut_to_ratio(&mut self, ratio: (usize, usize))
    where Self: AsMut<LayoutRef2<A>>;
}

impl<T, A> Ratioable<A> for T
where T: AsRef<LayoutRef2<A>> + AsMut<LayoutRef2<A>> + ?Sized
{
    fn aspect_ratio(&self) -> (usize, usize)
    {
        let layout = self.as_ref();
        (layout.ncols(), layout.nrows())
    }

    fn cut_to_ratio(&mut self, ratio: (usize, usize))
    {
        let layout = self.as_mut();
        layout.slice_collapse(s![..ratio.1, ..ratio.0]);
    }
}

let mut arr = array![[1, 2, 3], [4, 5, 6]];
assert_eq!(arr.aspect_ratio(), (3, 2));
arr.cut_to_ratio((2, 2));
assert_eq!(arr, array![[1, 2], [4, 5]]);

Continue reading for why we use AsRef instead of taking &LayoutRef directly.

§Writing Functions

Writing functions that accept LayoutRef is not as simple as taking a &LayoutRef argument, as the above examples show. This is because LayoutRef can be obtained either cheaply or expensively, depending on the method used. LayoutRef can be obtained from all kinds of arrays – owned, shared, viewed, referenced, and raw referenced – via .as_ref(). Critically, this way of obtaining a LayoutRef is cheap, as it does not guarantee that the underlying data is uniquely held.

However, LayoutRefs can be obtained a second way: they sit at the bottom of a “deref chain” going from shared arrays, through ArrayRef, through RawRef, and finally to LayoutRef. As a result, LayoutRefs can also be obtained via auto-dereferencing. When requesting a mutable reference – &mut LayoutRef – the deref_mut to ArrayRef triggers a (possibly expensive) guarantee that the data is uniquely held (see ArrayRef for more information).

To help users avoid this cost, functions that operate on LayoutRefs should take their parameters as a generic type T: AsRef<LayoutRef<A, D>>, as the above examples show. This aids the caller in two ways: they can pass their arrays by reference (&arr) instead of explicitly calling as_ref, and they will avoid paying a performance penalty for mutating the shape.

Source§

§Methods For All Array Types

Source

Return the total number of elements in the array.

Source

Return the length of axis.

The axis should be in the range Axis( 0 .. n ) where n is the number of dimensions (axes) of the array.

Panics if the axis is out of bounds.

Source

Return whether the array has any elements

Source

Return the number of dimensions (axes) in the array

Source

Return the shape of the array in its “pattern” form, an integer in the one-dimensional case, tuple in the n-dimensional cases and so on.

Source

Return the shape of the array as it’s stored in the array.

This is primarily useful for passing to other ArrayBase functions, such as when creating another array of the same shape and dimensionality.

use ndarray::Array;

let a = Array::from_elem((2, 3), 5.);

// Create an array of zeros that's the same shape and dimensionality as `a`.
let b = Array::<f64, _>::zeros(a.raw_dim());
Source

Return the shape of the array as a slice.

Note that you probably don’t want to use this to create an array of the same shape as another array because creating an array with e.g. Array::zeros() using a shape of type &[usize] results in a dynamic-dimensional array. If you want to create an array that has the same shape and dimensionality as another array, use .raw_dim() instead:

use ndarray::{Array, Array2};

let a = Array2::<i32>::zeros((3, 4));
let shape = a.shape();
assert_eq!(shape, &[3, 4]);

// Since `a.shape()` returned `&[usize]`, we get an `ArrayD` instance:
let b = Array::zeros(shape);
assert_eq!(a.clone().into_dyn(), b);

// To get the same dimension type, use `.raw_dim()` instead:
let c = Array::zeros(a.raw_dim());
assert_eq!(a, c);
Source

Return the strides of the array as a slice.

Source

Return the stride of axis.

The axis should be in the range Axis( 0 .. n ) where n is the number of dimensions (axes) of the array.

Panics if the axis is out of bounds.

Source§
Source

Slice the array in place without changing the number of dimensions.

In particular, if an axis is sliced with an index, the axis is collapsed, as in .collapse_axis(), rather than removed, as in .slice_move() or .index_axis_move().

See Slicing for full documentation. See also s!, SliceArg, and SliceInfo.

Panics in the following cases:

  • if an index is out of bounds
  • if a step size is zero
  • if SliceInfoElem::NewAxis is in info, e.g. if NewAxis was used in the s! macro
  • if D is IxDyn and info does not match the number of array axes
Source§
Source

Slice the array in place along the specified axis.

Panics if an index is out of bounds or step size is zero.
Panics if axis is out of bounds.

Source§
Source

Slice the array in place, with a closure specifying the slice for each axis.

This is especially useful for code which is generic over the dimensionality of the array.

Panics if an index is out of bounds or step size is zero.

Source§
Source

Selects index along the axis, collapsing the axis into length one.

Panics if axis or index is out of bounds.

Source§
Source

Return true if the array data is laid out in contiguous “C order” in memory (where the last index is the most rapidly varying).

Return false otherwise, i.e. the array is possibly not contiguous in memory, it has custom strides, etc.

Source§
Source

Swap axes ax and bx.

This does not move any data, it just adjusts the array’s dimensions and strides.

Panics if the axes are out of bounds.

use ndarray::arr2;

let mut a = arr2(&[[1., 2., 3.]]);
a.swap_axes(0, 1);
assert!(
    a == arr2(&[[1.], [2.], [3.]])
);
Source§
Source

Return an iterator over the length and stride of each axis.

Source

Return the axis with the greatest stride (by absolute value), preferring axes with len > 1.

Source

Reverse the stride of axis.

Panics if the axis is out of bounds.

Source

If possible, merge in the axis take to into.

Returns true iff the axes are now merged.

This method merges the axes if movement along the two original axes (moving fastest along the into axis) can be equivalently represented as movement along one (merged) axis. Merging the axes preserves this order in the merged axis. If take and into are the same axis, then the axis is “merged” if its length is ≤ 1.

If the return value is true, then the following hold:

  • The new length of the into axis is the product of the original lengths of the two axes.

  • The new length of the take axis is 0 if the product of the original lengths of the two axes is 0, and 1 otherwise.

If the return value is false, then merging is not possible, and the original shape and strides have been preserved.

Note that the ordering constraint means that if it’s possible to merge take into into, it’s usually not possible to merge into into take, and vice versa.

use ndarray::Array3;
use ndarray::Axis;

let mut a = Array3::<f64>::zeros((2, 3, 4));
assert!(a.merge_axes(Axis(1), Axis(2)));
assert_eq!(a.shape(), &[2, 1, 12]);

Panics if an axis is out of bounds.

Source§
Source

Return the number of rows (length of Axis(0)) in the two-dimensional array.

use ndarray::{array, Axis};

let array = array![[1., 2.],
                   [3., 4.],
                   [5., 6.]];
assert_eq!(array.nrows(), 3);

// equivalent ways of getting the dimensions
// get nrows, ncols by using dim:
let (m, n) = array.dim();
assert_eq!(m, array.nrows());
// get length of any particular axis with .len_of()
assert_eq!(m, array.len_of(Axis(0)));
Source§
Source

Return the number of columns (length of Axis(1)) in the two-dimensional array.

use ndarray::{array, Axis};

let array = array![[1., 2.],
                   [3., 4.],
                   [5., 6.]];
assert_eq!(array.ncols(), 2);

// equivalent ways of getting the dimensions
// get nrows, ncols by using dim:
let (m, n) = array.dim();
assert_eq!(n, array.ncols());
// get length of any particular axis with .len_of()
assert_eq!(n, array.len_of(Axis(1)));
Source

Return true if the array is square, false otherwise.

§Examples

Square:

use ndarray::array;
let array = array![[1., 2.], [3., 4.]];
assert!(array.is_square());

Not square:

use ndarray::array;
let array = array![[1., 2., 5.], [3., 4., 6.]];
assert!(!array.is_square());
Source§

§Methods for Dynamic-Dimensional Arrays

Source

Insert new array axis of length 1 at axis, modifying the shape and strides in-place.

Panics if the axis is out of bounds.

use ndarray::{Axis, arr2, arr3};

let mut a = arr2(&[[1, 2, 3], [4, 5, 6]]).into_dyn();
assert_eq!(a.shape(), &[2, 3]);

a.insert_axis_inplace(Axis(1));
assert_eq!(a, arr3(&[[[1, 2, 3]], [[4, 5, 6]]]).into_dyn());
assert_eq!(a.shape(), &[2, 1, 3]);
Source

Collapses the array to index along the axis and removes the axis, modifying the shape and strides in-place.

Panics if axis or index is out of bounds.

use ndarray::{Axis, arr1, arr2};

let mut a = arr2(&[[1, 2, 3], [4, 5, 6]]).into_dyn();
assert_eq!(a.shape(), &[2, 3]);

a.index_axis_inplace(Axis(1), 1);
assert_eq!(a, arr1(&[2, 5]).into_dyn());
assert_eq!(a.shape(), &[2]);
Source§
Source§

Converts this type into a mutable reference of the (usually inferred) input type.

Source§
Source§

Converts this type into a mutable reference of the (usually inferred) input type.

Source§
Source§

Converts this type into a mutable reference of the (usually inferred) input type.

Source§
Source§

Converts this type into a mutable reference of the (usually inferred) input type.

Source§
Source§

Converts this type into a shared reference of the (usually inferred) input type.

Source§
Source§

Converts this type into a shared reference of the (usually inferred) input type.

Source§
Source§

Converts this type into a shared reference of the (usually inferred) input type.

Source§
Source§

Converts this type into a shared reference of the (usually inferred) input type.