Skip to main content

alice/topology/
manifold.rs

1use alloc::boxed::Box;
2use alloc::vec::Vec;
3use crate::core::scalar::Scalar;
4
5pub trait Dim: Copy + Eq + core::fmt::Debug {
6    fn value(&self) -> usize;
7}
8
9#[derive(Clone, Copy, PartialEq, Eq, Debug)]
10pub struct Const<const N: usize>;
11
12#[derive(Clone, Copy, PartialEq, Eq, Debug)]
13pub struct Dynamic(usize);
14
15impl<const N: usize> Dim for Const<N> {
16    fn value(&self) -> usize {
17        N
18    }
19}
20
21impl Dynamic {
22    pub fn new(n: usize) -> Self {
23        Self(n)
24    }
25}
26
27impl Dim for Dynamic {
28    fn value(&self) -> usize {
29        self.0
30    }
31}
32
33pub struct Point<S: Scalar> {
34    coords: Vec<S>,
35}
36
37impl<S: Scalar> Point<S> {
38    pub fn new(coords: Vec<S>) -> Self {
39        Self { coords }
40    }
41
42    pub fn dim(&self) -> usize {
43        self.coords.len()
44    }
45
46    pub fn coords(&self) -> &[S] {
47        &self.coords
48    }
49
50    pub fn get(&self, i: usize) -> Option<&S> {
51        self.coords.get(i)
52    }
53}
54
55impl<S: Scalar + PartialEq> PartialEq for Point<S> {
56    fn eq(&self, other: &Self) -> bool {
57        self.coords == other.coords
58    }
59}
60
61impl<S: Scalar + Eq> Eq for Point<S> {}
62
63impl<S: Scalar + Clone> Clone for Point<S> {
64    fn clone(&self) -> Self {
65        Self {
66            coords: self.coords.clone(),
67        }
68    }
69}
70
71pub struct TangentVector<S: Scalar> {
72    components: Vec<S>,
73}
74
75impl<S: Scalar> TangentVector<S> {
76    pub fn new(components: Vec<S>) -> Self {
77        Self { components }
78    }
79
80    pub fn dim(&self) -> usize {
81        self.components.len()
82    }
83
84    pub fn components(&self) -> &[S] {
85        &self.components
86    }
87}
88
89impl<S: Scalar + Clone> Clone for TangentVector<S> {
90    fn clone(&self) -> Self {
91        Self {
92            components: self.components.clone(),
93        }
94    }
95}
96
97pub struct Chart<S: Scalar> {
98    dim: usize,
99    to_euclidean: Box<dyn Fn(&Point<S>) -> Point<S> + Send + Sync>,
100    from_euclidean: Box<dyn Fn(&Point<S>) -> Point<S> + Send + Sync>,
101    domain_check: Box<dyn Fn(&Point<S>) -> bool + Send + Sync>,
102}
103
104impl<S: Scalar> Chart<S> {
105    pub fn new<F, G, D>(dim: usize, to_euclidean: F, from_euclidean: G, domain_check: D) -> Self
106    where
107        F: Fn(&Point<S>) -> Point<S> + Send + Sync + 'static,
108        G: Fn(&Point<S>) -> Point<S> + Send + Sync + 'static,
109        D: Fn(&Point<S>) -> bool + Send + Sync + 'static,
110    {
111        Self {
112            dim,
113            to_euclidean: Box::new(to_euclidean),
114            from_euclidean: Box::new(from_euclidean),
115            domain_check: Box::new(domain_check),
116        }
117    }
118
119    pub fn dim(&self) -> usize {
120        self.dim
121    }
122
123    pub fn contains(&self, p: &Point<S>) -> bool {
124        (self.domain_check)(p)
125    }
126
127    pub fn to_euclidean(&self, p: &Point<S>) -> Point<S> {
128        (self.to_euclidean)(p)
129    }
130
131    pub fn from_euclidean(&self, p: &Point<S>) -> Point<S> {
132        (self.from_euclidean)(p)
133    }
134}
135
136pub struct Atlas<S: Scalar> {
137    charts: Vec<Chart<S>>,
138    dim: usize,
139}
140
141impl<S: Scalar> Atlas<S> {
142    pub fn new(dim: usize) -> Self {
143        Self {
144            charts: Vec::new(),
145            dim,
146        }
147    }
148
149    pub fn add_chart(&mut self, chart: Chart<S>) {
150        assert_eq!(
151            chart.dim(),
152            self.dim,
153            "chart dimension must match atlas dimension"
154        );
155        self.charts.push(chart);
156    }
157
158    pub fn dim(&self) -> usize {
159        self.dim
160    }
161
162    pub fn covers(&self, p: &Point<S>) -> bool {
163        self.charts.iter().any(|c| c.contains(p))
164    }
165
166    pub fn chart_for(&self, p: &Point<S>) -> Option<&Chart<S>> {
167        self.charts.iter().find(|c| c.contains(p))
168    }
169
170    pub fn charts(&self) -> &[Chart<S>] {
171        &self.charts
172    }
173}
174
175pub trait Manifold {
176    type Scalar: Scalar;
177    fn dim(&self) -> usize;
178    fn atlas(&self) -> &Atlas<Self::Scalar>;
179    fn tangent_space_dim(&self) -> usize {
180        self.dim()
181    }
182    fn contains(&self, p: &Point<Self::Scalar>) -> bool {
183        self.atlas().covers(p)
184    }
185    fn chart_for(&self, p: &Point<Self::Scalar>) -> Option<&Chart<Self::Scalar>> {
186        self.atlas().chart_for(p)
187    }
188}