From dcd87287bf1eb91a1c1656c645c8608ddd0cf607 Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Thu, 19 Nov 2020 09:27:34 -0800 Subject: [PATCH 1/9] Add DoubleEndedIterator test --- tests/core/matrix.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/core/matrix.rs b/tests/core/matrix.rs index ed7b26d2..6b248593 100644 --- a/tests/core/matrix.rs +++ b/tests/core/matrix.rs @@ -21,6 +21,15 @@ fn iter() { assert_eq!(*it.next().unwrap(), 6.0); assert!(it.next().is_none()); + let mut it = a.iter(); + assert_eq!(*it.next().unwrap(), 1.0); + assert_eq!(*it.next_back().unwrap(), 6.0); + assert_eq!(*it.next_back().unwrap(), 3.0); + assert_eq!(*it.next_back().unwrap(), 5.0); + assert_eq!(*it.next().unwrap(), 4.0); + assert_eq!(*it.next().unwrap(), 2.0); + assert!(it.next().is_none()); + let row = a.row(0); let mut it = row.iter(); assert_eq!(*it.next().unwrap(), 1.0); From 73d6ba0ca1195d883c03092fd0446e2c5533b5b1 Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Thu, 19 Nov 2020 09:35:43 -0800 Subject: [PATCH 2/9] Dummy implementation of DoubleEndedIterator --- src/base/iter.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/base/iter.rs b/src/base/iter.rs index 1f330d95..8a2a09ef 100644 --- a/src/base/iter.rs +++ b/src/base/iter.rs @@ -119,6 +119,15 @@ macro_rules! iterator { self.size } } + + impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + $Storage> DoubleEndedIterator + for $Name<'a, N, R, C, S> + { + #[inline] + fn next_back(&mut self) -> Option<$Ref> { + todo!() + } + } }; } From dd31f09105010739b5fb2dfa4a97f18329890eeb Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Thu, 19 Nov 2020 11:27:48 -0800 Subject: [PATCH 3/9] Test reverse --- tests/core/matrix.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/core/matrix.rs b/tests/core/matrix.rs index 6b248593..80ab3554 100644 --- a/tests/core/matrix.rs +++ b/tests/core/matrix.rs @@ -11,6 +11,7 @@ use na::{ #[test] fn iter() { let a = Matrix2x3::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0); + dbg!(a); let mut it = a.iter(); assert_eq!(*it.next().unwrap(), 1.0); @@ -30,6 +31,15 @@ fn iter() { assert_eq!(*it.next().unwrap(), 2.0); assert!(it.next().is_none()); + let mut it = a.iter().rev(); + assert_eq!(*it.next().unwrap(), 6.0); + assert_eq!(*it.next().unwrap(), 3.0); + assert_eq!(*it.next().unwrap(), 5.0); + assert_eq!(*it.next().unwrap(), 2.0); + assert_eq!(*it.next().unwrap(), 4.0); + assert_eq!(*it.next().unwrap(), 1.0); + assert!(it.next().is_none()); + let row = a.row(0); let mut it = row.iter(); assert_eq!(*it.next().unwrap(), 1.0); From d49af8e8b287a85fc3321e592866ec09825cc14e Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Thu, 19 Nov 2020 11:27:59 -0800 Subject: [PATCH 4/9] Implement next_back --- src/base/iter.rs | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/base/iter.rs b/src/base/iter.rs index 8a2a09ef..501ca459 100644 --- a/src/base/iter.rs +++ b/src/base/iter.rs @@ -125,7 +125,35 @@ macro_rules! iterator { { #[inline] fn next_back(&mut self) -> Option<$Ref> { - todo!() + unsafe { + if self.size == 0 { + None + } else { + // Pre-decrement `size` such that it now counts to the + // element we want to return. + self.size -= 1; + + // Fetch strides + let inner_stride = self.strides.0.value(); + let outer_stride = self.strides.1.value(); + debug_assert_eq!(outer_stride % inner_stride, 0); + let num_rows = outer_stride / inner_stride; + + // Compute rows and cols remaining + let outer_remaining = self.size / num_rows; + let inner_remaining = self.size % num_rows; + + // Compute pointer to last element + let last = self.ptr.offset( + (outer_remaining * outer_stride + inner_remaining * inner_stride) + as isize, + ); + + // We want either `& *last` or `&mut *last` here, depending + // on the mutability of `$Ref`. + Some(mem::transmute(last)) + } + } } } }; From 59f4e8a7d4495746b8f19c4d570df32c1885986a Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Thu, 19 Nov 2020 11:34:10 -0800 Subject: [PATCH 5/9] Remove dbg statement --- tests/core/matrix.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/core/matrix.rs b/tests/core/matrix.rs index 80ab3554..14eaeacd 100644 --- a/tests/core/matrix.rs +++ b/tests/core/matrix.rs @@ -11,7 +11,6 @@ use na::{ #[test] fn iter() { let a = Matrix2x3::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0); - dbg!(a); let mut it = a.iter(); assert_eq!(*it.next().unwrap(), 1.0); From 2bce1c31a6de18831d74d48bb90fc7f0acbf480e Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Thu, 19 Nov 2020 12:07:28 -0800 Subject: [PATCH 6/9] Bench iter() and iter().rev() --- benches/core/matrix.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/benches/core/matrix.rs b/benches/core/matrix.rs index 7b4f85bd..7f4432e3 100644 --- a/benches/core/matrix.rs +++ b/benches/core/matrix.rs @@ -136,6 +136,30 @@ fn mat500_mul_mat500(bench: &mut criterion::Criterion) { bench.bench_function("mat500_mul_mat500", move |bh| bh.iter(|| &a * &b)); } +fn iter(bench: &mut criterion::Criterion) { + let a = DMatrix::::new_random(1000, 1000); + + bench.bench_function("iter", move |bh| { + bh.iter(|| { + for value in a.iter() { + criterion::black_box(value); + } + }) + }); +} + +fn iter_rev(bench: &mut criterion::Criterion) { + let a = DMatrix::::new_random(1000, 1000); + + bench.bench_function("iter_rev", move |bh| { + bh.iter(|| { + for value in a.iter().rev() { + criterion::black_box(value); + } + }) + }); +} + fn copy_from(bench: &mut criterion::Criterion) { let a = DMatrix::::new_random(1000, 1000); let mut b = DMatrix::::new_random(1000, 1000); @@ -235,6 +259,8 @@ criterion_group!( mat10_mul_mat10_static, mat100_mul_mat100, mat500_mul_mat500, + iter, + iter_rev, copy_from, axpy, tr_mul_to, From eb3d787ed637e792e4aaae6d38bed01ad86158f6 Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Thu, 19 Nov 2020 12:43:29 -0800 Subject: [PATCH 7/9] Fix inner_size computation --- src/base/iter.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/base/iter.rs b/src/base/iter.rs index 501ca459..bd6e8fc2 100644 --- a/src/base/iter.rs +++ b/src/base/iter.rs @@ -133,15 +133,16 @@ macro_rules! iterator { // element we want to return. self.size -= 1; + // Compute number of rows + let inner_size = self.inner_end.offset_from(self.inner_ptr) as usize; + + // Compute rows and cols remaining + let outer_remaining = self.size / inner_size; + let inner_remaining = self.size % inner_size; + // Fetch strides let inner_stride = self.strides.0.value(); let outer_stride = self.strides.1.value(); - debug_assert_eq!(outer_stride % inner_stride, 0); - let num_rows = outer_stride / inner_stride; - - // Compute rows and cols remaining - let outer_remaining = self.size / num_rows; - let inner_remaining = self.size % num_rows; // Compute pointer to last element let last = self.ptr.offset( From d5ca2019a3f1b88d1ec7039fe4a8c21aa0456715 Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Thu, 19 Nov 2020 13:00:28 -0800 Subject: [PATCH 8/9] impl FusedIterator --- src/base/iter.rs | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/base/iter.rs b/src/base/iter.rs index bd6e8fc2..75de156e 100644 --- a/src/base/iter.rs +++ b/src/base/iter.rs @@ -1,5 +1,6 @@ //! Matrix iterators. +use std::iter::FusedIterator; use std::marker::PhantomData; use std::mem; @@ -111,15 +112,6 @@ macro_rules! iterator { } } - impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + $Storage> ExactSizeIterator - for $Name<'a, N, R, C, S> - { - #[inline] - fn len(&self) -> usize { - self.size - } - } - impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + $Storage> DoubleEndedIterator for $Name<'a, N, R, C, S> { @@ -157,6 +149,20 @@ macro_rules! iterator { } } } + + impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + $Storage> ExactSizeIterator + for $Name<'a, N, R, C, S> + { + #[inline] + fn len(&self) -> usize { + self.size + } + } + + impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + $Storage> FusedIterator + for $Name<'a, N, R, C, S> + { + } }; } From b25c2aa78cb9f8ba3a7b5ce0f8faed06e344851c Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Thu, 19 Nov 2020 16:30:59 -0800 Subject: [PATCH 9/9] Fix inner size --- src/base/iter.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/base/iter.rs b/src/base/iter.rs index 75de156e..f744cf02 100644 --- a/src/base/iter.rs +++ b/src/base/iter.rs @@ -125,17 +125,19 @@ macro_rules! iterator { // element we want to return. self.size -= 1; + // Fetch strides + let inner_stride = self.strides.0.value(); + let outer_stride = self.strides.1.value(); + // Compute number of rows - let inner_size = self.inner_end.offset_from(self.inner_ptr) as usize; + // Division should be exact + let inner_raw_size = self.inner_end.offset_from(self.inner_ptr) as usize; + let inner_size = inner_raw_size / inner_stride; // Compute rows and cols remaining let outer_remaining = self.size / inner_size; let inner_remaining = self.size % inner_size; - // Fetch strides - let inner_stride = self.strides.0.value(); - let outer_stride = self.strides.1.value(); - // Compute pointer to last element let last = self.ptr.offset( (outer_remaining * outer_stride + inner_remaining * inner_stride)