Skip to content

Commit db52eab

Browse files
committed
Adds documentation and aliases for LayoutRef
1 parent 289130d commit db52eab

File tree

2 files changed

+104
-1
lines changed

2 files changed

+104
-1
lines changed

src/aliases.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//!
33
44
use crate::dimension::Dim;
5-
use crate::{ArcArray, Array, ArrayRef, ArrayView, ArrayViewMut, Ix, IxDynImpl};
5+
use crate::{ArcArray, Array, ArrayRef, ArrayView, ArrayViewMut, Ix, IxDynImpl, LayoutRef};
66

77
/// Create a zero-dimensional index
88
#[allow(non_snake_case)]
@@ -140,6 +140,23 @@ pub type ArrayRef6<A> = ArrayRef<A, Ix6>;
140140
/// dynamic-dimensional array reference
141141
pub type ArrayRefD<A> = ArrayRef<A, IxDyn>;
142142

143+
/// zero-dimensional layout reference
144+
pub type LayoutRef0<A> = LayoutRef<A, Ix0>;
145+
/// one-dimensional layout reference
146+
pub type LayoutRef1<A> = LayoutRef<A, Ix1>;
147+
/// two-dimensional layout reference
148+
pub type LayoutRef2<A> = LayoutRef<A, Ix2>;
149+
/// three-dimensional layout reference
150+
pub type LayoutRef3<A> = LayoutRef<A, Ix3>;
151+
/// four-dimensional layout reference
152+
pub type LayoutRef4<A> = LayoutRef<A, Ix4>;
153+
/// five-dimensional layout reference
154+
pub type LayoutRef5<A> = LayoutRef<A, Ix5>;
155+
/// six-dimensional layout reference
156+
pub type LayoutRef6<A> = LayoutRef<A, Ix6>;
157+
/// dynamic-dimensional layout reference
158+
pub type LayoutRefD<A> = LayoutRef<A, IxDyn>;
159+
143160
/// zero-dimensional array view
144161
pub type ArrayView0<'a, A> = ArrayView<'a, A, Ix0>;
145162
/// one-dimensional array view

src/lib.rs

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1292,6 +1292,92 @@ where S: RawData
12921292
}
12931293

12941294
/// A reference to the layout of an *n*-dimensional array.
1295+
///
1296+
/// This type can be used to read and write to the layout of an array;
1297+
/// that is to say, its shape and strides. It does not provide any read
1298+
/// or write access to the array's underlying data. It is generic on two
1299+
/// types: `D`, its dimensionality, and `A`, the element type of its data.
1300+
///
1301+
/// ## Example
1302+
/// Say we wanted to write a function that provides the aspect ratio
1303+
/// of any 2D array: the ratio of its width (number of columns) to its
1304+
/// height (number of rows). We would write that as follows:
1305+
/// ```rust
1306+
/// use ndarray::{LayoutRef2, array};
1307+
///
1308+
/// fn aspect_ratio<T, A>(layout: &T) -> (usize, usize)
1309+
/// where T: AsRef<LayoutRef2<A>>
1310+
/// {
1311+
/// let layout = layout.as_ref();
1312+
/// (layout.ncols(), layout.nrows())
1313+
/// }
1314+
///
1315+
/// let arr = array![[1, 2], [3, 4]];
1316+
/// assert_eq!(aspect_ratio(&arr), (2, 2));
1317+
/// ```
1318+
/// Similarly, new traits that provide functions that only depend on
1319+
/// or alter the layout of an array should do so via a blanket
1320+
/// implementation. Lets write a trait that both provides the aspect ratio
1321+
/// and lets users cut down arrays to a desired aspect ratio.
1322+
/// For simplicity, we'll panic if the user provides an aspect ratio
1323+
/// where either element is larger than the array's size.
1324+
/// ```rust
1325+
/// use ndarray::{LayoutRef2, array, s};
1326+
///
1327+
/// trait Ratioable<A> {
1328+
/// fn aspect_ratio(&self) -> (usize, usize)
1329+
/// where Self: AsRef<LayoutRef2<A>>;
1330+
///
1331+
/// fn cut_to_ratio(&mut self, ratio: (usize, usize))
1332+
/// where Self: AsMut<LayoutRef2<A>>;
1333+
/// }
1334+
///
1335+
/// impl<T, A> Ratioable<A> for T
1336+
/// where T: AsRef<LayoutRef2<A>> + AsMut<LayoutRef2<A>>
1337+
/// {
1338+
/// fn aspect_ratio(&self) -> (usize, usize)
1339+
/// {
1340+
/// let layout = self.as_ref();
1341+
/// (layout.ncols(), layout.nrows())
1342+
/// }
1343+
///
1344+
/// fn cut_to_ratio(&mut self, ratio: (usize, usize))
1345+
/// {
1346+
/// let layout = self.as_mut();
1347+
/// layout.slice_collapse(s![..ratio.1, ..ratio.0]);
1348+
/// }
1349+
/// }
1350+
///
1351+
/// let mut arr = array![[1, 2, 3], [4, 5, 6]];
1352+
/// assert_eq!(arr.aspect_ratio(), (3, 2));
1353+
/// arr.cut_to_ratio((2, 2));
1354+
/// assert_eq!(arr, array![[1, 2], [4, 5]]);
1355+
/// ```
1356+
/// Continue reading for why we use `AsRef` instead of taking `&LayoutRef` directly.
1357+
///
1358+
/// ## Writing Functions
1359+
/// Writing functions that accept `LayoutRef` is not as simple as taking
1360+
/// a `&LayoutRef` argument, as the above examples show. This is because
1361+
/// `LayoutRef` can be obtained either cheaply or expensively, depending
1362+
/// on the method used. `LayoutRef` can be obtained from all kinds of arrays
1363+
/// -- [owned](Array), [shared](ArcArray), [viewed](ArrayView), [referenced](ArrayRef),
1364+
/// and [raw referenced](RawRef) -- via `.as_ref()`. Critically, this way of
1365+
/// obtaining a `LayoutRef` is cheap, as it does not guarantee that the
1366+
/// underlying data is uniquely held.
1367+
///
1368+
/// However, `LayoutRef`s can be obtained a second way: they sit at the bottom
1369+
/// of a "deref chain" going from shared arrays, through `ArrayRef`, through
1370+
/// `RawRef`, and finally to `LayoutRef`. As a result, `LayoutRef`s can also
1371+
/// be obtained via auto-dereferencing. When requesting a mutable reference --
1372+
/// `&mut LayoutRef` -- the `deref_mut` to `ArrayRef` triggers a (possibly
1373+
/// expensive) guarantee that the data is uniquely held (see [`ArrayRef`]
1374+
/// for more information).
1375+
///
1376+
/// To help users avoid this error cost, functions that operate on `LayoutRef`s
1377+
/// should take their parameters as a generic type `T: AsRef<LayoutRef<A, D>>`,
1378+
/// as the above examples show. This aids the caller in two ways: they can pass
1379+
/// their arrays by reference (`&arr`) instead of explicitly calling `as_ref`,
1380+
/// and they will avoid paying a performance penalty for mutating the shape.
12951381
//
12961382
// # Safety for Implementors
12971383
//

0 commit comments

Comments
 (0)