| 3 |
3 |
| 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 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}; |
|
| 13 use crate::euclidean::Euclidean; |
8 use crate::euclidean::Euclidean; |
| 14 use crate::instance::{Instance, InstanceMut, Decomposition, DecompositionMut, MyCow}; |
9 use crate::instance::{Decomposition, DecompositionMut, Instance, InstanceMut, MyCow}; |
| 15 use crate::mapping::Space; |
|
| 16 use crate::linops::AXPY; |
10 use crate::linops::AXPY; |
| 17 use crate::loc::Loc; |
11 use crate::loc::Loc; |
| 18 use crate::norms::{Norm, PairNorm, NormExponent, Normed, HasDual, L2}; |
12 use crate::mapping::Space; |
| 19 |
13 use crate::norms::{HasDual, Norm, NormExponent, Normed, PairNorm, L2}; |
| 20 #[derive(Debug,Clone,Copy,PartialEq,Eq,Serialize,Deserialize)] |
14 use crate::types::{Float, Num}; |
| 21 pub struct Pair<A, B> (pub A, pub B); |
15 use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; |
| 22 |
16 use serde::{Deserialize, Serialize}; |
| 23 impl<A, B> Pair<A,B> { |
17 use std::clone::Clone; |
| 24 pub fn new(a : A, b : B) -> Pair<A,B> { Pair(a, b) } |
18 |
| 25 } |
19 #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] |
| 26 |
20 pub struct Pair<A, B>(pub A, pub B); |
| 27 impl<A, B> From<(A,B)> for Pair<A,B> { |
21 |
| 28 #[inline] |
22 impl<A, B> Pair<A, B> { |
| 29 fn from((a, b) : (A, B)) -> Pair<A,B> { Pair(a, b) } |
23 pub fn new(a: A, b: B) -> Pair<A, B> { |
| 30 } |
24 Pair(a, b) |
| 31 |
25 } |
| 32 impl<A, B> From<Pair<A,B>> for (A,B) { |
26 } |
| 33 #[inline] |
27 |
| 34 fn from(Pair(a, b) : Pair<A, B>) -> (A,B) { (a, b) } |
28 impl<A, B> From<(A, B)> for Pair<A, B> { |
| |
29 #[inline] |
| |
30 fn from((a, b): (A, B)) -> Pair<A, B> { |
| |
31 Pair(a, b) |
| |
32 } |
| |
33 } |
| |
34 |
| |
35 impl<A, B> From<Pair<A, B>> for (A, B) { |
| |
36 #[inline] |
| |
37 fn from(Pair(a, b): Pair<A, B>) -> (A, B) { |
| |
38 (a, b) |
| |
39 } |
| 35 } |
40 } |
| 36 |
41 |
| 37 macro_rules! impl_binop { |
42 macro_rules! impl_binop { |
| 38 (($a : ty, $b : ty), $trait : ident, $fn : ident, $refl:ident, $refr:ident) => { |
43 (($a : ty, $b : ty), $trait : ident, $fn : ident, $refl:ident, $refr:ident) => { |
| 39 impl_binop!(@doit: $a, $b, $trait, $fn; |
44 impl_binop!(@doit: $a, $b, $trait, $fn; |
| 239 |
246 |
| 240 type PairOutput<F, A, B> = Pair<<A as Euclidean<F>>::Output, <B as Euclidean<F>>::Output>; |
247 type PairOutput<F, A, B> = Pair<<A as Euclidean<F>>::Output, <B as Euclidean<F>>::Output>; |
| 241 |
248 |
| 242 impl<A, B, F> Euclidean<F> for Pair<A, B> |
249 impl<A, B, F> Euclidean<F> for Pair<A, B> |
| 243 where |
250 where |
| 244 A : Euclidean<F>, |
251 A: Euclidean<F>, |
| 245 B : Euclidean<F>, |
252 B: Euclidean<F>, |
| 246 F : Float, |
253 F: Float, |
| 247 PairOutput<F, A, B> : Euclidean<F>, |
254 PairOutput<F, A, B>: Euclidean<F>, |
| 248 Self : Sized |
255 Self: Sized |
| 249 + Mul<F, Output=PairOutput<F, A, B>> + MulAssign<F> |
256 + Mul<F, Output = PairOutput<F, A, B>> |
| 250 + Div<F, Output=PairOutput<F, A, B>> + DivAssign<F> |
257 + MulAssign<F> |
| 251 + Add<Self, Output=PairOutput<F, A, B>> |
258 + Div<F, Output = PairOutput<F, A, B>> |
| 252 + Sub<Self, Output=PairOutput<F, A, B>> |
259 + DivAssign<F> |
| 253 + for<'b> Add<&'b Self, Output=PairOutput<F, A, B>> |
260 + Add<Self, Output = PairOutput<F, A, B>> |
| 254 + for<'b> Sub<&'b Self, Output=PairOutput<F, A, B>> |
261 + Sub<Self, Output = PairOutput<F, A, B>> |
| 255 + AddAssign<Self> + for<'b> AddAssign<&'b Self> |
262 + for<'b> Add<&'b Self, Output = PairOutput<F, A, B>> |
| 256 + SubAssign<Self> + for<'b> SubAssign<&'b Self> |
263 + for<'b> Sub<&'b Self, Output = PairOutput<F, A, B>> |
| 257 + Neg<Output=PairOutput<F, A, B>> |
264 + AddAssign<Self> |
| |
265 + for<'b> AddAssign<&'b Self> |
| |
266 + SubAssign<Self> |
| |
267 + for<'b> SubAssign<&'b Self> |
| |
268 + Neg<Output = PairOutput<F, A, B>>, |
| 258 { |
269 { |
| 259 type Output = PairOutput<F, A, B>; |
270 type Output = PairOutput<F, A, B>; |
| 260 |
271 |
| 261 fn dot<I : Instance<Self>>(&self, other : I) -> F { |
272 fn dot<I: Instance<Self>>(&self, other: I) -> F { |
| 262 let Pair(u, v) = other.decompose(); |
273 let Pair(u, v) = other.decompose(); |
| 263 self.0.dot(u) + self.1.dot(v) |
274 self.0.dot(u) + self.1.dot(v) |
| 264 } |
275 } |
| 265 |
276 |
| 266 fn norm2_squared(&self) -> F { |
277 fn norm2_squared(&self) -> F { |
| 267 self.0.norm2_squared() + self.1.norm2_squared() |
278 self.0.norm2_squared() + self.1.norm2_squared() |
| 268 } |
279 } |
| 269 |
280 |
| 270 fn dist2_squared<I : Instance<Self>>(&self, other : I) -> F { |
281 fn dist2_squared<I: Instance<Self>>(&self, other: I) -> F { |
| 271 let Pair(u, v) = other.decompose(); |
282 let Pair(u, v) = other.decompose(); |
| 272 self.0.dist2_squared(u) + self.1.dist2_squared(v) |
283 self.0.dist2_squared(u) + self.1.dist2_squared(v) |
| 273 } |
284 } |
| 274 } |
285 } |
| 275 |
286 |
| 276 impl<F, A, B, U, V> AXPY<F, Pair<U, V>> for Pair<A, B> |
287 impl<F, A, B, U, V> AXPY<F, Pair<U, V>> for Pair<A, B> |
| 277 where |
288 where |
| 278 U : Space, |
289 U: Space, |
| 279 V : Space, |
290 V: Space, |
| 280 A : AXPY<F, U>, |
291 A: AXPY<F, U>, |
| 281 B : AXPY<F, V>, |
292 B: AXPY<F, V>, |
| 282 F : Num, |
293 F: Num, |
| 283 Self : MulAssign<F>, |
294 Self: MulAssign<F>, |
| 284 Pair<A, B> : MulAssign<F>, |
295 Pair<A, B>: MulAssign<F>, |
| 285 Pair<A::Owned, B::Owned> : AXPY<F, Pair<U, V>>, |
296 Pair<A::Owned, B::Owned>: AXPY<F, Pair<U, V>>, |
| 286 { |
297 { |
| 287 |
|
| 288 type Owned = Pair<A::Owned, B::Owned>; |
298 type Owned = Pair<A::Owned, B::Owned>; |
| 289 |
299 |
| 290 fn axpy<I : Instance<Pair<U,V>>>(&mut self, α : F, x : I, β : F) { |
300 fn axpy<I: Instance<Pair<U, V>>>(&mut self, α: F, x: I, β: F) { |
| 291 let Pair(u, v) = x.decompose(); |
301 let Pair(u, v) = x.decompose(); |
| 292 self.0.axpy(α, u, β); |
302 self.0.axpy(α, u, β); |
| 293 self.1.axpy(α, v, β); |
303 self.1.axpy(α, v, β); |
| 294 } |
304 } |
| 295 |
305 |
| 296 fn copy_from<I : Instance<Pair<U,V>>>(&mut self, x : I) { |
306 fn copy_from<I: Instance<Pair<U, V>>>(&mut self, x: I) { |
| 297 let Pair(u, v) = x.decompose(); |
307 let Pair(u, v) = x.decompose(); |
| 298 self.0.copy_from(u); |
308 self.0.copy_from(u); |
| 299 self.1.copy_from(v); |
309 self.1.copy_from(v); |
| 300 } |
310 } |
| 301 |
311 |
| 302 fn scale_from<I : Instance<Pair<U,V>>>(&mut self, α : F, x : I) { |
312 fn scale_from<I: Instance<Pair<U, V>>>(&mut self, α: F, x: I) { |
| 303 let Pair(u, v) = x.decompose(); |
313 let Pair(u, v) = x.decompose(); |
| 304 self.0.scale_from(α, u); |
314 self.0.scale_from(α, u); |
| 305 self.1.scale_from(α, v); |
315 self.1.scale_from(α, v); |
| 306 } |
316 } |
| 307 |
317 |
| 319 |
329 |
| 320 /// [`Decomposition`] for working with [`Pair`]s. |
330 /// [`Decomposition`] for working with [`Pair`]s. |
| 321 #[derive(Copy, Clone, Debug)] |
331 #[derive(Copy, Clone, Debug)] |
| 322 pub struct PairDecomposition<D, Q>(D, Q); |
332 pub struct PairDecomposition<D, Q>(D, Q); |
| 323 |
333 |
| 324 impl<A : Space, B : Space> Space for Pair<A, B> { |
334 impl<A: Space, B: Space> Space for Pair<A, B> { |
| 325 type Decomp = PairDecomposition<A::Decomp, B::Decomp>; |
335 type Decomp = PairDecomposition<A::Decomp, B::Decomp>; |
| 326 } |
336 } |
| 327 |
337 |
| 328 impl<A, B, D, Q> Decomposition<Pair<A, B>> for PairDecomposition<D,Q> |
338 impl<A, B, D, Q> Decomposition<Pair<A, B>> for PairDecomposition<D, Q> |
| 329 where |
339 where |
| 330 A : Space, |
340 A: Space, |
| 331 B : Space, |
341 B: Space, |
| 332 D : Decomposition<A>, |
342 D: Decomposition<A>, |
| 333 Q : Decomposition<B>, |
343 Q: Decomposition<B>, |
| 334 { |
344 { |
| 335 type Decomposition<'b> = Pair<D::Decomposition<'b>, Q::Decomposition<'b>> where Pair<A, B> : 'b; |
345 type Decomposition<'b> |
| 336 type Reference<'b> = Pair<D::Reference<'b>, Q::Reference<'b>> where Pair<A, B> : 'b; |
346 = Pair<D::Decomposition<'b>, Q::Decomposition<'b>> |
| 337 |
347 where |
| 338 #[inline] |
348 Pair<A, B>: 'b; |
| 339 fn lift<'b>(Pair(u, v) : Self::Reference<'b>) -> Self::Decomposition<'b> { |
349 type Reference<'b> |
| |
350 = Pair<D::Reference<'b>, Q::Reference<'b>> |
| |
351 where |
| |
352 Pair<A, B>: 'b; |
| |
353 |
| |
354 #[inline] |
| |
355 fn lift<'b>(Pair(u, v): Self::Reference<'b>) -> Self::Decomposition<'b> { |
| 340 Pair(D::lift(u), Q::lift(v)) |
356 Pair(D::lift(u), Q::lift(v)) |
| 341 } |
357 } |
| 342 } |
358 } |
| 343 |
359 |
| 344 impl<A, B, U, V, D, Q> Instance<Pair<A, B>, PairDecomposition<D, Q>> for Pair<U, V> |
360 impl<A, B, U, V, D, Q> Instance<Pair<A, B>, PairDecomposition<D, Q>> for Pair<U, V> |
| 345 where |
361 where |
| 346 A : Space, |
362 A: Space, |
| 347 B : Space, |
363 B: Space, |
| 348 D : Decomposition<A>, |
364 D: Decomposition<A>, |
| 349 Q : Decomposition<B>, |
365 Q: Decomposition<B>, |
| 350 U : Instance<A, D>, |
366 U: Instance<A, D>, |
| 351 V : Instance<B, Q>, |
367 V: Instance<B, Q>, |
| 352 { |
368 { |
| 353 #[inline] |
369 #[inline] |
| 354 fn decompose<'b>(self) |
370 fn decompose<'b>( |
| 355 -> <PairDecomposition<D, Q> as Decomposition<Pair<A, B>>>::Decomposition<'b> |
371 self, |
| 356 where Self : 'b, Pair<A, B> : 'b |
372 ) -> <PairDecomposition<D, Q> as Decomposition<Pair<A, B>>>::Decomposition<'b> |
| |
373 where |
| |
374 Self: 'b, |
| |
375 Pair<A, B>: 'b, |
| 357 { |
376 { |
| 358 Pair(self.0.decompose(), self.1.decompose()) |
377 Pair(self.0.decompose(), self.1.decompose()) |
| 359 } |
378 } |
| 360 |
379 |
| 361 #[inline] |
380 #[inline] |
| 362 fn ref_instance(&self) |
381 fn ref_instance( |
| 363 -> <PairDecomposition<D, Q> as Decomposition<Pair<A, B>>>::Reference<'_> |
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, |
| 364 { |
391 { |
| 365 Pair(self.0.ref_instance(), self.1.ref_instance()) |
|
| 366 } |
|
| 367 |
|
| 368 #[inline] |
|
| 369 fn cow<'b>(self) -> MyCow<'b, Pair<A, B>> where Self : 'b{ |
|
| 370 MyCow::Owned(Pair(self.0.own(), self.1.own())) |
392 MyCow::Owned(Pair(self.0.own(), self.1.own())) |
| 371 } |
393 } |
| 372 |
394 |
| 373 #[inline] |
395 #[inline] |
| 374 fn own(self) -> Pair<A, B> { |
396 fn own(self) -> Pair<A, B> { |
| 375 Pair(self.0.own(), self.1.own()) |
397 Pair(self.0.own(), self.1.own()) |
| 376 } |
398 } |
| 377 } |
399 } |
| 378 |
400 |
| 379 |
|
| 380 impl<'a, A, B, U, V, D, Q> Instance<Pair<A, B>, PairDecomposition<D, Q>> for &'a Pair<U, V> |
401 impl<'a, A, B, U, V, D, Q> Instance<Pair<A, B>, PairDecomposition<D, Q>> for &'a Pair<U, V> |
| 381 where |
402 where |
| 382 A : Space, |
403 A: Space, |
| 383 B : Space, |
404 B: Space, |
| 384 D : Decomposition<A>, |
405 D: Decomposition<A>, |
| 385 Q : Decomposition<B>, |
406 Q: Decomposition<B>, |
| 386 U : Instance<A, D>, |
407 U: Instance<A, D>, |
| 387 V : Instance<B, Q>, |
408 V: Instance<B, Q>, |
| 388 &'a U : Instance<A, D>, |
409 &'a U: Instance<A, D>, |
| 389 &'a V : Instance<B, Q>, |
410 &'a V: Instance<B, Q>, |
| 390 { |
411 { |
| 391 #[inline] |
412 #[inline] |
| 392 fn decompose<'b>(self) |
413 fn decompose<'b>( |
| 393 -> <PairDecomposition<D, Q> as Decomposition<Pair<A, B>>>::Decomposition<'b> |
414 self, |
| 394 where Self : 'b, Pair<A, B> : 'b |
415 ) -> <PairDecomposition<D, Q> as Decomposition<Pair<A, B>>>::Decomposition<'b> |
| |
416 where |
| |
417 Self: 'b, |
| |
418 Pair<A, B>: 'b, |
| 395 { |
419 { |
| 396 Pair(D::lift(self.0.ref_instance()), Q::lift(self.1.ref_instance())) |
420 Pair( |
| 397 } |
421 D::lift(self.0.ref_instance()), |
| 398 |
422 Q::lift(self.1.ref_instance()), |
| 399 #[inline] |
423 ) |
| 400 fn ref_instance(&self) |
424 } |
| 401 -> <PairDecomposition<D, Q> as Decomposition<Pair<A, B>>>::Reference<'_> |
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 |
| |
436 Self: 'b, |
| 402 { |
437 { |
| 403 Pair(self.0.ref_instance(), self.1.ref_instance()) |
|
| 404 } |
|
| 405 |
|
| 406 #[inline] |
|
| 407 fn cow<'b>(self) -> MyCow<'b, Pair<A, B>> where Self : 'b { |
|
| 408 MyCow::Owned(self.own()) |
438 MyCow::Owned(self.own()) |
| 409 } |
439 } |
| 410 |
440 |
| 411 #[inline] |
441 #[inline] |
| 412 fn own(self) -> Pair<A, B> { |
442 fn own(self) -> Pair<A, B> { |
| 413 let Pair(ref u, ref v) = self; |
443 let Pair(ref u, ref v) = self; |
| 414 Pair(u.own(), v.own()) |
444 Pair(u.own(), v.own()) |
| 415 } |
445 } |
| 416 |
446 } |
| 417 } |
447 |
| 418 |
448 impl<A, B, D, Q> DecompositionMut<Pair<A, B>> for PairDecomposition<D, Q> |
| 419 impl<A, B, D, Q> DecompositionMut<Pair<A, B>> for PairDecomposition<D,Q> |
449 where |
| 420 where |
450 A: Space, |
| 421 A : Space, |
451 B: Space, |
| 422 B : Space, |
452 D: DecompositionMut<A>, |
| 423 D : DecompositionMut<A>, |
453 Q: DecompositionMut<B>, |
| 424 Q : DecompositionMut<B>, |
454 { |
| 425 { |
455 type ReferenceMut<'b> |
| 426 type ReferenceMut<'b> = Pair<D::ReferenceMut<'b>, Q::ReferenceMut<'b>> where Pair<A, B> : 'b; |
456 = Pair<D::ReferenceMut<'b>, Q::ReferenceMut<'b>> |
| |
457 where |
| |
458 Pair<A, B>: 'b; |
| 427 } |
459 } |
| 428 |
460 |
| 429 impl<A, B, U, V, D, Q> InstanceMut<Pair<A, B>, PairDecomposition<D, Q>> for Pair<U, V> |
461 impl<A, B, U, V, D, Q> InstanceMut<Pair<A, B>, PairDecomposition<D, Q>> for Pair<U, V> |
| 430 where |
462 where |
| 431 A : Space, |
463 A: Space, |
| 432 B : Space, |
464 B: Space, |
| 433 D : DecompositionMut<A>, |
465 D: DecompositionMut<A>, |
| 434 Q : DecompositionMut<B>, |
466 Q: DecompositionMut<B>, |
| 435 U : InstanceMut<A, D>, |
467 U: InstanceMut<A, D>, |
| 436 V : InstanceMut<B, Q>, |
468 V: InstanceMut<B, Q>, |
| 437 { |
469 { |
| 438 #[inline] |
470 #[inline] |
| 439 fn ref_instance_mut(&mut self) |
471 fn ref_instance_mut( |
| 440 -> <PairDecomposition<D, Q> as DecompositionMut<Pair<A, B>>>::ReferenceMut<'_> |
472 &mut self, |
| 441 { |
473 ) -> <PairDecomposition<D, Q> as DecompositionMut<Pair<A, B>>>::ReferenceMut<'_> { |
| 442 Pair(self.0.ref_instance_mut(), self.1.ref_instance_mut()) |
474 Pair(self.0.ref_instance_mut(), self.1.ref_instance_mut()) |
| 443 } |
475 } |
| 444 } |
476 } |
| 445 |
477 |
| 446 impl<'a, A, B, U, V, D, Q> InstanceMut<Pair<A, B>, PairDecomposition<D, Q>> for &'a mut Pair<U, V> |
478 impl<'a, A, B, U, V, D, Q> InstanceMut<Pair<A, B>, PairDecomposition<D, Q>> for &'a mut Pair<U, V> |
| 447 where |
479 where |
| 448 A : Space, |
480 A: Space, |
| 449 B : Space, |
481 B: Space, |
| 450 D : DecompositionMut<A>, |
482 D: DecompositionMut<A>, |
| 451 Q : DecompositionMut<B>, |
483 Q: DecompositionMut<B>, |
| 452 U : InstanceMut<A, D>, |
484 U: InstanceMut<A, D>, |
| 453 V : InstanceMut<B, Q>, |
485 V: InstanceMut<B, Q>, |
| 454 { |
486 { |
| 455 #[inline] |
487 #[inline] |
| 456 fn ref_instance_mut(&mut self) |
488 fn ref_instance_mut( |
| 457 -> <PairDecomposition<D, Q> as DecompositionMut<Pair<A, B>>>::ReferenceMut<'_> |
489 &mut self, |
| 458 { |
490 ) -> <PairDecomposition<D, Q> as DecompositionMut<Pair<A, B>>>::ReferenceMut<'_> { |
| 459 Pair(self.0.ref_instance_mut(), self.1.ref_instance_mut()) |
491 Pair(self.0.ref_instance_mut(), self.1.ref_instance_mut()) |
| 460 } |
492 } |
| 461 } |
493 } |
| 462 |
494 |
| 463 |
495 impl<F, A, B, ExpA, ExpB, ExpJ> Norm<F, PairNorm<ExpA, ExpB, ExpJ>> for Pair<A, B> |
| 464 impl<F, A, B, ExpA, ExpB, ExpJ> Norm<F, PairNorm<ExpA, ExpB, ExpJ>> |
496 where |
| 465 for Pair<A,B> |
497 F: Num, |
| 466 where |
498 ExpA: NormExponent, |
| 467 F : Num, |
499 ExpB: NormExponent, |
| 468 ExpA : NormExponent, |
500 ExpJ: NormExponent, |
| 469 ExpB : NormExponent, |
501 A: Norm<F, ExpA>, |
| 470 ExpJ : NormExponent, |
502 B: Norm<F, ExpB>, |
| 471 A : Norm<F, ExpA>, |
503 Loc<F, 2>: Norm<F, ExpJ>, |
| 472 B : Norm<F, ExpB>, |
504 { |
| 473 Loc<F, 2> : Norm<F, ExpJ>, |
505 fn norm(&self, PairNorm(expa, expb, expj): PairNorm<ExpA, ExpB, ExpJ>) -> F { |
| 474 { |
|
| 475 fn norm(&self, PairNorm(expa, expb, expj) : PairNorm<ExpA, ExpB, ExpJ>) -> F { |
|
| 476 Loc([self.0.norm(expa), self.1.norm(expb)]).norm(expj) |
506 Loc([self.0.norm(expa), self.1.norm(expb)]).norm(expj) |
| 477 } |
507 } |
| 478 } |
508 } |
| 479 |
509 |
| 480 |
510 impl<F: Float, A, B> Normed<F> for Pair<A, B> |
| 481 impl<F : Float, A, B> Normed<F> for Pair<A,B> |
511 where |
| 482 where |
512 A: Normed<F>, |
| 483 A : Normed<F>, |
513 B: Normed<F>, |
| 484 B : Normed<F>, |
|
| 485 { |
514 { |
| 486 type NormExp = PairNorm<A::NormExp, B::NormExp, L2>; |
515 type NormExp = PairNorm<A::NormExp, B::NormExp, L2>; |
| 487 |
516 |
| 488 #[inline] |
517 #[inline] |
| 489 fn norm_exponent(&self) -> Self::NormExp { |
518 fn norm_exponent(&self) -> Self::NormExp { |