algebraeon_geometry/
ambient_space.rs1use std::sync::atomic::AtomicUsize;
2
3use algebraeon_rings::linear::matrix::{Matrix, MatrixStructure};
4
5use super::*;
6#[derive(Debug, Clone)]
7pub struct AffineSpace<FS: OrderedRingStructure + FieldStructure> {
8 ordered_field: Rc<FS>,
9 affine_dimension: usize,
11 ident: usize,
12}
13
14impl<FS: OrderedRingStructure + FieldStructure> PartialEq for AffineSpace<FS> {
15 fn eq(&self, other: &Self) -> bool {
16 #[cfg(debug_assertions)]
17 if self.ident == other.ident {
18 assert_eq!(self.affine_dimension, other.affine_dimension);
19 assert_eq!(self.ordered_field, other.ordered_field);
20 }
21 self.ident == other.ident
22 }
23}
24
25impl<FS: OrderedRingStructure + FieldStructure> Eq for AffineSpace<FS> {}
26
27impl<FS: OrderedRingStructure + FieldStructure + Hash> Hash for AffineSpace<FS> {
28 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
29 self.ident.hash(state);
30 }
31}
32
33impl<FS: OrderedRingStructure + FieldStructure> AffineSpace<FS> {
34 pub fn new_affine(ordered_field: Rc<FS>, affine_dimension: usize) -> Self {
35 static COUNTER: AtomicUsize = AtomicUsize::new(0);
36 Self {
37 ordered_field,
38 affine_dimension,
39 ident: COUNTER.fetch_add(1, std::sync::atomic::Ordering::Relaxed),
40 }
41 }
42
43 pub fn new_empty(ordered_field: Rc<FS>) -> Self {
44 Self::new_affine(ordered_field, 0)
45 }
46
47 pub fn new_linear(ordered_field: Rc<FS>, linear_dimension: usize) -> Self {
48 Self::new_affine(ordered_field, linear_dimension + 1)
49 }
50
51 pub fn ordered_field(&self) -> Rc<FS> {
52 self.ordered_field.clone()
53 }
54
55 pub fn origin<SP: Borrow<Self> + Clone + From<Self>>(&self) -> Option<Vector<FS, SP>> {
56 Some(Vector::construct(self.clone().into(), |_i| {
57 self.ordered_field.zero()
58 }))
59 }
60
61 pub fn linear_dimension(&self) -> Option<usize> {
62 if self.affine_dimension == 0 {
63 None
64 } else {
65 Some(self.affine_dimension - 1)
66 }
67 }
68
69 pub fn affine_dimension(&self) -> usize {
70 self.affine_dimension
71 }
72
73 pub fn rows_from_vectors(&self, vecs: Vec<&Vector<FS, impl Borrow<Self>>>) -> Matrix<FS::Set> {
74 for vec in &vecs {
75 assert_eq!(self, vec.ambient_space().borrow());
76 }
77 Matrix::construct(vecs.len(), self.linear_dimension().unwrap(), |r, c| {
78 vecs[r].coordinate(c).clone()
79 })
80 }
81
82 pub fn cols_from_vectors(&self, vecs: Vec<&Vector<FS, impl Borrow<Self>>>) -> Matrix<FS::Set> {
83 self.rows_from_vectors(vecs).transpose()
84 }
85
86 pub fn determinant(&self, vecs: Vec<&Vector<FS, impl Borrow<Self>>>) -> FS::Set {
87 MatrixStructure::new(self.ordered_field())
88 .det(self.rows_from_vectors(vecs))
89 .unwrap()
90 }
91
92 pub fn rank(&self, vecs: Vec<&Vector<FS, impl Borrow<Self>>>) -> usize {
93 MatrixStructure::new(self.ordered_field()).rank(self.rows_from_vectors(vecs))
94 }
95
96 pub fn are_points_affine_independent(
97 &self,
98 points: Vec<&Vector<FS, impl Borrow<Self> + Clone>>,
99 ) -> bool {
100 for point in &points {
101 assert_eq!(self, point.ambient_space().borrow());
102 }
103 if points.len() != 0 {
104 let vecs = (1..points.len())
105 .map(|i| points[i] - points[0])
106 .collect::<Vec<_>>();
107 let mat = self.rows_from_vectors(vecs.iter().collect());
108 MatrixStructure::new(self.ordered_field()).rank(mat) == vecs.len()
111 } else {
112 true
113 }
114 }
115}
116
117pub fn vectors_from_rows<
118 FS: OrderedRingStructure + FieldStructure,
119 SP: Borrow<AffineSpace<FS>> + Clone,
120>(
121 sp: SP,
122 mat: &Matrix<FS::Set>,
123) -> Vec<Vector<FS, SP>> {
124 assert_eq!(mat.cols(), sp.borrow().linear_dimension().unwrap());
125 (0..mat.rows())
126 .map(|r| {
127 Vector::new(
128 sp.clone(),
129 (0..mat.cols())
130 .map(|c| mat.at(r, c).unwrap().clone())
131 .collect(),
132 )
133 })
134 .collect()
135}
136
137pub fn vectors_from_cols<
138 FS: OrderedRingStructure + FieldStructure,
139 SP: Borrow<AffineSpace<FS>> + Clone,
140>(
141 sp: SP,
142 mat: &Matrix<FS::Set>,
143) -> Vec<Vector<FS, SP>> {
144 assert_eq!(mat.rows(), sp.borrow().linear_dimension().unwrap());
145 vectors_from_rows(sp, &mat.transpose_ref())
146}
147
148pub fn vector_from_row<
149 FS: OrderedRingStructure + FieldStructure,
150 SP: Borrow<AffineSpace<FS>> + Clone,
151>(
152 sp: SP,
153 mat: &Matrix<FS::Set>,
154) -> Vector<FS, SP> {
155 assert_eq!(mat.rows(), 1);
156 assert_eq!(mat.cols(), sp.borrow().linear_dimension().unwrap());
157 vectors_from_rows(sp, mat).pop().unwrap()
158}
159
160pub fn vector_from_col<
161 FS: OrderedRingStructure + FieldStructure,
162 SP: Borrow<AffineSpace<FS>> + Clone,
163>(
164 sp: SP,
165 mat: &Matrix<FS::Set>,
166) -> Vector<FS, SP> {
167 assert_eq!(mat.rows(), sp.borrow().linear_dimension().unwrap());
168 assert_eq!(mat.cols(), 1);
169 vector_from_row(sp, &mat.transpose_ref())
170}
171
172pub fn common_space<
173 FS: OrderedRingStructure + FieldStructure,
174 SP: Borrow<AffineSpace<FS>> + Clone,
175>(
176 space1: SP,
177 space2: SP,
178) -> Option<SP> {
179 if space1.borrow() == space2.borrow() {
180 Some(space1)
181 } else {
182 None
183 }
184}