src/direct_product.rs

branch
dev
changeset 57
1b3b1687b9ed
child 59
9226980e45a7
equal deleted inserted replaced
56:5e3c1874797d 57:1b3b1687b9ed
1 /*!
2 Direct products of the form $A \times B$.
3
4 TODO: This could be easily much more generic if `derive_more` could derive arithmetic
5 operations on references.
6 */
7
8 use core::ops::{Mul,MulAssign,Div,DivAssign,Add,AddAssign,Sub,SubAssign,Neg};
9 use std::clone::Clone;
10 use serde::{Serialize, Deserialize};
11 use crate::types::{Num, Float};
12 use crate::{maybe_lifetime, maybe_ref, impl_vectorspace_ops};
13 use crate::euclidean::{Dot, Euclidean};
14
15 #[derive(Debug,Clone,PartialEq,Eq,Serialize,Deserialize)]
16 pub struct Pair<A, B> (pub A, pub B);
17
18 impl<A, B> Pair<A,B> {
19 pub fn new(a : A, b : B) -> Pair<A,B> { Pair{ 0 : a, 1 : b } }
20 }
21
22 impl<A, B> From<(A,B)> for Pair<A,B> {
23 #[inline]
24 fn from((a, b) : (A, B)) -> Pair<A,B> { Pair{ 0 : a, 1 : b } }
25 }
26
27 macro_rules! impl_binop {
28 ($trait : ident, $fn : ident, $refl:ident, $refr:ident) => {
29 impl_binop!(@doit: $trait, $fn;
30 maybe_lifetime!($refl, &'l Pair<A,B>),
31 (maybe_lifetime!($refl, &'l A), maybe_lifetime!($refl, &'l B));
32 maybe_lifetime!($refr, &'r Pair<Ai,Bi>),
33 (maybe_lifetime!($refr, &'r Ai), maybe_lifetime!($refr, &'r Bi));
34 $refl, $refr);
35 };
36
37 (@doit: $trait:ident, $fn:ident;
38 $self:ty, ($aself:ty, $bself:ty);
39 $in:ty, ($ain:ty, $bin:ty);
40 $refl:ident, $refr:ident) => {
41 impl<'l, 'r, A, B, Ai, Bi> $trait<$in>
42 for $self
43 where $aself: $trait<$ain>,
44 $bself: $trait<$bin> {
45 type Output = Pair<<$aself as $trait<$ain>>::Output,
46 <$bself as $trait<$bin>>::Output>;
47
48 #[inline]
49 fn $fn(self, y : $in) -> Self::Output {
50 Pair { 0 : maybe_ref!($refl, self.0).$fn(maybe_ref!($refr, y.0)),
51 1 : maybe_ref!($refl, self.1).$fn(maybe_ref!($refr, y.1)) }
52 }
53 }
54 };
55 }
56
57 macro_rules! impl_assignop {
58 ($trait : ident, $fn : ident, $refr:ident) => {
59 impl_assignop!(@doit: $trait, $fn;
60 maybe_lifetime!($refr, &'r Pair<Ai,Bi>),
61 (maybe_lifetime!($refr, &'r Ai), maybe_lifetime!($refr, &'r Bi));
62 $refr);
63 };
64 (@doit: $trait:ident, $fn:ident;
65 $in:ty, ($ain:ty, $bin:ty);
66 $refr:ident) => {
67 impl<'r, A, B, Ai, Bi> $trait<$in>
68 for Pair<A,B>
69 where A: $trait<$ain>,
70 B: $trait<$bin> {
71 #[inline]
72 fn $fn(&mut self, y : $in) -> () {
73 self.0.$fn(maybe_ref!($refr, y.0));
74 self.1.$fn(maybe_ref!($refr, y.1));
75 }
76 }
77 }
78 }
79
80 macro_rules! impl_scalarop {
81 ($trait : ident, $fn : ident, $refl:ident) => {
82 impl_scalarop!(@doit: $trait, $fn;
83 maybe_lifetime!($refl, &'l Pair<A,B>),
84 (maybe_lifetime!($refl, &'l A), maybe_lifetime!($refl, &'l B));
85 $refl);
86 };
87 (@doit: $trait:ident, $fn:ident;
88 $self:ty, ($aself:ty, $bself:ty);
89 $refl:ident) => {
90 // Scalar as Rhs
91 impl<'l, F : Num, A, B> $trait<F>
92 for $self
93 where $aself: $trait<F>,
94 $bself: $trait<F> {
95 type Output = Pair<<$aself as $trait<F>>::Output,
96 <$bself as $trait<F>>::Output>;
97 #[inline]
98 fn $fn(self, a : F) -> Self::Output {
99 Pair{ 0 : maybe_ref!($refl, self.0).$fn(a),
100 1 : maybe_ref!($refl, self.1).$fn(a)}
101 }
102 }
103 }
104 }
105
106 // Not used due to compiler overflow
107 #[allow(unused_macros)]
108 macro_rules! impl_scalarlhs_op {
109 ($trait:ident, $fn:ident, $refr:ident, $field:ty) => {
110 impl_scalarlhs_op!(@doit: $trait, $fn,
111 maybe_lifetime!($refr, &'r Pair<Ai,Bi>),
112 (maybe_lifetime!($refr, &'r Ai), maybe_lifetime!($refr, &'r Bi));
113 $refr, $field);
114 };
115 (@doit: $trait:ident, $fn:ident,
116 $in:ty, ($ain:ty, $bin:ty);
117 $refr:ident, $field:ty) => {
118 impl<'r, Ai, Bi> $trait<$in>
119 for $field
120 where $field : $trait<$ain>
121 + $trait<$bin> {
122 type Output = Pair<<$field as $trait<$ain>>::Output,
123 <$field as $trait<$bin>>::Output>;
124 #[inline]
125 fn $fn(self, x : $in) -> Self::Output {
126 Pair{ 0 : self.$fn(maybe_ref!($refr, x.0)),
127 1 : self.$fn(maybe_ref!($refr, x.1))}
128 }
129 }
130 };
131 }
132
133 macro_rules! impl_scalar_assignop {
134 ($trait : ident, $fn : ident) => {
135 impl<'r, F : Num, A, B> $trait<F>
136 for Pair<A,B>
137 where A: $trait<F>, B: $trait<F> {
138 #[inline]
139 fn $fn(&mut self, a : F) -> () {
140 self.0.$fn(a);
141 self.1.$fn(a);
142 }
143 }
144 }
145 }
146
147 macro_rules! impl_unaryop {
148 ($trait:ident, $fn:ident, $refl:ident) => {
149 impl_unaryop!(@doit: $trait, $fn;
150 maybe_lifetime!($refl, &'l Pair<A,B>),
151 (maybe_lifetime!($refl, &'l A), maybe_lifetime!($refl, &'l B));
152 $refl);
153 };
154 (@doit: $trait:ident, $fn:ident;
155 $self:ty, ($aself:ty, $bself:ty);
156 $refl : ident) => {
157 impl<'l, A, B> $trait
158 for $self
159 where $aself: $trait,
160 $bself: $trait {
161 type Output = Pair<<$aself as $trait>::Output,
162 <$bself as $trait>::Output>;
163 #[inline]
164 fn $fn(self) -> Self::Output {
165 Pair{ 0 : maybe_ref!($refl, self.0).$fn(),
166 1 : maybe_ref!($refl, self.1).$fn()}
167 }
168 }
169 }
170 }
171
172
173 impl_vectorspace_ops!(impl_binop, impl_assignop, impl_scalarop, impl_scalarlhs_op,
174 impl_scalar_assignop, impl_unaryop);
175
176
177 impl<A, B, U, V, F> Dot<Pair<U, V>, F> for Pair<A, B>
178 where
179 A : Dot<U, F>,
180 B : Dot<V, F>,
181 F : Num
182 {
183
184 fn dot(&self, Pair(ref u, ref v) : &Pair<U, V>) -> F {
185 self.0.dot(u) + self.1.dot(v)
186 }
187 }
188
189 impl<A, B, F> Euclidean<F> for Pair<A, B>
190 where
191 A : Euclidean<F>,
192 B : Euclidean<F>,
193 F : Float
194 {
195 type Output = Pair<<A as Euclidean<F>>::Output, <B as Euclidean<F>>::Output>;
196
197 fn similar_origin(&self) -> <Self as Euclidean<F>>::Output {
198 Pair(self.0.similar_origin(), self.1.similar_origin())
199 }
200
201 fn dist2_squared(&self, Pair(ref u, ref v) : &Self) -> F {
202 self.0.dist2_squared(u) + self.1.dist2_squared(v)
203 }
204 }
205
206 use crate::linops::AXPY;
207
208 impl<F, A, B, U, V> AXPY<F, Pair<U, V>> for Pair<A, B>
209 where
210 A : AXPY<F, U>,
211 B : AXPY<F, V>,
212 F : Num
213 {
214 fn axpy(&mut self, α : F, x : &Pair<U, V>, β : F) {
215 self.0.axpy(α, &x.0, β);
216 self.1.axpy(α, &x.1, β);
217 }
218
219 fn copy_from(&mut self, x : &Pair<U, V>,) {
220 self.0.copy_from(&x.0);
221 self.1.copy_from(&x.1);
222 }
223
224 fn scale_from(&mut self, α : F, x : &Pair<U, V>) {
225 self.0.scale_from(α, &x.0);
226 self.1.scale_from(α, &x.1);
227 }
228 }

mercurial