1use nalgebra as na;
4
5use crate::mesh::SubsetImpl;
6
7pub type Cochain<const DIM: usize, Primality> = CochainImpl<na::Const<DIM>, Primality>;
14
15#[derive(Clone)]
22pub struct CochainImpl<Dimension, Primality> {
23 pub values: na::DVector<f64>,
30 _marker: std::marker::PhantomData<(Dimension, Primality)>,
31}
32
33impl<Dimension, Primality> CochainImpl<Dimension, Primality> {
34 #[inline]
40 pub(crate) fn from_values(values: na::DVector<f64>) -> Self {
41 Self {
42 values,
43 _marker: std::marker::PhantomData,
44 }
45 }
46
47 #[inline]
48 pub(crate) fn zeros(len: usize) -> Self {
49 Self::from_values(na::DVector::zeros(len))
50 }
51
52 pub fn lerp(&self, end: &Self, t: f64) -> Self {
54 self + &(t * (end - self))
55 }
56
57 pub fn overwrite(&mut self, subset: &SubsetImpl<Dimension, Primality>, other: &Self) {
59 for i in subset.indices.ones() {
60 self.values[i] = other.values[i];
61 }
62 }
63}
64
65impl<Dimension, Primality> crate::operator::Operand for CochainImpl<Dimension, Primality> {
66 type Dimension = Dimension;
67 type Primality = Primality;
68
69 fn values(&self) -> &na::DVector<f64> {
70 &self.values
71 }
72
73 fn from_values(values: na::DVector<f64>) -> Self {
74 Self {
75 values,
76 _marker: std::marker::PhantomData,
77 }
78 }
79}
80
81impl<D, P> std::fmt::Debug for CochainImpl<D, P>
87where
88 D: na::DimName,
89{
90 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91 write!(f, "{}-cochain, values {:?}", D::USIZE, self.values)
92 }
93}
94
95impl<D, P> PartialEq for CochainImpl<D, P> {
96 fn eq(&self, other: &Self) -> bool {
97 self.values == other.values
98 }
99}
100
101impl<'a, D, const MESH_DIM: usize> std::ops::Index<crate::SimplexView<'a, D, MESH_DIM>>
104 for CochainImpl<D, crate::Primal>
105where
106 D: na::DimName,
107 na::Const<MESH_DIM>: na::DimNameSub<D>,
108{
109 type Output = f64;
110
111 fn index(&self, simplex: crate::SimplexView<'a, D, MESH_DIM>) -> &Self::Output {
112 &self.values[simplex.index()]
113 }
114}
115
116impl<'a, D, const MESH_DIM: usize> std::ops::IndexMut<crate::SimplexView<'a, D, MESH_DIM>>
117 for CochainImpl<D, crate::Primal>
118where
119 D: na::DimName,
120 na::Const<MESH_DIM>: na::DimNameSub<D>,
121{
122 fn index_mut(&mut self, simplex: crate::SimplexView<'a, D, MESH_DIM>) -> &mut Self::Output {
123 &mut self.values[simplex.index()]
124 }
125}
126
127impl<'a, D, const MESH_DIM: usize> std::ops::Index<crate::DualCellView<'a, D, MESH_DIM>>
128 for CochainImpl<D, crate::Dual>
129where
130 D: na::DimName,
131 na::Const<MESH_DIM>: na::DimNameSub<D>,
132{
133 type Output = f64;
134
135 fn index(&self, simplex: crate::DualCellView<'a, D, MESH_DIM>) -> &Self::Output {
136 &self.values[simplex.index()]
137 }
138}
139
140impl<'a, D, const MESH_DIM: usize> std::ops::IndexMut<crate::DualCellView<'a, D, MESH_DIM>>
141 for CochainImpl<D, crate::Dual>
142where
143 D: na::DimName,
144 na::Const<MESH_DIM>: na::DimNameSub<D>,
145{
146 fn index_mut(&mut self, simplex: crate::DualCellView<'a, D, MESH_DIM>) -> &mut Self::Output {
147 &mut self.values[simplex.index()]
148 }
149}
150
151impl<D, P> std::ops::Add for CochainImpl<D, P> {
154 type Output = Self;
155
156 fn add(self, rhs: Self) -> Self::Output {
157 CochainImpl::from_values(self.values + rhs.values)
158 }
159}
160
161impl<D, P> std::ops::Add<&CochainImpl<D, P>> for CochainImpl<D, P> {
162 type Output = Self;
163
164 fn add(self, rhs: &CochainImpl<D, P>) -> Self::Output {
165 CochainImpl::from_values(self.values + &rhs.values)
166 }
167}
168
169impl<D, P> std::ops::Add<CochainImpl<D, P>> for &CochainImpl<D, P> {
170 type Output = CochainImpl<D, P>;
171
172 fn add(self, rhs: CochainImpl<D, P>) -> Self::Output {
173 CochainImpl::from_values(&self.values + rhs.values)
174 }
175}
176
177impl<D, P> std::ops::Add for &CochainImpl<D, P> {
178 type Output = CochainImpl<D, P>;
179
180 fn add(self, rhs: Self) -> Self::Output {
181 CochainImpl::from_values(&self.values + &rhs.values)
182 }
183}
184
185impl<D, P> std::ops::AddAssign for CochainImpl<D, P> {
188 fn add_assign(&mut self, rhs: Self) {
189 self.values += rhs.values;
190 }
191}
192
193impl<D, P> std::ops::AddAssign<&CochainImpl<D, P>> for CochainImpl<D, P> {
194 fn add_assign(&mut self, rhs: &CochainImpl<D, P>) {
195 self.values += &rhs.values;
196 }
197}
198
199impl<D, P> std::ops::Neg for CochainImpl<D, P> {
202 type Output = Self;
203
204 fn neg(self) -> Self::Output {
205 Self::from_values(-self.values)
206 }
207}
208
209impl<D, P> std::ops::Neg for &CochainImpl<D, P> {
210 type Output = CochainImpl<D, P>;
211
212 fn neg(self) -> Self::Output {
213 CochainImpl::from_values(-&self.values)
214 }
215}
216
217impl<D, P> std::ops::Sub for CochainImpl<D, P> {
220 type Output = Self;
221
222 fn sub(self, rhs: Self) -> Self::Output {
223 Self::from_values(self.values - rhs.values)
224 }
225}
226
227impl<D, P> std::ops::Sub<&CochainImpl<D, P>> for CochainImpl<D, P> {
228 type Output = Self;
229
230 fn sub(self, rhs: &CochainImpl<D, P>) -> Self::Output {
231 CochainImpl::from_values(&self.values - &rhs.values)
232 }
233}
234
235impl<D, P> std::ops::Sub<CochainImpl<D, P>> for &CochainImpl<D, P> {
236 type Output = CochainImpl<D, P>;
237
238 fn sub(self, rhs: CochainImpl<D, P>) -> Self::Output {
239 CochainImpl::from_values(&self.values - &rhs.values)
240 }
241}
242
243impl<D, P> std::ops::Sub for &CochainImpl<D, P> {
244 type Output = CochainImpl<D, P>;
245
246 fn sub(self, rhs: Self) -> Self::Output {
247 CochainImpl::from_values(&self.values - &rhs.values)
248 }
249}
250
251impl<D, P> std::ops::SubAssign for CochainImpl<D, P> {
254 fn sub_assign(&mut self, rhs: Self) {
255 self.values -= rhs.values;
256 }
257}
258
259impl<D, P> std::ops::SubAssign<&CochainImpl<D, P>> for CochainImpl<D, P> {
260 fn sub_assign(&mut self, rhs: &CochainImpl<D, P>) {
261 self.values -= &rhs.values;
262 }
263}
264
265impl<D, P> std::ops::Mul<CochainImpl<D, P>> for f64 {
268 type Output = CochainImpl<D, P>;
269
270 fn mul(self, rhs: CochainImpl<D, P>) -> Self::Output {
271 CochainImpl::from_values(self * rhs.values)
272 }
273}
274
275impl<D, P> std::ops::Mul<&CochainImpl<D, P>> for f64 {
276 type Output = CochainImpl<D, P>;
277
278 fn mul(self, rhs: &CochainImpl<D, P>) -> Self::Output {
279 CochainImpl::from_values(self * &rhs.values)
280 }
281}