| 2 Array containers that support vector space operations on floats. |
2 Array containers that support vector space operations on floats. |
| 3 For working with small vectors in $ℝ^2$ or $ℝ^3$. |
3 For working with small vectors in $ℝ^2$ or $ℝ^3$. |
| 4 */ |
4 */ |
| 5 |
5 |
| 6 use crate::euclidean::*; |
6 use crate::euclidean::*; |
| 7 use crate::instance::{BasicDecomposition, Instance}; |
7 use crate::instance::{BasicDecomposition, Instance, Ownable}; |
| 8 use crate::linops::{Linear, Mapping, AXPY}; |
8 use crate::linops::{Linear, Mapping, VectorSpace, AXPY}; |
| 9 use crate::mapping::Space; |
9 use crate::mapping::Space; |
| 10 use crate::maputil::{map1, map1_mut, map2, map2_mut, FixedLength, FixedLengthMut}; |
10 use crate::maputil::{map1, map1_mut, map2, map2_mut, FixedLength, FixedLengthMut}; |
| 11 use crate::norms::*; |
11 use crate::norms::*; |
| 12 use crate::types::{Float, Num, SignedNum}; |
12 use crate::types::{Float, Num, SignedNum}; |
| 13 use serde::ser::{Serialize, SerializeSeq, Serializer}; |
13 use serde::ser::{Serialize, SerializeSeq, Serializer}; |
| 24 #[derive(Copy, Clone, Debug, PartialEq, Eq)] |
24 #[derive(Copy, Clone, Debug, PartialEq, Eq)] |
| 25 pub struct Loc<const N: usize, F = f64>( |
25 pub struct Loc<const N: usize, F = f64>( |
| 26 /// An array of the elements of the vector |
26 /// An array of the elements of the vector |
| 27 pub [F; N], |
27 pub [F; N], |
| 28 ); |
28 ); |
| |
29 |
| |
30 /// Trait for ownable-by-consumption objects |
| |
31 impl<const N: usize, F: Copy> Ownable for Loc<N, F> { |
| |
32 type OwnedVariant = Self; |
| |
33 |
| |
34 #[inline] |
| |
35 fn into_owned(self) -> Self::OwnedVariant { |
| |
36 self |
| |
37 } |
| |
38 |
| |
39 /// Returns an owned instance of a reference. |
| |
40 fn clone_owned(&self) -> Self::OwnedVariant { |
| |
41 self.clone() |
| |
42 } |
| |
43 } |
| 29 |
44 |
| 30 impl<F: Display, const N: usize> Display for Loc<N, F> { |
45 impl<F: Display, const N: usize> Display for Loc<N, F> { |
| 31 // Required method |
46 // Required method |
| 32 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { |
47 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { |
| 33 write!(f, "[")?; |
48 write!(f, "[")?; |
| 646 } |
661 } |
| 647 } |
662 } |
| 648 |
663 |
| 649 impl<F: Float, const N: usize> Projection<F, Linfinity> for Loc<N, F> { |
664 impl<F: Float, const N: usize> Projection<F, Linfinity> for Loc<N, F> { |
| 650 #[inline] |
665 #[inline] |
| |
666 fn proj_ball(mut self, ρ: F, exp: Linfinity) -> Self { |
| |
667 self.proj_ball_mut(ρ, exp); |
| |
668 self |
| |
669 } |
| |
670 } |
| |
671 |
| |
672 impl<F: Float, const N: usize> ProjectionMut<F, Linfinity> for Loc<N, F> { |
| |
673 #[inline] |
| 651 fn proj_ball_mut(&mut self, ρ: F, _: Linfinity) { |
674 fn proj_ball_mut(&mut self, ρ: F, _: Linfinity) { |
| 652 self.iter_mut() |
675 self.iter_mut() |
| 653 .for_each(|v| *v = num_traits::clamp(*v, -ρ, ρ)) |
676 .for_each(|v| *v = num_traits::clamp(*v, -ρ, ρ)) |
| 654 } |
677 } |
| 655 } |
678 } |
| 704 self.iter() |
727 self.iter() |
| 705 } |
728 } |
| 706 } |
729 } |
| 707 |
730 |
| 708 impl<F: Num, const N: usize> Space for Loc<N, F> { |
731 impl<F: Num, const N: usize> Space for Loc<N, F> { |
| |
732 type OwnedSpace = Self; |
| 709 type Decomp = BasicDecomposition; |
733 type Decomp = BasicDecomposition; |
| 710 } |
734 } |
| 711 |
735 |
| 712 impl<F: Float, const N: usize> Mapping<Loc<N, F>> for Loc<N, F> { |
736 impl<F: Float, const N: usize> Mapping<Loc<N, F>> for Loc<N, F> { |
| 713 type Codomain = F; |
737 type Codomain = F; |
| 717 } |
741 } |
| 718 } |
742 } |
| 719 |
743 |
| 720 impl<F: Float, const N: usize> Linear<Loc<N, F>> for Loc<N, F> {} |
744 impl<F: Float, const N: usize> Linear<Loc<N, F>> for Loc<N, F> {} |
| 721 |
745 |
| 722 impl<F: Float, const N: usize> AXPY<Loc<N, F>> for Loc<N, F> { |
746 impl<F: Float, const N: usize> VectorSpace for Loc<N, F> { |
| 723 type Field = F; |
747 type Field = F; |
| 724 type Owned = Self; |
748 type Owned = Self; |
| 725 |
749 |
| |
750 // #[inline] |
| |
751 // fn make_origin_generator(&self) -> StaticEuclideanOriginGenerator { |
| |
752 // StaticEuclideanOriginGenerator |
| |
753 // } |
| |
754 |
| |
755 #[inline] |
| |
756 fn similar_origin(&self) -> Self::Owned { |
| |
757 Self::ORIGIN |
| |
758 } |
| |
759 |
| |
760 #[inline] |
| |
761 fn similar_origin_inst<I: Instance<Self>>(_: I) -> Self::Owned { |
| |
762 Self::ORIGIN |
| |
763 } |
| |
764 |
| |
765 // #[inline] |
| |
766 // fn into_owned(self) -> Self::Owned { |
| |
767 // self |
| |
768 // } |
| |
769 } |
| |
770 |
| |
771 impl<F: Float, const N: usize> AXPY<Loc<N, F>> for Loc<N, F> { |
| 726 #[inline] |
772 #[inline] |
| 727 fn axpy<I: Instance<Loc<N, F>>>(&mut self, α: F, x: I, β: F) { |
773 fn axpy<I: Instance<Loc<N, F>>>(&mut self, α: F, x: I, β: F) { |
| 728 x.eval(|x̃| { |
774 x.eval(|x̃| { |
| 729 if β == F::ZERO { |
775 if β == F::ZERO { |
| 730 map2_mut(self, x̃, |yi, xi| *yi = α * (*xi)) |
776 map2_mut(self, x̃, |yi, xi| *yi = α * (*xi)) |
| 737 #[inline] |
783 #[inline] |
| 738 fn copy_from<I: Instance<Loc<N, F>>>(&mut self, x: I) { |
784 fn copy_from<I: Instance<Loc<N, F>>>(&mut self, x: I) { |
| 739 x.eval(|x̃| map2_mut(self, x̃, |yi, xi| *yi = *xi)) |
785 x.eval(|x̃| map2_mut(self, x̃, |yi, xi| *yi = *xi)) |
| 740 } |
786 } |
| 741 |
787 |
| 742 // #[inline] |
|
| 743 // fn make_origin_generator(&self) -> StaticEuclideanOriginGenerator { |
|
| 744 // StaticEuclideanOriginGenerator |
|
| 745 // } |
|
| 746 |
|
| 747 #[inline] |
|
| 748 fn similar_origin(&self) -> Self::Owned { |
|
| 749 Self::ORIGIN |
|
| 750 } |
|
| 751 |
|
| 752 #[inline] |
|
| 753 fn similar_origin_inst<I: Instance<Self>>(_: I) -> Self::Owned { |
|
| 754 Self::ORIGIN |
|
| 755 } |
|
| 756 |
|
| 757 #[inline] |
788 #[inline] |
| 758 fn set_zero(&mut self) { |
789 fn set_zero(&mut self) { |
| 759 *self = Self::ORIGIN; |
790 *self = Self::ORIGIN; |
| 760 } |
791 } |
| 761 } |
792 } |