Skip to main content

algebraeon_geometry/
ambient_space.rs

1use super::*;
2use crate::{
3    simplex_collection::LabelledSimplexCollection,
4    simplicial_disjoint_union::SimplicialDisjointUnion, vector::Vector,
5};
6use std::sync::atomic::AtomicUsize;
7
8/// An affine space over a field.
9/// affine_dimension = 0 => the empty space
10/// affine_dimension = 1 => one point space
11/// affine_dimension = 2 => a line
12/// affine_dimension = 3 => a plane
13/// ...
14#[derive(Debug, Clone)]
15pub struct AffineSpace<'f, FS: FieldSignature> {
16    field: &'f FS,
17    // linear dimension = affine dimension - 1
18    affine_dimension: usize,
19    ident: usize,
20}
21
22impl<'f, FS: FieldSignature> Copy for AffineSpace<'f, FS> {}
23
24impl<'f, FS: FieldSignature> PartialEq for AffineSpace<'f, FS> {
25    fn eq(&self, other: &Self) -> bool {
26        #[cfg(debug_assertions)]
27        if self.ident == other.ident {
28            assert_eq!(self.affine_dimension, other.affine_dimension);
29            assert_eq!(self.field(), other.field());
30        }
31        self.ident == other.ident
32    }
33}
34
35impl<'f, FS: FieldSignature> Eq for AffineSpace<'f, FS> {}
36
37impl<'f, FS: FieldSignature + Hash> Hash for AffineSpace<'f, FS> {
38    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
39        self.ident.hash(state);
40    }
41}
42
43impl<'f, FS: FieldSignature> AffineSpace<'f, FS> {
44    pub fn new_affine(field: &'f FS, affine_dimension: usize) -> Self {
45        static COUNTER: AtomicUsize = AtomicUsize::new(0);
46        Self {
47            field,
48            affine_dimension,
49            ident: COUNTER.fetch_add(1, std::sync::atomic::Ordering::Relaxed),
50        }
51    }
52
53    pub fn new_empty(field: &'f FS) -> Self {
54        Self::new_affine(field, 0)
55    }
56
57    pub fn new_linear(field: &'f FS, linear_dimension: usize) -> Self {
58        Self::new_affine(field, linear_dimension + 1)
59    }
60
61    pub fn field(&self) -> &'f FS {
62        self.field
63    }
64
65    pub fn origin(&self) -> Option<Vector<'f, FS>> {
66        Some(Vector::construct(*self, |_| self.field().zero()))
67    }
68
69    pub fn empty_subset(&self) -> impl LabelledSimplexCollection<'f, FS, ()>
70    where
71        FS: OrderedRingSignature,
72        FS::Set: Hash,
73    {
74        SimplicialDisjointUnion::new_unchecked(*self, std::collections::HashSet::new())
75    }
76
77    pub fn linear_dimension(&self) -> Option<usize> {
78        if self.affine_dimension == 0 {
79            None
80        } else {
81            Some(self.affine_dimension - 1)
82        }
83    }
84
85    pub fn affine_dimension(&self) -> usize {
86        self.affine_dimension
87    }
88}
89
90pub fn common_space<'s, 'f, FS: FieldSignature + 'f>(
91    space1: AffineSpace<'f, FS>,
92    space2: AffineSpace<'f, FS>,
93) -> Option<AffineSpace<'f, FS>> {
94    if space1 == space2 { Some(space1) } else { None }
95}