Skip to content

Commit a0466a7

Browse files
committed
Allow creating matrix iter with an owned view
1 parent c6ff3ee commit a0466a7

File tree

2 files changed

+145
-31
lines changed

2 files changed

+145
-31
lines changed

src/base/conversion.rs

+24
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,18 @@ impl<'a, T: Scalar, R: Dim, C: Dim, S: RawStorage<T, R, C>> IntoIterator
9898
}
9999
}
100100

101+
impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim> IntoIterator
102+
for Matrix<T, R, C, ViewStorage<'a, T, R, C, RStride, CStride>>
103+
{
104+
type Item = &'a T;
105+
type IntoIter = MatrixIter<'a, T, R, C, ViewStorage<'a, T, R, C, RStride, CStride>>;
106+
107+
#[inline]
108+
fn into_iter(self) -> Self::IntoIter {
109+
MatrixIter::new_owned(self.data)
110+
}
111+
}
112+
101113
impl<'a, T: Scalar, R: Dim, C: Dim, S: RawStorageMut<T, R, C>> IntoIterator
102114
for &'a mut Matrix<T, R, C, S>
103115
{
@@ -110,6 +122,18 @@ impl<'a, T: Scalar, R: Dim, C: Dim, S: RawStorageMut<T, R, C>> IntoIterator
110122
}
111123
}
112124

