orx_v/flat_jagged/into_jagged.rs
1use super::{uniform_end_indices::UniformEndIndices, FlatJagged};
2use crate::{NVec, D1};
3use alloc::vec::Vec;
4
5/// Transforms a `D1` vector into a jagged `D2` vector via `into_x` methods;
6/// or alternatively, creates a jagged `D2` vector view `as_x` methods.
7pub trait IntoJagged<T>: Sized + NVec<D1, T> {
8 /// Converts a `D1` vector into a jagged `D2` vector where each row is
9 /// identified by `row_end_indices`.
10 ///
11 /// Notice that `row_end_indices` is any `V1<usize>` which might be
12 /// a vector of indices or a functional vector, etc.
13 ///
14 /// # Panics
15 ///
16 /// Panics if:
17 /// * `row_end_indices` is **not** non-decreasing, or
18 /// * last element of `row_end_indices` is **not** equal to the length of this
19 /// flat vector.
20 ///
21 /// # Examples
22 ///
23 /// ```
24 /// use orx_v::*;
25 ///
26 /// let v1 = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
27 /// let end_indices = vec![1, 1, 4, 10]; // lengths => [1, 0, 3, 6]
28 /// let v2 = v1.into_jagged(end_indices);
29 /// assert_eq!(
30 /// v2.equality(&[vec![0], vec![], vec![1, 2, 3], vec![4, 5, 6, 7, 8, 9]]),
31 /// Equality::Equal
32 /// );
33 ///
34 /// let v1 = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
35 /// let end_indices = V.d1().fun(|[i]| (i + 1) * 5).bounded(2); // lengths => [5, 5]
36 /// let v2 = v1.into_jagged(end_indices);
37 /// assert_eq!(
38 /// v2.equality(&[vec![0, 1, 2, 3, 4], vec![5, 6, 7, 8, 9]]),
39 /// Equality::Equal
40 /// );
41 /// ```
42 fn into_jagged<I>(self, row_end_indices: I) -> FlatJagged<Self, I, T>
43 where
44 I: NVec<D1, usize>,
45 {
46 validate_row_end_indices(&self, &row_end_indices);
47 FlatJagged::new(self, row_end_indices)
48 }
49
50 /// From a flat `D1` vector, creates a jagged `D2` vector view where each row is
51 /// identified by `row_end_indices`.
52 ///
53 /// Notice that `row_end_indices` is any `V1<usize>` which might be
54 /// a vector of indices or a functional vector, etc.
55 ///
56 /// # Panics
57 ///
58 /// Panics if:
59 /// * `row_end_indices` is **not** non-decreasing, or
60 /// * last element of `row_end_indices` is **not** equal to the length of this
61 /// flat vector.
62 ///
63 /// # Examples
64 ///
65 /// ```
66 /// use orx_v::*;
67 ///
68 /// let v1 = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
69 ///
70 /// let end_indices = vec![1, 1, 4, 10]; // lengths => [1, 0, 3, 6]
71 /// let v2 = v1.as_jagged(&end_indices);
72 /// assert_eq!(
73 /// v2.equality(&[vec![0], vec![], vec![1, 2, 3], vec![4, 5, 6, 7, 8, 9]]),
74 /// Equality::Equal
75 /// );
76 ///
77 /// let end_indices = V.d1().fun(|[i]| (i + 1) * 5).bounded(2); // lengths => [5, 5]
78 /// let v2 = v1.as_jagged(&end_indices);
79 /// assert_eq!(
80 /// v2.equality(&[vec![0, 1, 2, 3, 4], vec![5, 6, 7, 8, 9]]),
81 /// Equality::Equal
82 /// );
83 /// ```
84 fn as_jagged<I>(&self, row_end_indices: I) -> FlatJagged<&Self, I, T>
85 where
86 I: NVec<D1, usize>,
87 {
88 validate_row_end_indices(self, &row_end_indices);
89 FlatJagged::new(self, row_end_indices)
90 }
91
92 /// From a flat `D1` vector, creates a mutable jagged `D2` vector view where each row is
93 /// identified by `row_end_indices`.
94 ///
95 /// Notice that `row_end_indices` is any `V1<usize>` which might be
96 /// a vector of indices or a functional vector, etc.
97 ///
98 /// # Panics
99 ///
100 /// Panics if:
101 /// * `row_end_indices` is **not** non-decreasing, or
102 /// * last element of `row_end_indices` is **not** equal to the length of this
103 /// flat vector.
104 ///
105 /// # Examples
106 ///
107 /// ```
108 /// use orx_v::*;
109 ///
110 /// let mut v1 = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
111 ///
112 /// let end_indices = vec![1, 1, 4, 10]; // lengths => [1, 0, 3, 6]
113 /// let mut v2 = v1.as_jagged_mut(&end_indices);
114 /// *v2.at_mut([2, 2]) += 10;
115 /// *v2.at_mut([3, 4]) *= 10;
116 /// assert_eq!(
117 /// v2.equality(&[vec![0], vec![], vec![1, 2, 13], vec![4, 5, 6, 7, 80, 9]]),
118 /// Equality::Equal
119 /// );
120 ///
121 /// let end_indices = V.d1().fun(|[i]| (i + 1) * 5).bounded(2); // lengths => [5, 5]
122 /// let mut v2 = v1.as_jagged_mut(&end_indices);
123 /// *v2.at_mut([0, 4]) += 100;
124 /// assert_eq!(
125 /// v2.equality(&[vec![0, 1, 2, 13, 104], vec![5, 6, 7, 80, 9]]),
126 /// Equality::Equal
127 /// );
128 /// ```
129 fn as_jagged_mut<I>(&mut self, row_end_indices: I) -> FlatJagged<&mut Self, I, T>
130 where
131 I: NVec<D1, usize>,
132 {
133 validate_row_end_indices(self, &row_end_indices);
134 FlatJagged::new(self, row_end_indices)
135 }
136
137 // from row lengths
138
139 /// Converts a `D1` vector into a jagged `D2` vector where each row is
140 /// identified by `row_lengths`.
141 ///
142 /// Notice that `row_lengths` is any `V1<usize>` which might be
143 /// a vector of indices or a functional vector, etc.
144 ///
145 /// Internally, this method will evaluate `row_end_indices`, store it in a
146 /// `Vec<usize>` and call `into_jagged` method.
147 ///
148 /// # Panics
149 ///
150 /// Panics if the sum of `row_lengths` do not add up to the length of this vector;
151 /// i.e., `self.card([])`.
152 ///
153 /// # Examples
154 ///
155 /// ```
156 /// use orx_v::*;
157 ///
158 /// let v1 = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
159 /// let row_lengths = vec![1, 0, 3, 6];
160 /// let v2 = v1.into_jagged_from_row_lengths(&row_lengths);
161 /// assert_eq!(
162 /// v2.equality(&[vec![0], vec![], vec![1, 2, 3], vec![4, 5, 6, 7, 8, 9]]),
163 /// Equality::Equal
164 /// );
165 ///
166 /// let v1 = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
167 /// let row_lengths = V.d1().constant(5).bounded(2); // lengths => [5, 5]
168 /// let v2 = v1.into_jagged_from_row_lengths(&row_lengths);
169 /// assert_eq!(
170 /// v2.equality(&[vec![0, 1, 2, 3, 4], vec![5, 6, 7, 8, 9]]),
171 /// Equality::Equal
172 /// );
173 /// ```
174 fn into_jagged_from_row_lengths<I>(self, row_lengths: &I) -> FlatJagged<Self, Vec<usize>, T>
175 where
176 I: NVec<D1, usize>,
177 {
178 validate_row_end_lengths(&self, row_lengths);
179 self.into_jagged(row_indices_from_row_lengths(row_lengths))
180 }
181
182 /// From a flat `D1` vector, creates a jagged `D2` vector view where each row is
183 /// identified by `row_lengths`.
184 ///
185 /// Notice that `row_lengths` is any `V1<usize>` which might be
186 /// a vector of indices or a functional vector, etc.
187 ///
188 /// Internally, this method will evaluate `row_end_indices`, store it in a
189 /// `Vec<usize>` and call `into_jagged` method.
190 ///
191 /// # Panics
192 ///
193 /// Panics if the sum of `row_lengths` do not add up to the length of this vector;
194 /// i.e., `self.card([])`.
195 ///
196 /// # Examples
197 ///
198 /// ```
199 /// use orx_v::*;
200 ///
201 /// let v1 = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
202 ///
203 /// let row_lengths = vec![1, 0, 3, 6]; // lengths => [1, 0, 3, 6]
204 /// let v2 = v1.as_jagged_from_row_lengths(&row_lengths);
205 /// assert_eq!(
206 /// v2.equality(&[vec![0], vec![], vec![1, 2, 3], vec![4, 5, 6, 7, 8, 9]]),
207 /// Equality::Equal
208 /// );
209 ///
210 /// let row_lengths = V.d1().constant(5).bounded(2); // lengths => [5, 5]
211 /// let v2 = v1.as_jagged_from_row_lengths(&row_lengths);
212 /// assert_eq!(
213 /// v2.equality(&[vec![0, 1, 2, 3, 4], vec![5, 6, 7, 8, 9]]),
214 /// Equality::Equal
215 /// );
216 /// ```
217 fn as_jagged_from_row_lengths<I>(&self, row_lengths: &I) -> FlatJagged<&Self, Vec<usize>, T>
218 where
219 I: NVec<D1, usize>,
220 {
221 validate_row_end_lengths(self, row_lengths);
222 self.as_jagged(row_indices_from_row_lengths(row_lengths))
223 }
224
225 /// From a flat `D1` vector, creates a mutable jagged `D2` vector view where each row is
226 /// identified by `row_lengths`.
227 ///
228 /// Notice that `row_lengths` is any `V1<usize>` which might be
229 /// a vector of indices or a functional vector, etc.
230 ///
231 /// Internally, this method will evaluate `row_end_indices`, store it in a
232 /// `Vec<usize>` and call `into_jagged` method.
233 ///
234 /// # Panics
235 ///
236 /// Panics if the sum of `row_lengths` do not add up to the length of this vector;
237 /// i.e., `self.card([])`.
238 ///
239 /// # Examples
240 ///
241 /// ```
242 /// use orx_v::*;
243 ///
244 /// let mut v1 = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
245 ///
246 /// let row_lengths = vec![1, 0, 3, 6]; // lengths => [1, 0, 3, 6]
247 /// let mut v2 = v1.as_jagged_mut_from_row_lengths(&row_lengths);
248 /// *v2.at_mut([2, 2]) += 10;
249 /// *v2.at_mut([3, 4]) *= 10;
250 /// assert_eq!(
251 /// v2.equality(&[vec![0], vec![], vec![1, 2, 13], vec![4, 5, 6, 7, 80, 9]]),
252 /// Equality::Equal
253 /// );
254 ///
255 /// let row_lengths = V.d1().constant(5).bounded(2); // lengths => [5, 5]
256 /// let mut v2 = v1.as_jagged_mut_from_row_lengths(&row_lengths);
257 /// *v2.at_mut([0, 4]) += 100;
258 /// assert_eq!(
259 /// v2.equality(&[vec![0, 1, 2, 13, 104], vec![5, 6, 7, 80, 9]]),
260 /// Equality::Equal
261 /// );
262 fn as_jagged_mut_from_row_lengths<I>(
263 &mut self,
264 row_lengths: &I,
265 ) -> FlatJagged<&mut Self, Vec<usize>, T>
266 where
267 I: NVec<D1, usize>,
268 {
269 validate_row_end_lengths(self, row_lengths);
270 self.as_jagged_mut(row_indices_from_row_lengths(row_lengths))
271 }
272
273 // with max child size
274
275 /// Converts a `D1` vector into a jagged `D2` vector where each row has the given
276 /// `uniform_length`, except that the last row might have fewer elements if the
277 /// cardinality of the `D1` vector is not divisible by the uniform length.
278 ///
279 /// # Examples
280 ///
281 /// ```
282 /// use orx_v::*;
283 ///
284 /// let v1 = [1, 2, 3, 4, 5, 6, 7, 8];
285 ///
286 /// let v2 = v1.into_jagged_with_uniform_lengths(3);
287 ///
288 /// assert_eq!(v2.card([]), 3);
289 /// assert_eq!(v2.card([0]), 3);
290 /// assert_eq!(v2.at([1, 2]), 6);
291 ///
292 /// assert_eq!(
293 /// v2.equality(&[vec![1, 2, 3], vec![4, 5, 6], vec![7, 8]]),
294 /// Equality::Equal
295 /// );
296 /// ```
297 fn into_jagged_with_uniform_lengths(
298 self,
299 uniform_length: usize,
300 ) -> FlatJagged<Self, UniformEndIndices, T> {
301 assert!(uniform_length > 0);
302 let row_end_indices = UniformEndIndices::new(uniform_length, self.card([]));
303 FlatJagged::new(self, row_end_indices)
304 }
305
306 /// From a flat `D1` vector, creates a jagged `D2` vector view where each row has
307 /// the given `uniform_length`, except that the last row might have fewer elements
308 /// if the cardinality of the `D1` vector is not divisible by the uniform length.
309 ///
310 /// # Examples
311 ///
312 /// ```
313 /// use orx_v::*;
314 ///
315 /// let v1 = [1, 2, 3, 4, 5, 6, 7, 8];
316 ///
317 /// let v2 = v1.as_jagged_with_uniform_lengths(3);
318 ///
319 /// assert_eq!(v2.card([]), 3);
320 /// assert_eq!(v2.card([0]), 3);
321 /// assert_eq!(v2.at([1, 2]), 6);
322 ///
323 /// assert_eq!(
324 /// v2.equality(&[vec![1, 2, 3], vec![4, 5, 6], vec![7, 8]]),
325 /// Equality::Equal
326 /// );
327 /// ```
328 fn as_jagged_with_uniform_lengths(
329 &self,
330 uniform_length: usize,
331 ) -> FlatJagged<&Self, UniformEndIndices, T> {
332 assert!(uniform_length > 0);
333 let row_end_indices = UniformEndIndices::new(uniform_length, self.card([]));
334 FlatJagged::new(self, row_end_indices)
335 }
336
337 /// From a flat `D1` vector, creates a mutable jagged `D2` vector view where each row has
338 /// the given `uniform_length`, except that the last row might have fewer elements
339 /// if the cardinality of the `D1` vector is not divisible by the uniform length.
340 ///
341 /// # Examples
342 ///
343 /// ```
344 /// use orx_v::*;
345 ///
346 /// let mut v1 = [1, 2, 3, 4, 5, 6, 7, 8];
347 ///
348 /// let mut v2 = v1.as_jagged_mut_with_uniform_lengths(3);
349 ///
350 /// v2.set([1, 2], 66);
351 /// *v2.at_mut([2, 0]) = 77;
352 ///
353 /// assert_eq!(
354 /// v2.equality(&[vec![1, 2, 3], vec![4, 5, 66], vec![77, 8]]),
355 /// Equality::Equal
356 /// );
357 /// ```
358 fn as_jagged_mut_with_uniform_lengths(
359 &mut self,
360 uniform_length: usize,
361 ) -> FlatJagged<&mut Self, UniformEndIndices, T> {
362 assert!(uniform_length > 0);
363 let row_end_indices = UniformEndIndices::new(uniform_length, self.card([]));
364 FlatJagged::new(self, row_end_indices)
365 }
366}
367
368impl<T, V: Sized + NVec<D1, T>> IntoJagged<T> for V {}
369
370// helpers
371
372fn row_indices_from_row_lengths<I>(row_lengths: &I) -> Vec<usize>
373where
374 I: NVec<D1, usize>,
375{
376 row_lengths
377 .all()
378 .scan(0, |x, y| {
379 *x += y;
380 Some(*x)
381 })
382 .collect()
383}
384
385fn validate_row_end_indices<T, V: NVec<D1, T>, I: NVec<D1, usize>>(flat_vec: &V, end_indices: I) {
386 let mut begin = 0;
387 for end in end_indices.all() {
388 assert!(end >= begin,
389 "`row_end_indices` must be a non-decreasing vector. \
390 For example, end indices [1, 2, 2, 5] represents a jagged vector with row lengths of [1, 1, 0, 3]. \
391 However, received a decreasing sequence [.., {}, {}, ..].",
392 begin, end
393 );
394 begin = end;
395 }
396 assert_eq!(flat_vec.card([]), begin,
397 "Last entry of the `row_end_indices` must equal the cardinality of the flat V1 storage. \
398 For example, end indices [1, 2, 2, 5] for flat storage [0, 1, 2, 3, 4] represents a jagged vector of \
399 [ [0], [1], [], [2, 3, 4] ]. \
400 However, received a flat storage cardinality of {} while the last entry of row end indices is {}.",
401 flat_vec.card([]), begin
402 );
403}
404
405fn validate_row_end_lengths<T, V: NVec<D1, T>, I: NVec<D1, usize>>(flat_vec: &V, lengths: I) {
406 let total_len: usize = lengths.all().sum();
407 assert_eq!(flat_vec.card([]), total_len,
408 "Sum of elements of `row_lengths` must equal the cardinality of the flat V1 storage. \
409 For example, row lengths [1, 1, 0, 3] for flat storage [0, 1, 2, 3, 4] represents a jagged vector of \
410 [ [0], [1], [], [2, 3, 4] ]. \
411 However, received a flat storage cardinality of {} while sum of row lengths is {}.",
412 flat_vec.card([]), total_len
413 );
414}