Skip to content

Commit

Permalink
Add column iterator (#137)
Browse files Browse the repository at this point in the history
* Sync and backported changes

* Fix errors

* Some fixes

* Iterator returns Column and ColumnMut

* Remove impl_col_row

* Fix tests

* Using matrix! macro for row_iter* and col_iter* doc tests

* Add slice tests

* Add row_stride

* Update mod.rs

Indentation

* Minor fix

* Better doc test for row or col iterator

* Fix typo

* Fix count and size_hint + Non-square matrix for column slice tests

* Fixing failed conflict resolution

* Fix alignment + Variable does not need to be mutable

* Alignment
  • Loading branch information
c410-f3r authored and AtheMathmo committed Feb 14, 2017
1 parent 364e633 commit f447a66
Show file tree
Hide file tree
Showing 3 changed files with 415 additions and 67 deletions.
166 changes: 128 additions & 38 deletions src/matrix/base/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
//! ```
use matrix::{Matrix, MatrixSlice, MatrixSliceMut};
use matrix::{Row, RowMut, Column, ColumnMut, Rows, RowsMut, Axes};
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};
Expand Down Expand Up @@ -211,19 +211,54 @@ pub trait BaseMatrix<T>: Sized {
}
}

/// 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 a = Matrix::new(3, 2, (0..6).collect::<Vec<usize>>());
/// let mut iter = a.row_iter();
///
/// // Prints "2" three times.
/// for row in a.row_iter() {
/// println!("{}", row.cols());
/// }
/// 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 {
Expand Down Expand Up @@ -393,7 +428,8 @@ pub trait BaseMatrix<T>: Sized {
/// # }
/// ```
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>
where B: 'b + BaseMatrix<T>,
M: MatrixMetric<'a, 'b, T, Self, B>
{
metric.metric(self, mat)
}
Expand Down Expand Up @@ -439,24 +475,26 @@ pub trait BaseMatrix<T>: Sized {
/// assert_eq!(rmin, vector![1.0, 2.0]);
/// # }
/// ```
fn min(&self, axis: Axes) -> Vector<T> where T: Copy + PartialOrd
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 } );
.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; });
utils::in_place_vec_bin_op(&mut mins, row.raw_slice(), |min, &r| if r < *min {
*min = r;
});
}
Vector::new(mins)
}
Expand All @@ -481,24 +519,26 @@ pub trait BaseMatrix<T>: Sized {
/// assert_eq!(rmax, vector![3.0, 4.0]);
/// # }
/// ```
fn max(&self, axis: Axes) -> Vector<T> where T: Copy + PartialOrd
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 } );
.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; });
utils::in_place_vec_bin_op(&mut maxs, row.raw_slice(), |max, &r| if r > *max {
*max = r;
});
}
Vector::new(maxs)
}
Expand Down Expand Up @@ -1019,9 +1059,12 @@ pub trait BaseMatrix<T>: Sized {
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());
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 => {
Expand Down Expand Up @@ -1062,8 +1105,12 @@ pub trait BaseMatrix<T>: Sized {
"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())
MatrixSlice::from_raw_parts(self.as_ptr()
.offset((start[0] * self.row_stride() + start[1]) as
isize),
rows,
cols,
self.row_stride())
}
}
}
Expand Down Expand Up @@ -1292,14 +1339,14 @@ pub trait BaseMatrixMut<T>: BaseMatrix<T> {

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());
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);
Expand Down Expand Up @@ -1354,21 +1401,56 @@ pub trait BaseMatrixMut<T>: BaseMatrix<T> {

}

/// 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::new(3, 2, (0..6).collect::<Vec<usize>>());
/// 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 {
Expand Down Expand Up @@ -1526,9 +1608,13 @@ pub trait BaseMatrixMut<T>: BaseMatrix<T> {
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());
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 => {
Expand Down Expand Up @@ -1574,8 +1660,12 @@ pub trait BaseMatrixMut<T>: BaseMatrix<T> {
"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())
MatrixSliceMut::from_raw_parts(self.as_mut_ptr()
.offset((start[0] * self.row_stride() + start[1]) as
isize),
rows,
cols,
self.row_stride())
}
}
}
Loading

0 comments on commit f447a66

Please sign in to comment.