From e3b5457fe62f9ddabe4cbfd18d4921f1c1a8b3e1 Mon Sep 17 00:00:00 2001 From: Austen Adler Date: Wed, 2 Jun 2021 18:50:06 -0400 Subject: [PATCH] Write vector multiplication --- src/calc.rs | 4 ++-- src/calc/entries.rs | 52 ++++++++++++++++++++++++++++++++++++++++----- src/calc/errors.rs | 3 +++ 3 files changed, 52 insertions(+), 7 deletions(-) diff --git a/src/calc.rs b/src/calc.rs index 426e00c..703c7b7 100644 --- a/src/calc.rs +++ b/src/calc.rs @@ -5,7 +5,7 @@ pub mod types; use crate::calc::entries::CalculatorEntry; use confy::{load, store}; -use entries::{Entry, Number, Vector}; +use entries::{Entry, Number, Vector, VectorDirection}; use errors::{CalculatorError, CalculatorResult}; use operations::{ ArithmeticOperation, CalculatorOperation, CalculatorStateChange, MacroState, OpArgs, @@ -552,7 +552,7 @@ impl Calculator { .unzip(); let entry = Entry::Vector(Vector { values, - direction: true, + direction: VectorDirection::Row, }); entries.push_front(count_entry); Ok(CalculatorStateChange { diff --git a/src/calc/entries.rs b/src/calc/entries.rs index c5b54c6..eb8d12e 100644 --- a/src/calc/entries.rs +++ b/src/calc/entries.rs @@ -30,9 +30,31 @@ impl PartialEq for Number { } } +#[derive(PartialEq, Copy, Clone, Debug, Serialize, Deserialize)] +pub enum VectorDirection { + Row, + Column, +} + +impl VectorDirection { + pub fn swap(&self) -> Self { + match self { + Self::Row => Self::Column, + Self::Column => Self::Row, + } + } + + pub fn get_separator(&self) -> &str { + match self { + Self::Row => " ", + Self::Column => "; ", + } + } +} + #[derive(Clone, PartialEq, Debug, Serialize, Deserialize)] pub struct Vector { - pub direction: bool, + pub direction: VectorDirection, pub values: Vec, } @@ -41,7 +63,7 @@ pub struct Vector { pub enum Entry { Number(Number), Vector(Vector), - // Matrix(Vec>), + // Matrix(Vec), } // macro_rules! op_child_call { @@ -297,7 +319,7 @@ impl CalculatorEntry for Vector { .iter() .map(|number| number.format_entry(display_mode)) .collect::>() - .join(if self.direction { "; " } else { " " }) + .join(self.direction.get_separator()) ) } // Mathematical operations @@ -316,7 +338,7 @@ impl CalculatorEntry for Vector { fn inverse(&self) -> CalculatorResult { Ok(Entry::Vector(Vector { values: self.values.clone(), - direction: !self.direction, + direction: self.direction.swap(), })) } fn sin(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult { @@ -397,7 +419,27 @@ impl CalculatorEntry for Vector { self.iterated_binary_vec(arg, Number::sub_num) } fn mul_vec(&self, arg: &Self) -> CalculatorResult { - self.iterated_binary_vec(arg, Number::mul_num) + if self.values.len() != arg.values.len() { + return Err(CalculatorError::DimensionMismatch); + } + match (self.direction, arg.direction) { + (VectorDirection::Row, VectorDirection::Column) => { + // Row by column -- will produce a scalar + self.values + .iter() + .zip(arg.values.iter()) + .try_fold(Entry::Number(Number::ZERO), |acc, (n1, n2)| { + acc.add(&n1.mul_num(n2)?) + }) + } + (VectorDirection::Column, VectorDirection::Row) => { + Err(CalculatorError::NotYetImplemented) + } + (VectorDirection::Row, VectorDirection::Row) + | (VectorDirection::Column, VectorDirection::Column) => { + Err(CalculatorError::DimensionMismatch) + } + } } fn div_vec(&self, arg: &Self) -> CalculatorResult { self.iterated_binary_vec(arg, Number::div_num) diff --git a/src/calc/errors.rs b/src/calc/errors.rs index 7421c8a..6882f60 100644 --- a/src/calc/errors.rs +++ b/src/calc/errors.rs @@ -15,6 +15,8 @@ pub enum CalculatorError { TypeMismatch, /// Dimensions must match DimensionMismatch, + /// Plans are in place to implement, but we are not there yet + NotYetImplemented, /// Thrown when an undo or redo cannot be performed CorruptStateChange(String), /// Cannot undo or redo @@ -50,6 +52,7 @@ impl fmt::Display for CalculatorError { Self::NotEnoughStackEntries => write!(f, "Not enough items in the stack"), Self::TypeMismatch => write!(f, "Type mismatch"), Self::DimensionMismatch => write!(f, "Dimension mismatch"), + Self::NotYetImplemented => write!(f, "Not yet implemented"), Self::CorruptStateChange(msg) => { write!(f, "Corrupt state change: {}", msg) }