4 */ |
4 */ |
5 |
5 |
6 use std::ops::{Add,Sub,AddAssign,SubAssign,Mul,Div,MulAssign,DivAssign,Neg,Index,IndexMut}; |
6 use std::ops::{Add,Sub,AddAssign,SubAssign,Mul,Div,MulAssign,DivAssign,Neg,Index,IndexMut}; |
7 use std::slice::{Iter,IterMut}; |
7 use std::slice::{Iter,IterMut}; |
8 use std::fmt::{Display, Formatter}; |
8 use std::fmt::{Display, Formatter}; |
|
9 use std::borrow::Borrow; |
9 use crate::types::{Float,Num,SignedNum}; |
10 use crate::types::{Float,Num,SignedNum}; |
10 use crate::maputil::{FixedLength,FixedLengthMut,map1,map2,map1_mut,map2_mut}; |
11 use crate::maputil::{FixedLength,FixedLengthMut,map1,map2,map1_mut,map2_mut}; |
11 use crate::euclidean::*; |
12 use crate::euclidean::*; |
12 use crate::norms::*; |
13 use crate::norms::*; |
13 use crate::linops::AXPY; |
14 use crate::linops::AXPY; |
20 #[derive(Copy,Clone,Debug,PartialEq,Eq)] |
21 #[derive(Copy,Clone,Debug,PartialEq,Eq)] |
21 pub struct Loc<F, const N : usize>( |
22 pub struct Loc<F, const N : usize>( |
22 /// An array of the elements of the vector |
23 /// An array of the elements of the vector |
23 pub [F; N] |
24 pub [F; N] |
24 ); |
25 ); |
|
26 |
|
27 impl<F : Num, const N : usize> HasScalarField for Loc<F, N> { |
|
28 type Field = F; |
|
29 } |
25 |
30 |
26 impl<F : Display, const N : usize> Display for Loc<F, N>{ |
31 impl<F : Display, const N : usize> Display for Loc<F, N>{ |
27 // Required method |
32 // Required method |
28 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { |
33 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { |
29 write!(f, "[")?; |
34 write!(f, "[")?; |
424 |
429 |
425 domination!(Linfinity, L1); |
430 domination!(Linfinity, L1); |
426 domination!(Linfinity, L2); |
431 domination!(Linfinity, L2); |
427 domination!(L2, L1); |
432 domination!(L2, L1); |
428 |
433 |
429 impl<F : Num,const N : usize> Dot<Loc<F, N>,F> for Loc<F, N> { |
434 impl<F : Num, T : Borrow<Loc<F, N>>, const N : usize> Dot<T> for Loc<F, N> { |
430 /// This implementation is not stabilised as it's meant to be used for very small vectors. |
435 /// This implementation is not stabilised as it's meant to be used for very small vectors. |
431 /// Use [`nalgebra`] for larger vectors. |
436 /// Use [`nalgebra`] for larger vectors. |
432 #[inline] |
437 #[inline] |
433 fn dot(&self, other : &Loc<F, N>) -> F { |
438 fn dot(&self, other : T) -> F { |
434 self.0.iter() |
439 self.0.iter() |
435 .zip(other.0.iter()) |
440 .zip(other.borrow().0.iter()) |
436 .fold(F::ZERO, |m, (&v, &w)| m + v * w) |
441 .fold(F::ZERO, |m, (&v, &w)| m + v * w) |
437 } |
442 } |
438 } |
443 } |
439 |
444 |
440 impl<F : Float,const N : usize> Euclidean<F> for Loc<F, N> { |
445 impl<F : Float,const N : usize> Euclidean for Loc<F, N> { |
441 type Output = Self; |
446 type Output = Self; |
442 |
447 |
443 #[inline] |
448 #[inline] |
444 fn similar_origin(&self) -> Self { |
449 fn similar_origin(&self) -> Self { |
445 Self::ORIGIN |
450 Self::ORIGIN |
481 |
486 |
482 impl<F : Num, const N : usize> Loc<F, N> { |
487 impl<F : Num, const N : usize> Loc<F, N> { |
483 pub const ORIGIN : Self = Loc([F::ZERO; N]); |
488 pub const ORIGIN : Self = Loc([F::ZERO; N]); |
484 } |
489 } |
485 |
490 |
486 impl<F : Float,const N : usize> StaticEuclidean<F> for Loc<F, N> { |
491 impl<F : Float,const N : usize> StaticEuclidean for Loc<F, N> { |
487 #[inline] |
492 #[inline] |
488 fn origin() -> Self { |
493 fn origin() -> Self { |
489 Self::ORIGIN |
494 Self::ORIGIN |
490 } |
495 } |
491 } |
496 } |
492 |
497 |
493 impl<F : Float, const N : usize> Norm<F, L2> for Loc<F, N> { |
498 impl<F : Float, const N : usize> Norm<L2> for Loc<F, N> { |
494 #[inline] |
499 #[inline] |
495 fn norm(&self, _ : L2) -> F { self.norm2() } |
500 fn norm(&self, _ : L2) -> F { self.norm2() } |
496 } |
501 } |
497 |
502 |
498 impl<F : Float, const N : usize> Dist<F, L2> for Loc<F, N> { |
503 impl<F : Float, const N : usize> Dist<L2> for Loc<F, N> { |
499 #[inline] |
504 #[inline] |
500 fn dist(&self, other : &Self, _ : L2) -> F { self.dist2(other) } |
505 fn dist(&self, other : &Self, _ : L2) -> F { self.dist2(other) } |
501 } |
506 } |
502 |
507 |
503 impl<F : Float, const N : usize> Norm<F, L1> for Loc<F, N> { |
508 impl<F : Float, const N : usize> Norm<L1> for Loc<F, N> { |
504 /// This implementation is not stabilised as it's meant to be used for very small vectors. |
509 /// This implementation is not stabilised as it's meant to be used for very small vectors. |
505 /// Use [`nalgebra`] for larger vectors. |
510 /// Use [`nalgebra`] for larger vectors. |
506 #[inline] |
511 #[inline] |
507 fn norm(&self, _ : L1) -> F { |
512 fn norm(&self, _ : L1) -> F { |
508 self.iter().fold(F::ZERO, |m, v| m + v.abs()) |
513 self.iter().fold(F::ZERO, |m, v| m + v.abs()) |
509 } |
514 } |
510 } |
515 } |
511 |
516 |
512 impl<F : Float, const N : usize> Dist<F, L1> for Loc<F, N> { |
517 impl<F : Float, const N : usize> Dist<L1> for Loc<F, N> { |
513 #[inline] |
518 #[inline] |
514 fn dist(&self, other : &Self, _ : L1) -> F { |
519 fn dist(&self, other : &Self, _ : L1) -> F { |
515 self.iter() |
520 self.iter() |
516 .zip(other.iter()) |
521 .zip(other.iter()) |
517 .fold(F::ZERO, |m, (&v, &w)| m + (v-w).abs() ) |
522 .fold(F::ZERO, |m, (&v, &w)| m + (v-w).abs() ) |
518 } |
523 } |
519 } |
524 } |
520 |
525 |
521 impl<F : Float, const N : usize> Projection<F, Linfinity> for Loc<F, N> { |
526 impl<F : Float, const N : usize> Projection<Linfinity> for Loc<F, N> { |
522 #[inline] |
527 #[inline] |
523 fn proj_ball_mut(&mut self, ρ : F, _ : Linfinity) { |
528 fn proj_ball_mut(&mut self, ρ : F, _ : Linfinity) { |
524 self.iter_mut().for_each(|v| *v = num_traits::clamp(*v, -ρ, ρ)) |
529 self.iter_mut().for_each(|v| *v = num_traits::clamp(*v, -ρ, ρ)) |
525 } |
530 } |
526 } |
531 } |
527 |
532 |
528 impl<F : Float, const N : usize> Norm<F, Linfinity> for Loc<F, N> { |
533 impl<F : Float, const N : usize> Norm<Linfinity> for Loc<F, N> { |
529 /// This implementation is not stabilised as it's meant to be used for very small vectors. |
534 /// This implementation is not stabilised as it's meant to be used for very small vectors. |
530 /// Use [`nalgebra`] for larger vectors. |
535 /// Use [`nalgebra`] for larger vectors. |
531 #[inline] |
536 #[inline] |
532 fn norm(&self, _ : Linfinity) -> F { |
537 fn norm(&self, _ : Linfinity) -> F { |
533 self.iter().fold(F::ZERO, |m, v| m.max(v.abs())) |
538 self.iter().fold(F::ZERO, |m, v| m.max(v.abs())) |
534 } |
539 } |
535 } |
540 } |
536 |
541 |
537 impl<F : Float, const N : usize> Dist<F, Linfinity> for Loc<F, N> { |
542 impl<F : Float, const N : usize> Dist<Linfinity> for Loc<F, N> { |
538 #[inline] |
543 #[inline] |
539 fn dist(&self, other : &Self, _ : Linfinity) -> F { |
544 fn dist(&self, other : &Self, _ : Linfinity) -> F { |
540 self.iter() |
545 self.iter() |
541 .zip(other.iter()) |
546 .zip(other.iter()) |
542 .fold(F::ZERO, |m, (&v, &w)| m.max((v-w).abs())) |
547 .fold(F::ZERO, |m, (&v, &w)| m.max((v-w).abs())) |
570 fn fl_iter(self) -> Self::Iter { |
575 fn fl_iter(self) -> Self::Iter { |
571 self.iter() |
576 self.iter() |
572 } |
577 } |
573 } |
578 } |
574 |
579 |
575 impl<F : Num, const N : usize> AXPY<F, Loc<F, N>> for Loc<F, N> { |
580 impl<'a, T : Borrow<Loc<F, N>>, F : Num, const N : usize> AXPY<F, T> for Loc<F, N> { |
576 |
581 #[inline] |
577 #[inline] |
582 fn axpy(&mut self, α : F, x : T, β : F) { |
578 fn axpy(&mut self, α : F, x : &Loc<F, N>, β : F) { |
|
579 if β == F::ZERO { |
583 if β == F::ZERO { |
580 map2_mut(self, x, |yi, xi| { *yi = α * (*xi) }) |
584 map2_mut(self, x.borrow(), |yi, xi| { *yi = α * (*xi) }) |
581 } else { |
585 } else { |
582 map2_mut(self, x, |yi, xi| { *yi = β * (*yi) + α * (*xi) }) |
586 map2_mut(self, x.borrow(), |yi, xi| { *yi = β * (*yi) + α * (*xi) }) |
583 } |
587 } |
584 } |
588 } |
585 |
589 |
586 #[inline] |
590 #[inline] |
587 fn copy_from(&mut self, x : &Loc<F, N>) { |
591 fn copy_from(&mut self, x : T) { |
588 map2_mut(self, x, |yi, xi| *yi = *xi ) |
592 map2_mut(self, x.borrow(), |yi, xi| *yi = *xi ) |
589 } |
593 } |
590 } |
594 } |