orx_v/
nvec.rs

1use crate::{dim::*, nvec_core::NVecCore, NVecCoreSealed};
2
3/// A `D` dimensional vector.
4///
5/// The objective of this trait to enable polymorphism over containers that are or
6/// that are capable of behaving as contagious data structures with efficient random
7/// access by indices of its elements.
8///
9/// [`V1`], [`V2`], etc. are type aliases for `NVec<D1, T>`, `NVec<D2, T>`, and so on.
10///
11/// # Motivation
12///
13/// The `NVec` trait mainly aims to support algorithms.
14/// The goal is to **implement the algorithm once** without considering the underlying
15/// type of the vectors, and it works for **all inputs** that behave like a multi-dimensional
16/// vector without any loss of performance.
17///
18/// The most straightforward example is the standard `Vec<T>` or `&[T]`; they both
19/// implement `V1<T>`.
20/// And consequently, `Vec<Vec<T>>` implements `V2<T>`.
21/// Actually, inner type can vary since `Vec<X>` implements `V2<T>` provided that `X`
22/// implements `V1<T>`.
23/// This might be the first example of polymorphism.
24/// This trait aims at enabling any type that makes sense to implement the vector trait
25/// with the corresponding dimension.
26///
27/// To elaborate the idea of polymorphism, consider an algorithm that requires a distance
28/// matrix as its input such that the (i,j)-th element of the matrix represents the
29/// distance from location i to location j. Our goal is to implement this algorithm once,
30/// which works with different distance matrix representations without any loss of
31/// performance.
32///
33/// Say our distance unit is `u32`, so our input distance matrix is `impl V2<u32>`.
34///
35/// ```ignore
36/// fn algorithm(distance_matrix: impl V2<u32>) { ... }
37/// ```
38///
39/// We want to be able to call `algorithm` with any input that makes sense as a distance
40/// matrix.
41///
42/// Let's think about what can implement `V2<u32>`?
43///
44/// ## Dense
45///
46/// We can store all distances in a 2-dimensional structure, `Vec<Vec<u32>>` for instance.
47/// As mentioned above, `Vec<Vec<u32>>` implements `V2<u32>`, so this works.
48///
49/// ```ignore
50/// let dense_matrix = vec![vec![0, 2, 3], vec![3, 0, 7], vec![2, 2, 0]];
51/// algorithm(&dense_matrix);
52/// ```
53///
54/// ## Flattened Dense
55///
56/// Sometimes it is advantageous to flatten matrices and treat the 1-dimensional structure
57/// as a 2-dimensional structure.
58///
59/// We can also treat a `V1<T>` as a jagged `V2<T>` by providing the additional information
60/// about the column lengths which can be any `V1<usize>`.
61///
62/// ```ignore
63/// let flat_storage = vec![0, 2, 3, 3, 0, 7, 2, 2, 0];
64/// let row_end_indices = V.d1().fun(|[i]| 3 * (i + 1)).bounded(3);
65/// let flat_dense_matrix = flat_storage.as_jagged(&row_end_indices);
66/// algorithm(&flat_dense_matrix);
67/// ```
68///
69/// ## Constant
70///
71/// Sometimes we have scenarios where all entries of the matrix are identical to some value.
72/// This is often very handy in input polymorphism.
73/// * Consider the shortest distance problem.
74///   When, all distances are equal to 1 (`d[i, j] = 1`, for all i, j),
75///   solution of the same problem represents the
76///   minimum number of arcs to reach the destination.
77/// * Consider the minimum cost flow problem.
78///   When all edges have infinite capacity (`cap[i, j] = INF`, for all i, j),
79///   and when we send one unit of flow from s to t,
80///   the solution represents the shortest path from s to t.
81///
82/// In order to use the `algorithm`, should we create an n-by-n storage of the same values?
83/// Not necessarily.
84///
85/// ```ignore
86/// let all_ones = V.d2().constant(1).with_rectangular_bounds([3, 3]);
87/// algorithm(&all_ones);
88/// ```
89///
90/// ## Sparse
91///
92/// Quite often, we run into a situation where our vector is sparse and we are worried about
93/// the wasted memory. Consider, for instance, that only certain locations are reachable from
94/// one location, and hence, only those pairs have distance values. We assume that the distances
95/// between all other locations are `u32::MAX`.
96///
97/// Should we fill an n-by-n storage where almost all elements are equal to `u32::MAX`?
98/// Not necessarily.
99///
100/// ```ignore
101/// let mut sparse_matrix = V.d2().sparse(u32::MAX);
102/// *sparse_matrix.at_mut([0, 1]) = 10;
103/// *sparse_matrix.at_mut([1, 2]) = 7;
104/// *sparse_matrix.at_mut([1, 3]) = 5;
105/// *sparse_matrix.at_mut([3, 8]) = 60;
106/// assert_eq!(sparse_matrix.lookup_len(), 4);
107/// algorithm(&sparse_matrix);
108/// ```
109///
110/// ## Functional
111///
112/// Sometimes, we do not prefer to store any distances at all. The reasons might vary.
113/// For instance,
114/// * computing the element might be so cheap that it doesn't make sense to store and look up,
115/// * the size of the matrix is critically large given the hardware, we prefer to pay the
116///   computational price of re-calculating the element every time it is requested.
117///
118/// In these cases, we can simply provide the function that computes the element.
119///
120/// ```ignore
121/// struct Location(u32, u32);
122/// fn euclidean(a: &Location, b: &Location) -> u32 {
123///     (((a.0 - b.0) * (a.0 - b.0) + (a.1 - b.1) * (a.1 - b.1)) as f64).sqrt() as u32
124/// }
125/// let locations = vec![Location(0, 3), Location(3, 2), Location(4, 1)];
126/// let euclidean_matrix = V.d2().fun(|[i, j]| euclidean(&locations[i], &locations[j]));
127/// algorithm(&euclidean_matrix);
128/// ```
129///
130/// ## Cached
131///
132/// Sometimes, we do not prefer to store distances but due to a different reason.
133/// * The matrix might be huge, while the algorithm accesses only a small subset of elements.
134/// * But we don't necessarily know ahead of time which elements will be accessed.
135/// * Instead of pre-computing the entire matrix, we can compute elements on demand.
136/// * However, unlike the Euclidean example above, the computation of the element might be
137///   relatively expensive.
138/// * In order to avoid repeating the computation of the element on repeated accesses,
139///   we cache the computed elements.
140///
141/// We can achieve this by simply calling `into_cached` on a functional vector.
142///
143/// ```ignore
144/// struct Address(/* coordinates */);
145/// fn distance_api(a: &Address, b: &Address) -> u32 {
146///     todo!("make an api call to get the shortest distance wrt routing on the road network")
147/// }
148/// let addresses = vec![Address(), Address(), Address()];
149/// let cached_distances = V
150///     .d2()
151///     .fun(|[i, j]| distance_api(&addresses[i], &addresses[j]))
152///     .into_cached();
153///
154/// assert_eq!(cached_distances.cache_len(), 0); // cache is initially empty
155/// algorithm(&cached_distances);
156/// ```
157///
158/// [`V1`]: crate::V1
159/// [`V2`]: crate::V2
160pub trait NVec<D: Dim, T>: NVecCore<D, T> {
161    // required
162
163    /// Returns the element at the `idx`-th position of the vector.
164    ///
165    /// Note that the dimensions of the vector and the index are equal;
166    /// and hence, the result is the scalar.
167    ///
168    /// # Panics
169    ///
170    /// Panics if the `idx` is not `in_bounds`.
171    ///
172    /// # Examples
173    ///
174    /// ```rust
175    /// use orx_v::*;
176    ///
177    /// let vec = vec![
178    ///     vec![0, 1, 2],
179    ///     vec![3],
180    ///     vec![4, 5],
181    /// ];
182    ///
183    /// assert_eq!(vec.at([0, 1]), 1);
184    /// assert_eq!(vec.at([1, 0]), 3);
185    /// assert_eq!(vec.at([2, 1]), 5);
186    ///
187    /// // vec.at([1, 1]); // panics!
188    /// assert_eq!(vec.try_at([1, 1]), None);
189    /// ```
190    fn at(&self, idx: impl IntoIdx<D>) -> T;
191
192    /// Returns the `i`-th child of the vector.
193    ///
194    /// Note that child has a dimension that is one less than the dimension
195    /// of this vector.
196    ///
197    /// # Panics
198    ///
199    /// Panics if `i` is out of bounds; i.e., `i >= vec.num_children()`.
200    ///
201    /// # Examples
202    ///
203    /// ```rust
204    /// use orx_v::*;
205    ///
206    /// // D2
207    /// let vec = vec![
208    ///     vec![0, 1, 2],
209    ///     vec![3],
210    ///     vec![4, 5],
211    /// ];
212    ///
213    /// // child is a D1 vec
214    /// let child = vec.child(2);
215    ///
216    /// assert_eq!(child.num_children(), 2);
217    ///
218    /// assert_eq!(child.at([0]), 4);
219    /// assert_eq!(child.at([1]), 5);
220    /// ```
221    fn child(&self, i: D::ChildIdx) -> impl NVec<D::PrevDim, T>;
222
223    /// Returns a flattened iterator over all scalar (D0) elements of the vector.
224    ///
225    /// In this sense, `all` can be considered similar to recursively
226    /// called flat map on higher dimensional collections.
227    ///
228    /// See [`all_in`] for creating an iterator over a given domain.
229    ///
230    /// # Examples
231    ///
232    /// ```rust
233    /// use orx_v::*;
234    ///
235    /// let vec = vec![
236    ///     vec![0, 1],
237    ///     vec![],
238    ///     vec![2],
239    /// ];
240    ///
241    /// let mut all = vec.all();
242    /// assert_eq!(all.next(), Some(0));
243    /// assert_eq!(all.next(), Some(1));
244    /// assert_eq!(all.next(), Some(2));
245    /// assert_eq!(all.next(), None);
246    /// ```
247    ///
248    /// # Panics
249    ///
250    /// Panics if the vector [`is_unbounded`] as this will lead to an infinite loop.
251    ///
252    /// The following are examples for unbounded vectors:
253    /// * [`ConstantVec`] => `V.d1().constant(42)`
254    /// * [`SparseVec`] => `V.d2().sparse(42)`
255    /// * [`FunVec`] => `V.d2().fun(|[i, j]| i + 42 * j)`
256    ///
257    /// Finite domain of these vectors can be set by calling:
258    /// * `bounded` for [`D1`] vectors,
259    /// * `with_rectangular_bounds` or `with_variable_bounds` for higher dimensional vectors.
260    ///
261    /// # Examples
262    ///
263    /// ```
264    /// use orx_v::*;
265    ///
266    /// let v1 = V.d1().constant(42).bounded(4);
267    /// assert_eq!(
268    ///     v1.all().collect::<Vec<_>>(),
269    ///     vec![42, 42, 42, 42],
270    /// );
271    ///
272    /// let mut v2 = V.d2().sparse(0).with_rectangular_bounds([2, 3]);
273    /// *v2.at_mut([0, 2]) = 42;
274    /// assert_eq!(
275    ///     v2.all().collect::<Vec<_>>(),
276    ///     vec![0, 0, 42, 0, 0, 0],
277    /// );
278    ///
279    /// let num_cols = [1, 0, 2, 1];
280    /// let v2 = V.d2().fun(|[i, j]| 10 * i + j).with_variable_bounds(&num_cols);
281    /// assert_eq!(
282    ///     v2.equality(&[vec![0], vec![], vec![20, 21], vec![30]]),
283    ///     Equality::Equal,
284    /// );
285    /// assert_eq!(
286    ///     v2.all().collect::<Vec<_>>(),
287    ///     vec![0, 20, 21, 30],
288    /// );
289    /// ```
290    ///
291    /// [`all_in`]: crate::NVec::all_in
292    /// [`is_unbounded`]: crate::NVec::is_unbounded
293    /// [`ConstantVec`]: crate::ConstantVec
294    /// [`SparseVec`]: crate::SparseVec
295    /// [`FunVec`]: crate::FunVec
296    /// [`D1`]: crate::D1
297    fn all(&self) -> impl Iterator<Item = T>;
298
299    // provided - nvec-card
300
301    /// Returns the number of children of the vector; i.e., number of
302    /// elements of the one lower dimension.
303    ///
304    /// If this vector is of dimension D2; `num_children` returns the
305    /// number of D1 children (V1) of this vector.
306    ///
307    /// # Examples
308    ///
309    /// ```rust
310    /// use orx_v::*;
311    ///
312    /// let vec = vec![
313    ///     vec![0, 1, 2],
314    ///     vec![3],
315    ///     vec![4, 5],
316    /// ];
317    ///
318    /// assert_eq!(vec.num_children(), 3);
319    ///
320    /// assert_eq!(vec.child(2).num_children(), 2);
321    /// ```
322    #[inline(always)]
323    fn num_children(&self) -> usize {
324        <Self as NVecCoreSealed<D, T>>::core_num_children(self)
325    }
326
327    /// Returns the cardinality of the vec in any of the lower dimensions.
328    ///
329    /// # Examples
330    ///
331    /// ```rust
332    /// use orx_v::*;
333    ///
334    /// let v2 = [
335    ///     vec![0, 2, 3],
336    ///     vec![1, 7],
337    ///     vec![],
338    ///     vec![10, 3, 4, 8],
339    /// ];
340    ///
341    /// // outer-most cardinality
342    /// assert_eq!(v2.card([]), 4);
343    ///
344    /// // cardinality of the first-degree child
345    /// assert_eq!(v2.card([3]), 4);
346    /// // equivalent to:
347    /// assert_eq!(v2.child(3).card([]), 4);
348    /// ```
349    ///
350    /// This logic works similarly for higher dimensions.
351    ///
352    /// ```rust
353    /// use orx_v::*;
354    ///
355    /// let v4 = [
356    ///     vec![ // 0
357    ///         vec![ // 0, 0
358    ///             vec![3],    // 0, 0, 0
359    ///             vec![1, 2], // 0, 0, 1
360    ///         ],
361    ///         vec![ // 0, 1
362    ///             vec![6, 7, 8], // 0, 1, 0
363    ///             vec![],        // 0, 1, 1
364    ///             vec![9],       // 0, 1, 2
365    ///         ],
366    ///     ]
367    /// ];
368    ///
369    /// assert_eq!(v4.card([]), 1);
370    /// assert_eq!(v4.card([0]), 2);
371    /// assert_eq!(v4.card([0, 0]), 2);
372    /// assert_eq!(v4.card([0, 0, 0]), 1);
373    /// assert_eq!(v4.card([0, 0, 1]), 2);
374    /// assert_eq!(v4.card([0, 1]), 3);
375    /// assert_eq!(v4.card([0, 1, 0]), 3);
376    /// assert_eq!(v4.card([0, 1, 1]), 0);
377    /// assert_eq!(v4.card([0, 1, 2]), 1);
378    /// ```
379    #[inline(always)]
380    fn card(&self, idx: impl Into<D::CardIdx>) -> usize {
381        <Self as NVecCoreSealed<D, T>>::core_card(self, idx)
382    }
383
384    /// Returns whether or not the vector is bounded.
385    ///
386    /// The following are examples for unbounded vectors:
387    /// * [`ConstantVec`] => `V.d1().constant(42)`
388    /// * [`SparseVec`] => `V.d2().sparse(42)`
389    /// * [`FunVec`] => `V.d2().fun(|[i, j]| i + 42 * j)`
390    ///
391    /// Finite domain of these vectors can be set by calling:
392    /// * `bounded` for [`D1`] vectors,
393    /// * `with_rectangular_bounds` or `with_variable_bounds` for higher dimensional vectors.
394    ///
395    /// # Example
396    ///
397    /// ```
398    /// use orx_v::*;
399    ///
400    /// let v2 = vec![
401    ///     vec![0, 1],
402    ///     vec![],
403    ///     vec![2],
404    /// ];
405    /// assert!(v2.is_bounded());
406    ///
407    /// let v1: &[usize] = v2[0].as_slice();
408    /// assert!(v1.is_bounded());
409    ///
410    /// // constant
411    ///
412    /// let v1 = V.d1().constant(42);
413    /// assert!(v1.is_unbounded());
414    ///
415    /// let v1 = V.d1().constant(42).bounded(10);
416    /// assert!(v1.is_bounded());
417    ///
418    /// // sparse
419    ///
420    /// let mut v2 = V.d2().sparse(0);
421    /// *v2.at_mut([0, 2]) = 42;
422    /// assert!(v2.is_unbounded());
423    ///
424    /// let mut v2 = V.d2().sparse(0).with_rectangular_bounds([2, 3]);
425    /// *v2.at_mut([0, 2]) = 42;
426    /// assert!(v2.is_bounded());
427    ///
428    /// // fun
429    ///
430    /// let v2 = V.d2().fun(|[i, j]| 10 * i + j);
431    /// assert!(v2.is_unbounded());
432    ///
433    /// let num_cols = [1, 0, 2, 1];
434    /// let v2 = V.d2().fun(|[i, j]| 10 * i + j).with_variable_bounds(&num_cols);
435    /// assert!(v2.is_bounded());
436    /// ```
437    ///
438    /// [`ConstantVec`]: crate::ConstantVec
439    /// [`SparseVec`]: crate::SparseVec
440    /// [`FunVec`]: crate::FunVec
441    #[inline(always)]
442    fn is_bounded(&self) -> bool {
443        <Self as NVecCoreSealed<D, T>>::core_num_children(self) < usize::MAX
444    }
445
446    /// Returns whether or not the cardinalities of the vector are rectangular.
447    /// A rectangular vector of dimension `D` has the same number of children
448    /// at a given lower dimension for all indices.
449    ///
450    /// * All empty vectors are rectangular.
451    /// * All `D1` vectors are dimensional.
452    /// * Two and higher dimensional matrices are rectangular.
453    ///
454    /// # Examples
455    ///
456    /// You may see examples of rectangular vectors below.
457    ///
458    /// ```
459    /// use orx_v::*;
460    ///
461    /// let vec = V.d3().empty::<i64>();
462    /// assert!(vec.is_rectangular());
463    ///
464    /// let vec = vec![1, 3, 4];
465    /// assert!(vec.is_rectangular());
466    ///
467    /// let vec = V.d4().constant(42).with_rectangular_bounds([1, 3, 2, 7]);
468    /// assert!(vec.is_rectangular());
469    ///
470    /// let vec = vec![
471    ///     vec![1, 2, 3],
472    ///     vec![4, 5, 6],
473    /// ];
474    /// assert!(vec.is_rectangular());
475    ///
476    /// let vec = vec![
477    ///     vec![
478    ///         vec![1, 2, 3],
479    ///     ],
480    ///     vec![
481    ///         vec![4, 5, 6],
482    ///     ],
483    /// ];
484    /// assert!(vec.is_rectangular());
485    ///
486    /// let flat_vec = vec![0, 1, 2, 3, 4, 5, 6, 7];
487    /// let row_end_indices = V.d1().fun(|[i]| 4 * (i + 1)).bounded(2);
488    /// let vec = flat_vec.as_jagged(&row_end_indices);
489    /// assert!(vec.is_rectangular());
490    ///
491    /// let vec = V.d2().fun(|[i, j]| i + j).with_rectangular_bounds([4, 2]);
492    /// assert!(vec.is_rectangular());
493    /// ```
494    ///
495    /// And below are examples for the non-rectangular or jagged vectors.
496    ///
497    /// ```
498    /// use orx_v::*;
499    ///
500    /// let lengths = vec![3, 2, 3];
501    /// let vec = V.d2().constant(42).with_variable_bounds(lengths);
502    /// assert!(!vec.is_rectangular());
503    ///
504    /// let vec = vec![
505    ///     vec![1, 2, 3],
506    ///     vec![4, 5, 6, 7],
507    /// ];
508    /// assert!(!vec.is_rectangular());
509    ///
510    /// let vec = vec![
511    ///     vec![
512    ///         vec![1, 2, 3],
513    ///     ],
514    ///     vec![
515    ///         vec![4, 5, 6, 7],
516    ///     ],
517    /// ];
518    /// assert!(!vec.is_rectangular());
519    ///
520    /// let vec = vec![
521    ///     vec![
522    ///         vec![1, 2, 3],
523    ///     ],
524    ///     vec![
525    ///         vec![4, 5, 6],
526    ///         vec![7, 8, 9],
527    ///     ],
528    /// ];
529    /// assert!(!vec.is_rectangular());
530    ///
531    /// let flat_vec = vec![0, 1, 2, 3, 4, 5, 6, 7];
532    /// let row_end_indices = vec![2, 5, 8];
533    /// let vec = flat_vec.as_jagged(&row_end_indices);
534    /// assert!(!vec.is_rectangular());
535    ///
536    /// let card = vec![3, 2, 3];
537    /// let vec = V.d2().fun(|[i, j]| i + j).with_variable_bounds(card);
538    /// assert!(!vec.is_rectangular());
539    /// ```
540    fn is_rectangular(&self) -> bool {
541        self.core_is_rectangular()
542    }
543
544    /// Returns whether or not the vector is unbounded.
545    ///
546    /// The following are examples for unbounded vectors:
547    /// * [`ConstantVec`] => `V.d1().constant(42)`
548    /// * [`SparseVec`] => `V.d2().sparse(42)`
549    /// * [`FunVec`] => `V.d2().fun(|[i, j]| i + 42 * j)`
550    ///
551    /// Finite domain of these vectors can be set by calling:
552    /// * `bounded` for [`D1`] vectors,
553    /// * `with_rectangular_bounds` or `with_variable_bounds` for higher dimensional vectors.
554    ///
555    /// # Example
556    ///
557    /// ```
558    /// use orx_v::*;
559    ///
560    /// let v2 = vec![
561    ///     vec![0, 1],
562    ///     vec![],
563    ///     vec![2],
564    /// ];
565    /// assert!(v2.is_bounded());
566    ///
567    /// let v1: &[usize] = v2[0].as_slice();
568    /// assert!(v1.is_bounded());
569    ///
570    /// // constant
571    ///
572    /// let v1 = V.d1().constant(42);
573    /// assert!(v1.is_unbounded());
574    ///
575    /// let v1 = V.d1().constant(42).bounded(10);
576    /// assert!(v1.is_bounded());
577    ///
578    /// // sparse
579    ///
580    /// let mut v2 = V.d2().sparse(0);
581    /// *v2.at_mut([0, 2]) = 42;
582    /// assert!(v2.is_unbounded());
583    ///
584    /// let mut v2 = V.d2().sparse(0).with_rectangular_bounds([2, 3]);
585    /// *v2.at_mut([0, 2]) = 42;
586    /// assert!(v2.is_bounded());
587    ///
588    /// // fun
589    ///
590    /// let v2 = V.d2().fun(|[i, j]| 10 * i + j);
591    /// assert!(v2.is_unbounded());
592    ///
593    /// let num_cols = [1, 0, 2, 1];
594    /// let v2 = V.d2().fun(|[i, j]| 10 * i + j).with_variable_bounds(&num_cols);
595    /// assert!(v2.is_bounded());
596    /// ```
597    ///
598    /// [`ConstantVec`]: crate::ConstantVec
599    /// [`SparseVec`]: crate::SparseVec
600    /// [`FunVec`]: crate::FunVec
601    #[inline(always)]
602    fn is_unbounded(&self) -> bool {
603        <Self as NVecCoreSealed<D, T>>::core_num_children(self) == usize::MAX
604    }
605
606    /// Returns whether or not the given `idx` is in bounds.
607    ///
608    /// Note that the index can be the same dimension as the vector
609    /// or any of the lower dimensions.
610    ///
611    /// # Examples
612    ///
613    /// ```rust
614    /// use orx_v::*;
615    ///
616    /// let vec = vec![
617    ///     vec![1, 2, 3],
618    ///     vec![4]
619    /// ];
620    ///
621    /// // d2
622    /// assert_eq!(vec.in_bounds([0, 2]), true);  // element 3
623    /// assert_eq!(vec.in_bounds([1, 0]), true);  // element 4
624    /// assert_eq!(vec.in_bounds([1, 1]), false); // X
625    /// assert_eq!(vec.in_bounds([2, 0]), false); // X
626    ///
627    /// // d1
628    /// assert_eq!(vec.in_bounds([0]), true);  // V1 [1, 2, 3]
629    /// assert_eq!(vec.in_bounds([1]), true);  // V1 [4]
630    /// assert_eq!(vec.in_bounds([2]), false); // X
631    ///
632    /// // d0
633    /// assert_eq!(vec.in_bounds([]), true); // V2 [[1, 2, 3], [4]]
634    /// ```
635    #[inline(always)]
636    fn in_bounds(&self, idx: impl Into<D::LeqIdx>) -> bool {
637        idx.into().in_leq_bounds(self)
638    }
639
640    /// Returns the cardinality equality of this vec with the `other`:
641    /// * Returns [`CardEquality::Equal`] iff the cardinality of the structures and
642    ///   all their corresponding children have equal cardinalities.
643    /// * Returns [`CardEquality::Unequal`] if cardinalities do not agree at at least one
644    ///   level. The tuple `(idx, card1, card2)` represents the following:
645    ///   * `idx` is the place the inequality in cardinalities are observed;
646    ///   * `card1` and `card2` are the unequal cardinalities at the given `idx` in the first and
647    ///     second vectors, respectively.
648    ///
649    /// # Examples
650    ///
651    /// ```rust
652    /// use orx_v::*;
653    ///
654    /// let a = vec![
655    ///     vec![0, 1, 2],
656    ///     vec![3, 4, 5, 6],
657    /// ];
658    ///
659    /// let b1 = vec![
660    ///     vec![7, 0, 3],
661    ///     vec![5, 2, 9, 5],
662    /// ];
663    /// let b2 = vec![
664    ///     vec![7, 0, 3],
665    ///     vec![5, 2, 9, 5, 42],
666    /// ];
667    /// let b3 = vec![
668    ///     vec![7, 0, 3],
669    ///     vec![5, 2, 9, 5],
670    ///     vec![],
671    /// ];
672    ///
673    /// // cardinalities are equal
674    /// assert_eq!(a.card_equality(&b1), CardEquality::Equal);
675    ///
676    /// // cardinalities of the 1-st-level children with index 1
677    /// // (`a.child(1)`) are different (4 != 5)
678    /// assert_eq!(
679    ///     a.card_equality(&b2),
680    ///     CardEquality::Unequal(IdxLeqD1::IdxD1([1]), 4, 5)
681    /// );
682    ///
683    /// // outer-most cardinalities are different (2 != 3)
684    /// assert_eq!(
685    ///     a.card_equality(&b3),
686    ///     CardEquality::Unequal(IdxLeqD1::IdxD0([]), 2, 3)
687    /// );
688    /// ```
689    fn card_equality(&self, other: &impl NVec<D, T>) -> CardEquality<D> {
690        D::CardIdx::card_equality(self, other)
691    }
692
693    // provided
694
695    /// Returns the element at the `idx`-th position of the vector if the
696    /// index is `in_bounds`; returns None otherwise.
697    ///
698    /// # Examples
699    ///
700    /// ```rust
701    /// use orx_v::*;
702    ///
703    /// let vec = vec![
704    ///     vec![0, 1, 2],
705    ///     vec![3],
706    ///     vec![4, 5],
707    /// ];
708    ///
709    /// assert_eq!(vec.try_at([0, 1]), Some(1));
710    /// assert_eq!(vec.try_at([1, 0]), Some(3));
711    /// assert_eq!(vec.try_at([2, 1]), Some(5));
712    ///
713    /// // vec.at([1, 1]); // panics!
714    /// assert_eq!(vec.try_at([1, 1]), None);
715    /// ```
716    fn try_at(&self, idx: impl IntoIdx<D>) -> Option<T> {
717        match D::in_bounds(idx, self) {
718            true => Some(self.at(idx)),
719            false => None,
720        }
721    }
722
723    /// Returns the equality of this vec with the `other`:
724    /// * Returns [`Equality::Equal`] iff the cardinality of the structures as
725    ///   well as all values at corresponding positions are equal.
726    /// * Returns [`Equality::UnequalCard`] if cardinalities do not agree at at least one
727    ///   level. The tuple `(idx, card1, card2)` represents the following:
728    ///   * `idx` is the place the inequality in cardinalities are observed;
729    ///   * `card1` and `card2` are the unequal cardinalities at the given `idx` in the first and
730    ///     second vectors, respectively.
731    /// * Returns [`Equality::UnequalValue`] if any of the values are different.
732    ///   The `(idx)` represents the index where the value inequality is observed.
733    ///
734    /// # Examples
735    ///
736    /// ```rust
737    /// use orx_v::*;
738    ///
739    /// let a = vec![
740    ///     vec![0, 1, 2],
741    ///     vec![3, 4, 5, 6],
742    /// ];
743    ///
744    /// let b1 = vec![
745    ///     vec![0, 1, 2],
746    ///     vec![3, 4, 5, 6],
747    /// ];
748    /// let b2 = vec![
749    ///     vec![0, 1, 2],
750    ///     vec![3, 4, 42, 6],
751    /// ];
752    /// let b3 = vec![
753    ///     vec![0, 1, 2],
754    ///     vec![3, 4, 5, 6, 42],
755    /// ];
756    /// let b4 = vec![
757    ///     vec![0, 1, 2],
758    ///     vec![3, 4, 5, 6],
759    ///     vec![42],
760    /// ];
761    ///
762    /// // vectors are equal
763    /// assert_eq!(a.equality(&b1), Equality::Equal);
764    ///
765    /// // values at [1, 2] are different
766    /// assert_eq!(a.equality(&b2), Equality::UnequalValue([1, 2]));
767    ///
768    /// // cardinalities of the 1-st-level children with index 1
769    /// // (`a.child(1)`) are different (3 != 4)
770    /// assert_eq!(
771    ///     a.equality(&b3),
772    ///     Equality::UnequalCard(IdxLeqD1::IdxD1([1]), 4, 5)
773    /// );
774    ///
775    /// // outer-most cardinalities are different (2 != 3)
776    /// assert_eq!(
777    ///     a.equality(&b4),
778    ///     Equality::UnequalCard(IdxLeqD1::IdxD0([]), 2, 3)
779    /// );
780    /// ```
781    fn equality(&self, other: &impl NVec<D, T>) -> Equality<D>
782    where
783        T: PartialEq,
784    {
785        D::CardIdx::equality(self, other)
786    }
787
788    /// Returns an iterator of all children of the vector.
789    ///
790    /// Note that child has a dimension that is one less than the dimension
791    /// of this vector.
792    ///
793    /// ```rust
794    /// use orx_v::*;
795    ///
796    /// // D2
797    /// let vec = vec![
798    ///     vec![0, 1, 2],
799    ///     vec![3],
800    ///     vec![4, 5],
801    /// ];
802    ///
803    /// let mut children = vec.children();
804    ///
805    /// assert_eq!(children.next().unwrap().equality(&[0, 1, 2]), Equality::Equal);
806    /// assert_eq!(children.next().unwrap().equality(&[3]), Equality::Equal);
807    /// assert_eq!(children.next().unwrap().equality(&[4, 5]), Equality::Equal);
808    /// assert!(children.next().is_none());
809    /// ```
810    fn children(&self) -> impl Iterator<Item = impl NVec<D::PrevDim, T>> {
811        (0..self.core_num_children()).map(|i| self.child(i.into()))
812    }
813
814    /// Returns an iterator of elements for the given `indices`.
815    ///
816    /// This method is useful especially when the vector `is_unbounded` and we would
817    /// like to iterate only over the given indices.
818    ///
819    /// # Panics
820    ///
821    /// Panics if any of the indices that `indices` iterator yields is out of bounds.
822    ///
823    /// # Examples
824    ///
825    /// ```rust
826    /// use orx_v::*;
827    ///
828    /// let vec = V.d1().constant(42);
829    /// assert!(vec.is_unbounded());
830    /// let mut all = vec.all_in(0..3);
831    /// assert_eq!(all.next(), Some(42));
832    /// assert_eq!(all.next(), Some(42));
833    /// assert_eq!(all.next(), Some(42));
834    /// assert_eq!(all.next(), None);
835    ///
836    /// let vec = vec![
837    ///     vec![0, 1],
838    ///     vec![],
839    ///     vec![2],
840    /// ];
841    ///
842    /// let mut all = vec.all_in([[0, 1], [2, 0]].into_iter());
843    /// assert_eq!(all.next(), Some(1));
844    /// assert_eq!(all.next(), Some(2));
845    /// assert_eq!(all.next(), None);
846    /// ```
847    fn all_in(&self, indices: impl Iterator<Item = impl IntoIdx<D>>) -> impl Iterator<Item = T> {
848        indices.map(|idx| self.at(idx.into_idx()))
849    }
850}
851
852// &V auto impl
853
854impl<T, D: Dim, V: NVec<D, T>> NVec<D, T> for &V {
855    #[inline(always)]
856    fn at(&self, idx: impl IntoIdx<D>) -> T {
857        <V as NVec<D, T>>::at(self, idx)
858    }
859
860    #[inline(always)]
861    fn child(&self, i: <D as Dim>::ChildIdx) -> impl NVec<<D as Dim>::PrevDim, T> {
862        <V as NVec<D, T>>::child(self, i)
863    }
864
865    fn all(&self) -> impl Iterator<Item = T> {
866        <V as NVec<D, T>>::all(self)
867    }
868}
869
870// &mut V auto impl
871
872impl<T, D: Dim, V: NVec<D, T>> NVec<D, T> for &mut V {
873    #[inline(always)]
874    fn at(&self, idx: impl IntoIdx<D>) -> T {
875        <V as NVec<D, T>>::at(self, idx)
876    }
877
878    #[inline(always)]
879    fn child(&self, i: <D as Dim>::ChildIdx) -> impl NVec<<D as Dim>::PrevDim, T> {
880        <V as NVec<D, T>>::child(self, i)
881    }
882
883    fn all(&self) -> impl Iterator<Item = T> {
884        <V as NVec<D, T>>::all(self)
885    }
886}