sim_lib_view_math/
matrix.rs1use sim_kernel::{Expr, Symbol};
8use sim_lib_scene::{node, sym};
9
10use crate::num::{as_f64, number};
11
12pub const MATRIX_LENS: &str = "view:math-matrix";
14
15pub fn matrix(rows: &[Vec<f64>]) -> Expr {
17 Expr::List(
18 rows.iter()
19 .map(|row| Expr::List(row.iter().map(|value| number(*value)).collect()))
20 .collect(),
21 )
22}
23
24pub fn matrix_view(value: &Expr) -> Expr {
26 let rows = matrix_rows(value);
27 node(
28 "matrix",
29 vec![("rows", Expr::List(rows)), ("editable", Expr::Bool(true))],
30 )
31}
32
33pub fn labeled_matrix_view(
35 lens: &str,
36 role: &str,
37 value: &Expr,
38 row_labels: &[&str],
39 col_labels: &[&str],
40) -> Expr {
41 node(
42 "matrix",
43 vec![
44 ("lens", Expr::Symbol(Symbol::new(lens))),
45 ("role", sym(role)),
46 ("rows", Expr::List(matrix_rows(value))),
47 ("row-labels", string_list(row_labels)),
48 ("col-labels", string_list(col_labels)),
49 ("editable", Expr::Bool(true)),
50 ],
51 )
52}
53
54pub fn set_cell(value: &Expr, row: usize, col: usize, new_value: f64) -> Expr {
57 let Expr::List(rows) = value else {
58 return value.clone();
59 };
60 let mut rows = rows.clone();
61 if let Some(Expr::List(cells)) = rows.get_mut(row)
62 && col < cells.len()
63 {
64 cells[col] = number(new_value);
65 }
66 Expr::List(rows)
67}
68
69pub fn cell(value: &Expr, row: usize, col: usize) -> Option<f64> {
71 let Expr::List(rows) = value else {
72 return None;
73 };
74 match rows.get(row) {
75 Some(Expr::List(cells)) => cells.get(col).and_then(as_f64),
76 _ => None,
77 }
78}
79
80pub fn cell_path(row: usize, col: usize) -> Expr {
83 sim_value::path::Path::new().index(row).index(col).to_expr()
84}
85
86fn matrix_rows(value: &Expr) -> Vec<Expr> {
87 match value {
88 Expr::List(rows) => rows
89 .iter()
90 .map(|row| match row {
91 Expr::List(cells) => Expr::List(cells.clone()),
92 other => Expr::List(vec![other.clone()]),
93 })
94 .collect(),
95 _ => Vec::new(),
96 }
97}
98
99fn string_list(values: &[&str]) -> Expr {
100 Expr::List(
101 values
102 .iter()
103 .map(|value| Expr::String((*value).to_owned()))
104 .collect(),
105 )
106}