1use alloc::vec::Vec;
2use core::marker::PhantomData;
3use crate::core::ops::{Group, Magma, Monoid, Semigroup, TopologicalGroup};
4use crate::groups::matrix_group::{GroupError, MatrixGroup};
5use crate::topology::manifold::{Atlas, Dim, Manifold};
6use crate::core::scalar::FiniteF64;
7use crate::maps::exp_log::HasExpMap;
8
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct Gl<D: Dim> {
11 inner: MatrixGroup,
12 _dim: PhantomData<D>,
13}
14
15#[derive(Debug, Clone, PartialEq, Eq)]
16pub struct GlAlgebra<D: Dim> {
17 inner: MatrixGroup,
18 _dim: PhantomData<D>,
19}
20
21impl<D: Dim> Gl<D> {
22 pub fn new(data: Vec<f64>, dim: D) -> Result<Self, GroupError> {
23 let n = dim.value();
24 let inner = MatrixGroup::new(data, n)?;
25 if libm::fabs(inner.det()) < 1e-14 {
26 return Err(GroupError::ConstraintViolated("matrix must be invertible"));
27 }
28 Ok(Self { inner, _dim: PhantomData })
29 }
30
31 pub fn identity(dim: D) -> Self {
32 Self { inner: MatrixGroup::identity(dim.value()), _dim: PhantomData }
33 }
34
35 pub fn n(&self) -> usize { self.inner.n() }
36 pub fn data(&self) -> Vec<f64> { self.inner.data() }
37 pub fn det(&self) -> f64 { self.inner.det() }
38}
39
40impl<D: Dim> GlAlgebra<D> {
41 pub fn new(data: Vec<f64>, dim: D) -> Result<Self, GroupError> {
42 let inner = MatrixGroup::new(data, dim.value())?;
43 Ok(Self { inner, _dim: PhantomData })
44 }
45
46 pub fn zero(dim: D) -> Self {
47 Self {
48 inner: MatrixGroup::new(alloc::vec![0.0; dim.value() * dim.value()], dim.value()).unwrap(),
49 _dim: PhantomData,
50 }
51 }
52
53 pub fn data(&self) -> Vec<f64> { self.inner.data() }
54 pub fn n(&self) -> usize { self.inner.n() }
55}
56
57impl<D: Dim> Magma for Gl<D> {
58 fn op(&self, other: &Self) -> Self {
59 Self {
60 inner: self.inner.mul(&other.inner).expect("GL multiplication must succeed"),
61 _dim: PhantomData,
62 }
63 }
64}
65
66impl<D: Dim> Semigroup for Gl<D> {}
67
68impl<D: Dim> Monoid for Gl<D> {
69 fn identity() -> Self {
70 panic!("GL identity requires dimension; use Gl::identity(dim)")
71 }
72}
73
74impl<D: Dim> Group for Gl<D> {
75 fn inverse(&self) -> Self {
76 Self {
77 inner: self.inner.inverse().expect("GL element must be invertible"),
78 _dim: PhantomData,
79 }
80 }
81}
82
83impl<D: Dim> TopologicalGroup for Gl<D> {}
84
85impl<D: Dim> Manifold for Gl<D> {
86 type Scalar = FiniteF64;
87 fn dim(&self) -> usize { self.inner.n() * self.inner.n() }
88 fn atlas(&self) -> &Atlas<FiniteF64> { unimplemented!("GL atlas not yet constructed") }
89}
90
91impl<D: Dim> HasExpMap for Gl<D> {
92 type Algebra = GlAlgebra<D>;
93 fn exp(x: &GlAlgebra<D>) -> Self {
94 Self { inner: x.inner.exp(), _dim: PhantomData }
95 }
96 fn log(&self) -> Option<GlAlgebra<D>> {
97 Some(GlAlgebra { inner: self.inner.log()?, _dim: PhantomData })
98 }
99}