| 435 impl<F: Float, const N: usize> Euclidean<F> for Loc<N, F> { |
435 impl<F: Float, const N: usize> Euclidean<F> for Loc<N, F> { |
| 436 /// This implementation is not stabilised as it's meant to be used for very small vectors. |
436 /// This implementation is not stabilised as it's meant to be used for very small vectors. |
| 437 /// Use [`nalgebra`] for larger vectors. |
437 /// Use [`nalgebra`] for larger vectors. |
| 438 #[inline] |
438 #[inline] |
| 439 fn dot<I: Instance<Self>>(&self, other: I) -> F { |
439 fn dot<I: Instance<Self>>(&self, other: I) -> F { |
| 440 self.0 |
440 other.eval_ref_decompose(|r| { |
| 441 .iter() |
441 self.0 |
| 442 .zip(other.ref_instance().0.iter()) |
442 .iter() |
| 443 .fold(F::ZERO, |m, (&v, &w)| m + v * w) |
443 .zip(r.0.iter()) |
| |
444 .fold(F::ZERO, |m, (&v, &w)| m + v * w) |
| |
445 }) |
| 444 } |
446 } |
| 445 |
447 |
| 446 /// This implementation is not stabilised as it's meant to be used for very small vectors. |
448 /// This implementation is not stabilised as it's meant to be used for very small vectors. |
| 447 /// Use [`nalgebra`] for larger vectors. |
449 /// Use [`nalgebra`] for larger vectors. |
| 448 #[inline] |
450 #[inline] |
| 449 fn norm2_squared(&self) -> F { |
451 fn norm2_squared(&self) -> F { |
| 450 self.iter().fold(F::ZERO, |m, &v| m + v * v) |
452 self.iter().fold(F::ZERO, |m, &v| m + v * v) |
| 451 } |
453 } |
| 452 |
454 |
| 453 fn dist2_squared<I: Instance<Self>>(&self, other: I) -> F { |
455 fn dist2_squared<I: Instance<Self>>(&self, other: I) -> F { |
| 454 self.iter() |
456 other.eval_ref_decompose(|r| { |
| 455 .zip(other.ref_instance().iter()) |
457 self.iter().zip(r.iter()).fold(F::ZERO, |m, (&v, &w)| { |
| 456 .fold(F::ZERO, |m, (&v, &w)| { |
|
| 457 let d = v - w; |
458 let d = v - w; |
| 458 m + d * d |
459 m + d * d |
| 459 }) |
460 }) |
| |
461 }) |
| 460 } |
462 } |
| 461 |
463 |
| 462 #[inline] |
464 #[inline] |
| 463 fn norm2(&self) -> F { |
465 fn norm2(&self) -> F { |
| 464 // Optimisation for N==1 that avoids squaring and square rooting. |
466 // Optimisation for N==1 that avoids squaring and square rooting. |
| 470 } |
472 } |
| 471 |
473 |
| 472 #[inline] |
474 #[inline] |
| 473 fn dist2<I: Instance<Self>>(&self, other: I) -> F { |
475 fn dist2<I: Instance<Self>>(&self, other: I) -> F { |
| 474 // Optimisation for N==1 that avoids squaring and square rooting. |
476 // Optimisation for N==1 that avoids squaring and square rooting. |
| 475 let otherr = other.ref_instance(); |
|
| 476 if N == 1 { |
477 if N == 1 { |
| 477 unsafe { *self.0.get_unchecked(0) - *otherr.0.get_unchecked(0) }.abs() |
478 other.eval_ref_decompose(|r| { |
| |
479 unsafe { *self.0.get_unchecked(0) - *r.0.get_unchecked(0) }.abs() |
| |
480 }) |
| 478 } else { |
481 } else { |
| 479 self.dist2_squared(other).sqrt() |
482 self.dist2_squared(other).sqrt() |
| 480 } |
483 } |
| 481 } |
484 } |
| 482 } |
485 } |
| 629 } |
632 } |
| 630 |
633 |
| 631 impl<F: Float, const N: usize> Dist<F, L1> for Loc<N, F> { |
634 impl<F: Float, const N: usize> Dist<F, L1> for Loc<N, F> { |
| 632 #[inline] |
635 #[inline] |
| 633 fn dist<I: Instance<Self>>(&self, other: I, _: L1) -> F { |
636 fn dist<I: Instance<Self>>(&self, other: I, _: L1) -> F { |
| 634 self.iter() |
637 other.eval_ref_decompose(|r| { |
| 635 .zip(other.ref_instance().iter()) |
638 self.iter() |
| 636 .fold(F::ZERO, |m, (&v, &w)| m + (v - w).abs()) |
639 .zip(r.iter()) |
| |
640 .fold(F::ZERO, |m, (&v, &w)| m + (v - w).abs()) |
| |
641 }) |
| 637 } |
642 } |
| 638 } |
643 } |
| 639 |
644 |
| 640 impl<F: Float, const N: usize> Projection<F, Linfinity> for Loc<N, F> { |
645 impl<F: Float, const N: usize> Projection<F, Linfinity> for Loc<N, F> { |
| 641 #[inline] |
646 #[inline] |
| 655 } |
660 } |
| 656 |
661 |
| 657 impl<F: Float, const N: usize> Dist<F, Linfinity> for Loc<N, F> { |
662 impl<F: Float, const N: usize> Dist<F, Linfinity> for Loc<N, F> { |
| 658 #[inline] |
663 #[inline] |
| 659 fn dist<I: Instance<Self>>(&self, other: I, _: Linfinity) -> F { |
664 fn dist<I: Instance<Self>>(&self, other: I, _: Linfinity) -> F { |
| 660 self.iter() |
665 other.eval_ref_decompose(|r| { |
| 661 .zip(other.ref_instance().iter()) |
666 self.iter() |
| 662 .fold(F::ZERO, |m, (&v, &w)| m.max((v - w).abs())) |
667 .zip(r.iter()) |
| |
668 .fold(F::ZERO, |m, (&v, &w)| m.max((v - w).abs())) |
| |
669 }) |
| 663 } |
670 } |
| 664 } |
671 } |
| 665 |
672 |
| 666 // Misc. |
673 // Misc. |
| 667 |
674 |
| 700 |
707 |
| 701 impl<F: Float, const N: usize> Mapping<Loc<N, F>> for Loc<N, F> { |
708 impl<F: Float, const N: usize> Mapping<Loc<N, F>> for Loc<N, F> { |
| 702 type Codomain = F; |
709 type Codomain = F; |
| 703 |
710 |
| 704 fn apply<I: Instance<Loc<N, F>>>(&self, x: I) -> Self::Codomain { |
711 fn apply<I: Instance<Loc<N, F>>>(&self, x: I) -> Self::Codomain { |
| 705 x.eval(|x̃| self.dot(x̃)) |
712 x.eval_decompose(|x̃| self.dot(x̃)) |
| 706 } |
713 } |
| 707 } |
714 } |
| 708 |
715 |
| 709 impl<F: Float, const N: usize> Linear<Loc<N, F>> for Loc<N, F> {} |
716 impl<F: Float, const N: usize> Linear<Loc<N, F>> for Loc<N, F> {} |
| 710 |
717 |