1use nalgebra as na;
4
5use crate::{mesh::SubsetImpl, DualCellView, SimplexView};
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>,
50 _marker: std::marker::PhantomData<(Dimension, Primality)>,
51}
52
53impl<Dimension, Primality> CochainImpl<Dimension, Primality> {
54 #[inline]
60 pub(crate) fn from_values(values: na::DVector<f64>) -> Self {
61 Self {
62 values,
63 _marker: std::marker::PhantomData,
64 }
65 }
66
67 #[inline]
68 pub(crate) fn zeros(len: usize) -> Self {
69 Self::from_values(na::DVector::zeros(len))
70 }
71
72 pub fn lerp(&self, end: &Self, t: f64) -> Self {
74 self + &(t * (end - self))
75 }
76
77 pub fn overwrite(&mut self, subset: &SubsetImpl<Dimension, Primality>, other: &Self) {
79 for i in subset.indices.ones() {
80 self.values[i] = other.values[i];
81 }
82 }
83}
84
85impl<Dimension, Primality> crate::operator::Operand for CochainImpl<Dimension, Primality> {
86 type Dimension = Dimension;
87 type Primality = Primality;
88
89 fn values(&self) -> &na::DVector<f64> {
90 &self.values
91 }
92
93 fn from_values(values: na::DVector<f64>) -> Self {
94 Self {
95 values,
96 _marker: std::marker::PhantomData,
97 }
98 }
99}
100
101impl<D, P> std::fmt::Debug for CochainImpl<D, P>
107where
108 D: na::DimName,
109{
110 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
111 write!(f, "{}-cochain, values {:?}", D::USIZE, self.values)
112 }
113}
114
115impl<D, P> PartialEq for CochainImpl<D, P> {
116 fn eq(&self, other: &Self) -> bool {
117 self.values == other.values
118 }
119}
120
121impl<'a, D, const MESH_DIM: usize> std::ops::Index<SimplexView<'a, D, MESH_DIM>>
124 for CochainImpl<D, crate::Primal>
125where
126 D: na::DimName,
127 na::Const<MESH_DIM>: na::DimNameSub<D>,
128{
129 type Output = f64;
130
131 fn index(&self, simplex: SimplexView<'a, D, MESH_DIM>) -> &Self::Output {
132 &self.values[simplex.index()]
133 }
134}
135
136impl<'a, D, const MESH_DIM: usize> std::ops::IndexMut<SimplexView<'a, D, MESH_DIM>>
137 for CochainImpl<D, crate::Primal>
138where
139 D: na::DimName,
140 na::Const<MESH_DIM>: na::DimNameSub<D>,
141{
142 fn index_mut(&mut self, simplex: SimplexView<'a, D, MESH_DIM>) -> &mut Self::Output {
143 &mut self.values[simplex.index()]
144 }
145}
146
147impl<'a, D, const MESH_DIM: usize> std::ops::Index<DualCellView<'a, D, MESH_DIM>>
148 for CochainImpl<D, crate::Dual>
149where
150 D: na::DimName,
151 na::Const<MESH_DIM>: na::DimNameSub<D>,
152{
153 type Output = f64;
154
155 fn index(&self, simplex: DualCellView<'a, D, MESH_DIM>) -> &Self::Output {
156 &self.values[simplex.index()]
157 }
158}
159
160impl<'a, D, const MESH_DIM: usize> std::ops::IndexMut<DualCellView<'a, D, MESH_DIM>>
161 for CochainImpl<D, crate::Dual>
162where
163 D: na::DimName,
164 na::Const<MESH_DIM>: na::DimNameSub<D>,
165{
166 fn index_mut(&mut self, simplex: DualCellView<'a, D, MESH_DIM>) -> &mut Self::Output {
167 &mut self.values[simplex.index()]
168 }
169}
170
171impl<D, P> std::ops::Add for CochainImpl<D, P> {
174 type Output = Self;
175
176 fn add(self, rhs: Self) -> Self::Output {
177 CochainImpl::from_values(self.values + rhs.values)
178 }
179}
180
181impl<D, P> std::ops::Add<&CochainImpl<D, P>> for CochainImpl<D, P> {
182 type Output = Self;
183
184 fn add(self, rhs: &CochainImpl<D, P>) -> Self::Output {
185 CochainImpl::from_values(self.values + &rhs.values)
186 }
187}
188
189impl<D, P> std::ops::Add<CochainImpl<D, P>> for &CochainImpl<D, P> {
190 type Output = CochainImpl<D, P>;
191
192 fn add(self, rhs: CochainImpl<D, P>) -> Self::Output {
193 CochainImpl::from_values(&self.values + rhs.values)
194 }
195}
196
197impl<D, P> std::ops::Add for &CochainImpl<D, P> {
198 type Output = CochainImpl<D, P>;
199
200 fn add(self, rhs: Self) -> Self::Output {
201 CochainImpl::from_values(&self.values + &rhs.values)
202 }
203}
204
205impl<D, P> std::ops::AddAssign for CochainImpl<D, P> {
208 fn add_assign(&mut self, rhs: Self) {
209 self.values += rhs.values;
210 }
211}
212
213impl<D, P> std::ops::AddAssign<&CochainImpl<D, P>> for CochainImpl<D, P> {
214 fn add_assign(&mut self, rhs: &CochainImpl<D, P>) {
215 self.values += &rhs.values;
216 }
217}
218
219impl<D, P> std::ops::Neg for CochainImpl<D, P> {
222 type Output = Self;
223
224 fn neg(self) -> Self::Output {
225 Self::from_values(-self.values)
226 }
227}
228
229impl<D, P> std::ops::Neg for &CochainImpl<D, P> {
230 type Output = CochainImpl<D, P>;
231
232 fn neg(self) -> Self::Output {
233 CochainImpl::from_values(-&self.values)
234 }
235}
236
237impl<D, P> std::ops::Sub for CochainImpl<D, P> {
240 type Output = Self;
241
242 fn sub(self, rhs: Self) -> Self::Output {
243 Self::from_values(self.values - rhs.values)
244 }
245}
246
247impl<D, P> std::ops::Sub<&CochainImpl<D, P>> for CochainImpl<D, P> {
248 type Output = Self;
249
250 fn sub(self, rhs: &CochainImpl<D, P>) -> Self::Output {
251 CochainImpl::from_values(&self.values - &rhs.values)
252 }
253}
254
255impl<D, P> std::ops::Sub<CochainImpl<D, P>> for &CochainImpl<D, P> {
256 type Output = CochainImpl<D, P>;
257
258 fn sub(self, rhs: CochainImpl<D, P>) -> Self::Output {
259 CochainImpl::from_values(&self.values - &rhs.values)
260 }
261}
262
263impl<D, P> std::ops::Sub for &CochainImpl<D, P> {
264 type Output = CochainImpl<D, P>;
265
266 fn sub(self, rhs: Self) -> Self::Output {
267 CochainImpl::from_values(&self.values - &rhs.values)
268 }
269}
270
271impl<D, P> std::ops::SubAssign for CochainImpl<D, P> {
274 fn sub_assign(&mut self, rhs: Self) {
275 self.values -= rhs.values;
276 }
277}
278
279impl<D, P> std::ops::SubAssign<&CochainImpl<D, P>> for CochainImpl<D, P> {
280 fn sub_assign(&mut self, rhs: &CochainImpl<D, P>) {
281 self.values -= &rhs.values;
282 }
283}
284
285impl<D, P> std::ops::Mul<CochainImpl<D, P>> for f64 {
288 type Output = CochainImpl<D, P>;
289
290 fn mul(self, rhs: CochainImpl<D, P>) -> Self::Output {
291 CochainImpl::from_values(self * rhs.values)
292 }
293}
294
295impl<D, P> std::ops::Mul<&CochainImpl<D, P>> for f64 {
296 type Output = CochainImpl<D, P>;
297
298 fn mul(self, rhs: &CochainImpl<D, P>) -> Self::Output {
299 CochainImpl::from_values(self * &rhs.values)
300 }
301}