Write vector multiplication

This commit is contained in:
Austen Adler 2021-06-02 18:50:06 -04:00
parent 0405d25998
commit e3b5457fe6
3 changed files with 52 additions and 7 deletions

View File

@ -5,7 +5,7 @@ pub mod types;
use crate::calc::entries::CalculatorEntry; use crate::calc::entries::CalculatorEntry;
use confy::{load, store}; use confy::{load, store};
use entries::{Entry, Number, Vector}; use entries::{Entry, Number, Vector, VectorDirection};
use errors::{CalculatorError, CalculatorResult}; use errors::{CalculatorError, CalculatorResult};
use operations::{ use operations::{
ArithmeticOperation, CalculatorOperation, CalculatorStateChange, MacroState, OpArgs, ArithmeticOperation, CalculatorOperation, CalculatorStateChange, MacroState, OpArgs,
@ -552,7 +552,7 @@ impl Calculator {
.unzip(); .unzip();
let entry = Entry::Vector(Vector { let entry = Entry::Vector(Vector {
values, values,
direction: true, direction: VectorDirection::Row,
}); });
entries.push_front(count_entry); entries.push_front(count_entry);
Ok(CalculatorStateChange { Ok(CalculatorStateChange {

View File

@ -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)] #[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct Vector { pub struct Vector {
pub direction: bool, pub direction: VectorDirection,
pub values: Vec<Number>, pub values: Vec<Number>,
} }
@ -41,7 +63,7 @@ pub struct Vector {
pub enum Entry { pub enum Entry {
Number(Number), Number(Number),
Vector(Vector), Vector(Vector),
// Matrix(Vec<Vec<Number>>), // Matrix(Vec<Vector>),
} }
// macro_rules! op_child_call { // macro_rules! op_child_call {
@ -297,7 +319,7 @@ impl CalculatorEntry for Vector {
.iter() .iter()
.map(|number| number.format_entry(display_mode)) .map(|number| number.format_entry(display_mode))
.collect::<Vec<String>>() .collect::<Vec<String>>()
.join(if self.direction { "; " } else { " " }) .join(self.direction.get_separator())
) )
} }
// Mathematical operations // Mathematical operations
@ -316,7 +338,7 @@ impl CalculatorEntry for Vector {
fn inverse(&self) -> CalculatorResult<Entry> { fn inverse(&self) -> CalculatorResult<Entry> {
Ok(Entry::Vector(Vector { Ok(Entry::Vector(Vector {
values: self.values.clone(), values: self.values.clone(),
direction: !self.direction, direction: self.direction.swap(),
})) }))
} }
fn sin(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult<Entry> { fn sin(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult<Entry> {
@ -397,7 +419,27 @@ impl CalculatorEntry for Vector {
self.iterated_binary_vec(arg, Number::sub_num) self.iterated_binary_vec(arg, Number::sub_num)
} }
fn mul_vec(&self, arg: &Self) -> CalculatorResult<Entry> { fn mul_vec(&self, arg: &Self) -> CalculatorResult<Entry> {
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<Entry> { fn div_vec(&self, arg: &Self) -> CalculatorResult<Entry> {
self.iterated_binary_vec(arg, Number::div_num) self.iterated_binary_vec(arg, Number::div_num)

View File

@ -15,6 +15,8 @@ pub enum CalculatorError {
TypeMismatch, TypeMismatch,
/// Dimensions must match /// Dimensions must match
DimensionMismatch, DimensionMismatch,
/// Plans are in place to implement, but we are not there yet
NotYetImplemented,
/// Thrown when an undo or redo cannot be performed /// Thrown when an undo or redo cannot be performed
CorruptStateChange(String), CorruptStateChange(String),
/// Cannot undo or redo /// Cannot undo or redo
@ -50,6 +52,7 @@ impl fmt::Display for CalculatorError {
Self::NotEnoughStackEntries => write!(f, "Not enough items in the stack"), Self::NotEnoughStackEntries => write!(f, "Not enough items in the stack"),
Self::TypeMismatch => write!(f, "Type mismatch"), Self::TypeMismatch => write!(f, "Type mismatch"),
Self::DimensionMismatch => write!(f, "Dimension mismatch"), Self::DimensionMismatch => write!(f, "Dimension mismatch"),
Self::NotYetImplemented => write!(f, "Not yet implemented"),
Self::CorruptStateChange(msg) => { Self::CorruptStateChange(msg) => {
write!(f, "Corrupt state change: {}", msg) write!(f, "Corrupt state change: {}", msg)
} }