Skip to main content

conspire/math/tensor/tuple/
mod.rs

1#[cfg(test)]
2mod test;
3
4pub(crate) mod list;
5pub(crate) mod vec;
6
7use crate::math::{
8    Differentiable, Erase, Jacobian, Quantity, Scalar, Solution, Tensor, TensorRank0, Vector,
9};
10use crate::units::UnitHalves;
11use std::{
12    fmt::{Display, Formatter, Result},
13    iter::Sum,
14    ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign},
15};
16
17/// A fixed-size nested collection of different tensors.
18#[derive(Clone, Debug, PartialEq)]
19pub struct TensorTuple<T1, T2>(pub T1, pub T2)
20where
21    T1: Tensor,
22    T2: Tensor;
23
24type First<V> = <V as UnitHalves>::First;
25type Second<V> = <V as UnitHalves>::Second;
26
27impl<T1, T2, V> Mul<Quantity<V>> for TensorTuple<T1, T2>
28where
29    V: UnitHalves,
30    T1: Mul<Quantity<First<V>>> + Tensor,
31    T2: Mul<Quantity<Second<V>>> + Tensor,
32    <T1 as Mul<Quantity<First<V>>>>::Output: Tensor,
33    <T2 as Mul<Quantity<Second<V>>>>::Output: Tensor,
34{
35    type Output = TensorTuple<
36        <T1 as Mul<Quantity<First<V>>>>::Output,
37        <T2 as Mul<Quantity<Second<V>>>>::Output,
38    >;
39    fn mul(self, quantity: Quantity<V>) -> Self::Output {
40        let (first, second) = quantity.halves();
41        TensorTuple(self.0 * first, self.1 * second)
42    }
43}
44
45impl<T1, T2, V> Mul<Quantity<V>> for &TensorTuple<T1, T2>
46where
47    V: UnitHalves,
48    T1: Clone + Mul<Quantity<First<V>>> + Tensor,
49    T2: Clone + Mul<Quantity<Second<V>>> + Tensor,
50    <T1 as Mul<Quantity<First<V>>>>::Output: Tensor,
51    <T2 as Mul<Quantity<Second<V>>>>::Output: Tensor,
52{
53    type Output = TensorTuple<
54        <T1 as Mul<Quantity<First<V>>>>::Output,
55        <T2 as Mul<Quantity<Second<V>>>>::Output,
56    >;
57    fn mul(self, quantity: Quantity<V>) -> Self::Output {
58        let (first, second) = quantity.halves();
59        TensorTuple(self.0.clone() * first, self.1.clone() * second)
60    }
61}
62
63impl<T1, T2, V> Div<Quantity<V>> for TensorTuple<T1, T2>
64where
65    V: UnitHalves,
66    T1: Div<Quantity<First<V>>> + Tensor,
67    T2: Div<Quantity<Second<V>>> + Tensor,
68    <T1 as Div<Quantity<First<V>>>>::Output: Tensor,
69    <T2 as Div<Quantity<Second<V>>>>::Output: Tensor,
70{
71    type Output = TensorTuple<
72        <T1 as Div<Quantity<First<V>>>>::Output,
73        <T2 as Div<Quantity<Second<V>>>>::Output,
74    >;
75    fn div(self, quantity: Quantity<V>) -> Self::Output {
76        let (first, second) = quantity.halves();
77        TensorTuple(self.0 / first, self.1 / second)
78    }
79}
80
81impl<T1, T2> Erase for TensorTuple<T1, T2>
82where
83    T1: Erase + Tensor,
84    T2: Erase + Tensor,
85    <T1 as Erase>::Erased: Tensor,
86    <T2 as Erase>::Erased: Tensor,
87{
88    type Erased = TensorTuple<<T1 as Erase>::Erased, <T2 as Erase>::Erased>;
89    fn erase(&self) -> &Self::Erased {
90        unsafe { &*(self as *const Self as *const Self::Erased) }
91    }
92}
93
94impl<T1, T2> Default for TensorTuple<T1, T2>
95where
96    T1: Tensor,
97    T2: Tensor,
98{
99    fn default() -> Self {
100        Self(T1::default(), T2::default())
101    }
102}
103
104impl<T1, T2> From<(T1, T2)> for TensorTuple<T1, T2>
105where
106    T1: Tensor,
107    T2: Tensor,
108{
109    fn from(tuple: (T1, T2)) -> Self {
110        Self(tuple.0, tuple.1)
111    }
112}
113
114impl<'a, T1, T2> From<&'a TensorTuple<T1, T2>> for (&'a T1, &'a T2)
115where
116    T1: Tensor,
117    T2: Tensor,
118{
119    fn from(tensor_tuple: &'a TensorTuple<T1, T2>) -> Self {
120        (&tensor_tuple.0, &tensor_tuple.1)
121    }
122}
123
124impl<T1, T2> From<TensorTuple<T1, T2>> for (T1, T2)
125where
126    T1: Tensor,
127    T2: Tensor,
128{
129    fn from(tensor_tuple: TensorTuple<T1, T2>) -> Self {
130        (tensor_tuple.0, tensor_tuple.1)
131    }
132}
133
134impl<T1, T2> From<Vector> for TensorTuple<T1, T2>
135where
136    T1: Tensor,
137    T2: Tensor,
138{
139    fn from(_vector: Vector) -> Self {
140        unimplemented!()
141    }
142}
143
144impl<T1, T2> Display for TensorTuple<T1, T2>
145where
146    T1: Tensor,
147    T2: Tensor,
148{
149    fn fmt(&self, f: &mut Formatter) -> Result {
150        write!(f, "({}, {})", self.0, self.1)
151    }
152}
153
154impl<T1, T2> Tensor for TensorTuple<T1, T2>
155where
156    T1: Tensor,
157    T2: Tensor,
158{
159    type Item = T1::Item;
160    type Unit = (<T1 as Tensor>::Unit, <T2 as Tensor>::Unit);
161    fn error_count_zero(&self, tol_abs: Scalar, tol_rel: Scalar) -> Option<usize> {
162        let error_count = self.0.error_count_zero(tol_abs, tol_rel).unwrap_or(0)
163            + self.1.error_count_zero(tol_abs, tol_rel).unwrap_or(0);
164        if error_count > 0 {
165            Some(error_count)
166        } else {
167            None
168        }
169    }
170    fn error_count(&self, tensor_tuple: &Self, tol_abs: Scalar, tol_rel: Scalar) -> Option<usize> {
171        let error_count = self
172            .0
173            .error_count(&tensor_tuple.0, tol_abs, tol_rel)
174            .unwrap_or(0)
175            + self
176                .1
177                .error_count(&tensor_tuple.1, tol_abs, tol_rel)
178                .unwrap_or(0);
179        if error_count > 0 {
180            Some(error_count)
181        } else {
182            None
183        }
184    }
185    fn full_contraction(&self, tensor_tuple: &Self) -> TensorRank0 {
186        self.0.full_contraction(&tensor_tuple.0) + self.1.full_contraction(&tensor_tuple.1)
187    }
188    fn is_zero(&self) -> bool {
189        self.0.is_zero() && self.1.is_zero()
190    }
191    fn iter(&self) -> impl Iterator<Item = &Self::Item> {
192        if self.size() == 0 {
193            self.0.iter()
194        } else {
195            unimplemented!()
196        }
197    }
198    fn iter_mut(&mut self) -> impl Iterator<Item = &mut Self::Item> {
199        if self.size() == 0 {
200            self.0.iter_mut()
201        } else {
202            unimplemented!()
203        }
204    }
205    fn len(&self) -> usize {
206        unimplemented!()
207    }
208    fn norm_inf(&self) -> Quantity<Self::Unit> {
209        Quantity::new(self.0.norm_inf().value().max(self.1.norm_inf().value()))
210    }
211    fn norm_l1(&self) -> Quantity<Self::Unit> {
212        Quantity::new(self.0.norm_l1().value() + self.1.norm_l1().value())
213    }
214    fn norm_p_sum(&self, p: TensorRank0) -> TensorRank0 {
215        self.0.norm_p_sum(p) + self.1.norm_p_sum(p)
216    }
217    fn size(&self) -> usize {
218        self.0.size() + self.1.size()
219    }
220    fn sub_abs(&self, tensor_tuple: &Self) -> Self {
221        Self(
222            self.0.sub_abs(&tensor_tuple.0),
223            self.1.sub_abs(&tensor_tuple.1),
224        )
225    }
226    fn sub_rel(&self, tensor_tuple: &Self) -> Self {
227        Self(
228            self.0.sub_rel(&tensor_tuple.0),
229            self.1.sub_rel(&tensor_tuple.1),
230        )
231    }
232}
233
234impl<T1, T2> Jacobian for TensorTuple<T1, T2>
235where
236    T1: Jacobian,
237    T2: Jacobian,
238{
239    fn fill_into(&self, vector: &mut Vector) {
240        let mut head = Vector::zero(self.0.size());
241        self.0.fill_into(&mut head);
242        let mut tail = Vector::zero(self.1.size());
243        self.1.fill_into(&mut tail);
244        head.into_iter()
245            .chain(tail)
246            .zip(vector.iter_mut())
247            .for_each(|(entry, vector_i)| *vector_i = entry)
248    }
249    fn fill_into_chained(self, other: Vector, vector: &mut Vector) {
250        let mut head = Vector::zero(self.0.size());
251        self.0.fill_into(&mut head);
252        let mut tail = Vector::zero(self.1.size());
253        self.1.fill_into(&mut tail);
254        head.into_iter()
255            .chain(tail)
256            .chain(other)
257            .zip(vector.iter_mut())
258            .for_each(|(entry, vector_i)| *vector_i = entry)
259    }
260}
261
262impl<T1, T2> Solution for TensorTuple<T1, T2>
263where
264    T1: Solution,
265    T2: Solution,
266{
267    fn decrement_from(&mut self, other: &Vector) {
268        let split = self.0.size();
269        let head: Vector = other.iter().take(split).copied().collect();
270        let tail: Vector = other.iter().skip(split).copied().collect();
271        self.0.decrement_from(&head);
272        self.1.decrement_from(&tail);
273    }
274    fn decrement_from_chained(&mut self, other: &mut Vector, vector: &Vector) {
275        let split = self.0.size();
276        let tail_len = self.1.size();
277        let head: Vector = vector.iter().take(split).copied().collect();
278        let tail: Vector = vector.iter().skip(split).take(tail_len).copied().collect();
279        self.0.decrement_from(&head);
280        self.1.decrement_from(&tail);
281        other
282            .iter_mut()
283            .zip(vector.iter().skip(split + tail_len))
284            .for_each(|(entry_i, vector_i)| *entry_i -= vector_i)
285    }
286}
287
288impl<T1, T2> Sum for TensorTuple<T1, T2>
289where
290    T1: Tensor,
291    T2: Tensor,
292{
293    fn sum<Ii>(iter: Ii) -> Self
294    where
295        Ii: Iterator<Item = Self>,
296    {
297        iter.reduce(|mut acc, item| {
298            acc.0 += item.0;
299            acc.1 += item.1;
300            acc
301        })
302        .unwrap_or_else(Self::default)
303    }
304}
305
306impl<T1, T2> Div<TensorRank0> for TensorTuple<T1, T2>
307where
308    T1: Tensor,
309    T2: Tensor,
310{
311    type Output = Self;
312    fn div(mut self, tensor_rank_0: TensorRank0) -> Self::Output {
313        self /= tensor_rank_0;
314        self
315    }
316}
317
318impl<T1, T2> Div<&TensorRank0> for TensorTuple<T1, T2>
319where
320    T1: Tensor,
321    T2: Tensor,
322{
323    type Output = Self;
324    fn div(mut self, tensor_rank_0: &TensorRank0) -> Self::Output {
325        self /= tensor_rank_0;
326        self
327    }
328}
329
330impl<T1, T2> DivAssign<TensorRank0> for TensorTuple<T1, T2>
331where
332    T1: Tensor,
333    T2: Tensor,
334{
335    fn div_assign(&mut self, tensor_rank_0: TensorRank0) {
336        self.0 /= &tensor_rank_0;
337        self.1 /= tensor_rank_0;
338    }
339}
340
341impl<T1, T2> DivAssign<&TensorRank0> for TensorTuple<T1, T2>
342where
343    T1: Tensor,
344    T2: Tensor,
345{
346    fn div_assign(&mut self, tensor_rank_0: &TensorRank0) {
347        self.0 /= tensor_rank_0;
348        self.1 /= tensor_rank_0;
349    }
350}
351
352impl<T1, T2> Mul<TensorRank0> for TensorTuple<T1, T2>
353where
354    T1: Tensor,
355    T2: Tensor,
356{
357    type Output = Self;
358    fn mul(mut self, tensor_rank_0: TensorRank0) -> Self::Output {
359        self *= tensor_rank_0;
360        self
361    }
362}
363
364impl<T1, T2> Mul<&TensorRank0> for TensorTuple<T1, T2>
365where
366    T1: Tensor,
367    T2: Tensor,
368{
369    type Output = Self;
370    fn mul(mut self, tensor_rank_0: &TensorRank0) -> Self::Output {
371        self *= tensor_rank_0;
372        self
373    }
374}
375
376impl<T1, T2> Mul<TensorRank0> for &TensorTuple<T1, T2>
377where
378    T1: Tensor,
379    T2: Tensor,
380{
381    type Output = TensorTuple<T1, T2>;
382    fn mul(self, tensor_rank_0: TensorRank0) -> Self::Output {
383        //
384        // Cloning for now to avoid trait recursion nightmare.
385        //
386        TensorTuple(
387            self.0.clone() * tensor_rank_0,
388            self.1.clone() * tensor_rank_0,
389        )
390    }
391}
392
393impl<T1, T2> MulAssign<TensorRank0> for TensorTuple<T1, T2>
394where
395    T1: Tensor,
396    T2: Tensor,
397{
398    fn mul_assign(&mut self, tensor_rank_0: TensorRank0) {
399        self.0 *= &tensor_rank_0;
400        self.1 *= tensor_rank_0;
401    }
402}
403
404impl<T1, T2> MulAssign<&TensorRank0> for TensorTuple<T1, T2>
405where
406    T1: Tensor,
407    T2: Tensor,
408{
409    fn mul_assign(&mut self, tensor_rank_0: &TensorRank0) {
410        self.0 *= tensor_rank_0;
411        self.1 *= tensor_rank_0;
412    }
413}
414
415impl<T1, T2> Add for TensorTuple<T1, T2>
416where
417    T1: Tensor,
418    T2: Tensor,
419{
420    type Output = Self;
421    fn add(mut self, tensor_tuple: Self) -> Self::Output {
422        self += tensor_tuple;
423        self
424    }
425}
426
427impl<T1, T2> Add<&Self> for TensorTuple<T1, T2>
428where
429    T1: Tensor,
430    T2: Tensor,
431{
432    type Output = Self;
433    fn add(mut self, tensor_tuple: &Self) -> Self::Output {
434        self += tensor_tuple;
435        self
436    }
437}
438
439impl<T1, T2> AddAssign for TensorTuple<T1, T2>
440where
441    T1: Tensor,
442    T2: Tensor,
443{
444    fn add_assign(&mut self, tensor_tuple: Self) {
445        self.0 += tensor_tuple.0;
446        self.1 += tensor_tuple.1;
447    }
448}
449
450impl<T1, T2> AddAssign<&Self> for TensorTuple<T1, T2>
451where
452    T1: Tensor,
453    T2: Tensor,
454{
455    fn add_assign(&mut self, tensor_tuple: &Self) {
456        self.0 += &tensor_tuple.0;
457        self.1 += &tensor_tuple.1;
458    }
459}
460
461impl<T1, T2> Sub for TensorTuple<T1, T2>
462where
463    T1: Tensor,
464    T2: Tensor,
465{
466    type Output = Self;
467    fn sub(mut self, tensor_tuple: Self) -> Self::Output {
468        self -= tensor_tuple;
469        self
470    }
471}
472
473impl<T1, T2> Sub<&Self> for TensorTuple<T1, T2>
474where
475    T1: Tensor,
476    T2: Tensor,
477{
478    type Output = Self;
479    fn sub(mut self, tensor_tuple: &Self) -> Self::Output {
480        self -= tensor_tuple;
481        self
482    }
483}
484
485impl<T1, T2> Sub for &TensorTuple<T1, T2>
486where
487    T1: Tensor,
488    T2: Tensor,
489{
490    type Output = TensorTuple<T1, T2>;
491    fn sub(self, tensor_tuple: Self) -> Self::Output {
492        self.clone() - tensor_tuple
493    }
494}
495
496impl<T1, T2> SubAssign for TensorTuple<T1, T2>
497where
498    T1: Tensor,
499    T2: Tensor,
500{
501    fn sub_assign(&mut self, tensor_tuple: Self) {
502        self.0 -= tensor_tuple.0;
503        self.1 -= tensor_tuple.1;
504    }
505}
506
507impl<T1, T2> SubAssign<&Self> for TensorTuple<T1, T2>
508where
509    T1: Tensor,
510    T2: Tensor,
511{
512    fn sub_assign(&mut self, tensor_tuple: &Self) {
513        self.0 -= &tensor_tuple.0;
514        self.1 -= &tensor_tuple.1;
515    }
516}
517
518impl<T1, T2> Sub<Vector> for TensorTuple<T1, T2>
519where
520    T1: Tensor + Sub<Vector, Output = T1>,
521    T2: Tensor + Sub<Vector, Output = T2>,
522{
523    type Output = Self;
524    fn sub(mut self, vector: Vector) -> Self::Output {
525        let split = self.0.size();
526        self.0 = self.0 - vector.iter().take(split).copied().collect::<Vector>();
527        self.1 = self.1 - vector.iter().skip(split).copied().collect::<Vector>();
528        self
529    }
530}
531
532impl<T1, T2> Sub<&Vector> for TensorTuple<T1, T2>
533where
534    T1: Tensor + Sub<Vector, Output = T1>,
535    T2: Tensor + Sub<Vector, Output = T2>,
536{
537    type Output = Self;
538    fn sub(mut self, vector: &Vector) -> Self::Output {
539        let split = self.0.size();
540        self.0 = self.0 - vector.iter().take(split).copied().collect::<Vector>();
541        self.1 = self.1 - vector.iter().skip(split).copied().collect::<Vector>();
542        self
543    }
544}
545
546impl<T0, T1, T4, T5> Div<TensorTuple<T0, T1>> for &TensorTuple<T4, T5>
547where
548    T0: Tensor,
549    T1: Tensor,
550    T4: Tensor,
551    T5: Tensor,
552{
553    type Output = TensorTuple<T4, T5>;
554    fn div(self, _tensor_tuple: TensorTuple<T0, T1>) -> Self::Output {
555        unimplemented!()
556    }
557}
558
559impl<T1, T2, T> Differentiable<T> for TensorTuple<T1, T2>
560where
561    T1: Differentiable<T> + Tensor,
562    T2: Differentiable<T> + Tensor,
563    <T1 as Differentiable<T>>::Derivative: Tensor,
564    <T2 as Differentiable<T>>::Derivative: Tensor,
565{
566    type Derivative =
567        TensorTuple<<T1 as Differentiable<T>>::Derivative, <T2 as Differentiable<T>>::Derivative>;
568}