Fix vector building
This commit is contained in:
parent
d92a6fbdb0
commit
677444b7ff
19
src/calc.rs
19
src/calc.rs
@ -548,14 +548,15 @@ impl Calculator {
|
||||
pub fn build_vector(&mut self) -> CalculatorResult<CalculatorStateChange> {
|
||||
let (count, count_entry) = self.peek_usize()?;
|
||||
let mut entries: Vec<Entry> = (1..=count)
|
||||
.rev()
|
||||
.map(|i| self.peek(i))
|
||||
.collect::<CalculatorResult<Vec<Entry>>>()?;
|
||||
|
||||
let new_entry = Vector::from(&entries)?;
|
||||
|
||||
entries.splice(1..1, vec![count_entry]);
|
||||
entries.push(count_entry);
|
||||
Ok(CalculatorStateChange {
|
||||
pop: OpArgs::Variable(Vec::from(entries)),
|
||||
pop: OpArgs::Variable(entries.into_iter().rev().collect::<Vec<Entry>>()),
|
||||
push: OpArgs::Unary(new_entry),
|
||||
})
|
||||
}
|
||||
@ -801,14 +802,10 @@ impl Calculator {
|
||||
self.stack.pop_front();
|
||||
}
|
||||
OpArgs::Variable(entries) => {
|
||||
if entries
|
||||
entries
|
||||
.iter()
|
||||
.enumerate()
|
||||
.any(|(i, e)| self.stack_eq(i, e).is_err())
|
||||
{
|
||||
// TODO: Return an error if there is one
|
||||
return Err(CalculatorError::ArithmeticError);
|
||||
}
|
||||
.try_for_each(|(i, e)| self.stack_eq(i, e))?;
|
||||
|
||||
for _ in 0..entries.len() {
|
||||
self.stack.pop_front();
|
||||
@ -819,11 +816,11 @@ impl Calculator {
|
||||
|
||||
match to_push {
|
||||
OpArgs::Unary(a) => {
|
||||
self.stack.push_front(a.clone()); // TODO: Remove the clones
|
||||
self.stack.push_front(a.clone());
|
||||
}
|
||||
OpArgs::Binary([a, b]) => {
|
||||
self.stack.push_front(b.clone()); // TODO: Remove the clones
|
||||
self.stack.push_front(a.clone()); // TODO: Remove the clones
|
||||
self.stack.push_front(b.clone());
|
||||
self.stack.push_front(a.clone());
|
||||
}
|
||||
OpArgs::Variable(entries) => {
|
||||
for e in entries.iter().rev() {
|
||||
|
@ -52,17 +52,29 @@ impl VectorDirection {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for VectorDirection {
|
||||
fn default() -> Self {
|
||||
// Column vectors are the default
|
||||
Self::Column
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
|
||||
pub struct Vector {
|
||||
pub values: Vec<Number>,
|
||||
pub direction: VectorDirection,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
|
||||
pub struct MatrixDimensions {
|
||||
rows: usize,
|
||||
columns: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
|
||||
pub struct Matrix {
|
||||
pub vectors: Vec<Vector>,
|
||||
pub dimensions: (usize, usize),
|
||||
pub direction: VectorDirection,
|
||||
pub dimensions: MatrixDimensions,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
|
||||
@ -252,11 +264,15 @@ impl CalculatorEntry for Matrix {
|
||||
Err(CalculatorError::TypeMismatch)
|
||||
}
|
||||
fn is_valid(&self) -> bool {
|
||||
self.vectors.len() == self.dimensions.0
|
||||
// The the number of vectors is equal to the 0th dimension
|
||||
self.vectors.len() == self.dimensions.columns
|
||||
// The number of elements in all vectors are equal to the 1st dimension, and each is valid
|
||||
&& self
|
||||
.vectors
|
||||
.iter()
|
||||
.all(|v| v.values.len() == self.dimensions.1 && v.is_valid())
|
||||
.all(|v| v.values.len() == self.dimensions.rows && v.is_valid())
|
||||
// The dimensions are not zero
|
||||
&& self.dimensions.rows > 0 && self.dimensions.columns > 0
|
||||
}
|
||||
fn format_entry(&self, display_mode: &CalculatorDisplayMode) -> String {
|
||||
format!(
|
||||
@ -265,7 +281,7 @@ impl CalculatorEntry for Matrix {
|
||||
.iter()
|
||||
.map(|vector| vector.format_entry(display_mode))
|
||||
.collect::<Vec<String>>()
|
||||
.join(self.direction.get_separator())
|
||||
.join(" ")
|
||||
)
|
||||
}
|
||||
|
||||
@ -275,22 +291,25 @@ impl CalculatorEntry for Matrix {
|
||||
}
|
||||
fn abs(&self) -> CalculatorResult<Entry> {
|
||||
// TODO: Compute determinant
|
||||
// let value: Entry = self
|
||||
// .vectors
|
||||
// .iter()
|
||||
// .try_fold(Entry::Number(Vector::ZERO), |acc, vector| {
|
||||
// acc.add(&vector.abs()?)
|
||||
// })?;
|
||||
// value.sqrt()
|
||||
Err(CalculatorError::NotYetImplemented)
|
||||
}
|
||||
fn inverse(&self) -> CalculatorResult<Entry> {
|
||||
// TODO: Matrix inverse
|
||||
// Ok(Entry::Vector(Self {
|
||||
// vectors: self.vectors.clone(),
|
||||
Err(CalculatorError::NotYetImplemented)
|
||||
// TODO: Figure out where to put transpose function.
|
||||
// Self {
|
||||
// vectors: self
|
||||
// .vectors
|
||||
// .iter()
|
||||
// .map(|v| v.inverse())
|
||||
// .map(|e| match e {
|
||||
// Ok(Entry::Vector(vector)) => Ok(vector),
|
||||
// _ => Err(CalculatorError::ArithmeticError),
|
||||
// })
|
||||
// .collect::<CalculatorResult<Vec<Vector>>>()?,
|
||||
// direction: self.direction.swap(),
|
||||
// }))
|
||||
self.iterated_unary(Vector::inverse)
|
||||
// dimensions: self.dimensions,
|
||||
// }
|
||||
// .validate()
|
||||
}
|
||||
fn sin(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult<Entry> {
|
||||
self.iterated_unary(|v| v.sin(angle_mode))
|
||||
@ -338,7 +357,32 @@ impl CalculatorEntry for Matrix {
|
||||
fn mul(&self, arg: &Entry) -> CalculatorResult<Entry> {
|
||||
// TODO: Correct implementation
|
||||
match arg {
|
||||
Entry::Matrix(m2) => self.iterated_binary_mat(m2, Vector::mul),
|
||||
Entry::Matrix(m2) => {
|
||||
if self.dimensions.columns != m2.dimensions.rows {
|
||||
return Err(CalculatorError::DimensionMismatch);
|
||||
}
|
||||
let dimensions = MatrixDimensions {
|
||||
rows: self.dimensions.rows,
|
||||
columns: m2.dimensions.columns,
|
||||
};
|
||||
|
||||
// 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]
|
||||
|
||||
// TODO
|
||||
let vectors = vec![];
|
||||
|
||||
Self {
|
||||
vectors,
|
||||
dimensions,
|
||||
}
|
||||
.validate()
|
||||
}
|
||||
Entry::Vector(_vector) => Err(CalculatorError::TypeMismatch),
|
||||
Entry::Number(number) => self.iterated_binary_num(number, Vector::mul),
|
||||
}
|
||||
@ -387,23 +431,30 @@ impl Matrix {
|
||||
})
|
||||
.collect::<CalculatorResult<Vec<Vector>>>()?;
|
||||
|
||||
// Get the depth of the matrix
|
||||
let depth = vectors
|
||||
// Get the num_rows and dimension of the matrix
|
||||
let first_vector = vectors
|
||||
.get(0)
|
||||
.ok_or(CalculatorError::NotEnoughStackEntries)?
|
||||
.values
|
||||
.len();
|
||||
.ok_or(CalculatorError::NotEnoughStackEntries)?;
|
||||
let num_rows = first_vector.values.len();
|
||||
let vector_direction = first_vector.direction;
|
||||
|
||||
if vectors.iter().any(|v| v.values.len() != depth) {
|
||||
// TODO: Only build a matrix for column vectors; transpose if they are row vectors
|
||||
|
||||
if vectors
|
||||
.iter()
|
||||
.any(|v| v.values.len() != num_rows || v.direction != vector_direction)
|
||||
{
|
||||
// One vector has a different length than another
|
||||
return Err(CalculatorError::DimensionMismatch);
|
||||
}
|
||||
|
||||
let dimensions: (usize, usize) = (vectors.len(), depth);
|
||||
let dimensions = MatrixDimensions {
|
||||
rows: num_rows,
|
||||
columns: vectors.len(),
|
||||
};
|
||||
Self {
|
||||
vectors,
|
||||
dimensions,
|
||||
direction: VectorDirection::Row,
|
||||
}
|
||||
.validate()
|
||||
}
|
||||
@ -431,8 +482,7 @@ impl Matrix {
|
||||
_ => Err(CalculatorError::ArithmeticError),
|
||||
})
|
||||
.collect::<CalculatorResult<Vec<Vector>>>()?,
|
||||
direction: self.direction,
|
||||
dimensions: self.dimensions,
|
||||
dimensions: self.dimensions.clone(),
|
||||
}
|
||||
.validate()
|
||||
}
|
||||
@ -452,8 +502,7 @@ impl Matrix {
|
||||
_ => Err(CalculatorError::ArithmeticError),
|
||||
})
|
||||
.collect::<CalculatorResult<Vec<Vector>>>()?,
|
||||
direction: self.direction,
|
||||
dimensions: self.dimensions,
|
||||
dimensions: self.dimensions.clone(),
|
||||
}
|
||||
.validate()
|
||||
}
|
||||
@ -463,7 +512,7 @@ impl Matrix {
|
||||
m2: &Self,
|
||||
op: impl Fn(&Vector, &Entry) -> CalculatorResult<Entry>,
|
||||
) -> CalculatorResult<Entry> {
|
||||
if self.dimensions != m2.dimensions && self.direction != m2.direction {
|
||||
if self.dimensions != m2.dimensions {
|
||||
return Err(CalculatorError::DimensionMismatch);
|
||||
}
|
||||
Self {
|
||||
@ -477,8 +526,7 @@ impl Matrix {
|
||||
_ => Err(CalculatorError::ArithmeticError),
|
||||
})
|
||||
.collect::<CalculatorResult<Vec<Vector>>>()?,
|
||||
direction: self.direction,
|
||||
dimensions: self.dimensions,
|
||||
dimensions: self.dimensions.clone(),
|
||||
}
|
||||
.validate()
|
||||
}
|
||||
@ -517,6 +565,7 @@ impl CalculatorEntry for Vector {
|
||||
value.sqrt()
|
||||
}
|
||||
fn inverse(&self) -> CalculatorResult<Entry> {
|
||||
// TODO: Correct implementation of this. This is the transpose
|
||||
Ok(Entry::Vector(Self {
|
||||
values: self.values.clone(),
|
||||
direction: self.direction.swap(),
|
||||
@ -629,17 +678,25 @@ impl Vector {
|
||||
if entries.len() == 0 {
|
||||
return Err(CalculatorError::NotEnoughStackEntries);
|
||||
}
|
||||
Ok(Entry::Vector(Self {
|
||||
Self {
|
||||
values: entries
|
||||
.iter()
|
||||
.map(|e| match e {
|
||||
Entry::Matrix(_) => Err(CalculatorError::TypeMismatch),
|
||||
Entry::Vector(_) => Err(CalculatorError::TypeMismatch),
|
||||
Entry::Matrix(_) | Entry::Vector(_) => Err(CalculatorError::TypeMismatch),
|
||||
Entry::Number(number) => Ok(number.clone()),
|
||||
})
|
||||
.collect::<CalculatorResult<Vec<Number>>>()?,
|
||||
direction: VectorDirection::Row,
|
||||
})) //.validate() <- TODO
|
||||
direction: VectorDirection::default(),
|
||||
}
|
||||
.validate()
|
||||
}
|
||||
|
||||
fn validate(self) -> CalculatorResult<Entry> {
|
||||
if self.is_valid() {
|
||||
Ok(Entry::Vector(self))
|
||||
} else {
|
||||
Err(CalculatorError::ArithmeticError)
|
||||
}
|
||||
}
|
||||
|
||||
fn iterated_unary(
|
||||
@ -928,8 +985,7 @@ impl Number {
|
||||
_ => Err(CalculatorError::ArithmeticError),
|
||||
})
|
||||
.collect::<CalculatorResult<Vec<Vector>>>()?,
|
||||
direction: matrix.direction,
|
||||
dimensions: matrix.dimensions,
|
||||
dimensions: matrix.dimensions.clone(),
|
||||
}
|
||||
.validate()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user