Fix more bugs

This commit is contained in:
Austen Adler 2021-06-04 22:54:32 -04:00
parent 456dc6dcd4
commit b5e944e82c
3 changed files with 77 additions and 50 deletions

View File

@ -570,7 +570,7 @@ impl Calculator {
.map(|i| self.peek(i))
.collect::<CalculatorResult<Vec<Entry>>>()?;
let new_entry = Matrix::from(&entries)?;
let new_entry = Matrix::from(&entries[..])?;
entries.push(count_entry);
Ok(CalculatorStateChange {

View File

@ -7,6 +7,42 @@ use serde::{Deserialize, Serialize};
use std::cmp::PartialEq;
use std::fmt;
pub trait CalculatorEntry
where
Self: Sized,
{
// Misc
fn is_valid(&self) -> bool;
/// Turns self into a valid entry
fn validate(self) -> CalculatorResult<Entry>;
fn format_entry(&self, display_mode: &CalculatorDisplayMode) -> String;
fn to_editable_string(&self) -> CalculatorResult<String>;
// Mathematical operations
// Unary
fn negate(&self) -> CalculatorResult<Entry>;
fn abs(&self) -> CalculatorResult<Entry>;
fn inverse(&self) -> CalculatorResult<Entry>;
fn transpose(&self) -> CalculatorResult<Entry>;
fn sin(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult<Entry>;
fn cos(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult<Entry>;
fn tan(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult<Entry>;
fn asin(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult<Entry>;
fn acos(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult<Entry>;
fn atan(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult<Entry>;
fn sqrt(&self) -> CalculatorResult<Entry>;
fn log(&self) -> CalculatorResult<Entry>;
fn ln(&self) -> CalculatorResult<Entry>;
// Binary
fn add(&self, arg: &Entry) -> CalculatorResult<Entry>;
fn sub(&self, arg: &Entry) -> CalculatorResult<Entry>;
fn mul(&self, arg: &Entry) -> CalculatorResult<Entry>;
fn div(&self, arg: &Entry) -> CalculatorResult<Entry>;
fn int_divide(&self, arg: &Entry) -> CalculatorResult<Entry>;
fn modulo(&self, arg: &Entry) -> CalculatorResult<Entry>;
fn pow(&self, arg: &Entry) -> CalculatorResult<Entry>;
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
pub struct Number {
pub value: f64,
@ -397,7 +433,6 @@ impl CalculatorEntry for Matrix {
}
}
fn mul(&self, arg: &Entry) -> CalculatorResult<Entry> {
// TODO: Correct implementation
match arg {
Entry::Matrix(m2) => {
if self.dimensions.columns != m2.dimensions.rows {
@ -409,15 +444,35 @@ impl CalculatorEntry for Matrix {
};
// A matrix is a list of column vectors, so transpose self and zip the columns
// let transposed_self = self.transpose()?;
// for i in dimensions.rows {
// for j in dimensions.columns {
// }
// }
// self.vectors[0]
let transposed_self: Self = match self.transpose()? {
Entry::Matrix(t) => t,
_ => {
return Err(CalculatorError::InternalError(String::from(
"Matrix transpose produced wrong type",
)))
}
};
// TODO
let vectors = vec![];
let mut vectors: Vec<Vector> = vec![];
for c in &m2.vectors {
let mut vector: Vector = Vector {
values: vec![],
direction: VectorDirection::Column,
};
for r in &transposed_self.vectors {
if let Entry::Number(number) =
c.transpose()?.mul(&Entry::Vector(r.clone()))?
{
vector.values.push(number);
} else {
return Err(CalculatorError::InternalError(String::from(
"Vector multiplication did not produce a number",
)));
}
}
vectors.push(vector);
}
Self {
vectors,
@ -425,7 +480,9 @@ impl CalculatorEntry for Matrix {
}
.validate()
}
Entry::Vector(_vector) => Err(CalculatorError::TypeMismatch),
Entry::Vector(vector) => self.mul(&Self::from(
&[Entry::Vector(vector.clone())], // Treat a vector as a 1D matrix
)?),
Entry::Number(number) => self.iterated_binary_num(number, Vector::mul),
}
}
@ -669,8 +726,7 @@ impl CalculatorEntry for Vector {
}
fn mul(&self, arg: &Entry) -> CalculatorResult<Entry> {
match arg {
// TODO: Matrix multiplication should be allowed
Entry::Matrix(_) => Err(CalculatorError::TypeMismatch),
Entry::Matrix(_matrix) => Matrix::from(&[Entry::Vector(self.clone())])?.mul(arg),
Entry::Vector(v2) => {
if self.values.len() != v2.values.len() {
return Err(CalculatorError::DimensionMismatch);
@ -686,7 +742,9 @@ impl CalculatorEntry for Vector {
})
}
(VectorDirection::Column, VectorDirection::Row) => {
Err(CalculatorError::NotYetImplemented)
// TODO: Do we need to clone?
Matrix::from(&[Entry::Vector(self.clone())])?
.mul(&Matrix::from(&[arg.clone()])?)
}
(VectorDirection::Row, VectorDirection::Row)
| (VectorDirection::Column, VectorDirection::Column) => {
@ -1041,42 +1099,6 @@ impl Number {
}
}
pub trait CalculatorEntry
where
Self: Sized,
{
// Misc
fn is_valid(&self) -> bool;
/// Turns self into a valid entry
fn validate(self) -> CalculatorResult<Entry>;
fn format_entry(&self, display_mode: &CalculatorDisplayMode) -> String;
fn to_editable_string(&self) -> CalculatorResult<String>;
// Mathematical operations
// Unary
fn negate(&self) -> CalculatorResult<Entry>;
fn abs(&self) -> CalculatorResult<Entry>;
fn inverse(&self) -> CalculatorResult<Entry>;
fn transpose(&self) -> CalculatorResult<Entry>;
fn sin(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult<Entry>;
fn cos(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult<Entry>;
fn tan(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult<Entry>;
fn asin(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult<Entry>;
fn acos(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult<Entry>;
fn atan(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult<Entry>;
fn sqrt(&self) -> CalculatorResult<Entry>;
fn log(&self) -> CalculatorResult<Entry>;
fn ln(&self) -> CalculatorResult<Entry>;
// Binary
fn add(&self, arg: &Entry) -> CalculatorResult<Entry>;
fn sub(&self, arg: &Entry) -> CalculatorResult<Entry>;
fn mul(&self, arg: &Entry) -> CalculatorResult<Entry>;
fn div(&self, arg: &Entry) -> CalculatorResult<Entry>;
fn int_divide(&self, arg: &Entry) -> CalculatorResult<Entry>;
fn modulo(&self, arg: &Entry) -> CalculatorResult<Entry>;
fn pow(&self, arg: &Entry) -> CalculatorResult<Entry>;
}
impl fmt::Display for Entry {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {

View File

@ -17,6 +17,8 @@ pub enum CalculatorError {
DimensionMismatch,
/// Plans are in place to implement, but we are not there yet
NotYetImplemented,
/// Internal computation error
InternalError(String),
/// Thrown when an undo or redo cannot be performed
CorruptStateChange(String),
/// Cannot undo or redo
@ -53,6 +55,9 @@ impl fmt::Display for CalculatorError {
Self::TypeMismatch => write!(f, "Type mismatch"),
Self::DimensionMismatch => write!(f, "Dimension mismatch"),
Self::NotYetImplemented => write!(f, "Not yet implemented"),
Self::InternalError(msg) => {
write!(f, "Internal error: {}", msg)
}
Self::CorruptStateChange(msg) => {
write!(f, "Corrupt state change: {}", msg)
}