ndstruct/dense.rs
1//! Dense
2//!
3//! A fully filled contiguous space of memory. If 1d, then this structure is the same as a vector;
4//! if 2d, then this structure is the same as a matrix; if 3d, then this structure is the same as
5//! a cube and so on for higher dimensions.
6
7mod dense_error;
8
9#[cfg(feature = "alloc")]
10use alloc::vec::Vec;
11use cl_aux::{ArrayWrapper, SingleTypeStorage};
12pub use dense_error::*;
13
14/// Dense backed by a static array.
15pub type DenseArray<DATA, const D: usize, const DN: usize> = Dense<[DATA; DN], D>;
16/// Dense backed by a mutable slice
17pub type DenseMut<'data, DATA, const D: usize> = Dense<&'data mut [DATA], D>;
18/// Dense backed by a slice
19pub type DenseRef<'data, DATA, const D: usize> = Dense<&'data [DATA], D>;
20#[cfg(feature = "alloc")]
21/// Dense backed by a dynamic vector.
22pub type DenseVec<DATA, const D: usize> = Dense<Vec<DATA>, D>;
23
24/// Base structure for all [Dense] variants.
25///
26/// # Types
27///
28/// * `D`: Number of dimensions
29/// * `DS`: Data Storage
30#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
31#[derive(Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd)]
32pub struct Dense<DS, const D: usize> {
33 pub(crate) data: DS,
34 pub(crate) dims: ArrayWrapper<usize, D>,
35}
36
37impl<DS, const D: usize> Dense<DS, D> {
38 /// The definitions of all dimensions.
39 ///
40 /// # Example
41 ///
42 /// ```rust
43 /// use ndstruct::doc_tests::dense_array_3;
44 /// assert_eq!(dense_array_3().dims(), &[4, 3, 3]);
45 /// ```
46 #[inline]
47 pub fn dims(&self) -> &[usize; D] {
48 &self.dims
49 }
50}
51
52impl<DATA, DS, const D: usize> Dense<DS, D>
53where
54 DS: AsRef<[<DS as SingleTypeStorage>::Item]> + SingleTypeStorage<Item = DATA>,
55{
56 /// Creates a valid [Dense] instance.
57 ///
58 /// # Arguments
59 ///
60 /// * `dims`: Array of dimensions
61 /// * `data`: Data collection
62 ///
63 /// # Example
64 #[cfg_attr(feature = "alloc", doc = "```rust")]
65 #[cfg_attr(not(feature = "alloc"), doc = "```ignore")]
66 /// use ndstruct::dense::{DenseArray, DenseVec};
67 /// // Matrix ([1, 2, 3], [4, 5, 6])
68 /// let mut _matrix = DenseArray::new([2, 3], [1, 2, 3, 4, 5, 6]);
69 /// // A bunch of nothing for your overflow needs
70 /// let _over_nine: ndstruct::Result<DenseVec<(), 9001>>;
71 /// _over_nine = DenseVec::new([0; 9001], vec![]);
72 /// ```
73 #[inline]
74 pub fn new(dims: [usize; D], data: DS) -> crate::Result<Self> {
75 if dims.iter().copied().any(|elem| elem >= D) {
76 return Err(DenseError::InvalidIndcs.into());
77 }
78 Ok(Self { data, dims: dims.into() })
79 }
80
81 /// The data that is being stored.
82 ///
83 /// # Example
84 ///
85 /// ```rust
86 /// use ndstruct::doc_tests::dense_array_3;
87 /// assert_eq!(dense_array_3().data(), &[
88 /// 1, 2, 3, 4, 5, 6, 7, 8, 9,
89 /// 10, 11, 12, 13, 14, 15, 16, 17, 18,
90 /// 19, 20, 21, 22, 23, 24, 25, 26, 27,
91 /// 28, 29, 30, 31, 32, 33, 34, 35, 36,
92 /// ]);
93 /// ```
94 #[inline]
95 pub fn data(&self) -> &[DATA] {
96 self.data.as_ref()
97 }
98
99 /// If any, retrieves an immutable data reference of a given set of indices.
100 ///
101 /// # Arguments
102 ///
103 /// * `indcs`: Indices of the desired data location
104 ///
105 /// # Example
106 ///
107 /// ```rust
108 /// use ndstruct::doc_tests::dense_array_3;
109 /// let elem = dense_array_3();
110 /// assert_eq!(elem.value([0, 0, 0]), Some(&1));
111 /// assert_eq!(elem.value([0, 0, 2]), Some(&3));
112 /// assert_eq!(elem.value([0, 2, 2]), Some(&9));
113 /// assert_eq!(elem.value([3, 2, 2]), Some(&36));
114 /// assert_eq!(elem.value([3, 2, 3]), None);
115 /// ```
116 #[inline]
117 pub fn value(&self, indcs: [usize; D]) -> Option<&DATA> {
118 self.data().get(self.idx(indcs))
119 }
120
121 // 1 * rows * cols * z
122 // 1 * rows * y
123 // 1 * x
124 fn dim_stride(&self, dim_idx: usize, target_dim_idx: usize) -> usize {
125 self.dims.iter().copied().skip(1).rev().skip(dim_idx).chain([target_dim_idx]).product()
126 }
127
128 fn idx(&self, indcs: [usize; D]) -> usize {
129 let mut rslt: usize = 0;
130 for (dim_idx, target_dim_idx) in (0..self.dims.len()).zip(indcs) {
131 rslt = rslt.wrapping_add(self.dim_stride(dim_idx, target_dim_idx));
132 }
133 rslt
134 }
135}