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}