diskann_utils/views/rowmajor/
iter.rs1use std::{marker::PhantomData, num::NonZeroUsize, ptr::NonNull};
7
8#[cfg(feature = "rayon")]
9use crate::views::rowmajor::MatrixMut;
10use crate::views::rowmajor::{Layout, Matrix, Mut, Ref};
11
12#[derive(Debug)]
18pub struct Rows<'a, T> {
19 ptr: NonNull<T>,
20 remaining: usize,
21 ncols: usize,
22 _lifetime: PhantomData<&'a [T]>,
23}
24
25impl<'a, T> Rows<'a, T> {
26 pub(super) fn new(m: Ref<'a, T>) -> Self {
27 let layout = m.layout();
28 Self {
29 ptr: m.as_nonnull(),
30 remaining: layout.nrows(),
31 ncols: layout.ncols(),
32 _lifetime: PhantomData,
33 }
34 }
35}
36
37unsafe impl<T> Send for Rows<'_, T> where T: Sync {}
39unsafe impl<T> Sync for Rows<'_, T> where T: Sync {}
41
42impl<'a, T> Iterator for Rows<'a, T> {
43 type Item = &'a [T];
44 fn next(&mut self) -> Option<&'a [T]> {
45 self.remaining.checked_sub(1).map(|remaining| {
46 let item =
49 unsafe { std::slice::from_raw_parts(self.ptr.as_ptr().cast_const(), self.ncols) };
50 self.remaining = remaining;
51
52 self.ptr = unsafe { self.ptr.add(self.ncols) };
55 item
56 })
57 }
58
59 fn size_hint(&self) -> (usize, Option<usize>) {
60 (self.remaining, Some(self.remaining))
61 }
62}
63
64impl<T> ExactSizeIterator for Rows<'_, T> {}
65impl<T> std::iter::FusedIterator for Rows<'_, T> {}
66
67#[derive(Debug)]
73pub struct RowsMut<'a, T> {
74 ptr: NonNull<T>,
75 remaining: usize,
76 ncols: usize,
77 _lifetime: PhantomData<&'a mut [T]>,
78}
79
80impl<'a, T> RowsMut<'a, T> {
81 pub(super) fn new(m: Mut<'a, T>) -> Self {
82 let layout = m.layout();
83 Self {
84 ptr: m.as_nonnull(),
85 remaining: layout.nrows(),
86 ncols: layout.ncols(),
87 _lifetime: PhantomData,
88 }
89 }
90}
91
92unsafe impl<T> Send for RowsMut<'_, T> where T: Send {}
94unsafe impl<T> Sync for RowsMut<'_, T> where T: Sync {}
96
97impl<'a, T> Iterator for RowsMut<'a, T> {
98 type Item = &'a mut [T];
99 fn next(&mut self) -> Option<&'a mut [T]> {
100 self.remaining.checked_sub(1).map(|remaining| {
101 let item = unsafe { std::slice::from_raw_parts_mut(self.ptr.as_ptr(), self.ncols) };
106 self.remaining = remaining;
107
108 self.ptr = unsafe { self.ptr.add(self.ncols) };
111 item
112 })
113 }
114
115 fn size_hint(&self) -> (usize, Option<usize>) {
116 (self.remaining, Some(self.remaining))
117 }
118}
119
120impl<T> ExactSizeIterator for RowsMut<'_, T> {}
121impl<T> std::iter::FusedIterator for RowsMut<'_, T> {}
122
123#[derive(Debug)]
129pub struct Windows<'a, T> {
130 ptr: NonNull<T>,
131 remaining: usize,
132 batchsize: NonZeroUsize,
133 ncols: usize,
134 _lifetime: PhantomData<&'a [T]>,
135}
136
137impl<'a, T> Windows<'a, T> {
138 pub(super) fn new(m: Ref<'a, T>, batchsize: NonZeroUsize) -> Self {
139 let layout = m.layout();
140 Self {
141 ptr: m.as_nonnull(),
142 remaining: layout.nrows(),
143 batchsize,
144 ncols: layout.ncols(),
145 _lifetime: PhantomData,
146 }
147 }
148}
149
150unsafe impl<T> Send for Windows<'_, T> where T: Sync {}
152unsafe impl<T> Sync for Windows<'_, T> where T: Sync {}
154
155impl<'a, T> Iterator for Windows<'a, T> {
156 type Item = Ref<'a, T>;
157 fn next(&mut self) -> Option<Ref<'a, T>> {
158 if self.remaining == 0 {
159 None
160 } else {
161 let next_remaining = self.remaining.saturating_sub(self.batchsize.get());
162 let nrows = self.remaining - next_remaining;
163
164 let window = unsafe {
168 Ref {
169 ptr: self.ptr,
170 layout: Layout::new_unchecked(nrows, self.ncols),
171 _lifetime: PhantomData,
172 }
173 };
174
175 self.ptr = unsafe { self.ptr.add(nrows * self.ncols) };
179 self.remaining = next_remaining;
180 Some(window)
181 }
182 }
183
184 fn size_hint(&self) -> (usize, Option<usize>) {
185 let remaining = self.remaining.div_ceil(self.batchsize.get());
186 (remaining, Some(remaining))
187 }
188}
189
190impl<T> ExactSizeIterator for Windows<'_, T> {}
191impl<T> std::iter::FusedIterator for Windows<'_, T> {}
192
193#[cfg(feature = "rayon")]
198pub(super) struct ParMut<'a, T> {
200 ptr: NonNull<T>,
201 layout: Layout<T>,
202 _lifetime: PhantomData<&'a mut [T]>,
203}
204
205#[cfg(feature = "rayon")]
207unsafe impl<T: Send> Send for ParMut<'_, T> {}
208#[cfg(feature = "rayon")]
211unsafe impl<T: Send> Sync for ParMut<'_, T> {}
212
213#[cfg(feature = "rayon")]
214impl<'a, T> ParMut<'a, T> {
215 pub(super) fn new<M>(matrix: &'a mut M) -> Self
216 where
217 M: MatrixMut<Element = T> + ?Sized,
218 {
219 let layout = matrix.layout();
220 let ptr = matrix.as_nonnull_mut();
221 Self {
222 ptr,
223 layout,
224 _lifetime: PhantomData,
225 }
226 }
227
228 pub(super) fn nrows(&self) -> usize {
229 self.layout.nrows()
230 }
231
232 pub(super) unsafe fn row_disjoint_unchecked(&self, row: usize) -> &'a mut [T] {
238 debug_assert!(row < self.layout.nrows());
239 let ncols = self.layout.ncols();
240
241 unsafe { std::slice::from_raw_parts_mut(self.ptr.as_ptr().add(row * ncols), ncols) }
245 }
246
247 pub(super) unsafe fn window_disjoint_unchecked(
253 &self,
254 rows: std::ops::Range<usize>,
255 ) -> Mut<'a, T> {
256 debug_assert!(rows.start <= rows.end);
257 debug_assert!(rows.end <= self.layout.nrows());
258
259 let ncols = self.layout.ncols();
260 let nrows = rows.end - rows.start;
261
262 let ptr = unsafe { self.ptr.add(rows.start * ncols) };
265
266 Mut {
267 ptr,
268 layout: unsafe { Layout::new_unchecked(nrows, ncols) },
271 _lifetime: PhantomData,
272 }
273 }
274}
275
276#[cfg(all(test, feature = "rayon"))]
277mod tests {
278 use super::ParMut;
279 use crate::views::rowmajor::{Matrix, MatrixMut, Owned};
280
281 #[test]
282 fn par_mut_zero_column_views_can_coexist() {
283 let mut matrix = Owned::from_element(usize::MAX, 0, 0);
284 let ptr = matrix.as_ptr();
285 let matrix = ParMut::new(&mut matrix);
286
287 let rows = unsafe {
289 [
290 matrix.row_disjoint_unchecked(0),
291 matrix.row_disjoint_unchecked(1),
292 matrix.row_disjoint_unchecked(usize::MAX - 1),
293 ]
294 };
295 let windows = unsafe {
298 [
299 matrix.window_disjoint_unchecked(0..2),
300 matrix.window_disjoint_unchecked(2..usize::MAX),
301 ]
302 };
303
304 assert!(rows.iter().all(|row| row.is_empty() && row.as_ptr() == ptr));
305 assert!(windows.iter().all(|window| {
306 window.ncols() == 0 && window.as_slice().is_empty() && window.as_ptr() == ptr
307 }));
308 }
309
310 #[test]
311 fn par_mut_disjoint_nonempty_views_can_coexist() {
312 let mut matrix = Owned::from_fn(6, 2, |rc| rc.row * 100 + rc.col);
313 {
314 let matrix = ParMut::new(&mut matrix);
315
316 let (row0, row1, mut window2, mut window4) = unsafe {
318 (
319 matrix.row_disjoint_unchecked(0),
320 matrix.row_disjoint_unchecked(1),
321 matrix.window_disjoint_unchecked(2..4),
322 matrix.window_disjoint_unchecked(4..6),
323 )
324 };
325 row0[0] = 10;
326 row1[1] = 11;
327
328 let mut window2_rows: Vec<_> = window2.rows_mut().collect();
329 let mut window4_rows: Vec<_> = window4.rows_mut().collect();
330 window2_rows[0][0] = 20;
331 window2_rows[1][1] = 31;
332 window4_rows[0][0] = 40;
333 window4_rows[1][1] = 51;
334 }
335
336 assert_eq!(
337 matrix.as_slice(),
338 &[10, 1, 100, 11, 20, 201, 300, 31, 40, 401, 500, 51]
339 );
340 }
341}