From e05b0726f1fe8401b5743048ab789e4cd019c689 Mon Sep 17 00:00:00 2001 From: Austen Adler Date: Tue, 1 Jun 2021 21:59:56 -0400 Subject: [PATCH] Started work on vectors --- src/calc.rs | 21 +- src/calc/entries.rs | 673 +++++++++++++++++++++++++++++++++----------- src/main.rs | 8 +- 3 files changed, 520 insertions(+), 182 deletions(-) diff --git a/src/calc.rs b/src/calc.rs index fd07534..0a8f0be 100644 --- a/src/calc.rs +++ b/src/calc.rs @@ -186,6 +186,8 @@ impl Calculator { CalculatorState::WaitingForSetting => self.setting_input(c), } } + // This function is very long, but it is just a match, so it should be fine + #[allow(clippy::too_many_lines)] fn normal_input(&mut self, c: char) -> CalculatorResult<()> { match c { c @ '0'..='9' | c @ '.' | c @ 'e' => match c { @@ -194,11 +196,7 @@ impl Calculator { Ok(()) } 'e' => { - if self.l.is_empty() { - let f = self.pop().or(Err(CalculatorError::NotEnoughStackEntries))?; - - self.l = f.to_string(); - } + self.edit()?; if !self.l.contains('e') { self.l.push('e'); @@ -437,10 +435,15 @@ impl Calculator { return Ok(()); } - self.l = self - .pop() - .or(Err(CalculatorError::NotEnoughStackEntries))? - .to_string(); + // Temporary check to see if we can get an editable string + let str = self.peek(0)?.to_editable_string()?; + + // If we got here, then there was no error. Pop + self.pop()?; + + // Set l after popping + self.l = str; + Ok(()) } /// Get the value of l diff --git a/src/calc/entries.rs b/src/calc/entries.rs index 785579b..6c2d4f5 100644 --- a/src/calc/entries.rs +++ b/src/calc/entries.rs @@ -1,5 +1,5 @@ -// use super::operations::CalculatorStateChange; -// TODO: This file kina blows. Tons of repetition. Do not know how to fix yet though +// TODO: Clippy is recommending pass by value instead of by ref, but I plan to add imaginary numbers, which will change this +#![allow(clippy::trivially_copy_pass_by_ref)] use super::errors::{CalculatorError, CalculatorResult}; use super::types::CalculatorAngleMode; use crate::calc::CalculatorDisplayMode; @@ -12,15 +12,6 @@ pub struct Number { pub value: f64, } -impl Number { - fn binary_op(arg: &Entry, op: impl Fn(&Number) -> Number) -> CalculatorResult { - match arg { - Entry::Number(number) => Ok(Entry::Number(op(number))), - Entry::Vector(vector) => Ok(vector.map_into(op)), - } - } -} - impl PartialEq for Number { fn eq(&self, other: &Self) -> bool { if self.value.is_nan() && other.value.is_nan() @@ -45,41 +36,6 @@ pub struct Vector { pub values: Vec, } -impl Vector { - fn binary_op( - &self, - arg: &Entry, - op: impl Fn((&Number, &Number)) -> Number, - ) -> CalculatorResult { - match arg { - // Entry::Number(number) => Ok(Entry::Number(op(number))), - Entry::Number(number) => Ok(self.map_into(|t| op((t, number)))), - Entry::Vector(vector) => { - if self.values.len() != vector.values.len() { - return Err(CalculatorError::ArithmeticError); - } - - Ok(Entry::Vector(Vector { - values: self - .values - .iter() - .zip(vector.values.iter()) - .map(op) - .collect(), - ..*self - })) - } - } - } - - pub fn map_into(&self, op: impl Fn(&Number) -> Number) -> Entry { - Entry::Vector(Vector { - values: (self.values.iter().map(op).collect()), - ..*self - }) - } -} - #[derive(Clone, PartialEq, Debug, Serialize, Deserialize)] #[serde(tag = "type")] pub enum Entry { @@ -88,7 +44,28 @@ pub enum Entry { // Matrix(Vec>), } +// macro_rules! op_child_call { +// ($a:ident, $op:ident) => { +// match $a { +// Self::Number(number) => number.$op(), +// Self::Vector(vector) => vector.$op(), +// } +// }; +// ($a:ident, $op:ident, $arg:expr) => { +// match $a { +// Self::Number(number) => number.$op($arg), +// Self::Vector(vector) => vector.$op($arg), +// } +// }; +// } + impl CalculatorEntry for Entry { + fn to_editable_string(&self) -> CalculatorResult { + match self { + Self::Number(number) => number.to_editable_string(), + Self::Vector(vector) => vector.to_editable_string(), + } + } fn format_entry(&self, display_mode: &CalculatorDisplayMode) -> String { match self { Self::Number(number) => number.format_entry(display_mode), @@ -101,36 +78,6 @@ impl CalculatorEntry for Entry { Self::Vector(vector) => vector.is_valid(), } } - fn add(&self, arg: &Self) -> CalculatorResult { - match self { - Self::Number(number) => number.add(arg), - Self::Vector(vector) => vector.add(arg), - } - } - fn sub(&self, arg: &Self) -> CalculatorResult { - match self { - Self::Number(number) => number.sub(arg), - Self::Vector(vector) => vector.sub(arg), - } - } - fn mul(&self, arg: &Self) -> CalculatorResult { - match self { - Self::Number(number) => number.mul(arg), - Self::Vector(vector) => vector.mul(arg), - } - } - fn div(&self, arg: &Self) -> CalculatorResult { - match self { - Self::Number(number) => number.div(arg), - Self::Vector(vector) => vector.div(arg), - } - } - fn int_divide(&self, arg: &Self) -> CalculatorResult { - match self { - Self::Number(number) => number.int_divide(arg), - Self::Vector(vector) => vector.int_divide(arg), - } - } fn negate(&self) -> CalculatorResult { match self { Self::Number(number) => number.negate(), @@ -149,12 +96,6 @@ impl CalculatorEntry for Entry { Self::Vector(vector) => vector.inverse(), } } - fn modulo(&self, arg: &Self) -> CalculatorResult { - match self { - Self::Number(number) => number.modulo(arg), - Self::Vector(vector) => vector.modulo(arg), - } - } fn sin(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult { match self { Self::Number(number) => number.sin(angle_mode), @@ -209,15 +150,141 @@ impl CalculatorEntry for Entry { Self::Vector(vector) => vector.ln(), } } + + fn add(&self, arg: &Self) -> CalculatorResult { + match arg { + Self::Number(number) => self.add_num(number), + Self::Vector(vector) => self.add_vec(vector), + } + } + fn sub(&self, arg: &Self) -> CalculatorResult { + match arg { + Self::Number(number) => self.sub_num(number), + Self::Vector(vector) => self.sub_vec(vector), + } + } + fn mul(&self, arg: &Self) -> CalculatorResult { + match arg { + Self::Number(number) => self.mul_num(number), + Self::Vector(vector) => self.mul_vec(vector), + } + } + fn div(&self, arg: &Self) -> CalculatorResult { + match arg { + Self::Number(number) => self.div_num(number), + Self::Vector(vector) => self.div_vec(vector), + } + } + fn int_divide(&self, arg: &Self) -> CalculatorResult { + match arg { + Self::Number(number) => self.int_divide_num(number), + Self::Vector(vector) => self.int_divide_vec(vector), + } + } + fn modulo(&self, arg: &Self) -> CalculatorResult { + match arg { + Self::Number(number) => self.modulo_num(number), + Self::Vector(vector) => self.modulo_vec(vector), + } + } fn pow(&self, arg: &Self) -> CalculatorResult { + match arg { + Self::Number(number) => self.pow_num(number), + Self::Vector(vector) => self.pow_vec(vector), + } + } + + fn add_vec(&self, arg: &Vector) -> CalculatorResult { match self { - Self::Number(number) => number.pow(arg), - Self::Vector(vector) => vector.pow(arg), + Self::Number(number) => number.add_vec(arg), + Self::Vector(vector) => vector.add_vec(arg), + } + } + fn sub_vec(&self, arg: &Vector) -> CalculatorResult { + match self { + Self::Number(number) => number.sub_vec(arg), + Self::Vector(vector) => vector.sub_vec(arg), + } + } + fn mul_vec(&self, arg: &Vector) -> CalculatorResult { + match self { + Self::Number(number) => number.mul_vec(arg), + Self::Vector(vector) => vector.mul_vec(arg), + } + } + fn div_vec(&self, arg: &Vector) -> CalculatorResult { + match self { + Self::Number(number) => number.div_vec(arg), + Self::Vector(vector) => vector.div_vec(arg), + } + } + fn int_divide_vec(&self, arg: &Vector) -> CalculatorResult { + match self { + Self::Number(number) => number.int_divide_vec(arg), + Self::Vector(vector) => vector.int_divide_vec(arg), + } + } + fn modulo_vec(&self, arg: &Vector) -> CalculatorResult { + match self { + Self::Number(number) => number.modulo_vec(arg), + Self::Vector(vector) => vector.modulo_vec(arg), + } + } + fn pow_vec(&self, arg: &Vector) -> CalculatorResult { + match self { + Self::Number(number) => number.pow_vec(arg), + Self::Vector(vector) => vector.pow_vec(arg), + } + } + + fn add_num(&self, arg: &Number) -> CalculatorResult { + match self { + Self::Number(number) => number.add_num(arg), + Self::Vector(vector) => vector.add_num(arg), + } + } + fn sub_num(&self, arg: &Number) -> CalculatorResult { + match self { + Self::Number(number) => number.sub_num(arg), + Self::Vector(vector) => vector.sub_num(arg), + } + } + fn mul_num(&self, arg: &Number) -> CalculatorResult { + match self { + Self::Number(number) => number.mul_num(arg), + Self::Vector(vector) => vector.mul_num(arg), + } + } + fn div_num(&self, arg: &Number) -> CalculatorResult { + match self { + Self::Number(number) => number.div_num(arg), + Self::Vector(vector) => vector.div_num(arg), + } + } + fn int_divide_num(&self, arg: &Number) -> CalculatorResult { + match self { + Self::Number(number) => number.int_divide_num(arg), + Self::Vector(vector) => vector.int_divide_num(arg), + } + } + fn modulo_num(&self, arg: &Number) -> CalculatorResult { + match self { + Self::Number(number) => number.modulo_num(arg), + Self::Vector(vector) => vector.modulo_num(arg), + } + } + fn pow_num(&self, arg: &Number) -> CalculatorResult { + match self { + Self::Number(number) => number.pow_num(arg), + Self::Vector(vector) => vector.pow_num(arg), } } } impl CalculatorEntry for Number { + fn to_editable_string(&self) -> CalculatorResult { + Ok(format!("{}", self.value)) + } fn format_entry(&self, display_mode: &CalculatorDisplayMode) -> String { match display_mode { CalculatorDisplayMode::Default => format!("{}", self.value), @@ -232,31 +299,6 @@ impl CalculatorEntry for Number { fn is_valid(&self) -> bool { !self.value.is_nan() && !self.value.is_infinite() } - fn add(&self, arg: &Entry) -> CalculatorResult { - Number::binary_op(&arg, |b| Self { - value: b.value + self.value, - }) - } - fn sub(&self, arg: &Entry) -> CalculatorResult { - Number::binary_op(&arg, |b| Self { - value: b.value - self.value, - }) - } - fn mul(&self, arg: &Entry) -> CalculatorResult { - Number::binary_op(&arg, |b| Self { - value: b.value * self.value, - }) - } - fn div(&self, arg: &Entry) -> CalculatorResult { - Number::binary_op(&arg, |b| Self { - value: b.value / self.value, - }) - } - fn int_divide(&self, arg: &Entry) -> CalculatorResult { - Number::binary_op(&arg, |b| Self { - value: b.value.div_euclid(self.value), - }) - } fn negate(&self) -> CalculatorResult { Ok(Entry::Number(Self { value: -self.value })) } @@ -270,11 +312,6 @@ impl CalculatorEntry for Number { value: self.value.recip(), })) } - fn modulo(&self, arg: &Entry) -> CalculatorResult { - Number::binary_op(&arg, |b| Self { - value: b.value % self.value, - }) - } fn sin(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult { Ok(Entry::Number(Self { value: match angle_mode { @@ -344,21 +381,142 @@ impl CalculatorEntry for Number { value: self.value.ln(), })) } + + fn add(&self, arg: &Entry) -> CalculatorResult { + match arg { + Entry::Vector(vector) => self.add_vec(vector), + Entry::Number(number) => self.add_num(number), + } + } + fn sub(&self, arg: &Entry) -> CalculatorResult { + match arg { + Entry::Vector(vector) => self.sub_vec(vector), + Entry::Number(number) => self.sub_num(number), + } + } + fn mul(&self, arg: &Entry) -> CalculatorResult { + match arg { + Entry::Vector(vector) => self.mul_vec(vector), + Entry::Number(number) => self.mul_num(number), + } + } + fn div(&self, arg: &Entry) -> CalculatorResult { + match arg { + Entry::Vector(vector) => self.div_vec(vector), + Entry::Number(number) => self.div_num(number), + } + } + fn int_divide(&self, arg: &Entry) -> CalculatorResult { + match arg { + Entry::Vector(vector) => self.int_divide_vec(vector), + Entry::Number(number) => self.int_divide_num(number), + } + } + fn modulo(&self, arg: &Entry) -> CalculatorResult { + match arg { + Entry::Vector(vector) => self.modulo_vec(vector), + Entry::Number(number) => self.modulo_num(number), + } + } fn pow(&self, arg: &Entry) -> CalculatorResult { - Number::binary_op(&arg, |b| Self { - value: b.value.powf(self.value), - }) + match arg { + Entry::Vector(vector) => self.pow_vec(vector), + Entry::Number(number) => self.pow_num(number), + } + } + + fn add_vec(&self, arg: &Vector) -> CalculatorResult { + self.iterated_binary(arg, Self::add_num) + } + fn sub_vec(&self, arg: &Vector) -> CalculatorResult { + self.iterated_binary(arg, Self::sub_num) + } + fn mul_vec(&self, arg: &Vector) -> CalculatorResult { + self.iterated_binary(arg, Self::mul_num) + } + fn div_vec(&self, arg: &Vector) -> CalculatorResult { + self.iterated_binary(arg, Self::div_num) + } + fn int_divide_vec(&self, arg: &Vector) -> CalculatorResult { + self.iterated_binary(arg, Self::int_divide_num) + } + fn modulo_vec(&self, arg: &Vector) -> CalculatorResult { + self.iterated_binary(arg, Self::modulo_num) + } + fn pow_vec(&self, arg: &Vector) -> CalculatorResult { + self.iterated_binary(arg, Self::pow_num) + } + + fn add_num(&self, arg: &Number) -> CalculatorResult { + Ok(Entry::Number(Self { + value: arg.value + self.value, + })) + } + fn sub_num(&self, arg: &Number) -> CalculatorResult { + Ok(Entry::Number(Self { + value: arg.value - self.value, + })) + } + fn mul_num(&self, arg: &Number) -> CalculatorResult { + Ok(Entry::Number(Self { + value: arg.value * self.value, + })) + } + fn div_num(&self, arg: &Number) -> CalculatorResult { + Ok(Entry::Number(Self { + value: arg.value / self.value, + })) + } + fn int_divide_num(&self, arg: &Number) -> CalculatorResult { + Ok(Entry::Number(Self { + value: arg.value.div_euclid(self.value), + })) + } + fn modulo_num(&self, arg: &Number) -> CalculatorResult { + Ok(Entry::Number(Self { + value: arg.value % self.value, + })) + } + fn pow_num(&self, arg: &Number) -> CalculatorResult { + Ok(Entry::Number(Self { + value: arg.value.powf(self.value), + })) + } +} + +impl Number { + fn iterated_binary( + self, + vector: &Vector, + op: impl Fn(&Self, &Self) -> CalculatorResult, + ) -> CalculatorResult { + Ok(Entry::Vector(Vector { + values: vector + .values + .iter() + .map(|n| op(&self, n)) + .map(|e| match e { + // Only numbers are valid in a vector + Ok(Entry::Number(number)) => Ok(number), + _ => Err(CalculatorError::ArithmeticError), + }) + .collect::>>()?, + direction: vector.direction, + })) } } impl CalculatorEntry for Vector { // Misc + fn to_editable_string(&self) -> CalculatorResult { + // TODO: Eventualy we can parse and edit a vector as a string + Err(CalculatorError::TypeMismatch) + } fn is_valid(&self) -> bool { - !self - .values + self.values .iter() .find(|number| !number.is_valid()) - .is_some() + .is_none() } fn format_entry(&self, display_mode: &CalculatorDisplayMode) -> String { format!( @@ -371,80 +529,237 @@ impl CalculatorEntry for Vector { ) } // Mathematical operations - fn add(&self, arg: &Entry) -> CalculatorResult { - self.binary_op(&arg, |(a, b)| Number { - value: b.value + a.value, - }) - } - fn sub(&self, arg: &Entry) -> CalculatorResult { - self.binary_op(&arg, |(a, b)| Number { - value: b.value - a.value, - }) - } - fn mul(&self, arg: &Entry) -> CalculatorResult { - self.binary_op(&arg, |(a, b)| Number { - value: b.value * a.value, - }) - } - fn div(&self, arg: &Entry) -> CalculatorResult { - self.binary_op(&arg, |(a, b)| Number { - value: b.value / a.value, - }) - } - fn int_divide(&self, arg: &Entry) -> CalculatorResult { - self.binary_op(&arg, |(a, b)| Number { - value: b.value.div_euclid(a.value), - }) - } fn negate(&self) -> CalculatorResult { - Ok(self.map_into(|n| Number { value: -n.value })) + self.iterated_unary(Number::negate) } fn abs(&self) -> CalculatorResult { - Ok(self.map_into(|n| Number { - value: n.value.abs(), - })) + self.iterated_unary(Number::abs) } fn inverse(&self) -> CalculatorResult { - Ok(Entry::Vector(Vector { - direction: !self.direction, - ..*self - })) + self.iterated_unary(Number::inverse) + } + fn sin(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult { + self.iterated_unary(|n| n.sin(angle_mode)) + } + fn cos(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult { + self.iterated_unary(|n| n.cos(angle_mode)) + } + fn tan(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult { + self.iterated_unary(|n| n.tan(angle_mode)) + } + fn asin(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult { + self.iterated_unary(|n| n.asin(angle_mode)) + } + fn acos(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult { + self.iterated_unary(|n| n.acos(angle_mode)) + } + fn atan(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult { + self.iterated_unary(|n| n.atan(angle_mode)) + } + fn sqrt(&self) -> CalculatorResult { + self.iterated_unary(Number::sqrt) + } + fn log(&self) -> CalculatorResult { + self.iterated_unary(Number::log) + } + fn ln(&self) -> CalculatorResult { + self.iterated_unary(Number::ln) + } + + fn add(&self, arg: &Entry) -> CalculatorResult { + match arg { + Entry::Vector(vector) => self.add_vec(vector), + Entry::Number(number) => self.add_num(number), + } + } + fn sub(&self, arg: &Entry) -> CalculatorResult { + match arg { + Entry::Vector(vector) => self.sub_vec(vector), + Entry::Number(number) => self.sub_num(number), + } + } + fn mul(&self, arg: &Entry) -> CalculatorResult { + match arg { + Entry::Vector(vector) => self.mul_vec(vector), + Entry::Number(number) => self.mul_num(number), + } + } + fn div(&self, arg: &Entry) -> CalculatorResult { + match arg { + Entry::Vector(vector) => self.div_vec(vector), + Entry::Number(number) => self.div_num(number), + } + } + fn int_divide(&self, arg: &Entry) -> CalculatorResult { + match arg { + Entry::Vector(vector) => self.int_divide_vec(vector), + Entry::Number(number) => self.int_divide_num(number), + } } fn modulo(&self, arg: &Entry) -> CalculatorResult { - self.binary_op(&arg, |(a, b)| Number { - value: b.value % a.value, - }) + match arg { + Entry::Vector(vector) => self.modulo_vec(vector), + Entry::Number(number) => self.modulo_num(number), + } } - fn sin(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult {} - fn cos(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult {} - fn tan(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult {} - fn asin(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult {} - fn acos(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult {} - fn atan(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult {} - fn sqrt(&self) -> CalculatorResult {} - fn log(&self) -> CalculatorResult {} - fn ln(&self) -> CalculatorResult {} fn pow(&self, arg: &Entry) -> CalculatorResult { - self.binary_op(&arg, |(a, b)| Number { - value: b.value.powf(a.value), - }) + match arg { + Entry::Vector(vector) => self.pow_vec(vector), + Entry::Number(number) => self.pow_num(number), + } + } + + fn add_vec(&self, arg: &Self) -> CalculatorResult { + self.iterated_binary_vec(arg, Number::add_num) + } + fn sub_vec(&self, arg: &Self) -> CalculatorResult { + self.iterated_binary_vec(arg, Number::sub_num) + } + fn mul_vec(&self, arg: &Self) -> CalculatorResult { + self.iterated_binary_vec(arg, Number::mul_num) + } + fn div_vec(&self, arg: &Self) -> CalculatorResult { + self.iterated_binary_vec(arg, Number::div_num) + } + fn int_divide_vec(&self, arg: &Self) -> CalculatorResult { + self.iterated_binary_vec(arg, Number::int_divide_num) + } + fn modulo_vec(&self, arg: &Self) -> CalculatorResult { + self.iterated_binary_vec(arg, Number::modulo_num) + } + fn pow_vec(&self, arg: &Self) -> CalculatorResult { + self.iterated_binary_vec(arg, Number::pow_num) + } + + fn add_num(&self, arg: &Number) -> CalculatorResult { + self.iterated_binary_num(arg, Number::add_num) + } + fn sub_num(&self, arg: &Number) -> CalculatorResult { + self.iterated_binary_num(arg, Number::sub_num) + } + fn mul_num(&self, arg: &Number) -> CalculatorResult { + self.iterated_binary_num(arg, Number::mul_num) + } + fn div_num(&self, arg: &Number) -> CalculatorResult { + self.iterated_binary_num(arg, Number::div_num) + } + fn int_divide_num(&self, arg: &Number) -> CalculatorResult { + self.iterated_binary_num(arg, Number::int_divide_num) + } + fn modulo_num(&self, arg: &Number) -> CalculatorResult { + self.iterated_binary_num(arg, Number::modulo_num) + } + fn pow_num(&self, arg: &Number) -> CalculatorResult { + self.iterated_binary_num(arg, Number::pow_num) } } -pub trait CalculatorEntry { +impl Vector { + fn iterated_unary( + &self, + op: impl Fn(&Number) -> CalculatorResult, + ) -> CalculatorResult { + Ok(Entry::Vector(Self { + values: self + .values + .iter() + .map(|n| op(n)) + .map(|e| match e { + // Only numbers are valid in a vector + Ok(Entry::Number(number)) => Ok(number), + _ => Err(CalculatorError::ArithmeticError), + }) + .collect::>>()?, + direction: true, + })) + } + + fn iterated_binary_vec( + &self, + v2: &Self, + op: impl Fn(&Number, &Number) -> CalculatorResult, + ) -> CalculatorResult { + if self.values.len() != v2.values.len() { + return Err(CalculatorError::ArithmeticError); + } + if self.direction != v2.direction { + // TODO: Return a different error + return Err(CalculatorError::ArithmeticError); + } + Ok(Entry::Vector(Self { + values: self + .values + .iter() + .zip(v2.values.iter()) + .map(|(n1, n2)| op(n1, n2)) + .map(|e| match e { + // Only numbers are valid in a vector + Ok(Entry::Number(number)) => Ok(number), + _ => Err(CalculatorError::ArithmeticError), + }) + .collect::>>()?, + direction: true, + })) + } + fn iterated_binary_num( + &self, + n2: &Number, + op: impl Fn(&Number, &Number) -> CalculatorResult, + ) -> CalculatorResult { + Ok(Entry::Vector(Self { + values: self + .values + .iter() + .map(|n| op(n, n2)) + .map(|e| match e { + // Only numbers are valid in a vector + Ok(Entry::Number(number)) => Ok(number), + _ => Err(CalculatorError::ArithmeticError), + }) + .collect::>>()?, + direction: true, + })) + } +} + +pub trait CalculatorEntry +where + Self: Sized, +{ // Misc fn is_valid(&self) -> bool; fn format_entry(&self, display_mode: &CalculatorDisplayMode) -> String; + fn to_editable_string(&self) -> CalculatorResult; // Mathematical operations + // Binary fn add(&self, arg: &Entry) -> CalculatorResult; fn sub(&self, arg: &Entry) -> CalculatorResult; fn mul(&self, arg: &Entry) -> CalculatorResult; fn div(&self, arg: &Entry) -> CalculatorResult; fn int_divide(&self, arg: &Entry) -> CalculatorResult; + fn modulo(&self, arg: &Entry) -> CalculatorResult; + fn pow(&self, arg: &Entry) -> CalculatorResult; + + fn add_vec(&self, arg: &Vector) -> CalculatorResult; + fn sub_vec(&self, arg: &Vector) -> CalculatorResult; + fn mul_vec(&self, arg: &Vector) -> CalculatorResult; + fn div_vec(&self, arg: &Vector) -> CalculatorResult; + fn int_divide_vec(&self, arg: &Vector) -> CalculatorResult; + fn modulo_vec(&self, arg: &Vector) -> CalculatorResult; + fn pow_vec(&self, arg: &Vector) -> CalculatorResult; + + fn add_num(&self, arg: &Number) -> CalculatorResult; + fn sub_num(&self, arg: &Number) -> CalculatorResult; + fn mul_num(&self, arg: &Number) -> CalculatorResult; + fn div_num(&self, arg: &Number) -> CalculatorResult; + fn int_divide_num(&self, arg: &Number) -> CalculatorResult; + fn modulo_num(&self, arg: &Number) -> CalculatorResult; + fn pow_num(&self, arg: &Number) -> CalculatorResult; + + // Unary fn negate(&self) -> CalculatorResult; fn abs(&self) -> CalculatorResult; fn inverse(&self) -> CalculatorResult; - fn modulo(&self, arg: &Entry) -> CalculatorResult; fn sin(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult; fn cos(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult; fn tan(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult; @@ -454,13 +769,13 @@ pub trait CalculatorEntry { fn sqrt(&self) -> CalculatorResult; fn log(&self) -> CalculatorResult; fn ln(&self) -> CalculatorResult; - fn pow(&self, arg: &Entry) -> CalculatorResult; } impl fmt::Display for Entry { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - Self::Number(Number { value }) => write!(f, "{}", value), + Self::Number(number) => write!(f, "{}", number), + Self::Vector(vector) => write!(f, "{}", vector), } } } @@ -471,6 +786,20 @@ impl fmt::Display for Number { } } +impl fmt::Display for Vector { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "[{}]", + self.values + .iter() + .map(|number| format!("{}", number)) + .collect::>() + .join("; ") + ) + } +} + // Based on https://stackoverflow.com/a/65266882 fn scientific(f: f64, precision: usize) -> String { let mut ret = format!("{:.precision$E}", f, precision = precision); diff --git a/src/main.rs b/src/main.rs index 72372d0..3085d25 100644 --- a/src/main.rs +++ b/src/main.rs @@ -135,7 +135,13 @@ impl App { .calculator .registers .iter() - .map(|(key, value)| format!("{}: {}", key, value)) + .map(|(key, value)| { + format!( + "{}: {}", + key, + value.format_entry(&self.calculator.display_mode) + ) + }) .fold(String::new(), |acc, s| acc + &s + "\n") .trim_end(), },