Skip to main content

conspire/math/tensor/quantity/sparse_vec/
mod.rs

1use super::Quantity;
2use crate::math::{Tensor, TensorRank0};
3use crate::units::Dimensionless;
4use std::{
5    fmt::{self, Debug, Display, Formatter, Result},
6    iter::Sum,
7    ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Sub, SubAssign},
8};
9
10/// A sparse vector of quantities, storing only inserted entries.
11pub struct QuantitySparseVec<U = Dimensionless>(pub(super) Vec<(usize, Quantity<U>)>);
12
13impl<U> Clone for QuantitySparseVec<U> {
14    fn clone(&self) -> Self {
15        Self(self.0.clone())
16    }
17}
18
19impl<U> Debug for QuantitySparseVec<U> {
20    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
21        Debug::fmt(&self.0, f)
22    }
23}
24
25impl<U> Default for QuantitySparseVec<U> {
26    fn default() -> Self {
27        Self(Vec::new())
28    }
29}
30
31impl<U> PartialEq for QuantitySparseVec<U> {
32    fn eq(&self, other: &Self) -> bool {
33        self.0 == other.0
34    }
35}
36
37impl<U> QuantitySparseVec<U> {
38    pub fn entries(&self) -> impl Iterator<Item = (usize, &Quantity<U>)> {
39        self.0.iter().map(|(column, entry)| (*column, entry))
40    }
41}
42
43impl<U> FromIterator<Quantity<U>> for QuantitySparseVec<U> {
44    fn from_iter<T>(into_iterator: T) -> Self
45    where
46        T: IntoIterator<Item = Quantity<U>>,
47    {
48        Self(into_iterator.into_iter().enumerate().collect())
49    }
50}
51
52impl<U> Index<usize> for QuantitySparseVec<U> {
53    type Output = Quantity<U>;
54    fn index(&self, index: usize) -> &Self::Output {
55        match self.0.binary_search_by_key(&index, |&(column, _)| column) {
56            Ok(k) => &self.0[k].1,
57            Err(_) => panic!("Entry ({index}) not present."),
58        }
59    }
60}
61
62impl<U> IndexMut<usize> for QuantitySparseVec<U> {
63    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
64        let k = match self.0.binary_search_by_key(&index, |&(column, _)| column) {
65            Ok(k) => k,
66            Err(k) => {
67                self.0.insert(k, (index, Quantity::new(0.0)));
68                k
69            }
70        };
71        &mut self.0[k].1
72    }
73}
74
75impl<U> Display for QuantitySparseVec<U> {
76    fn fmt(&self, f: &mut Formatter) -> Result {
77        write!(f, "Need to implement Display")
78    }
79}
80
81impl<U> Tensor for QuantitySparseVec<U> {
82    type Item = Quantity<U>;
83    type Unit = U;
84    fn iter(&self) -> impl Iterator<Item = &Self::Item> {
85        self.0.iter().map(|(_, entry)| entry)
86    }
87    fn iter_mut(&mut self) -> impl Iterator<Item = &mut Self::Item> {
88        self.0.iter_mut().map(|(_, entry)| entry)
89    }
90    fn len(&self) -> usize {
91        self.0.len()
92    }
93    fn size(&self) -> usize {
94        self.0.len()
95    }
96}
97
98fn merge<U>(
99    a: QuantitySparseVec<U>,
100    b: &QuantitySparseVec<U>,
101    sign: TensorRank0,
102) -> QuantitySparseVec<U> {
103    let mut merged = a;
104    b.0.iter()
105        .for_each(|(column, entry)| merged[*column] += entry * sign);
106    merged
107}
108
109impl<U> Add for QuantitySparseVec<U> {
110    type Output = Self;
111    fn add(self, other: Self) -> Self {
112        merge(self, &other, 1.0)
113    }
114}
115
116impl<U> Add<&Self> for QuantitySparseVec<U> {
117    type Output = Self;
118    fn add(self, other: &Self) -> Self {
119        merge(self, other, 1.0)
120    }
121}
122
123impl<U> AddAssign for QuantitySparseVec<U> {
124    fn add_assign(&mut self, other: Self) {
125        other
126            .0
127            .into_iter()
128            .for_each(|(column, entry)| self[column] += entry);
129    }
130}
131
132impl<U> AddAssign<&Self> for QuantitySparseVec<U> {
133    fn add_assign(&mut self, other: &Self) {
134        other
135            .0
136            .iter()
137            .for_each(|(column, entry)| self[*column] += entry);
138    }
139}
140
141impl<U> Sub for QuantitySparseVec<U> {
142    type Output = Self;
143    fn sub(self, other: Self) -> Self {
144        merge(self, &other, -1.0)
145    }
146}
147
148impl<U> Sub<&Self> for QuantitySparseVec<U> {
149    type Output = Self;
150    fn sub(self, other: &Self) -> Self {
151        merge(self, other, -1.0)
152    }
153}
154
155impl<U> SubAssign for QuantitySparseVec<U> {
156    fn sub_assign(&mut self, other: Self) {
157        other
158            .0
159            .into_iter()
160            .for_each(|(column, entry)| self[column] -= entry);
161    }
162}
163
164impl<U> SubAssign<&Self> for QuantitySparseVec<U> {
165    fn sub_assign(&mut self, other: &Self) {
166        other
167            .0
168            .iter()
169            .for_each(|(column, entry)| self[*column] -= entry);
170    }
171}
172
173impl<U> Mul<TensorRank0> for QuantitySparseVec<U> {
174    type Output = Self;
175    fn mul(mut self, scalar: TensorRank0) -> Self {
176        self *= &scalar;
177        self
178    }
179}
180
181impl<U> MulAssign<TensorRank0> for QuantitySparseVec<U> {
182    fn mul_assign(&mut self, scalar: TensorRank0) {
183        self.0.iter_mut().for_each(|(_, entry)| *entry *= &scalar);
184    }
185}
186
187impl<U> MulAssign<&TensorRank0> for QuantitySparseVec<U> {
188    fn mul_assign(&mut self, scalar: &TensorRank0) {
189        self.0.iter_mut().for_each(|(_, entry)| *entry *= scalar);
190    }
191}
192
193impl<U> Div<TensorRank0> for QuantitySparseVec<U> {
194    type Output = Self;
195    fn div(mut self, scalar: TensorRank0) -> Self {
196        self /= &scalar;
197        self
198    }
199}
200
201impl<U> DivAssign<TensorRank0> for QuantitySparseVec<U> {
202    fn div_assign(&mut self, scalar: TensorRank0) {
203        self.0.iter_mut().for_each(|(_, entry)| *entry /= &scalar);
204    }
205}
206
207impl<U> DivAssign<&TensorRank0> for QuantitySparseVec<U> {
208    fn div_assign(&mut self, scalar: &TensorRank0) {
209        self.0.iter_mut().for_each(|(_, entry)| *entry /= scalar);
210    }
211}
212
213impl<U> Sum for QuantitySparseVec<U> {
214    fn sum<T>(iter: T) -> Self
215    where
216        T: Iterator<Item = Self>,
217    {
218        iter.fold(Self::default(), |sum, entry| sum + entry)
219    }
220}