diff --git a/math/src/matrix.rs b/math/src/matrix.rs index b96eb6d..5f677bb 100644 --- a/math/src/matrix.rs +++ b/math/src/matrix.rs @@ -36,6 +36,14 @@ impl Matrix { pub fn column(&self, j: usize) -> Vec { self.iter_column(j).cloned().collect() } + + pub fn append_row_zeroes(&mut self) { + self.append_row(vec![T::zero(); self.width]) + } + + pub fn append_column_zeroes(&mut self) { + self.append_column(vec![T::zero(); self.height()]) + } } impl Matrix { @@ -75,6 +83,25 @@ impl Matrix { pub fn can_mul(&self, other: &Self) -> bool { self.width == other.height() } + + pub fn append_row(&mut self, mut row: Vec) { + if row.len() != self.width { + panic!("Unable to append row with len {} to matrix with width {}", row.len(), self.width); + } + self.data.append(&mut row); + } + + pub fn append_column(&mut self, column: Vec) { + let height = self.height(); + if column.len() != height { + panic!("Unable to append row with len {} to matrix with width {}", column.len(), height); + } + for (i, e) in column.into_iter().enumerate() { + let insert_at = (i + 1) * self.width + i; + self.data.insert(insert_at, e); + } + self.width += 1; + } } impl Index for Matrix { @@ -175,4 +202,62 @@ mod tests { assert_eq!(matrix.column(1), vec![2, 5, 8]); assert_eq!(matrix.column(2), vec![3, 6, 9]); } + + #[test] + fn append_row_and_column() { + let mut matrix = matrix![2; + 1, 2, + 3, 4 + ]; + matrix.append_row(vec![5, 6]); + assert_eq!(matrix, matrix![2; + 1, 2, + 3, 4, + 5, 6 + ]); + matrix.append_column(vec![7, 8, 9]); + assert_eq!(matrix, matrix![3; + 1, 2, 7, + 3, 4, 8, + 5, 6, 9 + ]); + } + + #[test] + fn append_row_and_column_zeroes() { + let mut matrix = matrix![2; + 1, 2, + 3, 4 + ]; + matrix.append_row_zeroes(); + assert_eq!(matrix, matrix![2; + 1, 2, + 3, 4, + 0, 0 + ]); + matrix.append_column_zeroes(); + assert_eq!(matrix, matrix![3; + 1, 2, 0, + 3, 4, 0, + 0, 0, 0 + ]); + } + + #[test] + #[should_panic(expected = "Unable to append")] + fn append_row_wrong_width() { + matrix![2; + 1, 2, + 3, 4 + ].append_row(vec![1, 2, 3]); + } + + #[test] + #[should_panic(expected = "Unable to append")] + fn append_column_wrong_height() { + matrix![2; + 1, 2, + 3, 4 + ].append_column(vec![1, 2, 3]); + } } diff --git a/web/index.html b/web/index.html index d0b1245..f01b0d6 100644 --- a/web/index.html +++ b/web/index.html @@ -1,5 +1,5 @@ - + Mathematical diff --git a/web/index.scss b/web/index.scss index d10053c..0e50fa8 100644 --- a/web/index.scss +++ b/web/index.scss @@ -1,5 +1,18 @@ $bg-color: #2b2927; +$text-color: #e2e19c; +$cell-color: #473b34; html, body { background-color: $bg-color; + color: $text-color; + position: absolute; + top: 50%; + left: 50%; +} + +.matrix-cell { + background-color: $cell-color; + color: $text-color; + border: solid 1px black; + width: 30pt; } diff --git a/web/src/main.rs b/web/src/main.rs index 6f6fb95..914006f 100644 --- a/web/src/main.rs +++ b/web/src/main.rs @@ -1,9 +1,95 @@ +use math::matrix::Matrix; use yew::prelude::*; +pub struct MatrixComponent { + matrix: Matrix +} + +pub enum MatrixMsg { + CellChange(Cell), + AddRow, + AddColumn +} + +impl Component for MatrixComponent { + type Message = MatrixMsg; + type Properties = (); + + fn create(_ctx: &Context) -> Self { + Self { matrix: Matrix::new_zeroes(3, 3) } + } + + fn update(&mut self, _ctx: &Context, msg: Self::Message) -> bool { + match msg { + MatrixMsg::CellChange(cell) => self.matrix[cell.i][cell.j] = cell.value, + MatrixMsg::AddRow => self.matrix.append_row_zeroes(), + MatrixMsg::AddColumn => self.matrix.append_column_zeroes() + } + return true; + } + + fn view(&self, ctx: &Context) -> Html { + let on_cell_change = ctx.link().callback(MatrixMsg::CellChange); + html! { + { + self.matrix.iter_rows().enumerate().map(|(i, row)| html! { + { + row.iter().enumerate().map(|(j, e)| { + let cell = Cell { i, j, value: *e }; + html! { + + } + }).collect::() + } + + }).collect::() + } +
+ +
+ } + } +} + +pub struct MatrixCellComponent; + +#[derive(PartialEq, Properties)] +pub struct MatrixCellProps { + pub cell: Cell, + pub on_cell_change: Callback +} + +#[derive(PartialEq, Clone, Copy)] +pub struct Cell { + i: usize, j: usize, value: f64 +} + +impl Component for MatrixCellComponent { + type Message = (); + type Properties = MatrixCellProps; + + fn create(_ctx: &Context) -> Self { + Self + } + + fn view(&self, ctx: &Context) -> Html { + let cell = ctx.props().cell.clone(); + let oninput = ctx.props().on_cell_change + .reform(move |e: InputEvent| + Cell { i: cell.i, j: cell.j, value: e.as_f64().unwrap_or_default() } + ); + html! { + + } + } +} + #[function_component] fn App() -> Html { html! { -

{"Hello World!"}

+ <> + + } }