nalgebra/src/base/indexing.rs

770 lines
22 KiB
Rust
Raw Normal View History

2018-12-04 05:32:47 +08:00
//! Indexing
2021-08-16 00:12:17 +08:00
#![allow(clippy::reversed_empty_ranges)]
2018-12-03 04:00:08 +08:00
use crate::base::storage::{RawStorage, RawStorageMut};
2020-04-06 00:49:48 +08:00
use crate::base::{
Const, Dim, DimDiff, DimName, DimSub, Dynamic, Matrix, MatrixView, MatrixViewMut, Scalar, U1,
2020-04-06 00:49:48 +08:00
};
2018-12-03 04:00:08 +08:00
use std::ops;
2021-04-12 22:06:47 +08:00
// N.B.: Not a public trait!
2020-04-06 00:49:48 +08:00
trait DimRange<D: Dim> {
2018-12-04 05:32:47 +08:00
/// The number of elements indexed by this range.
2018-12-03 04:00:08 +08:00
type Length: Dim;
/// The lower bound of the range, inclusive.
fn lower(&self, dimension: D) -> usize;
/// The number of elements included in the range.
fn length(&self, dimension: D) -> Self::Length;
/// Produces true if `Self` is contained within `dimension`.
fn contained_by(&self, dimension: D) -> bool;
}
impl<D: Dim> DimRange<D> for usize {
type Length = U1;
#[inline(always)]
fn lower(&self, _: D) -> usize {
*self
}
#[inline(always)]
fn length(&self, _: D) -> Self::Length {
Const::<1>
2018-12-03 04:00:08 +08:00
}
#[inline(always)]
fn contained_by(&self, dimension: D) -> bool {
*self < dimension.value()
}
}
#[test]
fn dimrange_usize() {
2021-08-16 00:12:17 +08:00
assert!(!DimRange::contained_by(&0, Const::<0>));
2021-07-06 05:51:27 +08:00
assert!(DimRange::contained_by(&0, Const::<1>));
2018-12-03 04:00:08 +08:00
}
impl<D: Dim> DimRange<D> for ops::Range<usize> {
type Length = Dynamic;
#[inline(always)]
fn lower(&self, _: D) -> usize {
self.start
}
#[inline(always)]
fn length(&self, _: D) -> Self::Length {
Dynamic::new(self.end.saturating_sub(self.start))
}
#[inline(always)]
fn contained_by(&self, dimension: D) -> bool {
(self.start < dimension.value()) && (self.end <= dimension.value())
}
}
#[test]
fn dimrange_range_usize() {
2021-08-16 00:12:17 +08:00
assert!(!DimRange::contained_by(&(0..0), Const::<0>));
assert!(!DimRange::contained_by(&(0..1), Const::<0>));
2021-07-06 05:51:27 +08:00
assert!(DimRange::contained_by(&(0..1), Const::<1>));
assert!(DimRange::contained_by(
&((usize::MAX - 1)..usize::MAX),
Dynamic::new(usize::MAX)
));
2020-04-06 00:49:48 +08:00
assert_eq!(
2021-07-06 05:51:27 +08:00
DimRange::length(&((usize::MAX - 1)..usize::MAX), Dynamic::new(usize::MAX)),
2020-04-06 00:49:48 +08:00
Dynamic::new(1)
);
assert_eq!(
2021-07-06 05:51:27 +08:00
DimRange::length(&(usize::MAX..(usize::MAX - 1)), Dynamic::new(usize::MAX)),
2020-04-06 00:49:48 +08:00
Dynamic::new(0)
);
assert_eq!(
2021-07-06 05:51:27 +08:00
DimRange::length(&(usize::MAX..usize::MAX), Dynamic::new(usize::MAX)),
2020-04-06 00:49:48 +08:00
Dynamic::new(0)
);
2018-12-03 04:00:08 +08:00
}
impl<D: Dim> DimRange<D> for ops::RangeFrom<usize> {
type Length = Dynamic;
#[inline(always)]
fn lower(&self, _: D) -> usize {
self.start
}
#[inline(always)]
fn length(&self, dimension: D) -> Self::Length {
(self.start..dimension.value()).length(dimension)
}
#[inline(always)]
fn contained_by(&self, dimension: D) -> bool {
self.start < dimension.value()
}
}
#[test]
fn dimrange_rangefrom_usize() {
2021-08-16 00:12:17 +08:00
assert!(!DimRange::contained_by(&(0..), Const::<0>));
assert!(!DimRange::contained_by(&(0..), Const::<0>));
2021-07-06 05:51:27 +08:00
assert!(DimRange::contained_by(&(0..), Const::<1>));
assert!(DimRange::contained_by(
&((usize::MAX - 1)..),
Dynamic::new(usize::MAX)
));
2020-04-06 00:49:48 +08:00
assert_eq!(
2021-07-06 05:51:27 +08:00
DimRange::length(&((usize::MAX - 1)..), Dynamic::new(usize::MAX)),
2020-04-06 00:49:48 +08:00
Dynamic::new(1)
);
assert_eq!(
2021-07-06 05:51:27 +08:00
DimRange::length(&(usize::MAX..), Dynamic::new(usize::MAX)),
2020-04-06 00:49:48 +08:00
Dynamic::new(0)
);
2018-12-03 04:00:08 +08:00
}
2018-12-04 05:32:47 +08:00
impl<D: Dim, T: Dim> DimRange<D> for ops::RangeFrom<T>
2020-04-06 00:49:48 +08:00
where
D: DimSub<T>,
2018-12-04 05:32:47 +08:00
{
type Length = DimDiff<D, T>;
#[inline(always)]
fn lower(&self, _: D) -> usize {
self.start.value()
}
#[inline(always)]
fn length(&self, dimension: D) -> Self::Length {
dimension.sub(self.start)
}
#[inline(always)]
fn contained_by(&self, _: D) -> bool {
true
}
}
#[test]
fn dimrange_rangefrom_dimname() {
assert_eq!(DimRange::length(&(Const::<1>..), Const::<5>), Const::<4>);
2018-12-04 05:32:47 +08:00
}
2018-12-03 04:00:08 +08:00
impl<D: Dim> DimRange<D> for ops::RangeFull {
type Length = D;
#[inline(always)]
fn lower(&self, _: D) -> usize {
0
}
#[inline(always)]
fn length(&self, dimension: D) -> Self::Length {
dimension
}
#[inline(always)]
fn contained_by(&self, _: D) -> bool {
true
}
}
#[test]
fn dimrange_rangefull() {
2021-07-06 05:51:27 +08:00
assert!(DimRange::contained_by(&(..), Const::<0>));
assert_eq!(DimRange::length(&(..), Const::<1>), Const::<1>);
2018-12-03 04:00:08 +08:00
}
impl<D: Dim> DimRange<D> for ops::RangeInclusive<usize> {
type Length = Dynamic;
#[inline(always)]
fn lower(&self, _: D) -> usize {
*self.start()
}
#[inline(always)]
fn length(&self, _: D) -> Self::Length {
2020-04-06 00:49:48 +08:00
Dynamic::new(if self.end() < self.start() {
0
} else {
self.end().wrapping_sub(self.start().wrapping_sub(1))
})
2018-12-03 04:00:08 +08:00
}
#[inline(always)]
fn contained_by(&self, dimension: D) -> bool {
(*self.start() < dimension.value()) && (*self.end() < dimension.value())
}
}
#[test]
fn dimrange_rangeinclusive_usize() {
2021-08-16 00:12:17 +08:00
assert!(!DimRange::contained_by(&(0..=0), Const::<0>));
2021-07-06 05:51:27 +08:00
assert!(DimRange::contained_by(&(0..=0), Const::<1>));
2021-08-16 00:12:17 +08:00
assert!(!DimRange::contained_by(
&(usize::MAX..=usize::MAX),
Dynamic::new(usize::MAX)
));
assert!(!DimRange::contained_by(
&((usize::MAX - 1)..=usize::MAX),
Dynamic::new(usize::MAX)
));
2021-07-06 05:51:27 +08:00
assert!(DimRange::contained_by(
&((usize::MAX - 1)..=(usize::MAX - 1)),
Dynamic::new(usize::MAX)
));
assert_eq!(DimRange::length(&(0..=0), Const::<1>), Dynamic::new(1));
2020-04-06 00:49:48 +08:00
assert_eq!(
2021-07-06 05:51:27 +08:00
DimRange::length(&((usize::MAX - 1)..=usize::MAX), Dynamic::new(usize::MAX)),
2020-04-06 00:49:48 +08:00
Dynamic::new(2)
);
assert_eq!(
2021-07-06 05:51:27 +08:00
DimRange::length(&(usize::MAX..=(usize::MAX - 1)), Dynamic::new(usize::MAX)),
2020-04-06 00:49:48 +08:00
Dynamic::new(0)
);
assert_eq!(
2021-07-06 05:51:27 +08:00
DimRange::length(&(usize::MAX..=usize::MAX), Dynamic::new(usize::MAX)),
2020-04-06 00:49:48 +08:00
Dynamic::new(1)
);
2018-12-03 04:00:08 +08:00
}
2020-04-06 00:49:48 +08:00
impl<D: Dim> DimRange<D> for ops::RangeTo<usize> {
2018-12-03 04:00:08 +08:00
type Length = Dynamic;
#[inline(always)]
fn lower(&self, _: D) -> usize {
0
}
#[inline(always)]
fn length(&self, _: D) -> Self::Length {
Dynamic::new(self.end)
}
#[inline(always)]
fn contained_by(&self, dimension: D) -> bool {
self.end <= dimension.value()
}
}
#[test]
fn dimrange_rangeto_usize() {
2021-07-06 05:51:27 +08:00
assert!(DimRange::contained_by(&(..0), Const::<0>));
2021-08-16 00:12:17 +08:00
assert!(!DimRange::contained_by(&(..1), Const::<0>));
2021-07-06 05:51:27 +08:00
assert!(DimRange::contained_by(&(..0), Const::<1>));
assert!(DimRange::contained_by(
&(..(usize::MAX - 1)),
Dynamic::new(usize::MAX)
));
2020-04-06 00:49:48 +08:00
assert_eq!(
2021-07-06 05:51:27 +08:00
DimRange::length(&(..(usize::MAX - 1)), Dynamic::new(usize::MAX)),
Dynamic::new(usize::MAX - 1)
2020-04-06 00:49:48 +08:00
);
assert_eq!(
2021-07-06 05:51:27 +08:00
DimRange::length(&(..usize::MAX), Dynamic::new(usize::MAX)),
Dynamic::new(usize::MAX)
2020-04-06 00:49:48 +08:00
);
2018-12-03 04:00:08 +08:00
}
2020-04-06 00:49:48 +08:00
impl<D: Dim> DimRange<D> for ops::RangeToInclusive<usize> {
2018-12-03 04:00:08 +08:00
type Length = Dynamic;
#[inline(always)]
fn lower(&self, _: D) -> usize {
0
}
#[inline(always)]
fn length(&self, _: D) -> Self::Length {
Dynamic::new(self.end + 1)
}
#[inline(always)]
fn contained_by(&self, dimension: D) -> bool {
self.end < dimension.value()
}
}
#[test]
fn dimrange_rangetoinclusive_usize() {
2021-08-16 00:12:17 +08:00
assert!(!DimRange::contained_by(&(..=0), Const::<0>));
assert!(!DimRange::contained_by(&(..=1), Const::<0>));
2021-07-06 05:51:27 +08:00
assert!(DimRange::contained_by(&(..=0), Const::<1>));
2021-08-16 00:12:17 +08:00
assert!(!DimRange::contained_by(
&(..=(usize::MAX)),
Dynamic::new(usize::MAX)
));
2021-07-06 05:51:27 +08:00
assert!(DimRange::contained_by(
&(..=(usize::MAX - 1)),
Dynamic::new(usize::MAX)
));
2020-04-06 00:49:48 +08:00
assert_eq!(
2021-07-06 05:51:27 +08:00
DimRange::length(&(..=(usize::MAX - 1)), Dynamic::new(usize::MAX)),
Dynamic::new(usize::MAX)
2020-04-06 00:49:48 +08:00
);
2018-12-03 04:00:08 +08:00
}
/// A helper trait used for indexing operations.
pub trait MatrixIndex<'a, T, R: Dim, C: Dim, S: RawStorage<T, R, C>>: Sized {
2018-12-03 04:00:08 +08:00
/// The output type returned by methods.
2020-04-06 00:49:48 +08:00
type Output: 'a;
2018-12-03 04:00:08 +08:00
/// Produces true if the given matrix is contained by this index.
2018-12-04 05:32:47 +08:00
#[doc(hidden)]
2021-04-11 17:00:38 +08:00
fn contained_by(&self, matrix: &Matrix<T, R, C, S>) -> bool;
2018-12-03 04:00:08 +08:00
/// Produces a shared view of the data at this location if in bounds,
/// or `None`, otherwise.
2018-12-04 05:32:47 +08:00
#[doc(hidden)]
2018-12-03 04:00:08 +08:00
#[inline(always)]
2021-04-11 17:00:38 +08:00
fn get(self, matrix: &'a Matrix<T, R, C, S>) -> Option<Self::Output> {
2018-12-03 04:00:08 +08:00
if self.contained_by(matrix) {
2020-04-06 00:49:48 +08:00
Some(unsafe { self.get_unchecked(matrix) })
2018-12-03 04:00:08 +08:00
} else {
None
}
}
/// Produces a shared view of the data at this location if in bounds
/// without any bounds checking.
#[doc(hidden)]
2021-04-11 17:00:38 +08:00
unsafe fn get_unchecked(self, matrix: &'a Matrix<T, R, C, S>) -> Self::Output;
2018-12-03 04:00:08 +08:00
/// Produces a shared view to the data at this location, or panics
/// if out of bounds.
2018-12-04 05:32:47 +08:00
#[doc(hidden)]
2018-12-03 04:00:08 +08:00
#[inline(always)]
2021-04-11 17:00:38 +08:00
fn index(self, matrix: &'a Matrix<T, R, C, S>) -> Self::Output {
2018-12-03 04:00:08 +08:00
self.get(matrix).expect("Index out of bounds.")
}
}
/// A helper trait used for indexing operations.
pub trait MatrixIndexMut<'a, T, R: Dim, C: Dim, S: RawStorageMut<T, R, C>>:
2021-04-11 17:00:38 +08:00
MatrixIndex<'a, T, R, C, S>
2020-04-06 00:49:48 +08:00
{
2018-12-03 04:00:08 +08:00
/// The output type returned by methods.
2020-04-06 00:49:48 +08:00
type OutputMut: 'a;
2018-12-03 04:00:08 +08:00
/// Produces a mutable view of the data at this location, without
/// performing any bounds checking.
#[doc(hidden)]
2021-04-11 17:00:38 +08:00
unsafe fn get_unchecked_mut(self, matrix: &'a mut Matrix<T, R, C, S>) -> Self::OutputMut;
2018-12-03 04:00:08 +08:00
/// Produces a mutable view of the data at this location, if in
/// bounds.
2018-12-04 05:32:47 +08:00
#[doc(hidden)]
2018-12-03 04:00:08 +08:00
#[inline(always)]
2021-04-11 17:00:38 +08:00
fn get_mut(self, matrix: &'a mut Matrix<T, R, C, S>) -> Option<Self::OutputMut> {
2018-12-03 04:00:08 +08:00
if self.contained_by(matrix) {
2020-04-06 00:49:48 +08:00
Some(unsafe { self.get_unchecked_mut(matrix) })
2018-12-03 04:00:08 +08:00
} else {
None
}
}
/// Produces a mutable view of the data at this location, or panics
/// if out of bounds.
#[doc(hidden)]
#[inline(always)]
2021-04-11 17:00:38 +08:00
fn index_mut(self, matrix: &'a mut Matrix<T, R, C, S>) -> Self::OutputMut {
2018-12-03 04:00:08 +08:00
self.get_mut(matrix).expect("Index out of bounds.")
}
}
2020-11-15 23:57:49 +08:00
/// # Slicing based on ranges
2018-12-08 23:24:47 +08:00
/// ## Indices to Individual Elements
/// ### Two-Dimensional Indices
2018-12-03 04:00:08 +08:00
/// ```
/// # use nalgebra::*;
/// let matrix = Matrix2::new(0, 2,
/// 1, 3);
2018-12-04 05:32:47 +08:00
///
2018-12-03 04:00:08 +08:00
/// 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);
/// ```
///
/// ### Linear Address Indexing
/// ```
/// # use nalgebra::*;
/// let matrix = Matrix2::new(0, 2,
/// 1, 3);
2018-12-04 05:32:47 +08:00
///
2018-12-03 04:00:08 +08:00
/// 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));
/// ```
///
2018-12-08 23:24:47 +08:00
/// ## Indices to Individual Rows and Columns
2018-12-03 04:00:08 +08:00
/// ### Index to a Row
/// ```
/// # use nalgebra::*;
/// let matrix = Matrix2::new(0, 2,
/// 1, 3);
2018-12-04 05:32:47 +08:00
///
2018-12-03 04:00:08 +08:00
/// assert!(matrix.index((0, ..))
/// .eq(&Matrix1x2::new(0, 2)));
/// ```
///
/// ### Index to a Column
/// ```
/// # use nalgebra::*;
/// let matrix = Matrix2::new(0, 2,
/// 1, 3);
2018-12-04 05:32:47 +08:00
///
2018-12-03 04:00:08 +08:00
/// assert!(matrix.index((.., 0))
/// .eq(&Matrix2x1::new(0,
/// 1)));
/// ```
///
2018-12-08 23:24:47 +08:00
/// ## Indices to Parts of Individual Rows and Columns
2018-12-03 04:00:08 +08:00
/// ### Index to a Partial Row
/// ```
/// # use nalgebra::*;
/// let matrix = Matrix3::new(0, 3, 6,
/// 1, 4, 7,
/// 2, 5, 8);
2018-12-04 05:32:47 +08:00
///
2018-12-03 04:00:08 +08:00
/// assert!(matrix.index((0, ..2))
/// .eq(&Matrix1x2::new(0, 3)));
/// ```
///
/// ### Index to a Partial Column
/// ```
/// # use nalgebra::*;
/// let matrix = Matrix3::new(0, 3, 6,
/// 1, 4, 7,
/// 2, 5, 8);
2018-12-04 05:32:47 +08:00
///
2018-12-03 04:00:08 +08:00
/// assert!(matrix.index((..2, 0))
/// .eq(&Matrix2x1::new(0,
/// 1)));
2018-12-04 05:32:47 +08:00
///
/// assert!(matrix.index((Const::<1>.., 0))
2018-12-04 05:32:47 +08:00
/// .eq(&Matrix2x1::new(1,
/// 2)));
2018-12-03 04:00:08 +08:00
/// ```
2018-12-08 23:24:47 +08:00
/// ## Indices to Ranges of Rows and Columns
2018-12-03 04:00:08 +08:00
/// ### Index to a Range of Rows
/// ```
/// # use nalgebra::*;
/// let matrix = Matrix3::new(0, 3, 6,
/// 1, 4, 7,
/// 2, 5, 8);
2018-12-04 05:32:47 +08:00
///
2018-12-03 04:00:08 +08:00
/// assert!(matrix.index((1..3, ..))
/// .eq(&Matrix2x3::new(1, 4, 7,
/// 2, 5, 8)));
/// ```
/// ### Index to a Range of Columns
/// ```
/// # use nalgebra::*;
/// 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)));
/// ```
impl<T, R: Dim, C: Dim, S: RawStorage<T, R, C>> Matrix<T, R, C, S> {
2018-12-03 04:00:08 +08:00
/// Produces a view of the data at the given index, or
/// `None` if the index is out of bounds.
#[inline]
#[must_use]
2018-12-03 04:00:08 +08:00
pub fn get<'a, I>(&'a self, index: I) -> Option<I::Output>
where
2021-04-11 17:00:38 +08:00
I: MatrixIndex<'a, T, R, C, S>,
2018-12-03 04:00:08 +08:00
{
index.get(self)
}
/// Produces a mutable view of the data at the given index, or
/// `None` if the index is out of bounds.
#[inline]
#[must_use]
2018-12-03 04:00:08 +08:00
pub fn get_mut<'a, I>(&'a mut self, index: I) -> Option<I::OutputMut>
where
S: RawStorageMut<T, R, C>,
2021-04-11 17:00:38 +08:00
I: MatrixIndexMut<'a, T, R, C, S>,
2018-12-03 04:00:08 +08:00
{
index.get_mut(self)
}
/// Produces a view of the data at the given index, or
/// panics if the index is out of bounds.
#[inline]
#[must_use]
2018-12-03 04:00:08 +08:00
pub fn index<'a, I>(&'a self, index: I) -> I::Output
where
2021-04-11 17:00:38 +08:00
I: MatrixIndex<'a, T, R, C, S>,
2018-12-03 04:00:08 +08:00
{
index.index(self)
}
/// Produces a mutable view of the data at the given index, or
/// panics if the index is out of bounds.
#[inline]
pub fn index_mut<'a, I>(&'a mut self, index: I) -> I::OutputMut
where
S: RawStorageMut<T, R, C>,
2021-04-11 17:00:38 +08:00
I: MatrixIndexMut<'a, T, R, C, S>,
2018-12-03 04:00:08 +08:00
{
index.index_mut(self)
}
/// Produces a view of the data at the given index, without doing
/// any bounds checking.
#[inline]
#[must_use]
2018-12-03 04:00:08 +08:00
pub unsafe fn get_unchecked<'a, I>(&'a self, index: I) -> I::Output
where
2021-04-11 17:00:38 +08:00
I: MatrixIndex<'a, T, R, C, S>,
2018-12-03 04:00:08 +08:00
{
index.get_unchecked(self)
}
/// Returns a mutable view of the data at the given index, without doing
/// any bounds checking.
#[inline]
#[must_use]
2018-12-03 04:00:08 +08:00
pub unsafe fn get_unchecked_mut<'a, I>(&'a mut self, index: I) -> I::OutputMut
where
S: RawStorageMut<T, R, C>,
2021-04-11 17:00:38 +08:00
I: MatrixIndexMut<'a, T, R, C, S>,
2018-12-03 04:00:08 +08:00
{
index.get_unchecked_mut(self)
}
}
// EXTRACT A SINGLE ELEMENT BY 1D LINEAR ADDRESS
impl<'a, T, R, C, S> MatrixIndex<'a, T, R, C, S> for usize
2018-12-03 04:00:08 +08:00
where
T: Scalar,
R: Dim,
C: Dim,
S: RawStorage<T, R, C>,
2018-12-03 04:00:08 +08:00
{
2021-04-11 17:00:38 +08:00
type Output = &'a T;
2018-12-03 04:00:08 +08:00
#[doc(hidden)]
#[inline(always)]
2021-04-11 17:00:38 +08:00
fn contained_by(&self, matrix: &Matrix<T, R, C, S>) -> bool {
2018-12-03 04:00:08 +08:00
*self < matrix.len()
}
#[doc(hidden)]
#[inline(always)]
2021-04-11 17:00:38 +08:00
unsafe fn get_unchecked(self, matrix: &'a Matrix<T, R, C, S>) -> Self::Output {
2021-10-06 23:02:02 +08:00
let nrows = matrix.shape().0;
let row = self % nrows;
let col = self / nrows;
matrix.data.get_unchecked(row, col)
2018-12-03 04:00:08 +08:00
}
}
impl<'a, T, R, C, S> MatrixIndexMut<'a, T, R, C, S> for usize
2018-12-03 04:00:08 +08:00
where
T: Scalar,
R: Dim,
C: Dim,
S: RawStorageMut<T, R, C>,
2018-12-03 04:00:08 +08:00
{
2021-04-11 17:00:38 +08:00
type OutputMut = &'a mut T;
2018-12-03 04:00:08 +08:00
#[doc(hidden)]
#[inline(always)]
2021-04-11 17:00:38 +08:00
unsafe fn get_unchecked_mut(self, matrix: &'a mut Matrix<T, R, C, S>) -> Self::OutputMut
2020-04-06 00:49:48 +08:00
where
S: RawStorageMut<T, R, C>,
2018-12-03 04:00:08 +08:00
{
2021-10-31 21:27:32 +08:00
let nrows = matrix.shape().0;
let row = self % nrows;
let col = self / nrows;
matrix.data.get_unchecked_mut(row, col)
2018-12-03 04:00:08 +08:00
}
}
// EXTRACT A SINGLE ELEMENT BY 2D COORDINATES
impl<'a, T: 'a, R, C, S> MatrixIndex<'a, T, R, C, S> for (usize, usize)
2018-12-03 04:00:08 +08:00
where
R: Dim,
C: Dim,
S: RawStorage<T, R, C>,
2018-12-03 04:00:08 +08:00
{
2021-04-11 17:00:38 +08:00
type Output = &'a T;
2018-12-03 04:00:08 +08:00
#[doc(hidden)]
#[inline(always)]
2021-04-11 17:00:38 +08:00
fn contained_by(&self, matrix: &Matrix<T, R, C, S>) -> bool {
2018-12-03 04:00:08 +08:00
let (rows, cols) = self;
let (nrows, ncols) = matrix.shape_generic();
2018-12-03 04:00:08 +08:00
DimRange::contained_by(rows, nrows) && DimRange::contained_by(cols, ncols)
}
#[doc(hidden)]
#[inline(always)]
2021-04-11 17:00:38 +08:00
unsafe fn get_unchecked(self, matrix: &'a Matrix<T, R, C, S>) -> Self::Output {
2018-12-03 04:00:08 +08:00
let (row, col) = self;
matrix.data.get_unchecked(row, col)
}
}
impl<'a, T: 'a, R, C, S> MatrixIndexMut<'a, T, R, C, S> for (usize, usize)
2018-12-03 04:00:08 +08:00
where
R: Dim,
C: Dim,
S: RawStorageMut<T, R, C>,
2018-12-03 04:00:08 +08:00
{
2021-04-11 17:00:38 +08:00
type OutputMut = &'a mut T;
2018-12-03 04:00:08 +08:00
#[doc(hidden)]
#[inline(always)]
2021-04-11 17:00:38 +08:00
unsafe fn get_unchecked_mut(self, matrix: &'a mut Matrix<T, R, C, S>) -> Self::OutputMut
2020-04-06 00:49:48 +08:00
where
S: RawStorageMut<T, R, C>,
2018-12-03 04:00:08 +08:00
{
let (row, col) = self;
matrix.data.get_unchecked_mut(row, col)
}
}
2018-12-04 05:32:47 +08:00
macro_rules! impl_index_pair {
(
$R: ident,
$C: ident,
[<$($RTyP: ident : $RTyPB: ty,)*> usize => $ROut: ty
$(where $RConstraintType: ty: $RConstraintBound: ident<$($RConstraintBoundParams: ty $( = $REqBound: ty )*),*>)*],
[<$($CTyP: ident : $CTyPB: ty,)*> usize => $COut: ty
$(where $CConstraintType: ty: $CConstraintBound: ident<$($CConstraintBoundParams: ty $( = $CEqBound: ty )*),*>)*]
) => {};
(
$R: ident,
$C: ident,
[<$($RTyP: ident: $RTyPB: tt),*> $RIdx: ty => $ROut: ty
$(where $RConstraintType: ty: $RConstraintBound: ident $(<$($RConstraintBoundParams: ty $( = $REqBound: ty )*),*>)* )*],
[<$($CTyP: ident: $CTyPB: tt),*> $CIdx: ty => $COut: ty
$(where $CConstraintType: ty: $CConstraintBound: ident $(<$($CConstraintBoundParams: ty $( = $CEqBound: ty )*),*>)* )*]
) =>
{
impl<'a, T, $R, $C, S, $($RTyP : $RTyPB,)* $($CTyP : $CTyPB),*> MatrixIndex<'a, T, $R, $C, S> for ($RIdx, $CIdx)
2018-12-03 04:00:08 +08:00
where
T: Scalar,
$R: Dim,
$C: Dim,
S: RawStorage<T, R, C>,
2018-12-04 05:32:47 +08:00
$( $RConstraintType: $RConstraintBound $(<$( $RConstraintBoundParams $( = $REqBound )*),*>)* ,)*
$( $CConstraintType: $CConstraintBound $(<$( $CConstraintBoundParams $( = $CEqBound )*),*>)* ),*
2018-12-03 04:00:08 +08:00
{
type Output = MatrixView<'a, T, $ROut, $COut, S::RStride, S::CStride>;
2018-12-03 04:00:08 +08:00
#[doc(hidden)]
#[inline(always)]
2021-04-11 17:00:38 +08:00
fn contained_by(&self, matrix: &Matrix<T, $R, $C, S>) -> bool {
2018-12-03 04:00:08 +08:00
let (rows, cols) = self;
let (nrows, ncols) = matrix.shape_generic();
2018-12-03 04:00:08 +08:00
DimRange::contained_by(rows, nrows) && DimRange::contained_by(cols, ncols)
}
#[doc(hidden)]
#[inline(always)]
2021-04-11 17:00:38 +08:00
unsafe fn get_unchecked(self, matrix: &'a Matrix<T, $R, $C, S>) -> Self::Output {
use crate::base::ViewStorage;
2018-12-03 04:00:08 +08:00
let (rows, cols) = self;
let (nrows, ncols) = matrix.shape_generic();
2018-12-03 04:00:08 +08:00
let data =
ViewStorage::new_unchecked(&matrix.data,
2018-12-03 04:00:08 +08:00
(rows.lower(nrows), cols.lower(ncols)),
(rows.length(nrows), cols.length(ncols)));
Matrix::from_data_statically_unchecked(data)
2018-12-03 04:00:08 +08:00
}
}
impl<'a, T, $R, $C, S, $($RTyP : $RTyPB,)* $($CTyP : $CTyPB),*> MatrixIndexMut<'a, T, $R, $C, S> for ($RIdx, $CIdx)
2018-12-03 04:00:08 +08:00
where
T: Scalar,
$R: Dim,
$C: Dim,
S: RawStorageMut<T, R, C>,
2018-12-04 05:32:47 +08:00
$( $RConstraintType: $RConstraintBound $(<$( $RConstraintBoundParams $( = $REqBound )*),*>)* ,)*
$( $CConstraintType: $CConstraintBound $(<$( $CConstraintBoundParams $( = $CEqBound )*),*>)* ),*
2018-12-03 04:00:08 +08:00
{
type OutputMut = MatrixViewMut<'a, T, $ROut, $COut, S::RStride, S::CStride>;
2018-12-03 04:00:08 +08:00
#[doc(hidden)]
#[inline(always)]
2021-04-11 17:00:38 +08:00
unsafe fn get_unchecked_mut(self, matrix: &'a mut Matrix<T, $R, $C, S>) -> Self::OutputMut {
use crate::base::ViewStorageMut;
2018-12-03 04:00:08 +08:00
let (rows, cols) = self;
let (nrows, ncols) = matrix.shape_generic();
2018-12-03 04:00:08 +08:00
let data =
ViewStorageMut::new_unchecked(&mut matrix.data,
2018-12-03 04:00:08 +08:00
(rows.lower(nrows), cols.lower(ncols)),
(rows.length(nrows), cols.length(ncols)));
Matrix::from_data_statically_unchecked(data)
2018-12-03 04:00:08 +08:00
}
}
}
}
2018-12-04 05:32:47 +08:00
macro_rules! impl_index_pairs {
(index $R: ident with {} index $C: ident with {$($r: tt,)* }) => {};
(index $R: ident with {$lh : tt, $($lt : tt,)*}
index $C: ident with { $($r: tt,)* }) =>
{
$(
impl_index_pair!{$R, $C, $lh, $r}
)*
impl_index_pairs!{index $R with {$($lt,)*} index $C with {$($r,)*}}
}
2018-12-03 04:00:08 +08:00
}
2020-04-06 00:49:48 +08:00
impl_index_pairs! {
2018-12-04 05:32:47 +08:00
index R with {
[<> usize => U1],
[<> ops::Range<usize> => Dynamic],
[<> ops::RangeFrom<usize> => Dynamic],
[<> ops::RangeFull => R],
[<> ops::RangeInclusive<usize> => Dynamic],
[<> ops::RangeTo<usize> => Dynamic],
[<> ops::RangeToInclusive<usize> => Dynamic],
[<I: Dim> ops::RangeFrom<I>
=> DimDiff<R, I>
where R: DimSub<I>],
}
index C with {
[<> usize => U1],
[<> ops::Range<usize> => Dynamic],
[<> ops::RangeFrom<usize> => Dynamic],
[<> ops::RangeFull => C],
[<> ops::RangeInclusive<usize> => Dynamic],
[<> ops::RangeTo<usize> => Dynamic],
[<> ops::RangeToInclusive<usize> => Dynamic],
[<J: DimName> ops::RangeFrom<J>
=> DimDiff<C, J>
where C: DimSub<J>],
}
}