# rustsim/nalgebra

Merged
merged 4 commits into from Dec 29, 2018

## Conversation

Projects
None yet
2 participants
Member

### jswrenn commented Dec 2, 2018 • edited

This P.R. overloads matrix indexing in the same manner that the standard library overloads slice indexing.

## Modes of Indexing

Matrices can be indexed in three ways, each with different safety guarantees:

• `get` produces `Some` reference to the element(s) at the index, or `None` if the index is out of bounds
• `index` produces a reference to the element(s) at the index, or panics if the index is out of bounds
• `get_unchecked` produces a reference to the element(s) at the index, without bounds checking

Each of these has a corresponding `_mut` counterpart that produces a mutable reference to the element(s) at the given location.

## Types of Indices

Matrices can be indexed by a `usize`, or with any pair of `usize`, `Range<usize>`, `RangeFrom<usize>`, `RangeFull`, `RangeInclusive<usize>`, `RangeTo<usize>`, and `RangeToInclusive<usize>`.

Indexing by `usize` and `(usize, usize)` produces a reference to the element at that location. All other two-dimensional indices produce a `MatrixSlice`.

Some examples:

### Indices to Individual Elements

#### Two-Dimensional Indices

```let matrix = Matrix2::new(0, 2,
1, 3);

assert_eq!(matrix.index((0, 0)), &0);
assert_eq!(matrix.index((1, 0)), &1);
assert_eq!(matrix.index((0, 1)), &2);
assert_eq!(matrix.index((1, 1)), &3);```

```let matrix = Matrix2::new(0, 2,
1, 3);

assert_eq!(matrix.get(0), Some(&0));
assert_eq!(matrix.get(1), Some(&1));
assert_eq!(matrix.get(2), Some(&2));
assert_eq!(matrix.get(3), Some(&3));```

### Indices to Individual Rows and Columns

#### Index to a Row

```let matrix = Matrix2::new(0, 2,
1, 3);

assert!(matrix.index((0, ..))
.eq(&Matrix1x2::new(0, 2)));```

#### Index to a Column

```let matrix = Matrix2::new(0, 2,
1, 3);

assert!(matrix.index((.., 0))
.eq(&Matrix2x1::new(0,
1)));```

### Indices to Parts of Individual Rows and Columns

#### Index to a Partial Row

```let matrix = Matrix3::new(0, 3, 6,
1, 4, 7,
2, 5, 8);

assert!(matrix.index((0, ..2))
.eq(&Matrix1x2::new(0, 3)));```

#### Index to a Partial Column

```let matrix = Matrix3::new(0, 3, 6,
1, 4, 7,
2, 5, 8);

assert!(matrix.index((..2, 0))
.eq(&Matrix2x1::new(0,
1)));```

### Indices to Ranges of Rows and Columns

#### Index to a Range of Rows

```let matrix = Matrix3::new(0, 3, 6,
1, 4, 7,
2, 5, 8);

assert!(matrix.index((1..3, ..))
.eq(&Matrix2x3::new(1, 4, 7,
2, 5, 8)));```

#### Index to a Range of Columns

```let matrix = Matrix3::new(0, 3, 6,
1, 4, 7,
2, 5, 8);

assert!(matrix.index((.., 1..3))
.eq(&Matrix3x2::new(3, 6,
4, 7,
5, 8)));```

## Future Work

This PR can be extended in a non-breaking way to permit:

• Further overloading two-dimensional indexing whereby the row and column components are ranges of `Dim` (and thus the output can be a `MatrixSlice` of size known at compile-time). This just requires some tricky code-generation work that the current macros can't handle.

### jswrenn added some commits Dec 2, 2018

``` Overloaded Indexing ```
``` 7e4a864 ```
``` MutMatrixIndex -> MatrixIndexMut ```
``` 21f3f6e ```

Member

### sebcrozet commented Dec 3, 2018

 This is amazing! I will take a closer look and get back to you this week.
``` groundwork for indexing with typenums ```
``` 9f9e575 ```
Member

### jswrenn commented Dec 3, 2018

 9f9e575 implements the groundwork for indexing with typenums and adds a proof-of-concept `MatrixIndex` implementation for index pairs where one of the components is a `ops::RangeFrom`. To support the other range types, we're going to need to do some work to surface more of typenum's type-level operators as `Dim` operators (namely `IsLess`). This seems like a significant undertaking, and I don't think I'll get to it in this PR.

Merged

Member

### sebcrozet left a comment

 Great PR overall! The macro for generating the `MatrixIndex{Mut}` trait for all pairs of range type is very interesting! I agree that indexing with ranges based on `DimName` types can be left to another PR. Also it seems impossible to use type-lever integers as bounds of `Range` because both ends of `a..b` must have the same type. The only requested change is about a typo for `indices` instead of `indices`.
src/base/indexing.rs Outdated
``` typofix: indicies -> indices ```
``` 817b86d ```

### sebcrozet merged commit `5a9a1eb` into rustsim:master Dec 29, 2018 1 check passed

#### 1 check passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details
Member

### sebcrozet commented Dec 29, 2018

 Thanks!