algebraeon_geometry/
ambient_space.rs

1use 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    //linear dimension = affine dimension - 1
10    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            // println!("{:?}", mat);
109            // println!("{:?} {:?}", vecs.len(), MatrixStructure::new(self.ordered_field()).rank(mat.clone()));
110            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}