src/direct_product.rs

changeset 198
3868555d135c
parent 189
14193146d8f2
equal deleted inserted replaced
94:1f19c6bbf07b 198:3868555d135c
4 TODO: This could be easily much more generic if `derive_more` could derive arithmetic 4 TODO: This could be easily much more generic if `derive_more` could derive arithmetic
5 operations on references. 5 operations on references.
6 */ 6 */
7 7
8 use crate::euclidean::Euclidean; 8 use crate::euclidean::Euclidean;
9 use crate::instance::{Decomposition, DecompositionMut, Instance, InstanceMut, MyCow}; 9 use crate::instance::{Decomposition, DecompositionMut, Instance, InstanceMut, MyCow, Ownable};
10 use crate::linops::AXPY; 10 use crate::linops::{VectorSpace, AXPY};
11 use crate::loc::Loc; 11 use crate::loc::Loc;
12 use crate::mapping::Space; 12 use crate::mapping::Space;
13 use crate::norms::{HasDual, Norm, NormExponent, Normed, PairNorm, L2}; 13 use crate::norms::{Dist, HasDual, Norm, NormExponent, Normed, PairNorm, L2};
14 use crate::types::{Float, Num}; 14 use crate::types::{Float, Num};
15 use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; 15 use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
16 use serde::{Deserialize, Serialize}; 16 use serde::{Deserialize, Serialize};
17 use std::clone::Clone; 17 use std::clone::Clone;
18 18
37 fn from(Pair(a, b): Pair<A, B>) -> (A, B) { 37 fn from(Pair(a, b): Pair<A, B>) -> (A, B) {
38 (a, b) 38 (a, b)
39 } 39 }
40 } 40 }
41 41
42 macro_rules! impl_binop { 42 macro_rules! impl_unary {
43 (($a : ty, $b : ty), $trait : ident, $fn : ident, $refl:ident, $refr:ident) => { 43 ($trait:ident, $fn:ident) => {
44 impl_binop!(@doit: $a, $b, $trait, $fn; 44 impl<A, B> $trait for Pair<A, B>
45 maybe_lifetime!($refl, &'l Pair<$a,$b>), 45 where
46 (maybe_lifetime!($refl, &'l $a), 46 A: $trait,
47 maybe_lifetime!($refl, &'l $b)); 47 B: $trait,
48 maybe_lifetime!($refr, &'r Pair<Ai,Bi>), 48 {
49 (maybe_lifetime!($refr, &'r Ai), 49 type Output = Pair<A::Output, B::Output>;
50 maybe_lifetime!($refr, &'r Bi)); 50 fn $fn(self) -> Self::Output {
51 $refl, $refr); 51 let Pair(a, b) = self;
52 Pair(a.$fn(), b.$fn())
53 }
54 }
55
56 // Compiler overflow
57 // impl<'a, A, B> $trait for &'a Pair<A, B>
58 // where
59 // &'a A: $trait,
60 // &'a B: $trait,
61 // {
62 // type Output = Pair<<&'a A as $trait>::Output, <&'a B as $trait>::Output>;
63 // fn $fn(self) -> Self::Output {
64 // let Pair(ref a, ref b) = self;
65 // Pair(a.$fn(), b.$fn())
66 // }
67 // }
52 }; 68 };
53 69 }
54 (@doit: $a:ty, $b:ty, 70
55 $trait:ident, $fn:ident; 71 impl_unary!(Neg, neg);
56 $self:ty, ($aself:ty, $bself:ty); 72
57 $in:ty, ($ain:ty, $bin:ty); 73 macro_rules! impl_binary {
58 $refl:ident, $refr:ident) => { 74 ($trait:ident, $fn:ident) => {
59 impl<'l, 'r, Ai, Bi> $trait<$in> 75 impl<A, B, C, D> $trait<Pair<C, D>> for Pair<A, B>
60 for $self 76 where
61 where $aself: $trait<$ain>, 77 A: $trait<C>,
62 $bself: $trait<$bin> { 78 B: $trait<D>,
63 type Output = Pair<<$aself as $trait<$ain>>::Output, 79 {
64 <$bself as $trait<$bin>>::Output>; 80 type Output = Pair<A::Output, B::Output>;
65 81 fn $fn(self, Pair(c, d): Pair<C, D>) -> Self::Output {
66 #[inline] 82 let Pair(a, b) = self;
67 fn $fn(self, y : $in) -> Self::Output { 83 Pair(a.$fn(c), b.$fn(d))
68 Pair(maybe_ref!($refl, self.0).$fn(maybe_ref!($refr, y.0)), 84 }
69 maybe_ref!($refl, self.1).$fn(maybe_ref!($refr, y.1))) 85 }
86
87 impl<'a, A, B, C, D> $trait<Pair<C, D>> for &'a Pair<A, B>
88 where
89 &'a A: $trait<C>,
90 &'a B: $trait<D>,
91 {
92 type Output = Pair<<&'a A as $trait<C>>::Output, <&'a B as $trait<D>>::Output>;
93 fn $fn(self, Pair(c, d): Pair<C, D>) -> Self::Output {
94 let Pair(ref a, ref b) = self;
95 Pair(a.$fn(c), b.$fn(d))
96 }
97 }
98
99 impl<'a, 'b, A, B, C, D> $trait<&'b Pair<C, D>> for &'a Pair<A, B>
100 where
101 &'a A: $trait<&'b C>,
102 &'a B: $trait<&'b D>,
103 {
104 type Output = Pair<<&'a A as $trait<&'b C>>::Output, <&'a B as $trait<&'b D>>::Output>;
105 fn $fn(self, Pair(ref c, ref d): &'b Pair<C, D>) -> Self::Output {
106 let Pair(ref a, ref b) = self;
107 Pair(a.$fn(c), b.$fn(d))
108 }
109 }
110
111 impl<'b, A, B, C, D> $trait<&'b Pair<C, D>> for Pair<A, B>
112 where
113 A: $trait<&'b C>,
114 B: $trait<&'b D>,
115 {
116 type Output = Pair<<A as $trait<&'b C>>::Output, <B as $trait<&'b D>>::Output>;
117 fn $fn(self, Pair(ref c, ref d): &'b Pair<C, D>) -> Self::Output {
118 let Pair(a, b) = self;
119 Pair(a.$fn(c), b.$fn(d))
70 } 120 }
71 } 121 }
72 }; 122 };
73 } 123 }
74 124
75 macro_rules! impl_assignop { 125 impl_binary!(Add, add);
76 (($a : ty, $b : ty), $trait : ident, $fn : ident, $refr:ident) => { 126 impl_binary!(Sub, sub);
77 impl_assignop!(@doit: $a, $b, 127
78 $trait, $fn; 128 macro_rules! impl_scalar {
79 maybe_lifetime!($refr, &'r Pair<Ai,Bi>), 129 ($trait:ident, $fn:ident) => {
80 (maybe_lifetime!($refr, &'r Ai), 130 impl<A, B, F: Num> $trait<F> for Pair<A, B>
81 maybe_lifetime!($refr, &'r Bi)); 131 where
82 $refr); 132 A: $trait<F>,
133 B: $trait<F>,
134 {
135 type Output = Pair<A::Output, B::Output>;
136 fn $fn(self, t: F) -> Self::Output {
137 let Pair(a, b) = self;
138 Pair(a.$fn(t), b.$fn(t))
139 }
140 }
141
142 impl<'a, A, B, F: Num> $trait<F> for &'a Pair<A, B>
143 where
144 &'a A: $trait<F>,
145 &'a B: $trait<F>,
146 {
147 type Output = Pair<<&'a A as $trait<F>>::Output, <&'a B as $trait<F>>::Output>;
148 fn $fn(self, t: F) -> Self::Output {
149 let Pair(ref a, ref b) = self;
150 Pair(a.$fn(t), b.$fn(t))
151 }
152 }
153
154 // impl<'a, 'b, A, B> $trait<&'b $F> for &'a Pair<A, B>
155 // where
156 // &'a A: $trait<&'b $F>,
157 // &'a B: $trait<&'b $F>,
158 // {
159 // type Output =
160 // Pair<<&'a A as $trait<&'b $F>>::Output, <&'a B as $trait<&'b $F>>::Output>;
161 // fn $fn(self, t: &'b $F) -> Self::Output {
162 // let Pair(ref a, ref b) = self;
163 // Pair(a.$fn(t), b.$fn(t))
164 // }
165 // }
166
167 // impl<'b, A, B> $trait<&'b $F> for Pair<A, B>
168 // where
169 // A: $trait<&'b $F>,
170 // B: $trait<&'b $F>,
171 // {
172 // type Output = Pair<<A as $trait<&'b $F>>::Output, <B as $trait<&'b $F>>::Output>;
173 // fn $fn(self, t: &'b $F) -> Self::Output {
174 // let Pair(a, b) = self;
175 // Pair(a.$fn(t), b.$fn(t))
176 // }
177 // }
83 }; 178 };
84 (@doit: $a : ty, $b : ty, 179 }
85 $trait:ident, $fn:ident; 180
86 $in:ty, ($ain:ty, $bin:ty); 181 impl_scalar!(Mul, mul);
87 $refr:ident) => { 182 impl_scalar!(Div, div);
88 impl<'r, Ai, Bi> $trait<$in> 183
89 for Pair<$a,$b> 184 macro_rules! impl_scalar_lhs {
90 where $a: $trait<$ain>, 185 ($trait:ident, $fn:ident, $F:ty) => {
91 $b: $trait<$bin> { 186 impl<A, B> $trait<Pair<A, B>> for $F
92 #[inline] 187 where
93 fn $fn(&mut self, y : $in) -> () { 188 $F: $trait<A> + $trait<B>,
94 self.0.$fn(maybe_ref!($refr, y.0)); 189 {
95 self.1.$fn(maybe_ref!($refr, y.1)); 190 type Output = Pair<<$F as $trait<A>>::Output, <$F as $trait<B>>::Output>;
96 } 191 fn $fn(self, Pair(a, b): Pair<A, B>) -> Self::Output {
97 } 192 Pair(self.$fn(a), self.$fn(b))
98 } 193 }
99 } 194 }
100 195
101 macro_rules! impl_scalarop { 196 // Compiler overflow:
102 (($a : ty, $b : ty), $field : ty, $trait : ident, $fn : ident, $refl:ident) => { 197 //
103 impl_scalarop!(@doit: $field, 198 // impl<'a, A, B> $trait<&'a Pair<A, B>> for $F
104 $trait, $fn; 199 // where
105 maybe_lifetime!($refl, &'l Pair<$a,$b>), 200 // $F: $trait<&'a A> + $trait<&'a B>,
106 (maybe_lifetime!($refl, &'l $a), 201 // {
107 maybe_lifetime!($refl, &'l $b)); 202 // type Output = Pair<<$F as $trait<&'a A>>::Output, <$F as $trait<&'a B>>::Output>;
108 $refl); 203 // fn $fn(self, Pair(a, b): &'a Pair<A, B>) -> Self::Output {
204 // Pair(self.$fn(a), self.$fn(b))
205 // }
206 // }
109 }; 207 };
110 (@doit: $field : ty, 208 }
111 $trait:ident, $fn:ident; 209
112 $self:ty, ($aself:ty, $bself:ty); 210 impl_scalar_lhs!(Mul, mul, f32);
113 $refl:ident) => { 211 impl_scalar_lhs!(Mul, mul, f64);
114 // Scalar as Rhs 212 impl_scalar_lhs!(Div, div, f32);
115 impl<'l> $trait<$field> 213 impl_scalar_lhs!(Div, div, f64);
116 for $self 214
117 where $aself: $trait<$field>, 215 macro_rules! impl_binary_mut {
118 $bself: $trait<$field> { 216 ($trait:ident, $fn:ident) => {
119 type Output = Pair<<$aself as $trait<$field>>::Output, 217 impl<'a, A, B, C, D> $trait<Pair<C, D>> for Pair<A, B>
120 <$bself as $trait<$field>>::Output>; 218 where
121 #[inline] 219 A: $trait<C>,
122 fn $fn(self, a : $field) -> Self::Output { 220 B: $trait<D>,
123 Pair(maybe_ref!($refl, self.0).$fn(a), 221 {
124 maybe_ref!($refl, self.1).$fn(a)) 222 fn $fn(&mut self, Pair(c, d): Pair<C, D>) {
125 } 223 let Pair(ref mut a, ref mut b) = self;
126 } 224 a.$fn(c);
127 } 225 b.$fn(d);
128 } 226 }
129 227 }
130 // Not used due to compiler overflow 228
131 #[allow(unused_macros)] 229 impl<'a, 'b, A, B, C, D> $trait<&'b Pair<C, D>> for Pair<A, B>
132 macro_rules! impl_scalarlhs_op { 230 where
133 (($a : ty, $b : ty), $field : ty, $trait:ident, $fn:ident, $refr:ident) => { 231 A: $trait<&'b C>,
134 impl_scalarlhs_op!(@doit: $trait, $fn, 232 B: $trait<&'b D>,
135 maybe_lifetime!($refr, &'r Pair<$a,$b>), 233 {
136 (maybe_lifetime!($refr, &'r $a), 234 fn $fn(&mut self, Pair(ref c, ref d): &'b Pair<C, D>) {
137 maybe_lifetime!($refr, &'r $b)); 235 let Pair(ref mut a, ref mut b) = self;
138 $refr, $field); 236 a.$fn(c);
237 b.$fn(d);
238 }
239 }
139 }; 240 };
140 (@doit: $trait:ident, $fn:ident, 241 }
141 $in:ty, ($ain:ty, $bin:ty); 242
142 $refr:ident, $field:ty) => { 243 impl_binary_mut!(AddAssign, add_assign);
143 impl<'r> $trait<$in> 244 impl_binary_mut!(SubAssign, sub_assign);
144 for $field 245
145 where $field : $trait<$ain> 246 macro_rules! impl_scalar_mut {
146 + $trait<$bin> { 247 ($trait:ident, $fn:ident) => {
147 type Output = Pair<<$field as $trait<$ain>>::Output, 248 impl<'a, A, B, F: Num> $trait<F> for Pair<A, B>
148 <$field as $trait<$bin>>::Output>; 249 where
149 #[inline] 250 A: $trait<F>,
150 fn $fn(self, x : $in) -> Self::Output { 251 B: $trait<F>,
151 Pair(self.$fn(maybe_ref!($refr, x.0)), 252 {
152 self.$fn(maybe_ref!($refr, x.1))) 253 fn $fn(&mut self, t: F) {
254 let Pair(ref mut a, ref mut b) = self;
255 a.$fn(t);
256 b.$fn(t);
153 } 257 }
154 } 258 }
155 }; 259 };
156 } 260 }
157 261
158 macro_rules! impl_scalar_assignop { 262 impl_scalar_mut!(MulAssign, mul_assign);
159 (($a : ty, $b : ty), $field : ty, $trait : ident, $fn : ident) => { 263 impl_scalar_mut!(DivAssign, div_assign);
160 impl<'r> $trait<$field> for Pair<$a, $b> 264
161 where 265 /// Trait for ownable-by-consumption objects
162 $a: $trait<$field>, 266 impl<A, B> Ownable for Pair<A, B>
163 $b: $trait<$field>, 267 where
164 { 268 A: Ownable,
165 #[inline] 269 B: Ownable,
166 fn $fn(&mut self, a: $field) -> () { 270 {
167 self.0.$fn(a); 271 type OwnedVariant = Pair<A::OwnedVariant, B::OwnedVariant>;
168 self.1.$fn(a); 272
169 } 273 #[inline]
170 } 274 fn into_owned(self) -> Self::OwnedVariant {
171 }; 275 Pair(self.0.into_owned(), self.1.into_owned())
172 } 276 }
173 277
174 macro_rules! impl_unaryop { 278 #[inline]
175 (($a : ty, $b : ty), $trait:ident, $fn:ident, $refl:ident) => { 279 fn clone_owned(&self) -> Self::OwnedVariant {
176 impl_unaryop!(@doit: $trait, $fn; 280 Pair(self.0.clone_owned(), self.1.clone_owned())
177 maybe_lifetime!($refl, &'l Pair<$a,$b>), 281 }
178 (maybe_lifetime!($refl, &'l $a), 282
179 maybe_lifetime!($refl, &'l $b)); 283 #[inline]
180 $refl); 284 fn cow_owned<'b>(self) -> MyCow<'b, Self::OwnedVariant>
181 }; 285 where
182 (@doit: $trait:ident, $fn:ident; 286 Self: 'b,
183 $self:ty, ($aself:ty, $bself:ty); 287 {
184 $refl : ident) => { 288 MyCow::Owned(self.into_owned())
185 impl<'l> $trait 289 }
186 for $self 290
187 where $aself: $trait, 291 #[inline]
188 $bself: $trait { 292 fn ref_cow_owned<'b>(&'b self) -> MyCow<'b, Self::OwnedVariant>
189 type Output = Pair<<$aself as $trait>::Output, 293 where
190 <$bself as $trait>::Output>; 294 Self: 'b,
191 #[inline] 295 {
192 fn $fn(self) -> Self::Output { 296 MyCow::Owned(self.clone_owned())
193 Pair(maybe_ref!($refl, self.0).$fn(), 297 }
194 maybe_ref!($refl, self.1).$fn()) 298 }
195 } 299
196 } 300 /// We only support 'closed' `Euclidean` `Pair`s, as more general ones cause
197 } 301 /// compiler overflows.
198 } 302 impl<A, B, F: Float> Euclidean<F> for Pair<A, B>
199
200 #[macro_export]
201 macro_rules! impl_pair_vectorspace_ops {
202 (($a:ty, $b:ty), $field:ty) => {
203 impl_pair_vectorspace_ops!(@binary, ($a, $b), Add, add);
204 impl_pair_vectorspace_ops!(@binary, ($a, $b), Sub, sub);
205 impl_pair_vectorspace_ops!(@assign, ($a, $b), AddAssign, add_assign);
206 impl_pair_vectorspace_ops!(@assign, ($a, $b), SubAssign, sub_assign);
207 impl_pair_vectorspace_ops!(@scalar, ($a, $b), $field, Mul, mul);
208 impl_pair_vectorspace_ops!(@scalar, ($a, $b), $field, Div, div);
209 // Compiler overflow
210 // $(
211 // impl_pair_vectorspace_ops!(@scalar_lhs, ($a, $b), $field, $impl_scalarlhs_op, Mul, mul);
212 // )*
213 impl_pair_vectorspace_ops!(@scalar_assign, ($a, $b), $field, MulAssign, mul_assign);
214 impl_pair_vectorspace_ops!(@scalar_assign, ($a, $b), $field, DivAssign, div_assign);
215 impl_pair_vectorspace_ops!(@unary, ($a, $b), Neg, neg);
216 };
217 (@binary, ($a : ty, $b : ty), $trait : ident, $fn : ident) => {
218 impl_binop!(($a, $b), $trait, $fn, ref, ref);
219 impl_binop!(($a, $b), $trait, $fn, ref, noref);
220 impl_binop!(($a, $b), $trait, $fn, noref, ref);
221 impl_binop!(($a, $b), $trait, $fn, noref, noref);
222 };
223 (@assign, ($a : ty, $b : ty), $trait : ident, $fn :ident) => {
224 impl_assignop!(($a, $b), $trait, $fn, ref);
225 impl_assignop!(($a, $b), $trait, $fn, noref);
226 };
227 (@scalar, ($a : ty, $b : ty), $field : ty, $trait : ident, $fn :ident) => {
228 impl_scalarop!(($a, $b), $field, $trait, $fn, ref);
229 impl_scalarop!(($a, $b), $field, $trait, $fn, noref);
230 };
231 (@scalar_lhs, ($a : ty, $b : ty), $field : ty, $trait : ident, $fn : ident) => {
232 impl_scalarlhs_op!(($a, $b), $field, $trait, $fn, ref);
233 impl_scalarlhs_op!(($a, $b), $field, $trait, $fn, noref);
234 };
235 (@scalar_assign, ($a : ty, $b : ty), $field : ty, $trait : ident, $fn : ident) => {
236 impl_scalar_assignop!(($a, $b), $field, $trait, $fn);
237 };
238 (@unary, ($a : ty, $b : ty), $trait : ident, $fn : ident) => {
239 impl_unaryop!(($a, $b), $trait, $fn, ref);
240 impl_unaryop!(($a, $b), $trait, $fn, noref);
241 };
242 }
243
244 impl_pair_vectorspace_ops!((f32, f32), f32);
245 impl_pair_vectorspace_ops!((f64, f64), f64);
246
247 type PairOutput<F, A, B> = Pair<<A as Euclidean<F>>::Output, <B as Euclidean<F>>::Output>;
248
249 impl<A, B, F> Euclidean<F> for Pair<A, B>
250 where 303 where
251 A: Euclidean<F>, 304 A: Euclidean<F>,
252 B: Euclidean<F>, 305 B: Euclidean<F>,
253 F: Float, 306 // //Pair<A, B>: Euclidean<F>,
254 PairOutput<F, A, B>: Euclidean<F>, 307 // Self: Sized
255 Self: Sized 308 // + Mul<F, Output = Self::OwnedEuclidean>
256 + Mul<F, Output = PairOutput<F, A, B>> 309 // + MulAssign<F>
257 + MulAssign<F> 310 // + Div<F, Output = Self::OwnedEuclidean>
258 + Div<F, Output = PairOutput<F, A, B>> 311 // + DivAssign<F>
259 + DivAssign<F> 312 // + Add<Self, Output = Self::OwnedEuclidean>
260 + Add<Self, Output = PairOutput<F, A, B>> 313 // + Sub<Self, Output = Self::OwnedEuclidean>
261 + Sub<Self, Output = PairOutput<F, A, B>> 314 // + for<'b> Add<&'b Self, Output = Self::OwnedEuclidean>
262 + for<'b> Add<&'b Self, Output = PairOutput<F, A, B>> 315 // + for<'b> Sub<&'b Self, Output = Self::OwnedEuclidean>
263 + for<'b> Sub<&'b Self, Output = PairOutput<F, A, B>> 316 // + AddAssign<Self>
264 + AddAssign<Self> 317 // + for<'b> AddAssign<&'b Self>
265 + for<'b> AddAssign<&'b Self> 318 // + SubAssign<Self>
266 + SubAssign<Self> 319 // + for<'b> SubAssign<&'b Self>
267 + for<'b> SubAssign<&'b Self> 320 // + Neg<Output = Self::OwnedEuclidean>,
268 + Neg<Output = PairOutput<F, A, B>>, 321 {
269 { 322 type PrincipalE = Pair<A::PrincipalE, B::PrincipalE>;
270 type Output = PairOutput<F, A, B>;
271 323
272 fn dot<I: Instance<Self>>(&self, other: I) -> F { 324 fn dot<I: Instance<Self>>(&self, other: I) -> F {
273 let Pair(u, v) = other.decompose(); 325 other.eval_decompose(|Pair(u, v)| self.0.dot(u) + self.1.dot(v))
274 self.0.dot(u) + self.1.dot(v)
275 } 326 }
276 327
277 fn norm2_squared(&self) -> F { 328 fn norm2_squared(&self) -> F {
278 self.0.norm2_squared() + self.1.norm2_squared() 329 self.0.norm2_squared() + self.1.norm2_squared()
279 } 330 }
280 331
281 fn dist2_squared<I: Instance<Self>>(&self, other: I) -> F { 332 fn dist2_squared<I: Instance<Self>>(&self, other: I) -> F {
282 let Pair(u, v) = other.decompose(); 333 other.eval_decompose(|Pair(u, v)| self.0.dist2_squared(u) + self.1.dist2_squared(v))
283 self.0.dist2_squared(u) + self.1.dist2_squared(v) 334 }
284 } 335 }
285 } 336
286 337 impl<F, A, B> VectorSpace for Pair<A, B>
287 impl<F, A, B, U, V> AXPY<F, Pair<U, V>> for Pair<A, B> 338 where
339 A: VectorSpace<Field = F>,
340 B: VectorSpace<Field = F>,
341 F: Num,
342 {
343 type Field = F;
344 type PrincipalV = Pair<A::PrincipalV, B::PrincipalV>;
345
346 /// Return a similar zero as `self`.
347 fn similar_origin(&self) -> Self::PrincipalV {
348 Pair(self.0.similar_origin(), self.1.similar_origin())
349 }
350
351 // #[inline]
352 // fn into_owned(self) -> Self::Owned {
353 // Pair(self.0.into_owned(), self.1.into_owned())
354 // }
355 }
356
357 impl<F, A, B, U, V> AXPY<Pair<U, V>> for Pair<A, B>
288 where 358 where
289 U: Space, 359 U: Space,
290 V: Space, 360 V: Space,
291 A: AXPY<F, U>, 361 A: AXPY<U, Field = F>,
292 B: AXPY<F, V>, 362 B: AXPY<V, Field = F>,
293 F: Num, 363 F: Num,
294 Self: MulAssign<F>, 364 // Self: MulAssign<F> + DivAssign<F>,
295 Pair<A, B>: MulAssign<F>, 365 // Pair<A, B>: MulAssign<F> + DivAssign<F>,
296 Pair<A::Owned, B::Owned>: AXPY<F, Pair<U, V>>, 366 {
297 {
298 type Owned = Pair<A::Owned, B::Owned>;
299
300 fn axpy<I: Instance<Pair<U, V>>>(&mut self, α: F, x: I, β: F) { 367 fn axpy<I: Instance<Pair<U, V>>>(&mut self, α: F, x: I, β: F) {
301 let Pair(u, v) = x.decompose(); 368 x.eval_decompose(|Pair(u, v)| {
302 self.0.axpy(α, u, β); 369 self.0.axpy(α, u, β);
303 self.1.axpy(α, v, β); 370 self.1.axpy(α, v, β);
371 })
304 } 372 }
305 373
306 fn copy_from<I: Instance<Pair<U, V>>>(&mut self, x: I) { 374 fn copy_from<I: Instance<Pair<U, V>>>(&mut self, x: I) {
307 let Pair(u, v) = x.decompose(); 375 x.eval_decompose(|Pair(u, v)| {
308 self.0.copy_from(u); 376 self.0.copy_from(u);
309 self.1.copy_from(v); 377 self.1.copy_from(v);
378 })
310 } 379 }
311 380
312 fn scale_from<I: Instance<Pair<U, V>>>(&mut self, α: F, x: I) { 381 fn scale_from<I: Instance<Pair<U, V>>>(&mut self, α: F, x: I) {
313 let Pair(u, v) = x.decompose(); 382 x.eval_decompose(|Pair(u, v)| {
314 self.0.scale_from(α, u); 383 self.0.scale_from(α, u);
315 self.1.scale_from(α, v); 384 self.1.scale_from(α, v);
316 } 385 })
317
318 /// Return a similar zero as `self`.
319 fn similar_origin(&self) -> Self::Owned {
320 Pair(self.0.similar_origin(), self.1.similar_origin())
321 } 386 }
322 387
323 /// Set self to zero. 388 /// Set self to zero.
324 fn set_zero(&mut self) { 389 fn set_zero(&mut self) {
325 self.0.set_zero(); 390 self.0.set_zero();
330 /// [`Decomposition`] for working with [`Pair`]s. 395 /// [`Decomposition`] for working with [`Pair`]s.
331 #[derive(Copy, Clone, Debug)] 396 #[derive(Copy, Clone, Debug)]
332 pub struct PairDecomposition<D, Q>(D, Q); 397 pub struct PairDecomposition<D, Q>(D, Q);
333 398
334 impl<A: Space, B: Space> Space for Pair<A, B> { 399 impl<A: Space, B: Space> Space for Pair<A, B> {
400 type Principal = Pair<A::Principal, B::Principal>;
335 type Decomp = PairDecomposition<A::Decomp, B::Decomp>; 401 type Decomp = PairDecomposition<A::Decomp, B::Decomp>;
336 } 402 }
337 403
338 impl<A, B, D, Q> Decomposition<Pair<A, B>> for PairDecomposition<D, Q> 404 impl<A, B, D, Q> Decomposition<Pair<A, B>> for PairDecomposition<D, Q>
339 where 405 where
365 Q: Decomposition<B>, 431 Q: Decomposition<B>,
366 U: Instance<A, D>, 432 U: Instance<A, D>,
367 V: Instance<B, Q>, 433 V: Instance<B, Q>,
368 { 434 {
369 #[inline] 435 #[inline]
370 fn decompose<'b>( 436 fn eval_ref<'b, R>(&'b self, f: impl FnOnce(Pair<D::Reference<'b>, Q::Reference<'b>>) -> R) -> R
371 self, 437 where
372 ) -> <PairDecomposition<D, Q> as Decomposition<Pair<A, B>>>::Decomposition<'b> 438 Pair<A, B>: 'b,
373 where
374 Self: 'b, 439 Self: 'b,
375 Pair<A, B>: 'b, 440 {
441 self.0.eval_ref(|a| self.1.eval_ref(|b| f(Pair(a, b))))
442 }
443
444 #[inline]
445 fn cow<'b>(self) -> MyCow<'b, Pair<A::Principal, B::Principal>>
446 where
447 Self: 'b,
448 {
449 MyCow::Owned(Pair(self.0.own(), self.1.own()))
450 }
451
452 #[inline]
453 fn own(self) -> Pair<A::Principal, B::Principal> {
454 Pair(self.0.own(), self.1.own())
455 }
456
457 #[inline]
458 fn decompose<'b>(self) -> Pair<D::Decomposition<'b>, Q::Decomposition<'b>>
459 where
460 Self: 'b,
376 { 461 {
377 Pair(self.0.decompose(), self.1.decompose()) 462 Pair(self.0.decompose(), self.1.decompose())
378 }
379
380 #[inline]
381 fn ref_instance(
382 &self,
383 ) -> <PairDecomposition<D, Q> as Decomposition<Pair<A, B>>>::Reference<'_> {
384 Pair(self.0.ref_instance(), self.1.ref_instance())
385 }
386
387 #[inline]
388 fn cow<'b>(self) -> MyCow<'b, Pair<A, B>>
389 where
390 Self: 'b,
391 {
392 MyCow::Owned(Pair(self.0.own(), self.1.own()))
393 }
394
395 #[inline]
396 fn own(self) -> Pair<A, B> {
397 Pair(self.0.own(), self.1.own())
398 } 463 }
399 } 464 }
400 465
401 impl<'a, A, B, U, V, D, Q> Instance<Pair<A, B>, PairDecomposition<D, Q>> for &'a Pair<U, V> 466 impl<'a, A, B, U, V, D, Q> Instance<Pair<A, B>, PairDecomposition<D, Q>> for &'a Pair<U, V>
402 where 467 where
407 U: Instance<A, D>, 472 U: Instance<A, D>,
408 V: Instance<B, Q>, 473 V: Instance<B, Q>,
409 &'a U: Instance<A, D>, 474 &'a U: Instance<A, D>,
410 &'a V: Instance<B, Q>, 475 &'a V: Instance<B, Q>,
411 { 476 {
412 #[inline] 477 fn eval_ref<'b, R>(&'b self, f: impl FnOnce(Pair<D::Reference<'b>, Q::Reference<'b>>) -> R) -> R
413 fn decompose<'b>( 478 where
414 self, 479 Pair<A, B>: 'b,
415 ) -> <PairDecomposition<D, Q> as Decomposition<Pair<A, B>>>::Decomposition<'b>
416 where
417 Self: 'b, 480 Self: 'b,
418 Pair<A, B>: 'b, 481 {
419 { 482 self.0.eval_ref(|a| self.1.eval_ref(|b| f(Pair(a, b))))
420 Pair( 483 }
421 D::lift(self.0.ref_instance()), 484
422 Q::lift(self.1.ref_instance()), 485 #[inline]
423 ) 486 fn cow<'b>(self) -> MyCow<'b, Pair<A::Principal, B::Principal>>
424 }
425
426 #[inline]
427 fn ref_instance(
428 &self,
429 ) -> <PairDecomposition<D, Q> as Decomposition<Pair<A, B>>>::Reference<'_> {
430 Pair(self.0.ref_instance(), self.1.ref_instance())
431 }
432
433 #[inline]
434 fn cow<'b>(self) -> MyCow<'b, Pair<A, B>>
435 where 487 where
436 Self: 'b, 488 Self: 'b,
437 { 489 {
438 MyCow::Owned(self.own()) 490 MyCow::Owned(self.own())
439 } 491 }
440 492
441 #[inline] 493 #[inline]
442 fn own(self) -> Pair<A, B> { 494 fn own(self) -> Pair<A::Principal, B::Principal> {
443 let Pair(ref u, ref v) = self; 495 let Pair(ref u, ref v) = self;
444 Pair(u.own(), v.own()) 496 Pair(u.own(), v.own())
497 }
498
499 #[inline]
500 fn decompose<'b>(self) -> Pair<D::Decomposition<'b>, Q::Decomposition<'b>>
501 where
502 Self: 'b,
503 {
504 let Pair(u, v) = self;
505 Pair(u.decompose(), v.decompose())
445 } 506 }
446 } 507 }
447 508
448 impl<A, B, D, Q> DecompositionMut<Pair<A, B>> for PairDecomposition<D, Q> 509 impl<A, B, D, Q> DecompositionMut<Pair<A, B>> for PairDecomposition<D, Q>
449 where 510 where
490 ) -> <PairDecomposition<D, Q> as DecompositionMut<Pair<A, B>>>::ReferenceMut<'_> { 551 ) -> <PairDecomposition<D, Q> as DecompositionMut<Pair<A, B>>>::ReferenceMut<'_> {
491 Pair(self.0.ref_instance_mut(), self.1.ref_instance_mut()) 552 Pair(self.0.ref_instance_mut(), self.1.ref_instance_mut())
492 } 553 }
493 } 554 }
494 555
495 impl<F, A, B, ExpA, ExpB, ExpJ> Norm<F, PairNorm<ExpA, ExpB, ExpJ>> for Pair<A, B> 556 impl<F, A, B, ExpA, ExpB, ExpJ> Norm<PairNorm<ExpA, ExpB, ExpJ>, F> for Pair<A, B>
496 where 557 where
497 F: Num, 558 F: Num,
498 ExpA: NormExponent, 559 ExpA: NormExponent,
499 ExpB: NormExponent, 560 ExpB: NormExponent,
500 ExpJ: NormExponent, 561 ExpJ: NormExponent,
501 A: Norm<F, ExpA>, 562 A: Norm<ExpA, F>,
502 B: Norm<F, ExpB>, 563 B: Norm<ExpB, F>,
503 Loc<F, 2>: Norm<F, ExpJ>, 564 Loc<2, F>: Norm<ExpJ, F>,
504 { 565 {
505 fn norm(&self, PairNorm(expa, expb, expj): PairNorm<ExpA, ExpB, ExpJ>) -> F { 566 fn norm(&self, PairNorm(expa, expb, expj): PairNorm<ExpA, ExpB, ExpJ>) -> F {
506 Loc([self.0.norm(expa), self.1.norm(expb)]).norm(expj) 567 Loc([self.0.norm(expa), self.1.norm(expb)]).norm(expj)
507 } 568 }
508 } 569 }
509 570
571 impl<F, A, B, ExpA, ExpB, ExpJ> Dist<PairNorm<ExpA, ExpB, ExpJ>, F> for Pair<A, B>
572 where
573 F: Num,
574 ExpA: NormExponent,
575 ExpB: NormExponent,
576 ExpJ: NormExponent,
577 A: Dist<ExpA, F>,
578 B: Dist<ExpB, F>,
579 Loc<2, F>: Norm<ExpJ, F>,
580 {
581 fn dist<I: Instance<Self>>(
582 &self,
583 x: I,
584 PairNorm(expa, expb, expj): PairNorm<ExpA, ExpB, ExpJ>,
585 ) -> F {
586 x.eval_decompose(|Pair(x1, x2)| {
587 Loc([self.0.dist(x1, expa), self.1.dist(x2, expb)]).norm(expj)
588 })
589 }
590 }
591
592 impl<F, A, B> Norm<L2, F> for Pair<A, B>
593 where
594 F: Num,
595 A: Norm<L2, F>,
596 B: Norm<L2, F>,
597 Loc<2, F>: Norm<L2, F>,
598 {
599 fn norm(&self, _: L2) -> F {
600 Loc([self.0.norm(L2), self.1.norm(L2)]).norm(L2)
601 }
602 }
603
604 impl<F, A, B> Dist<L2, F> for Pair<A, B>
605 where
606 F: Num,
607 A: Dist<L2, F>,
608 B: Dist<L2, F>,
609 Loc<2, F>: Norm<L2, F>,
610 {
611 fn dist<I: Instance<Self>>(&self, x: I, _: L2) -> F {
612 x.eval_decompose(|Pair(x1, x2)| Loc([self.0.dist(x1, L2), self.1.dist(x2, L2)]).norm(L2))
613 }
614 }
615
510 impl<F: Float, A, B> Normed<F> for Pair<A, B> 616 impl<F: Float, A, B> Normed<F> for Pair<A, B>
511 where 617 where
512 A: Normed<F>, 618 A: Normed<F>,
513 B: Normed<F>, 619 B: Normed<F>,
514 { 620 {
529 where 635 where
530 A: HasDual<F>, 636 A: HasDual<F>,
531 B: HasDual<F>, 637 B: HasDual<F>,
532 { 638 {
533 type DualSpace = Pair<A::DualSpace, B::DualSpace>; 639 type DualSpace = Pair<A::DualSpace, B::DualSpace>;
534 } 640
641 fn dual_origin(&self) -> <Self::DualSpace as VectorSpace>::PrincipalV {
642 Pair(self.0.dual_origin(), self.1.dual_origin())
643 }
644 }
645
646 #[cfg(feature = "pyo3")]
647 mod python {
648 use super::Pair;
649 use pyo3::conversion::FromPyObject;
650 use pyo3::types::{PyAny, PyTuple};
651 use pyo3::{Borrowed, Bound, IntoPyObject, PyErr, Python};
652
653 impl<'py, A, B> IntoPyObject<'py> for Pair<A, B>
654 where
655 A: IntoPyObject<'py>,
656 B: IntoPyObject<'py>,
657 {
658 type Target = PyTuple;
659 type Error = PyErr;
660 type Output = Bound<'py, Self::Target>;
661
662 fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
663 (self.0, self.1).into_pyobject(py)
664 }
665 }
666
667 /*
668 impl<'a, 'py, A, B> IntoPyObject<'py> for &'a mut Pair<A, B>
669 where
670 &'a mut A: IntoPyObject<'py>,
671 &'a mut B: IntoPyObject<'py>,
672 {
673 type Target = PyTuple;
674 type Error = PyErr;
675 type Output = Bound<'py, Self::Target>;
676
677 fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
678 (&mut self.0, &mut self.1).into_pyobject(py)
679 }
680 }
681
682 impl<'a, 'py, A, B> IntoPyObject<'py> for &'a Pair<A, B>
683 where
684 &'a A: IntoPyObject<'py>,
685 &'a B: IntoPyObject<'py>,
686 {
687 type Target = PyTuple;
688 type Error = PyErr;
689 type Output = Bound<'py, Self::Target>;
690
691 fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
692 (&self.0, &self.1).into_pyobject(py)
693 }
694 }
695 */
696
697 impl<'a, 'py, A, B> FromPyObject<'a, 'py> for Pair<A, B>
698 where
699 A: Clone + FromPyObject<'a, 'py>,
700 B: Clone + FromPyObject<'a, 'py>,
701 {
702 type Error = PyErr;
703
704 fn extract(ob: Borrowed<'a, 'py, PyAny>) -> Result<Self, PyErr> {
705 FromPyObject::extract(ob).map(|(a, b)| Pair(a, b))
706 }
707 }
708 }

mercurial