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