| //! Traits for matrices operations. |
| //! |
| //! These traits defines operations for structs representing matrices arranged in row-major order. |
| //! |
| //! Implementations are provided for |
| //! - `Matrix`: an owned matrix |
| //! - `MatrixSlice`: a borrowed immutable block of `Matrix` |
| //! - `MatrixSliceMut`: a borrowed mutable block of `Matrix` |
| //! |
| //! ``` |
| //! use rulinalg::matrix::{Matrix, BaseMatrix}; |
| //! |
| //! let a = Matrix::new(3,3, (0..9).collect::<Vec<usize>>()); |
| //! |
| //! // Manually create our slice - [[4,5],[7,8]]. |
| //! let mat_slice = a.sub_slice([0,1], 3, 2); |
| //! |
| //! // We can perform arithmetic with mixing owned and borrowed versions |
| //! let _new_mat = &mat_slice.transpose() * &a; |
| //! ``` |
| use std::vec::*; |
| use matrix::{Matrix, MatrixSlice, MatrixSliceMut}; |
| use matrix::{Cols, ColsMut, Row, RowMut, Column, ColumnMut, Rows, RowsMut, Axes}; |
| use matrix::{DiagOffset, Diagonal, DiagonalMut}; |
| use matrix::{back_substitution, forward_substitution}; |
| use matrix::{SliceIter, SliceIterMut}; |
| use norm::{MatrixNorm, MatrixMetric}; |
| use vector::Vector; |
| use utils; |
| use libnum::{Zero, Float}; |
| use error::Error; |
| |
| use std::any::Any; |
| use std::cmp::min; |
| use std::marker::PhantomData; |
| use std::mem; |
| use std::ops::{Add, Mul, Div}; |
| use std::ptr; |
| use std::slice; |
| |
| mod impl_base; |
| |
| /// Trait for immutable matrix structs. |
| pub trait BaseMatrix<T>: Sized { |
| /// Rows in the matrix. |
| fn rows(&self) -> usize; |
| |
| /// Columns in the matrix. |
| fn cols(&self) -> usize; |
| |
| /// Row stride in the matrix. |
| fn row_stride(&self) -> usize; |
| |
| /// Returns true if the matrix contais no elements |
| fn is_empty(&self) -> bool { |
| self.rows() == 0 || self.cols() == 0 |
| } |
| |
| /// Top left index of the matrix. |
| fn as_ptr(&self) -> *const T; |
| |
| /// Returns a `MatrixSlice` over the whole matrix. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// use rulinalg::matrix::{Matrix, BaseMatrix}; |
| /// |
| /// let a = Matrix::new(3, 3, vec![2.0; 9]); |
| /// let b = a.as_slice(); |
| /// ``` |
| fn as_slice(&self) -> MatrixSlice<T> { |
| unsafe { |
| MatrixSlice::from_raw_parts(self.as_ptr(), self.rows(), self.cols(), self.row_stride()) |
| } |
| } |
| |
| /// Get a reference to an element in the matrix without bounds checking. |
| unsafe fn get_unchecked(&self, index: [usize; 2]) -> &T { |
| &*(self.as_ptr().offset((index[0] * self.row_stride() + index[1]) as isize)) |
| } |
| |
| /// Get a reference to an element in the matrix. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] extern crate rulinalg; fn main() { |
| /// use rulinalg::matrix::{Matrix, BaseMatrix}; |
| /// |
| /// let mat = matrix![0, 1; |
| /// 3, 4; |
| /// 6, 7]; |
| /// |
| /// assert_eq!(mat.get([0, 2]), None); |
| /// assert_eq!(mat.get([3, 0]), None); |
| /// |
| /// assert_eq!( *mat.get([0, 0]).unwrap(), 0) |
| /// # } |
| /// ``` |
| fn get(&self, index: [usize; 2]) -> Option<&T> { |
| let row_ind = index[0]; |
| let col_ind = index[1]; |
| |
| if row_ind >= self.rows() || col_ind >= self.cols() { |
| None |
| } else { |
| unsafe { Some(self.get_unchecked(index)) } |
| } |
| } |
| |
| /// Returns the column of a matrix at the given index. |
| /// `None` if the index is out of bounds. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] extern crate rulinalg; fn main() { |
| /// use rulinalg::matrix::{Matrix, BaseMatrix}; |
| /// |
| /// let mat = matrix![0, 1, 2; |
| /// 3, 4, 5; |
| /// 6, 7, 8]; |
| /// let col = mat.col(1); |
| /// let expected = matrix![1usize; 4; 7]; |
| /// assert_matrix_eq!(*col, expected); |
| /// # } |
| /// ``` |
| /// |
| /// # Panics |
| /// |
| /// Will panic if the column index is out of bounds. |
| fn col(&self, index: usize) -> Column<T> { |
| if index < self.cols() { |
| unsafe { self.col_unchecked(index) } |
| } else { |
| panic!("Column index out of bounds.") |
| } |
| } |
| |
| /// Returns the column of a matrix at the given |
| /// index without doing a bounds check. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] extern crate rulinalg; fn main() { |
| /// use rulinalg::matrix::{Matrix, BaseMatrix}; |
| /// |
| /// let mat = matrix![0, 1, 2; |
| /// 3, 4, 5; |
| /// 6, 7, 8]; |
| /// let col = unsafe { mat.col_unchecked(2) }; |
| /// let expected = matrix![2usize; 5; 8]; |
| /// assert_matrix_eq!(*col, expected); |
| /// # } |
| /// ``` |
| unsafe fn col_unchecked(&self, index: usize) -> Column<T> { |
| let ptr = self.as_ptr().offset(index as isize); |
| Column { col: MatrixSlice::from_raw_parts(ptr, self.rows(), 1, self.row_stride()) } |
| } |
| |
| /// Returns the row of a matrix at the given index. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] extern crate rulinalg; fn main() { |
| /// use rulinalg::matrix::{Matrix, BaseMatrix}; |
| /// |
| /// let mat = matrix![0, 1, 2; |
| /// 3, 4, 5; |
| /// 6, 7, 8]; |
| /// let row = mat.row(1); |
| /// let expected = matrix![3usize, 4, 5]; |
| /// assert_matrix_eq!(*row, expected); |
| /// # } |
| /// ``` |
| /// |
| /// # Panics |
| /// |
| /// Will panic if the row index is out of bounds. |
| fn row(&self, index: usize) -> Row<T> { |
| if index < self.rows() { |
| unsafe { self.row_unchecked(index) } |
| } else { |
| panic!("Row index out of bounds.") |
| } |
| } |
| |
| /// Returns the row of a matrix at the given index without doing unbounds checking |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] extern crate rulinalg; fn main() { |
| /// use rulinalg::matrix::{Matrix, BaseMatrix}; |
| /// |
| /// let mat = matrix![0, 1, 2; |
| /// 3, 4, 5; |
| /// 6, 7, 8]; |
| /// let row = unsafe { mat.row_unchecked(2) }; |
| /// let expected = matrix![6usize, 7, 8]; |
| /// assert_matrix_eq!(*row, expected); |
| /// # } |
| /// ``` |
| unsafe fn row_unchecked(&self, index: usize) -> Row<T> { |
| let ptr = self.as_ptr().offset((self.row_stride() * index) as isize); |
| Row { row: MatrixSlice::from_raw_parts(ptr, 1, self.cols(), self.row_stride()) } |
| } |
| |
| /// Returns an iterator over the matrix data. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] extern crate rulinalg; fn main() { |
| /// use rulinalg::matrix::{Matrix, BaseMatrix}; |
| /// |
| /// let mat = matrix![0, 1, 2; |
| /// 3, 4, 5; |
| /// 6, 7, 8]; |
| /// let slice = mat.sub_slice([1, 1], 2, 2); |
| /// |
| /// let slice_data = slice.iter().map(|v| *v).collect::<Vec<usize>>(); |
| /// assert_eq!(slice_data, vec![4, 5, 7, 8]); |
| /// # } |
| /// ``` |
| fn iter<'a>(&self) -> SliceIter<'a, T> |
| where T: 'a |
| { |
| SliceIter { |
| slice_start: self.as_ptr(), |
| row_pos: 0, |
| col_pos: 0, |
| slice_rows: self.rows(), |
| slice_cols: self.cols(), |
| row_stride: self.row_stride(), |
| _marker: PhantomData::<&T>, |
| } |
| } |
| |
| /// Iterate over the columns of the matrix. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] extern crate rulinalg; fn main() { |
| /// use rulinalg::matrix::{Matrix, BaseMatrix}; |
| /// |
| /// let a = matrix![0, 1; |
| /// 2, 3; |
| /// 4, 5]; |
| /// |
| /// let mut iter = a.col_iter(); |
| /// |
| /// assert_matrix_eq!(*iter.next().unwrap(), matrix![ 0; 2; 4 ]); |
| /// assert_matrix_eq!(*iter.next().unwrap(), matrix![ 1; 3; 5 ]); |
| /// assert!(iter.next().is_none()); |
| /// # } |
| /// ``` |
| fn col_iter(&self) -> Cols<T> { |
| Cols { |
| _marker: PhantomData::<&T>, |
| col_pos: 0, |
| row_stride: self.row_stride() as isize, |
| slice_cols: self.cols(), |
| slice_rows: self.rows(), |
| slice_start: self.as_ptr(), |
| } |
| } |
| |
| /// Iterate over the rows of the matrix. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] extern crate rulinalg; fn main() { |
| /// use rulinalg::matrix::{Matrix, BaseMatrix}; |
| /// let a = matrix![0, 1, 2; |
| /// 3, 4, 5; |
| /// 6, 7, 8]; |
| /// |
| /// let mut iter = a.row_iter(); |
| /// |
| /// assert_matrix_eq!(*iter.next().unwrap(), matrix![ 0, 1, 2 ]); |
| /// assert_matrix_eq!(*iter.next().unwrap(), matrix![ 3, 4, 5 ]); |
| /// assert_matrix_eq!(*iter.next().unwrap(), matrix![ 6, 7, 8 ]); |
| /// assert!(iter.next().is_none()); |
| /// # } |
| /// ``` |
| fn row_iter(&self) -> Rows<T> { |
| Rows { |
| slice_start: self.as_ptr(), |
| row_pos: 0, |
| slice_rows: self.rows(), |
| slice_cols: self.cols(), |
| row_stride: self.row_stride() as isize, |
| _marker: PhantomData::<&T>, |
| } |
| } |
| |
| /// Iterate over diagonal entries |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] extern crate rulinalg; |
| /// |
| /// # fn main() { |
| /// use rulinalg::matrix::{DiagOffset, Matrix, BaseMatrix}; |
| /// |
| /// let a = matrix![0, 1, 2; |
| /// 3, 4, 5; |
| /// 6, 7, 8]; |
| /// // Print super diag [1, 5] |
| /// for d in a.diag_iter(DiagOffset::Above(1)) { |
| /// println!("{}", d); |
| /// } |
| /// |
| /// // Print sub diag [3, 7] |
| /// // Equivalent to `diag_iter(DiagOffset::Below(1))` |
| /// for d in a.diag_iter(DiagOffset::from(-1)) { |
| /// println!("{}", d); |
| /// } |
| /// # } |
| /// ``` |
| /// |
| /// # Panics |
| /// |
| /// If using an `Above` or `Below` offset which is |
| /// out-of-bounds this function will panic. |
| /// |
| /// This function will never panic if the `Main` diagonal |
| /// offset is used. |
| fn diag_iter(&self, k: DiagOffset) -> Diagonal<T, Self> { |
| let (diag_len, diag_start) = match k.into() { |
| DiagOffset::Main => (min(self.rows(), self.cols()), 0), |
| DiagOffset::Above(m) => { |
| assert!(m < self.cols(), |
| "Offset diagonal is not within matrix dimensions."); |
| (min(self.rows(), self.cols() - m), m) |
| } |
| DiagOffset::Below(m) => { |
| assert!(m < self.rows(), |
| "Offset diagonal is not within matrix dimensions."); |
| (min(self.rows() - m, self.cols()), m * self.row_stride()) |
| } |
| }; |
| |
| Diagonal { |
| matrix: self, |
| diag_pos: diag_start, |
| diag_end: diag_start + diag_len.saturating_sub(1) * self.row_stride() + diag_len, |
| _marker: PhantomData::<&T>, |
| } |
| } |
| |
| /// The sum of the rows of the matrix. |
| /// |
| /// Returns a Vector equal to the sums of elements over the matrices rows. |
| /// |
| /// Note that the resulting vector is identical to the sums of |
| /// elements along each column of the matrix. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] extern crate rulinalg; fn main() { |
| /// use rulinalg::matrix::{Matrix, BaseMatrix}; |
| /// |
| /// let a = matrix![1.0, 2.0; |
| /// 3.0, 4.0]; |
| /// |
| /// let c = a.sum_rows(); |
| /// assert_eq!(c, vector![4.0, 6.0]); |
| /// # } |
| /// ``` |
| fn sum_rows(&self) -> Vector<T> |
| where T: Copy + Zero + Add<T, Output = T> |
| { |
| let mut sum_rows = vec![T::zero(); self.cols()]; |
| for row in self.row_iter() { |
| utils::in_place_vec_bin_op(&mut sum_rows, row.raw_slice(), |sum, &r| *sum = *sum + r); |
| } |
| Vector::new(sum_rows) |
| } |
| |
| /// The sum of the columns of the matrix. |
| /// |
| /// Returns a Vector equal to the sums of elements over the matrices columns. |
| /// |
| /// Note that the resulting vector is identical to the sums of |
| /// elements along each row of the matrix. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] extern crate rulinalg; fn main() { |
| /// use rulinalg::matrix::{Matrix, BaseMatrix}; |
| /// |
| /// let a = matrix![1.0, 2.0; |
| /// 3.0, 4.0]; |
| /// |
| /// let c = a.sum_cols(); |
| /// assert_eq!(c, vector![3.0, 7.0]); |
| /// # } |
| /// ``` |
| fn sum_cols(&self) -> Vector<T> |
| where T: Copy + Zero + Add<T, Output = T> |
| { |
| let mut col_sum = Vec::with_capacity(self.rows()); |
| col_sum.extend(self.row_iter().map(|row| utils::unrolled_sum(row.raw_slice()))); |
| Vector::new(col_sum) |
| } |
| |
| /// Compute given matrix norm for matrix. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] extern crate rulinalg; fn main() { |
| /// use rulinalg::matrix::BaseMatrix; |
| /// use rulinalg::norm::Euclidean; |
| /// |
| /// let a = matrix![3.0, 4.0]; |
| /// let c = a.norm(Euclidean); |
| /// |
| /// assert_eq!(c, 5.0); |
| /// # } |
| /// ``` |
| fn norm<N: MatrixNorm<T, Self>>(&self, norm: N) -> T |
| where T: Float |
| { |
| norm.norm(self) |
| } |
| |
| /// Compute the metric distance between two matrices. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] extern crate rulinalg; fn main() { |
| /// use rulinalg::matrix::BaseMatrix; |
| /// use rulinalg::norm::Euclidean; |
| /// |
| /// let a = matrix![3.0, 4.0; |
| /// 1.0, 2.0]; |
| /// let b = matrix![2.0, 5.0; |
| /// 0.0, 3.0]; |
| /// |
| /// // Compute the square root of the sum of |
| /// // elementwise squared-differences |
| /// let c = a.metric(&b, Euclidean); |
| /// |
| /// assert_eq!(c, 2.0); |
| /// # } |
| /// ``` |
| fn metric<'a, 'b, B, M>(&'a self, mat: &'b B, metric: M) -> T |
| where B: 'b + BaseMatrix<T>, |
| M: MatrixMetric<'a, 'b, T, Self, B> |
| { |
| metric.metric(self, mat) |
| } |
| |
| /// The sum of all elements in the matrix |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] extern crate rulinalg; fn main() { |
| /// use rulinalg::matrix::BaseMatrix; |
| /// |
| /// let a = matrix![1.0, 2.0; |
| /// 3.0, 4.0]; |
| /// |
| /// let c = a.sum(); |
| /// assert_eq!(c, 10.0); |
| /// # } |
| /// ``` |
| fn sum(&self) -> T |
| where T: Copy + Zero + Add<T, Output = T> |
| { |
| self.row_iter() |
| .fold(T::zero(), |
| |sum, row| sum + utils::unrolled_sum(row.raw_slice())) |
| } |
| |
| /// The min of the specified axis of the matrix. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] extern crate rulinalg; fn main() { |
| /// use rulinalg::matrix::{Matrix, BaseMatrix, Axes}; |
| /// |
| /// let a = matrix![1.0, 2.0; |
| /// 3.0, 4.0]; |
| /// |
| /// let cmin = a.min(Axes::Col); |
| /// assert_eq!(cmin, vector![1.0, 3.0]); |
| /// |
| /// let rmin = a.min(Axes::Row); |
| /// assert_eq!(rmin, vector![1.0, 2.0]); |
| /// # } |
| /// ``` |
| fn min(&self, axis: Axes) -> Vector<T> |
| where T: Copy + PartialOrd |
| { |
| match axis { |
| Axes::Col => { |
| let mut mins: Vec<T> = Vec::with_capacity(self.rows()); |
| for row in self.row_iter() { |
| let min = row.iter() |
| .skip(1) |
| .fold(row[0], |m, &v| if v < m { v } else { m }); |
| mins.push(min); |
| } |
| Vector::new(mins) |
| } |
| Axes::Row => { |
| let mut mins: Vec<T> = self.row(0).raw_slice().into(); |
| for row in self.row_iter().skip(1) { |
| utils::in_place_vec_bin_op(&mut mins, row.raw_slice(), |min, &r| if r < *min { |
| *min = r; |
| }); |
| } |
| Vector::new(mins) |
| } |
| } |
| } |
| |
| /// The max of the specified axis of the matrix. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] extern crate rulinalg; fn main() { |
| /// use rulinalg::matrix::{BaseMatrix, Axes}; |
| /// |
| /// let a = matrix![1.0, 2.0; |
| /// 3.0, 4.0]; |
| /// |
| /// let cmax = a.max(Axes::Col); |
| /// assert_eq!(cmax, vector![2.0, 4.0]); |
| /// |
| /// let rmax = a.max(Axes::Row); |
| /// assert_eq!(rmax, vector![3.0, 4.0]); |
| /// # } |
| /// ``` |
| fn max(&self, axis: Axes) -> Vector<T> |
| where T: Copy + PartialOrd |
| { |
| match axis { |
| Axes::Col => { |
| let mut maxs: Vec<T> = Vec::with_capacity(self.rows()); |
| for row in self.row_iter() { |
| let max = row.iter() |
| .skip(1) |
| .fold(row[0], |m, &v| if v > m { v } else { m }); |
| maxs.push(max); |
| } |
| Vector::new(maxs) |
| } |
| Axes::Row => { |
| let mut maxs: Vec<T> = self.row(0).raw_slice().into(); |
| for row in self.row_iter().skip(1) { |
| utils::in_place_vec_bin_op(&mut maxs, row.raw_slice(), |max, &r| if r > *max { |
| *max = r; |
| }); |
| } |
| Vector::new(maxs) |
| } |
| } |
| } |
| |
| /// Convert the matrix struct into a owned Matrix. |
| fn into_matrix(self) -> Matrix<T> |
| where T: Copy |
| { |
| self.row_iter().collect() |
| } |
| |
| /// Select rows from matrix |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// use rulinalg::matrix::{Matrix, BaseMatrix}; |
| /// |
| /// let a = Matrix::<f64>::ones(3,3); |
| /// |
| /// let b = &a.select_rows(&[2]); |
| /// assert_eq!(b.rows(), 1); |
| /// assert_eq!(b.cols(), 3); |
| /// |
| /// let c = &a.select_rows(&[1,2]); |
| /// assert_eq!(c.rows(), 2); |
| /// assert_eq!(c.cols(), 3); |
| /// ``` |
| /// |
| /// # Panics |
| /// |
| /// - Panics if row indices exceed the matrix dimensions. |
| fn select_rows<'a, I>(&self, rows: I) -> Matrix<T> |
| where T: Copy, |
| I: IntoIterator<Item = &'a usize>, |
| I::IntoIter: ExactSizeIterator + Clone |
| { |
| let row_iter = rows.into_iter(); |
| let mut mat_vec = Vec::with_capacity(row_iter.len() * self.cols()); |
| |
| for row in row_iter.clone() { |
| assert!(*row < self.rows(), |
| "Row index is greater than number of rows."); |
| } |
| |
| for row_idx in row_iter.clone() { |
| unsafe { |
| let row = self.row_unchecked(*row_idx); |
| mat_vec.extend_from_slice(row.raw_slice()); |
| } |
| } |
| |
| Matrix { |
| cols: self.cols(), |
| rows: row_iter.len(), |
| data: mat_vec, |
| } |
| } |
| |
| /// Select columns from matrix |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// use rulinalg::matrix::{Matrix, BaseMatrix}; |
| /// |
| /// let a = Matrix::<f64>::ones(3,3); |
| /// let b = &a.select_cols(&[2]); |
| /// assert_eq!(b.rows(), 3); |
| /// assert_eq!(b.cols(), 1); |
| /// |
| /// let c = &a.select_cols(&[1,2]); |
| /// assert_eq!(c.rows(), 3); |
| /// assert_eq!(c.cols(), 2); |
| /// ``` |
| /// |
| /// # Panics |
| /// |
| /// - Panics if column indices exceed the matrix dimensions. |
| fn select_cols<'a, I>(&self, cols: I) -> Matrix<T> |
| where T: Copy, |
| I: IntoIterator<Item = &'a usize>, |
| I::IntoIter: ExactSizeIterator + Clone |
| { |
| let col_iter = cols.into_iter(); |
| let mut mat_vec = Vec::with_capacity(col_iter.len() * self.rows()); |
| |
| for col in col_iter.clone() { |
| assert!(*col < self.cols(), |
| "Column index is greater than number of columns."); |
| } |
| |
| unsafe { |
| for i in 0..self.rows() { |
| for col in col_iter.clone() { |
| mat_vec.push(*self.get_unchecked([i, *col])); |
| } |
| } |
| } |
| |
| Matrix { |
| cols: col_iter.len(), |
| rows: self.rows(), |
| data: mat_vec, |
| } |
| } |
| |
| /// The elementwise product of two matrices. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] extern crate rulinalg; fn main() { |
| /// use rulinalg::matrix::{Matrix, BaseMatrix}; |
| /// |
| /// let a = matrix![1.0, 2.0; |
| /// 3.0, 4.0]; |
| /// let b = matrix![1.0, 2.0; |
| /// 3.0, 4.0]; |
| /// |
| /// let c = &a.elemul(&b); |
| /// assert_matrix_eq!(c, &matrix![1.0, 4.0; 9.0, 16.0]); |
| /// } |
| /// ``` |
| /// |
| /// # Panics |
| /// |
| /// - The matrices have different row counts. |
| /// - The matrices have different column counts. |
| fn elemul(&self, m: &Self) -> Matrix<T> |
| where T: Copy + Mul<T, Output = T> |
| { |
| assert!(self.rows() == m.rows(), "Matrix row counts not equal."); |
| assert!(self.cols() == m.cols(), "Matrix column counts not equal."); |
| |
| let mut data = Vec::with_capacity(self.rows() * self.cols()); |
| for (self_r, m_r) in self.row_iter().zip(m.row_iter()) { |
| data.extend_from_slice(&utils::vec_bin_op(self_r.raw_slice(), m_r.raw_slice(), T::mul)); |
| } |
| Matrix::new(self.rows(), self.cols(), data) |
| } |
| |
| /// The elementwise division of two matrices. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] extern crate rulinalg; fn main() { |
| /// use rulinalg::matrix::{Matrix, BaseMatrix}; |
| /// |
| /// let a = matrix![1.0, 2.0; |
| /// 3.0, 4.0]; |
| /// let b = matrix![1.0, 2.0; |
| /// 3.0, 4.0]; |
| /// |
| /// let c = &a.elediv(&b); |
| /// assert_matrix_eq!(c, &matrix![1.0, 1.0; 1.0, 1.0]); |
| /// # } |
| /// ``` |
| /// |
| /// # Panics |
| /// |
| /// - The matrices have different row counts. |
| /// - The matrices have different column counts. |
| fn elediv(&self, m: &Self) -> Matrix<T> |
| where T: Copy + Div<T, Output = T> |
| { |
| assert!(self.rows() == m.rows(), "Matrix row counts not equal."); |
| assert!(self.cols() == m.cols(), "Matrix column counts not equal."); |
| |
| let mut data = Vec::with_capacity(self.rows() * self.cols()); |
| for (self_r, m_r) in self.row_iter().zip(m.row_iter()) { |
| data.extend_from_slice(&utils::vec_bin_op(self_r.raw_slice(), m_r.raw_slice(), T::div)); |
| } |
| Matrix::new(self.rows(), self.cols(), data) |
| } |
| |
| /// Select block matrix from matrix |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// use rulinalg::matrix::{Matrix, BaseMatrix}; |
| /// |
| /// let a = Matrix::<f64>::identity(3); |
| /// let b = &a.select(&[0,1], &[1,2]); |
| /// |
| /// // We get the 2x2 block matrix in the upper right corner. |
| /// assert_eq!(b.rows(), 2); |
| /// assert_eq!(b.cols(), 2); |
| /// |
| /// // Prints [0,0, 1,0] |
| /// println!("{:?}", b.data()); |
| /// ``` |
| /// |
| /// # Panics |
| /// |
| /// - Panics if row or column indices exceed the matrix dimensions. |
| fn select(&self, rows: &[usize], cols: &[usize]) -> Matrix<T> |
| where T: Copy |
| { |
| |
| let mut mat_vec = Vec::with_capacity(cols.len() * rows.len()); |
| |
| for col in cols { |
| assert!(*col < self.cols(), |
| "Column index is greater than number of columns."); |
| } |
| |
| for row in rows { |
| assert!(*row < self.rows(), |
| "Row index is greater than number of columns."); |
| } |
| |
| unsafe { |
| for row in rows { |
| for col in cols { |
| mat_vec.push(*self.get_unchecked([*row, *col])); |
| } |
| } |
| } |
| |
| Matrix { |
| cols: cols.len(), |
| rows: rows.len(), |
| data: mat_vec, |
| } |
| } |
| |
| /// Horizontally concatenates two matrices. With self on the left. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] extern crate rulinalg; fn main() { |
| /// use rulinalg::matrix::{Matrix, BaseMatrix}; |
| /// |
| /// let a = matrix![1.0, 2.0; |
| /// 3.0, 4.0; |
| /// 5.0, 6.0]; |
| /// let b = matrix![4.0; |
| /// 5.0; |
| /// 6.0]; |
| /// |
| /// let c = &a.hcat(&b); |
| /// assert_eq!(c.cols(), a.cols() + b.cols()); |
| /// assert_eq!(c[[1, 2]], 5.0); |
| /// # } |
| /// ``` |
| /// |
| /// # Panics |
| /// |
| /// - Self and m have different row counts. |
| fn hcat<S>(&self, m: &S) -> Matrix<T> |
| where T: Copy, |
| S: BaseMatrix<T> |
| { |
| assert!(self.rows() == m.rows(), "Matrix row counts are not equal."); |
| |
| let mut new_data = Vec::with_capacity((self.cols() + m.cols()) * self.rows()); |
| |
| for (self_row, m_row) in self.row_iter().zip(m.row_iter()) { |
| new_data.extend_from_slice(self_row.raw_slice()); |
| new_data.extend_from_slice(m_row.raw_slice()); |
| } |
| |
| Matrix { |
| cols: (self.cols() + m.cols()), |
| rows: self.rows(), |
| data: new_data, |
| } |
| } |
| |
| /// Vertically concatenates two matrices. With self on top. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] extern crate rulinalg; fn main() { |
| /// use rulinalg::matrix::{Matrix, BaseMatrix}; |
| /// |
| /// let a = matrix![1.0, 2.0, 3.0; |
| /// 4.0, 5.0, 6.0]; |
| /// let b = matrix![4.0, 5.0, 6.0];; |
| /// |
| /// let c = &a.vcat(&b); |
| /// assert_eq!(c.rows(), a.rows() + b.rows()); |
| /// assert_eq!(c[[2, 2]], 6.0); |
| /// # } |
| /// ``` |
| /// |
| /// # Panics |
| /// |
| /// - Self and m have different column counts. |
| fn vcat<S>(&self, m: &S) -> Matrix<T> |
| where T: Copy, |
| S: BaseMatrix<T> |
| { |
| assert!(self.cols() == m.cols(), |
| "Matrix column counts are not equal."); |
| |
| let mut new_data = Vec::with_capacity((self.rows() + m.rows()) * self.cols()); |
| |
| for row in self.row_iter().chain(m.row_iter()) { |
| new_data.extend_from_slice(row.raw_slice()); |
| } |
| |
| Matrix { |
| cols: self.cols(), |
| rows: (self.rows() + m.rows()), |
| data: new_data, |
| } |
| } |
| |
| /// Extract the diagonal of the matrix |
| /// |
| /// Examples |
| /// |
| /// ``` |
| /// # #[macro_use] |
| /// # extern crate rulinalg; |
| /// |
| /// use rulinalg::matrix::BaseMatrix; |
| /// |
| /// # fn main() { |
| /// let a = matrix![1, 2, 3; |
| /// 4, 5, 6; |
| /// 7, 8, 9].diag().cloned().collect::<Vec<_>>(); |
| /// let b = matrix![1, 2; |
| /// 3, 4; |
| /// 5, 6].diag().cloned().collect::<Vec<_>>(); |
| /// |
| /// assert_eq!(a, vec![1, 5, 9]); |
| /// assert_eq!(b, vec![1, 4]); |
| /// # } |
| /// ``` |
| fn diag(&self) -> Diagonal<T, Self> { |
| self.diag_iter(DiagOffset::Main) |
| } |
| |
| /// Tranposes the given matrix |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] extern crate rulinalg; fn main() { |
| /// use rulinalg::matrix::{Matrix, BaseMatrix}; |
| /// |
| /// let mat = matrix![1.0, 2.0, 3.0; |
| /// 4.0, 5.0, 6.0]; |
| /// |
| /// let expected = matrix![1.0, 4.0; |
| /// 2.0, 5.0; |
| /// 3.0, 6.0]; |
| /// assert_matrix_eq!(mat.transpose(), expected); |
| /// # } |
| /// ``` |
| fn transpose(&self) -> Matrix<T> |
| where T: Copy |
| { |
| let mut new_data = Vec::with_capacity(self.rows() * self.cols()); |
| |
| unsafe { |
| new_data.set_len(self.rows() * self.cols()); |
| for i in 0..self.cols() { |
| for j in 0..self.rows() { |
| *new_data.get_unchecked_mut(i * self.rows() + j) = *self.get_unchecked([j, i]); |
| } |
| } |
| } |
| |
| Matrix { |
| cols: self.rows(), |
| rows: self.cols(), |
| data: new_data, |
| } |
| } |
| |
| /// Checks if matrix is diagonal. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] extern crate rulinalg; fn main() { |
| /// use rulinalg::matrix::{Matrix, BaseMatrix}; |
| /// |
| /// let a = matrix![1.0, 0.0; |
| /// 0.0, 1.0]; |
| /// let a_diag = a.is_diag(); |
| /// |
| /// assert_eq!(a_diag, true); |
| /// |
| /// let b = matrix![1.0, 0.0; |
| /// 1.0, 0.0]; |
| /// let b_diag = b.is_diag(); |
| /// |
| /// assert_eq!(b_diag, false); |
| /// # } |
| /// ``` |
| fn is_diag(&self) -> bool |
| where T: Zero + PartialEq |
| { |
| let mut next_diag = 0usize; |
| self.iter().enumerate().all(|(i, data)| if i == next_diag { |
| next_diag += self.cols() + 1; |
| true |
| } else { |
| data == &T::zero() |
| }) |
| } |
| |
| /// Solves an upper triangular linear system. |
| /// |
| /// Given a matrix `A` and a vector `b`, this function returns the |
| /// solution of the upper triangular system `Ux = b`, where `U` is |
| /// the upper triangular part of `A`. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] extern crate rulinalg; fn main() { |
| /// use rulinalg::matrix::BaseMatrix; |
| /// use std::f32; |
| /// |
| /// let u = matrix![1.0, 2.0; |
| /// 0.0, 1.0]; |
| /// let y = vector![3.0, 1.0]; |
| /// |
| /// let x = u.solve_u_triangular(y).expect("A solution should exist!"); |
| /// assert!((x[0] - 1.0) < f32::EPSILON); |
| /// assert!((x[1] - 1.0) < f32::EPSILON); |
| /// # } |
| /// ``` |
| /// |
| /// # Panics |
| /// |
| /// - Vector size and matrix column count are not equal. |
| /// |
| /// # Failures |
| /// |
| /// - There is no valid solution to the system (matrix is singular). |
| /// - The matrix is empty. |
| fn solve_u_triangular(&self, y: Vector<T>) -> Result<Vector<T>, Error> |
| where T: Any + Float |
| { |
| assert!(self.cols() == y.size(), |
| format!("Vector size {0} != {1} Matrix column count.", |
| y.size(), |
| self.cols())); |
| |
| back_substitution(self, y) |
| } |
| |
| /// Solves a lower triangular linear system. |
| /// |
| /// Given a matrix `A` and a vector `b`, this function returns the |
| /// solution of the lower triangular system `Lx = b`, where `L` is |
| /// the lower triangular part of `A`. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] extern crate rulinalg; fn main() { |
| /// use rulinalg::matrix::BaseMatrix; |
| /// use std::f32; |
| /// |
| /// let l = matrix![1.0, 0.0; |
| /// 2.0, 1.0]; |
| /// let y = vector![1.0, 3.0]; |
| /// |
| /// let x = l.solve_l_triangular(y).expect("A solution should exist!"); |
| /// println!("{:?}", x); |
| /// assert!((x[0] - 1.0) < f32::EPSILON); |
| /// assert!((x[1] - 1.0) < f32::EPSILON); |
| /// # } |
| /// ``` |
| /// |
| /// # Panics |
| /// |
| /// - Vector size and matrix column count are not equal. |
| /// |
| /// # Failures |
| /// |
| /// - There is no valid solution to the system (matrix is singular). |
| /// - The matrix is empty. |
| fn solve_l_triangular(&self, y: Vector<T>) -> Result<Vector<T>, Error> |
| where T: Any + Float |
| { |
| assert!(self.cols() == y.size(), |
| format!("Vector size {0} != {1} Matrix column count.", |
| y.size(), |
| self.cols())); |
| |
| forward_substitution(self, y) |
| } |
| |
| /// Split the matrix at the specified axis returning two `MatrixSlice`s. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// use rulinalg::matrix::{Axes, Matrix, BaseMatrix}; |
| /// |
| /// let a = Matrix::new(3,3, vec![2.0; 9]); |
| /// let (b,c) = a.split_at(1, Axes::Row); |
| /// ``` |
| fn split_at(&self, mid: usize, axis: Axes) -> (MatrixSlice<T>, MatrixSlice<T>) { |
| let slice_1: MatrixSlice<T>; |
| let slice_2: MatrixSlice<T>; |
| |
| match axis { |
| Axes::Row => { |
| assert!(mid < self.rows()); |
| unsafe { |
| slice_1 = MatrixSlice::from_raw_parts(self.as_ptr(), |
| mid, |
| self.cols(), |
| self.row_stride()); |
| slice_2 = MatrixSlice::from_raw_parts(self.as_ptr() |
| .offset((mid * self.row_stride()) as |
| isize), |
| self.rows() - mid, |
| self.cols(), |
| self.row_stride()); |
| } |
| } |
| Axes::Col => { |
| assert!(mid < self.cols()); |
| unsafe { |
| slice_1 = MatrixSlice::from_raw_parts(self.as_ptr(), |
| self.rows(), |
| mid, |
| self.row_stride()); |
| slice_2 = MatrixSlice::from_raw_parts(self.as_ptr().offset(mid as isize), |
| self.rows(), |
| self.cols() - mid, |
| self.row_stride()); |
| } |
| } |
| } |
| |
| (slice_1, slice_2) |
| } |
| |
| /// Produce a `MatrixSlice` from an existing matrix. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// use rulinalg::matrix::{Matrix, BaseMatrix, MatrixSlice}; |
| /// |
| /// let a = Matrix::new(3,3, (0..9).collect::<Vec<usize>>()); |
| /// let slice = MatrixSlice::from_matrix(&a, [1,1], 2, 2); |
| /// let new_slice = slice.sub_slice([0,0], 1, 1); |
| /// ``` |
| fn sub_slice<'a>(&self, start: [usize; 2], rows: usize, cols: usize) -> MatrixSlice<'a, T> |
| where T: 'a |
| { |
| assert!(start[0] + rows <= self.rows(), |
| "View dimensions exceed matrix dimensions."); |
| assert!(start[1] + cols <= self.cols(), |
| "View dimensions exceed matrix dimensions."); |
| |
| unsafe { |
| MatrixSlice::from_raw_parts(self.as_ptr() |
| .offset((start[0] * self.row_stride() + start[1]) as |
| isize), |
| rows, |
| cols, |
| self.row_stride()) |
| } |
| } |
| } |
| |
| /// Trait for mutable matrices. |
| pub trait BaseMatrixMut<T>: BaseMatrix<T> { |
| /// Top left index of the slice. |
| fn as_mut_ptr(&mut self) -> *mut T; |
| |
| /// Returns a `MatrixSliceMut` over the whole matrix. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// use rulinalg::matrix::{Matrix, BaseMatrixMut}; |
| /// |
| /// let mut a = Matrix::new(3, 3, vec![2.0; 9]); |
| /// let b = a.as_mut_slice(); |
| /// ``` |
| fn as_mut_slice(&mut self) -> MatrixSliceMut<T> { |
| unsafe { |
| MatrixSliceMut::from_raw_parts(self.as_mut_ptr(), |
| self.rows(), |
| self.cols(), |
| self.row_stride()) |
| } |
| } |
| |
| /// Get a mutable reference to an element in the matrix without bounds checks. |
| unsafe fn get_unchecked_mut(&mut self, index: [usize; 2]) -> &mut T { |
| &mut *(self.as_mut_ptr().offset((index[0] * self.row_stride() + index[1]) as isize)) |
| } |
| |
| /// Get a mutable reference to an element in the matrix. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] extern crate rulinalg; fn main() { |
| /// use rulinalg::matrix::{Matrix, BaseMatrix, BaseMatrixMut}; |
| /// |
| /// let mut mat = matrix![0, 1; |
| /// 3, 4; |
| /// 6, 7]; |
| /// |
| /// assert_eq!(mat.get_mut([0, 2]), None); |
| /// assert_eq!(mat.get_mut([3, 0]), None); |
| /// |
| /// assert_eq!(*mat.get_mut([0, 0]).unwrap(), 0); |
| /// *mat.get_mut([0,0]).unwrap() = 2; |
| /// assert_eq!(*mat.get_mut([0, 0]).unwrap(), 2); |
| /// # } |
| /// ``` |
| fn get_mut(&mut self, index: [usize; 2]) -> Option<&mut T> { |
| let row_ind = index[0]; |
| let col_ind = index[1]; |
| |
| if row_ind >= self.rows() || col_ind >= self.cols() { |
| None |
| } else { |
| unsafe { Some(self.get_unchecked_mut(index)) } |
| } |
| } |
| |
| /// Returns a mutable iterator over the matrix. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] extern crate rulinalg; fn main() { |
| /// use rulinalg::matrix::{Matrix, BaseMatrixMut}; |
| /// |
| /// let mut a = Matrix::new(3,3, (0..9).collect::<Vec<usize>>()); |
| /// |
| /// { |
| /// let mut slice = a.sub_slice_mut([1,1], 2, 2); |
| /// |
| /// for d in slice.iter_mut() { |
| /// *d = *d + 2; |
| /// } |
| /// } |
| /// |
| /// // Only the matrix slice is updated. |
| /// assert_matrix_eq!(a, matrix![0, 1, 2; 3, 6, 7; 6, 9, 10]); |
| /// # } |
| /// ``` |
| fn iter_mut<'a>(&mut self) -> SliceIterMut<'a, T> |
| where T: 'a |
| { |
| SliceIterMut { |
| slice_start: self.as_mut_ptr(), |
| row_pos: 0, |
| col_pos: 0, |
| slice_rows: self.rows(), |
| slice_cols: self.cols(), |
| row_stride: self.row_stride(), |
| _marker: PhantomData::<&mut T>, |
| } |
| } |
| |
| /// Returns a mutable reference to the column of a matrix at the given index. |
| /// `None` if the index is out of bounds. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] |
| /// # extern crate rulinalg; |
| /// |
| /// # fn main() { |
| /// use rulinalg::matrix::{Matrix, BaseMatrixMut}; |
| /// |
| /// let mut mat = matrix![0, 1, 2; |
| /// 3, 4, 5; |
| /// 6, 7, 8]; |
| /// let mut slice = mat.sub_slice_mut([1,1], 2, 2); |
| /// { |
| /// let col = slice.col_mut(1); |
| /// let mut expected = matrix![5usize; 8]; |
| /// assert_matrix_eq!(*col, expected); |
| /// } |
| /// # } |
| /// ``` |
| /// |
| /// # Panics |
| /// |
| /// Will panic if the column index is out of bounds. |
| fn col_mut(&mut self, index: usize) -> ColumnMut<T> { |
| if index < self.cols() { |
| unsafe { self.col_unchecked_mut(index) } |
| } else { |
| panic!("Column index out of bounds.") |
| } |
| } |
| |
| /// Returns a mutable reference to the column of a matrix at the given index |
| /// without doing a bounds check. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] |
| /// # extern crate rulinalg; |
| /// |
| /// # fn main() { |
| /// use rulinalg::matrix::{Matrix, BaseMatrixMut}; |
| /// |
| /// let mut mat = matrix![0, 1, 2; |
| /// 3, 4, 5; |
| /// 6, 7, 8]; |
| /// let mut slice = mat.sub_slice_mut([1,1], 2, 2); |
| /// let col = unsafe { slice.col_unchecked_mut(1) }; |
| /// let mut expected = matrix![5usize; 8]; |
| /// assert_matrix_eq!(*col, expected); |
| /// # } |
| /// ``` |
| unsafe fn col_unchecked_mut(&mut self, index: usize) -> ColumnMut<T> { |
| let ptr = self.as_mut_ptr().offset(index as isize); |
| ColumnMut { col: MatrixSliceMut::from_raw_parts(ptr, self.rows(), 1, self.row_stride()) } |
| } |
| |
| /// Returns a mutable reference to the row of a matrix at the given index. |
| /// `None` if the index is out of bounds. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] |
| /// # extern crate rulinalg; |
| /// |
| /// # fn main() { |
| /// use rulinalg::matrix::{Matrix, BaseMatrixMut}; |
| /// |
| /// let mut mat = matrix![0, 1, 2; |
| /// 3, 4, 5; |
| /// 6, 7, 8]; |
| /// let mut slice = mat.sub_slice_mut([1,1], 2, 2); |
| /// { |
| /// let row = slice.row_mut(1); |
| /// let mut expected = matrix![7usize, 8]; |
| /// assert_matrix_eq!(*row, expected); |
| /// } |
| /// # } |
| /// ``` |
| /// |
| /// # Panics |
| /// |
| /// Will panic if the row index is out of bounds. |
| fn row_mut(&mut self, index: usize) -> RowMut<T> { |
| if index < self.rows() { |
| unsafe { self.row_unchecked_mut(index) } |
| } else { |
| panic!("Row index out of bounds.") |
| } |
| } |
| |
| /// Returns a mutable reference to the row of a matrix at the given index |
| /// without doing a bounds check. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] |
| /// # extern crate rulinalg; |
| /// |
| /// # fn main() { |
| /// use rulinalg::matrix::{Matrix, BaseMatrixMut}; |
| /// |
| /// let mut mat = matrix![0, 1, 2; |
| /// 3, 4, 5; |
| /// 6, 7, 8]; |
| /// let mut slice = mat.sub_slice_mut([1,1], 2, 2); |
| /// let row = unsafe { slice.row_unchecked_mut(1) }; |
| /// let mut expected = matrix![7usize, 8]; |
| /// assert_matrix_eq!(*row, expected); |
| /// # } |
| /// ``` |
| unsafe fn row_unchecked_mut(&mut self, index: usize) -> RowMut<T> { |
| let ptr = self.as_mut_ptr().offset((self.row_stride() * index) as isize); |
| RowMut { row: MatrixSliceMut::from_raw_parts(ptr, 1, self.cols(), self.row_stride()) } |
| } |
| |
| /// Swaps two rows in a matrix. |
| /// |
| /// If `a == b`, this method does nothing. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] extern crate rulinalg; |
| /// # fn main() { |
| /// use rulinalg::matrix::{Matrix, BaseMatrixMut}; |
| /// |
| /// let mut x = matrix![0, 1; |
| /// 2, 3; |
| /// 4, 5; |
| /// 6, 7]; |
| /// |
| /// x.swap_rows(1, 3); |
| /// let expected = matrix![0, 1; |
| /// 6, 7; |
| /// 4, 5; |
| /// 2, 3]; |
| /// |
| /// assert_matrix_eq!(x, expected); |
| /// # } |
| /// ``` |
| /// |
| /// # Panics |
| /// |
| /// Panics if `a` or `b` are out of bounds. |
| fn swap_rows(&mut self, a: usize, b: usize) { |
| assert!(a < self.rows(), |
| format!("Row index {0} larger than row count {1}", a, self.rows())); |
| assert!(b < self.rows(), |
| format!("Row index {0} larger than row count {1}", b, self.rows())); |
| |
| if a != b { |
| unsafe { |
| let row_a = slice::from_raw_parts_mut(self.as_mut_ptr() |
| .offset((self.row_stride() * a) as |
| isize), |
| self.cols()); |
| let row_b = slice::from_raw_parts_mut(self.as_mut_ptr() |
| .offset((self.row_stride() * b) as |
| isize), |
| self.cols()); |
| |
| for (x, y) in row_a.into_iter().zip(row_b.into_iter()) { |
| mem::swap(x, y); |
| } |
| } |
| } |
| |
| } |
| |
| /// Swaps two columns in a matrix. |
| /// |
| /// If `a == b`, this method does nothing. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] extern crate rulinalg; |
| /// # fn main() { |
| /// use rulinalg::matrix::{Matrix, BaseMatrixMut}; |
| /// |
| /// let mut x = matrix![0, 1; |
| /// 2, 3; |
| /// 4, 5]; |
| /// |
| /// x.swap_cols(0, 1); |
| /// let expected = matrix![1, 0; |
| /// 3, 2; |
| /// 5, 4]; |
| /// |
| /// assert_matrix_eq!(x, expected); |
| /// # } |
| /// ``` |
| /// |
| /// # Panics |
| /// |
| /// Panics if `a` or `b` are out of bounds. |
| fn swap_cols(&mut self, a: usize, b: usize) { |
| assert!(a < self.cols(), |
| format!("Row index {0} larger than row count {1}", a, self.rows())); |
| assert!(b < self.cols(), |
| format!("Row index {0} larger than row count {1}", b, self.rows())); |
| |
| if a != b { |
| unsafe { |
| for i in 0..self.rows() { |
| let a_ptr: *mut T = self.get_unchecked_mut([i, a]); |
| let b_ptr: *mut T = self.get_unchecked_mut([i, b]); |
| ptr::swap(a_ptr, b_ptr); |
| } |
| } |
| } |
| |
| } |
| |
| /// Iterate over the mutable columns of the matrix. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] extern crate rulinalg; fn main() { |
| /// use rulinalg::matrix::{Matrix, BaseMatrixMut}; |
| /// |
| /// let mut a = matrix![0, 1; |
| /// 2, 3; |
| /// 4, 5]; |
| /// |
| /// for mut col in a.col_iter_mut() { |
| /// *col += 1; |
| /// } |
| /// |
| /// // Now contains the range 1..7 |
| /// println!("{}", a); |
| /// # } |
| /// ``` |
| fn col_iter_mut(&mut self) -> ColsMut<T> { |
| ColsMut { |
| _marker: PhantomData::<&mut T>, |
| col_pos: 0, |
| row_stride: self.row_stride() as isize, |
| slice_cols: self.cols(), |
| slice_rows: self.rows(), |
| slice_start: self.as_mut_ptr(), |
| } |
| } |
| |
| /// Iterate over the mutable rows of the matrix. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] extern crate rulinalg; fn main() { |
| /// use rulinalg::matrix::{Matrix, BaseMatrixMut}; |
| /// |
| /// let mut a = matrix![0, 1; |
| /// 2, 3; |
| /// 4, 5]; |
| /// |
| /// for mut row in a.row_iter_mut() { |
| /// *row += 1; |
| /// } |
| /// |
| /// // Now contains the range 1..7 |
| /// println!("{}", a); |
| /// # } |
| /// ``` |
| fn row_iter_mut(&mut self) -> RowsMut<T> { |
| RowsMut { |
| slice_start: self.as_mut_ptr(), |
| row_pos: 0, |
| slice_rows: self.rows(), |
| slice_cols: self.cols(), |
| row_stride: self.row_stride() as isize, |
| _marker: PhantomData::<&mut T>, |
| } |
| } |
| |
| /// Iterate over diagonal entries mutably |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] extern crate rulinalg; |
| /// |
| /// # fn main() { |
| /// use rulinalg::matrix::{Matrix, BaseMatrixMut, DiagOffset}; |
| /// |
| /// let mut a = matrix![0, 1, 2; |
| /// 3, 4, 5; |
| /// 6, 7, 8]; |
| /// |
| /// // Increment super diag |
| /// for d in a.diag_iter_mut(DiagOffset::Above(1)) { |
| /// *d = *d + 1; |
| /// } |
| /// |
| /// // Zero the sub-diagonal (sets 3 and 7 to 0) |
| /// // Equivalent to `diag_iter(DiagOffset::Below(1))` |
| /// for sub_d in a.diag_iter_mut(DiagOffset::from(-1)) { |
| /// *sub_d = 0; |
| /// } |
| /// |
| /// println!("{}", a); |
| /// # } |
| /// ``` |
| /// |
| /// # Panics |
| /// |
| /// If using an `Above` or `Below` offset which is |
| /// out-of-bounds this function will panic. |
| /// |
| /// This function will never panic if the `Main` diagonal |
| /// offset is used. |
| fn diag_iter_mut(&mut self, k: DiagOffset) -> DiagonalMut<T, Self> { |
| let (diag_len, diag_start) = match k.into() { |
| DiagOffset::Main => (min(self.rows(), self.cols()), 0), |
| DiagOffset::Above(m) => { |
| assert!(m < self.cols(), |
| "Offset diagonal is not within matrix dimensions."); |
| (min(self.rows(), self.cols() - m), m) |
| } |
| DiagOffset::Below(m) => { |
| assert!(m < self.rows(), |
| "Offset diagonal is not within matrix dimensions."); |
| (min(self.rows() - m, self.cols()), m * self.row_stride()) |
| } |
| }; |
| |
| |
| let diag_end = diag_start + (diag_len - 1) * self.row_stride() + diag_len; |
| DiagonalMut { |
| matrix: self, |
| diag_pos: diag_start, |
| diag_end: diag_end, |
| _marker: PhantomData::<&mut T>, |
| } |
| } |
| |
| /// Sets the underlying matrix data to the target data. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// use rulinalg::matrix::{Matrix, BaseMatrixMut}; |
| /// |
| /// let mut mat = Matrix::<f32>::zeros(4,4); |
| /// let one_block = Matrix::<f32>::ones(2,2); |
| /// |
| /// // Get a mutable slice of the upper left 2x2 block. |
| /// let mat_block = mat.sub_slice_mut([0,0], 2, 2); |
| /// |
| /// // Set the upper left 2x2 block to be ones. |
| /// mat_block.set_to(one_block); |
| /// ``` |
| /// |
| /// # Panics |
| /// |
| /// Panics if the dimensions of `self` and `target` are not the same. |
| fn set_to<M: BaseMatrix<T>>(mut self, target: M) |
| where T: Copy |
| { |
| assert!(self.rows() == target.rows(), |
| "Target has different row count to self."); |
| assert!(self.cols() == target.cols(), |
| "Target has different column count to self."); |
| for (mut s, t) in self.row_iter_mut().zip(target.row_iter()) { |
| // Vectorized assignment per row. |
| utils::in_place_vec_bin_op(s.raw_slice_mut(), t.raw_slice(), |x, &y| *x = y); |
| } |
| } |
| |
| /// Applies a function to each element in the matrix. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # #[macro_use] extern crate rulinalg; fn main() { |
| /// use rulinalg::matrix::{Matrix, BaseMatrixMut}; |
| /// |
| /// fn add_two(a: f64) -> f64 { |
| /// a + 2f64 |
| /// } |
| /// |
| /// let a = Matrix::new(2, 2, vec![0.;4]); |
| /// |
| /// let b = a.apply(&add_two); |
| /// |
| /// assert_eq!(b, matrix![2.0, 2.0; 2.0, 2.0]); |
| /// # } |
| /// ``` |
| fn apply(mut self, f: &Fn(T) -> T) -> Self |
| where T: Copy |
| { |
| for val in self.iter_mut() { |
| *val = f(*val); |
| } |
| self |
| } |
| |
| /// Split the matrix at the specified axis returning two `MatrixSliceMut`s. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// use rulinalg::matrix::{Axes, Matrix, BaseMatrixMut}; |
| /// |
| /// let mut a = Matrix::new(3,3, vec![2.0; 9]); |
| /// let (b, c) = a.split_at_mut(1, Axes::Col); |
| /// ``` |
| fn split_at_mut(&mut self, mid: usize, axis: Axes) -> (MatrixSliceMut<T>, MatrixSliceMut<T>) { |
| |
| let slice_1: MatrixSliceMut<T>; |
| let slice_2: MatrixSliceMut<T>; |
| |
| match axis { |
| Axes::Row => { |
| assert!(mid < self.rows()); |
| unsafe { |
| slice_1 = MatrixSliceMut::from_raw_parts(self.as_mut_ptr(), |
| mid, |
| self.cols(), |
| self.row_stride()); |
| slice_2 = MatrixSliceMut::from_raw_parts(self.as_mut_ptr() |
| .offset((mid * |
| self.row_stride()) as |
| isize), |
| self.rows() - mid, |
| self.cols(), |
| self.row_stride()); |
| } |
| } |
| Axes::Col => { |
| assert!(mid < self.cols()); |
| unsafe { |
| slice_1 = MatrixSliceMut::from_raw_parts(self.as_mut_ptr(), |
| self.rows(), |
| mid, |
| self.row_stride()); |
| slice_2 = MatrixSliceMut::from_raw_parts(self.as_mut_ptr() |
| .offset(mid as isize), |
| self.rows(), |
| self.cols() - mid, |
| self.row_stride()); |
| } |
| } |
| } |
| |
| (slice_1, slice_2) |
| } |
| |
| /// Produce a `MatrixSliceMut` from an existing matrix. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// use rulinalg::matrix::{Matrix, MatrixSliceMut, BaseMatrixMut}; |
| /// |
| /// let mut a = Matrix::new(3,3, (0..9).collect::<Vec<usize>>()); |
| /// let mut slice = MatrixSliceMut::from_matrix(&mut a, [1,1], 2, 2); |
| /// let new_slice = slice.sub_slice_mut([0,0], 1, 1); |
| /// ``` |
| fn sub_slice_mut<'a>(&mut self, |
| start: [usize; 2], |
| rows: usize, |
| cols: usize) |
| -> MatrixSliceMut<'a, T> |
| where T: 'a |
| { |
| assert!(start[0] + rows <= self.rows(), |
| "View dimensions exceed matrix dimensions."); |
| assert!(start[1] + cols <= self.cols(), |
| "View dimensions exceed matrix dimensions."); |
| |
| unsafe { |
| MatrixSliceMut::from_raw_parts(self.as_mut_ptr() |
| .offset((start[0] * self.row_stride() + start[1]) as |
| isize), |
| rows, |
| cols, |
| self.row_stride()) |
| } |
| } |
| } |