Skip to main content

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}