Skip to main content

alice/maps/
exp_log.rs

1use crate::maps::faer_bridge;
2
3pub trait HasExpMap: Sized {
4    type Algebra: Clone + PartialEq;
5    fn exp(x: &Self::Algebra) -> Self;
6    fn log(&self) -> Option<Self::Algebra>;
7}
8
9pub trait MatrixExpMap: HasExpMap {
10    fn matrix_data(x: &Self::Algebra) -> (alloc::vec::Vec<f64>, usize);
11    fn from_matrix_data(data: alloc::vec::Vec<f64>, n: usize) -> Self;
12    fn algebra_from_matrix_data(data: alloc::vec::Vec<f64>, n: usize) -> Self::Algebra;
13    fn to_matrix_data(&self) -> (alloc::vec::Vec<f64>, usize);
14}
15
16impl<T: MatrixExpMap> HasExpMap for T {
17    type Algebra = T::Algebra;
18    fn exp(x: &Self::Algebra) -> Self {
19        let (data, n) = T::matrix_data(x);
20        let result = faer_bridge::matrix_exp(&data, n);
21        T::from_matrix_data(result, n)
22    }
23    fn log(&self) -> Option<Self::Algebra> {
24        let (data, n) = self.to_matrix_data();
25        let result = faer_bridge::matrix_log(&data, n)?;
26        Some(T::algebra_from_matrix_data(result, n))
27    }
28}
29
30pub fn exp_log_roundtrip_error(
31    data: &[f64],
32    n: usize,
33) -> Option<f64> {
34    let exp_data = faer_bridge::matrix_exp(data, n);
35    let log_data = faer_bridge::matrix_log(&exp_data, n)?;
36    let max_err = data.iter()
37        .zip(log_data.iter())
38        .map(|(a, b)| libm::fabs(a - b))
39        .fold(0.0f64, f64::max);
40    Some(max_err)
41}
42
43pub fn log_exp_roundtrip_error(
44    data: &[f64],
45    n: usize,
46) -> Option<f64> {
47    let log_data = faer_bridge::matrix_log(data, n)?;
48    let exp_data = faer_bridge::matrix_exp(&log_data, n);
49    let max_err = data.iter()
50        .zip(exp_data.iter())
51        .map(|(a, b)| libm::fabs(a - b))
52        .fold(0.0f64, f64::max);
53    Some(max_err)
54}