1use algebraeon_rings::linear::matrix::Matrix;
2use std::borrow::Borrow;
3use std::hash::Hash;
4
5use super::*;
6
7#[derive(Clone)]
8pub struct Vector<FS: OrderedRingStructure + FieldStructure, SP: Borrow<AffineSpace<FS>>> {
9 ambient_space: SP,
10 coordinates: Vec<FS::Set>, }
12
13impl<FS: OrderedRingStructure + FieldStructure, SP: Borrow<AffineSpace<FS>>> std::fmt::Debug
14 for Vector<FS, SP>
15{
16 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17 f.debug_struct("Vector")
18 .field("coordinates", &self.coordinates)
19 .finish()
20 }
21}
22
23impl<FS: OrderedRingStructure + FieldStructure, SP: Borrow<AffineSpace<FS>>> PartialEq
24 for Vector<FS, SP>
25{
26 fn eq(&self, other: &Self) -> bool {
27 match common_space(self.ambient_space.borrow(), other.ambient_space.borrow()) {
28 Some(space) => {
29 let n = space.linear_dimension().unwrap();
30 (0..n).all(|i| {
31 space
32 .ordered_field()
33 .equal(self.coordinate(i), other.coordinate(i))
34 })
35 }
36 None => false,
37 }
38 }
39}
40
41impl<FS: OrderedRingStructure + FieldStructure, SP: Borrow<AffineSpace<FS>>> Eq for Vector<FS, SP> {}
42
43impl<FS: OrderedRingStructure + FieldStructure, SP: Borrow<AffineSpace<FS>>> Hash for Vector<FS, SP>
44where
45 FS::Set: Hash,
46{
47 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
48 self.coordinates.hash(state);
50 }
51}
52
53impl<FS: OrderedRingStructure + FieldStructure, SP: Borrow<AffineSpace<FS>>> Vector<FS, SP> {
54 pub fn new(ambient_space: SP, coordinates: Vec<FS::Set>) -> Self {
55 assert_eq!(
56 ambient_space.borrow().linear_dimension().unwrap(),
57 coordinates.len()
58 );
59 Self {
60 ambient_space,
61 coordinates,
62 }
63 }
64
65 pub fn construct(ambient_space: SP, mut coordinate_func: impl FnMut(usize) -> FS::Set) -> Self {
66 let coordinates = (0..ambient_space.borrow().linear_dimension().unwrap())
67 .map(|i| coordinate_func(i))
68 .collect();
69 Self {
70 ambient_space,
71 coordinates,
72 }
73 }
74
75 pub fn zero(ambient_space: SP) -> Self {
76 let ordered_field = ambient_space.borrow().ordered_field();
77 Self::construct(ambient_space, |_i| ordered_field.zero())
78 }
79
80 pub fn ambient_space(&self) -> &SP {
81 &self.ambient_space
82 }
83
84 pub fn coordinate(&self, i: usize) -> &FS::Set {
93 self.coordinates.get(i).unwrap()
94 }
95
96 pub fn coordinate_mut(&mut self, i: usize) -> &mut FS::Set {
97 self.coordinates.get_mut(i).unwrap()
98 }
99
100 pub fn into_row(&self) -> Matrix<FS::Set> {
101 Matrix::construct(
102 1,
103 self.ambient_space().borrow().linear_dimension().unwrap(),
104 |_r, c| self.coordinate(c).clone(),
105 )
106 }
107
108 pub fn into_col(&self) -> Matrix<FS::Set> {
109 Matrix::construct(
110 self.ambient_space().borrow().linear_dimension().unwrap(),
111 1,
112 |r, _c| self.coordinate(r).clone(),
113 )
114 }
115}
116
117impl<FS: OrderedRingStructure + FieldStructure, SP: Borrow<AffineSpace<FS>> + Clone> std::ops::Neg
119 for &Vector<FS, SP>
120{
121 type Output = Vector<FS, SP>;
122
123 fn neg(self) -> Self::Output {
124 Vector {
125 ambient_space: self.ambient_space.clone(),
126 coordinates: self
127 .coordinates
128 .iter()
129 .map(|x| self.ambient_space().borrow().ordered_field().neg(x))
130 .collect(),
131 }
132 }
133}
134
135impl<FS: OrderedRingStructure + FieldStructure, SP: Borrow<AffineSpace<FS>> + Clone>
137 std::ops::Add<&Vector<FS, SP>> for &Vector<FS, SP>
138{
139 type Output = Vector<FS, SP>;
140
141 fn add(self, other: &Vector<FS, SP>) -> Self::Output {
142 match common_space(self.ambient_space.clone(), other.ambient_space.clone()) {
143 Some(space) => {
144 let n = space.borrow().linear_dimension().unwrap();
145 let coordinates = (0..n)
146 .map(|i| {
147 space
148 .borrow()
149 .ordered_field()
150 .add(self.coordinate(i), other.coordinate(i))
151 })
152 .collect();
153 Vector {
154 ambient_space: space,
155 coordinates,
156 }
157 }
158 None => panic!("Can't add vectors belonging to different spaces"),
159 }
160 }
161}
162
163impl<FS: OrderedRingStructure + FieldStructure, SP: Borrow<AffineSpace<FS>> + Clone>
165 std::ops::AddAssign<&Vector<FS, SP>> for Vector<FS, SP>
166{
167 fn add_assign(&mut self, other: &Vector<FS, SP>) {
168 match common_space(self.ambient_space.clone(), other.ambient_space.clone()) {
169 Some(space) => {
170 let n = space.borrow().linear_dimension().unwrap();
171 for i in 0..n {
172 space
173 .borrow()
174 .ordered_field()
175 .add_mut(self.coordinate_mut(i), other.coordinate(i));
176 }
177 }
178 None => panic!("Can't add vectors belonging to different spaces"),
179 }
180 }
181}
182
183impl<FS: OrderedRingStructure + FieldStructure, SP: Borrow<AffineSpace<FS>> + Clone>
185 std::ops::Sub<&Vector<FS, SP>> for &Vector<FS, SP>
186{
187 type Output = Vector<FS, SP>;
188
189 fn sub(self, other: &Vector<FS, SP>) -> Self::Output {
190 self + &(-other)
191 }
192}
193
194impl<FS: OrderedRingStructure + FieldStructure, SP: Borrow<AffineSpace<FS>> + Clone>
196 Vector<FS, SP>
197{
198 pub fn scalar_mul(&self, other: &FS::Set) -> Vector<FS, SP> {
199 Vector {
200 ambient_space: self.ambient_space.clone(),
201 coordinates: self
202 .coordinates
203 .iter()
204 .map(|x| self.ambient_space().borrow().ordered_field().mul(x, other))
205 .collect(),
206 }
207 }
208}
209
210#[cfg(test)]
211mod tests {
212 use algebraeon_nzq::rational::*;
213 use algebraeon_sets::structure::*;
214
215 use super::*;
216
217 #[test]
218 fn vector_from_mat() {
219 let space = AffineSpace::new_linear(Rational::structure(), 2);
220 let mat = Matrix::<Rational>::from_rows(vec![
221 vec![Rational::from(1), Rational::from(2)],
222 vec![Rational::from(3), Rational::from(4)],
223 ]);
224
225 mat.pprint();
226
227 let mut vecs = vectors_from_rows(&space, &mat);
228 let v2 = vecs.pop().unwrap();
229 let v1 = vecs.pop().unwrap();
230 println!("v1 = {:?}", v1);
231 println!("v2 = {:?}", v2);
232
233 assert_eq!(
234 v1,
235 Vector::new(&space, vec![Rational::from(1), Rational::from(2)])
236 );
237 assert_eq!(
238 v2,
239 Vector::new(&space, vec![Rational::from(3), Rational::from(4)])
240 );
241 }
242
243 #[test]
244 fn det() {
245 let space = AffineSpace::new_linear(Rational::structure(), 2);
246 let v1 = Vector::new(&space, vec![Rational::from(3), Rational::from(2)]);
247 let v2 = Vector::new(&space, vec![Rational::from(5), Rational::from(7)]);
248 assert_eq!(space.determinant(vec![&v1, &v2]), Rational::from(11));
249 }
250
251 #[test]
252 fn test_abgroup() {
253 let space_ab = AffineSpace::new_linear(Rational::structure(), 2);
254 let a = Vector::new(&space_ab, vec![Rational::from(1), Rational::from(2)]);
255 let b = Vector::new(&space_ab, vec![Rational::from(6), Rational::from(3)]);
256 let c = Vector::new(&space_ab, vec![Rational::from(7), Rational::from(5)]);
257
258 let space_xy = AffineSpace::new_linear(Rational::structure(), 2);
259 let x = Vector::new(&space_xy, vec![Rational::from(1), Rational::from(2)]);
260 let y = Vector::new(&space_xy, vec![Rational::from(6), Rational::from(3)]);
261 let z = Vector::new(&space_xy, vec![Rational::from(7), Rational::from(5)]);
262 let w = Vector::new(&space_xy, vec![Rational::from(-2), Rational::from(-4)]);
263
264 assert_eq!(c, &a + &b);
265 assert_eq!(z, &x + &y);
266 assert_eq!(a, a);
267 assert_ne!(a, b);
268 assert_ne!(a, x); assert_ne!(x.scalar_mul(&Rational::from(-2)), z);
270 assert_eq!(x.scalar_mul(&Rational::from(-2)), w);
271 }
272}