math_rs/matrix/float/
parser.rs

1use crate::{
2    matrix::traits::{Matrix, Parseable, Serializable},
3    result::{MathError, Result},
4};
5
6use super::MatrixF32;
7
8impl Parseable for MatrixF32 {
9    fn parse(input: &str, tolerance: f32) -> Result<Self> {
10        parse_matrix(input, tolerance)
11    }
12}
13
14impl Serializable for MatrixF32 {
15    fn serialize(&self) -> String {
16        serialize_matrix(self)
17    }
18}
19
20pub fn parse_matrix(input: &str, tolerance: f32) -> Result<MatrixF32> {
21    let mut matrix = vec![];
22    let processed_input = input.trim().split_whitespace().collect::<String>();
23    let inner = processed_input
24        .trim_start_matches('{')
25        .trim_end_matches('}')
26        .trim();
27    for row_str in inner.split("},{") {
28        let row = row_str
29            .split(',')
30            .map(|s| -> Result<f32> {
31                s.parse().map_err(|_| {
32                    MathError::MatrixError(format!("Could not parse matrix due to parsing error",))
33                })
34            })
35            .collect::<Result<Vec<f32>>>()?;
36        matrix.push(row);
37    }
38    MatrixF32::new(matrix, tolerance)
39}
40
41pub fn serialize_matrix(matrix: &MatrixF32) -> String {
42    let mut result = String::new();
43    let push_row = |res: &mut String, row_number: usize| {
44        res.push('{');
45        for j in 0..matrix.columns() - 1 {
46            // TODO: Remove this unwrap
47            res.push_str(matrix.get(row_number, j).unwrap().to_string().as_str());
48            res.push_str(", ")
49        }
50        res.push_str(
51            matrix
52                .get(row_number, matrix.columns() - 1)
53                .unwrap()
54                .to_string()
55                .as_str(),
56        );
57        res.push('}');
58    };
59
60    result.push('{');
61    for i in 0..matrix.rows() - 1 {
62        push_row(&mut result, i);
63        result.push_str(", ");
64    }
65    push_row(&mut result, matrix.rows() - 1);
66
67    result.push('}');
68    result
69}
70
71#[cfg(test)]
72mod test {
73
74    use std::str::FromStr;
75
76    use super::{serialize_matrix, MatrixF32};
77
78    const TOLERANCE: f32 = 1E-12;
79
80    #[test]
81    fn parse_2x2() {
82        let matrix = MatrixF32::from_str("{{1,2},{2,3}}")
83            .expect("Should have been able to parse this matrix");
84
85        println!("{matrix}");
86        pretty_assertions::assert_eq!(
87            matrix,
88            MatrixF32::new(vec![vec![1.0, 2.0], vec![2.0, 3.0]], TOLERANCE)
89                .expect("Should've been able to built this matrix")
90        )
91    }
92
93    #[test]
94    fn parse_3x5() {
95        let matrix = MatrixF32::from_str("{{1,2,3,4,5}, {5,4,3,2,1}, {0,0,0,0,0}}")
96            .expect("Should have been able to parse this matrix");
97        println!("{matrix}");
98        pretty_assertions::assert_eq!(
99            matrix,
100            MatrixF32::new(
101                vec![
102                    vec![1.0, 2.0, 3.0, 4.0, 5.0],
103                    vec![5.0, 4.0, 3.0, 2.0, 1.0],
104                    vec![0.0, 0.0, 0.0, 0.0, 0.0]
105                ],
106                TOLERANCE
107            )
108            .expect("Should've been able to built this matrix")
109        )
110    }
111
112    #[test]
113    fn serialize_2x2() {
114        let matrix = MatrixF32::new(vec![vec![1.1, 1.1], vec![1.1, 1.1]], TOLERANCE).unwrap();
115        pretty_assertions::assert_str_eq!("{{1.1, 1.1}, {1.1, 1.1}}", serialize_matrix(&matrix))
116    }
117}