125+
impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim> IntoIterator
126+
for Matrix<T, R, C, ViewStorageMut<'a, T, R, C, RStride, CStride>>
127+
{
128+
type Item = &'a mut T;
129+
type IntoIter = MatrixIterMut<'a, T, R, C, ViewStorageMut<'a, T, R, C, RStride, CStride>>;
130+
131+
#[inline]
132+
fn into_iter(self) -> Self::IntoIter {
133+
MatrixIterMut::new_owned_mut(self.data)
134+
}
135+
}
136+
113137
impl<T: Scalar, const D: usize> From<[T; D]> for SVector<T, D> {
114138
#[inline]
115139
fn from(arr: [T; D]) -> Self {

src/base/iter.rs

+121-31
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,29 @@ use std::mem;
1212

1313
use crate::base::dimension::{Dim, U1};
1414
use crate::base::storage::{RawStorage, RawStorageMut};
15-
use crate::base::{Matrix, MatrixView, MatrixViewMut, Scalar};
15+
use crate::base::{Matrix, MatrixView, MatrixViewMut, Scalar, ViewStorage, ViewStorageMut};
16+
17+
#[derive(Clone, Debug)]
18+
struct RawIter<Ptr, T, R: Dim, C: Dim, RStride: Dim, CStride: Dim> {
19+
ptr: Ptr,
20+
inner_ptr: Ptr,
21+
inner_end: Ptr,
22+
size: usize,
23+
strides: (RStride, CStride),
24+
_phantoms: PhantomData<(fn() -> T, R, C)>,
25+
}
1626

1727
macro_rules! iterator {
1828
(struct $Name:ident for $Storage:ident.$ptr: ident -> $Ptr:ty, $Ref:ty, $SRef: ty, $($derives:ident),* $(,)?) => {
19-
/// An iterator through a dense matrix with arbitrary strides matrix.
20-
#[derive($($derives),*)]
21-
pub struct $Name<'a, T, R: Dim, C: Dim, S: 'a + $Storage<T, R, C>> {
22-
ptr: $Ptr,
23-
inner_ptr: $Ptr,
24-
inner_end: $Ptr,
25-
size: usize, // We can't use an end pointer here because a stride might be zero.
26-
strides: (S::RStride, S::CStride),
27-
_phantoms: PhantomData<($Ref, R, C, S)>,
28-
}
29-
3029
// TODO: we need to specialize for the case where the matrix storage is owned (in which
3130
// case the iterator is trivial because it does not have any stride).
32-
impl<'a, T, R: Dim, C: Dim, S: 'a + $Storage<T, R, C>> $Name<'a, T, R, C, S> {
31+
impl<T, R: Dim, C: Dim, RStride: Dim, CStride: Dim>
32+
RawIter<$Ptr, T, R, C, RStride, CStride>
33+
{
3334
/// Creates a new iterator for the given matrix storage.
34-
pub fn new(storage: $SRef) -> $Name<'a, T, R, C, S> {
35+
fn new<'a, S: $Storage<T, R, C, RStride = RStride, CStride = CStride>>(
36+
storage: $SRef,
37+
) -> Self {
3538
let shape = storage.shape();
3639
let strides = storage.strides();
3740
let inner_offset = shape.0.value() * strides.0.value();
@@ -55,7 +58,7 @@ macro_rules! iterator {
5558
unsafe { ptr.add(inner_offset) }
5659
};
5760

58-
$Name {
61+
RawIter {
5962
ptr,
6063
inner_ptr: ptr,
6164
inner_end,
@@ -66,11 +69,13 @@ macro_rules! iterator {
6669
}
6770
}
6871

69-
impl<'a, T, R: Dim, C: Dim, S: 'a + $Storage<T, R, C>> Iterator for $Name<'a, T, R, C, S> {
70-
type Item = $Ref;
72+
impl<T, R: Dim, C: Dim, RStride: Dim, CStride: Dim> Iterator
73+
for RawIter<$Ptr, T, R, C, RStride, CStride>
74+
{
75+
type Item = $Ptr;
7176

7277
#[inline]
73-
fn next(&mut self) -> Option<$Ref> {
78+
fn next(&mut self) -> Option<Self::Item> {
7479
unsafe {
7580
if self.size == 0 {
7681
None
@@ -102,10 +107,7 @@ macro_rules! iterator {
102107
self.ptr = self.ptr.add(stride);
103108
}
104109

105-
// We want either `& *last` or `&mut *last` here, depending
106-
// on the mutability of `$Ref`.
107-
#[allow(clippy::transmute_ptr_to_ref)]
108-
Some(mem::transmute(old))
110+
Some(old)
109111
}
110112
}
111113
}
@@ -121,11 +123,11 @@ macro_rules! iterator {
121123
}
122124
}
123125

124-
impl<'a, T, R: Dim, C: Dim, S: 'a + $Storage<T, R, C>> DoubleEndedIterator
125-
for $Name<'a, T, R, C, S>
126+
impl<T, R: Dim, C: Dim, RStride: Dim, CStride: Dim> DoubleEndedIterator
127+
for RawIter<$Ptr, T, R, C, RStride, CStride>
126128
{
127129
#[inline]
128-
fn next_back(&mut self) -> Option<$Ref> {
130+
fn next_back(&mut self) -> Option<Self::Item> {
129131
unsafe {
130132
if self.size == 0 {
131133
None
@@ -152,24 +154,88 @@ macro_rules! iterator {
152154
.ptr
153155
.add((outer_remaining * outer_stride + inner_remaining * inner_stride));
154156

155-
// We want either `& *last` or `&mut *last` here, depending
156-
// on the mutability of `$Ref`.
157-
#[allow(clippy::transmute_ptr_to_ref)]
158-
Some(mem::transmute(last))
157+
Some(last)
159158
}
160159
}
161160
}
162161
}
163162

164-
impl<'a, T, R: Dim, C: Dim, S: 'a + $Storage<T, R, C>> ExactSizeIterator
165-
for $Name<'a, T, R, C, S>
163+
impl<T, R: Dim, C: Dim, RStride: Dim, CStride: Dim> ExactSizeIterator
164+
for RawIter<$Ptr, T, R, C, RStride, CStride>
166165
{
167166
#[inline]
168167
fn len(&self) -> usize {
169168
self.size
170169
}
171170
}
172171

172+
impl<T, R: Dim, C: Dim, RStride: Dim, CStride: Dim> FusedIterator
173+
for RawIter<$Ptr, T, R, C, RStride, CStride>
174+
{
175+
}
176+
177+
/// An iterator through a dense matrix with arbitrary strides matrix.
178+
#[derive($($derives),*)]
179+
pub struct $Name<'a, T, R: Dim, C: Dim, S: 'a + $Storage<T, R, C>> {
180+
inner: RawIter<$Ptr, T, R, C, S::RStride, S::CStride>,
181+
_marker: PhantomData<$Ref>,
182+
}
183+
184+
impl<'a, T, R: Dim, C: Dim, S: 'a + $Storage<T, R, C>> $Name<'a, T, R, C, S> {
185+
/// Creates a new iterator for the given matrix storage.
186+
pub fn new(storage: $SRef) -> Self {
187+
Self {
188+
inner: RawIter::<$Ptr, T, R, C, S::RStride, S::CStride>::new(storage),
189+
_marker: PhantomData,
190+
}
191+
}
192+
}
193+
194+
impl<'a, T, R: Dim, C: Dim, S: 'a + $Storage<T, R, C>> Iterator for $Name<'a, T, R, C, S> {
195+
type Item = $Ref;
196+
197+
#[inline(always)]
198+
fn next(&mut self) -> Option<Self::Item> {
199+
// We want either `& *last` or `&mut *last` here, depending
200+
// on the mutability of `$Ref`.
201+
#[allow(clippy::transmute_ptr_to_ref)]
202+
self.inner.next().map(|ptr| unsafe { mem::transmute(ptr) })
203+
}
204+
205+
#[inline(always)]
206+
fn size_hint(&self) -> (usize, Option<usize>) {
207+
self.inner.size_hint()
208+
}
209+
210+
#[inline(always)]
211+
fn count(self) -> usize {
212+
self.inner.count()
213+
}
214+
}
215+
216+
impl<'a, T, R: Dim, C: Dim, S: 'a + $Storage<T, R, C>> DoubleEndedIterator
217+
for $Name<'a, T, R, C, S>
218+
{
219+
#[inline(always)]
220+
fn next_back(&mut self) -> Option<Self::Item> {
221+
// We want either `& *last` or `&mut *last` here, depending
222+
// on the mutability of `$Ref`.
223+
#[allow(clippy::transmute_ptr_to_ref)]
224+
self.inner
225+
.next_back()
226+
.map(|ptr| unsafe { mem::transmute(ptr) })
227+
}
228+
}
229+
230+
impl<'a, T, R: Dim, C: Dim, S: 'a + $Storage<T, R, C>> ExactSizeIterator
231+
for $Name<'a, T, R, C, S>
232+
{
233+
#[inline(always)]
234+
fn len(&self) -> usize {
235+
self.inner.len()
236+
}
237+
}
238+
173239
impl<'a, T, R: Dim, C: Dim, S: 'a + $Storage<T, R, C>> FusedIterator
174240
for $Name<'a, T, R, C, S>
175241
{
@@ -180,6 +246,30 @@ macro_rules! iterator {
180246
iterator!(struct MatrixIter for RawStorage.ptr -> *const T, &'a T, &'a S, Clone, Debug);
181247
iterator!(struct MatrixIterMut for RawStorageMut.ptr_mut -> *mut T, &'a mut T, &'a mut S, Debug);
182248

249+
impl<'a, T, R: Dim, C: Dim, RStride: Dim, CStride: Dim>
250+
MatrixIter<'a, T, R, C, ViewStorage<'a, T, R, C, RStride, CStride>>
251+
{
252+
/// Creates a new iterator for the given matrix storage view.
253+
pub fn new_owned(storage: ViewStorage<'a, T, R, C, RStride, CStride>) -> Self {
254+
Self {
255+
inner: RawIter::<*const T, T, R, C, RStride, CStride>::new(&storage),
256+
_marker: PhantomData,
257+
}
258+
}
259+
}
260+
261+
impl<'a, T, R: Dim, C: Dim, RStride: Dim, CStride: Dim>
262+
MatrixIterMut<'a, T, R, C, ViewStorageMut<'a, T, R, C, RStride, CStride>>
263+
{
264+
/// Creates a new iterator for the given matrix storage view.
265+
pub fn new_owned_mut(mut storage: ViewStorageMut<'a, T, R, C, RStride, CStride>) -> Self {
266+
Self {
267+
inner: RawIter::<*mut T, T, R, C, RStride, CStride>::new(&mut storage),
268+
_marker: PhantomData,
269+
}
270+
}
271+
}
272+
183273
/*
184274
*
185275
* Row iterators.

0 commit comments

Comments
 (0)