Fix more bugs
This commit is contained in:
parent
456dc6dcd4
commit
b5e944e82c
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user