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}