Started work on vectors
This commit is contained in:
parent
bfae3cafce
commit
e05b0726f1
21
src/calc.rs
21
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
|
||||
|
@ -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<Entry> {
|
||||
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<Number>,
|
||||
}
|
||||
|
||||
impl Vector {
|
||||
fn binary_op(
|
||||
&self,
|
||||
arg: &Entry,
|
||||
op: impl Fn((&Number, &Number)) -> Number,
|
||||
) -> CalculatorResult<Entry> {
|
||||
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<Vec<Number>>),
|
||||
}
|
||||
|
||||
// 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<String> {
|
||||
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<Self> {
|
||||
match self {
|
||||
Self::Number(number) => number.add(arg),
|
||||
Self::Vector(vector) => vector.add(arg),
|
||||
}
|
||||
}
|
||||
fn sub(&self, arg: &Self) -> CalculatorResult<Self> {
|
||||
match self {
|
||||
Self::Number(number) => number.sub(arg),
|
||||
Self::Vector(vector) => vector.sub(arg),
|
||||
}
|
||||
}
|
||||
fn mul(&self, arg: &Self) -> CalculatorResult<Self> {
|
||||
match self {
|
||||
Self::Number(number) => number.mul(arg),
|
||||
Self::Vector(vector) => vector.mul(arg),
|
||||
}
|
||||
}
|
||||
fn div(&self, arg: &Self) -> CalculatorResult<Self> {
|
||||
match self {
|
||||
Self::Number(number) => number.div(arg),
|
||||
Self::Vector(vector) => vector.div(arg),
|
||||
}
|
||||
}
|
||||
fn int_divide(&self, arg: &Self) -> CalculatorResult<Self> {
|
||||
match self {
|
||||
Self::Number(number) => number.int_divide(arg),
|
||||
Self::Vector(vector) => vector.int_divide(arg),
|
||||
}
|
||||
}
|
||||
fn negate(&self) -> CalculatorResult<Self> {
|
||||
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<Self> {
|
||||
match self {
|
||||
Self::Number(number) => number.modulo(arg),
|
||||
Self::Vector(vector) => vector.modulo(arg),
|
||||
}
|
||||
}
|
||||
fn sin(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult<Self> {
|
||||
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<Self> {
|
||||
match arg {
|
||||
Self::Number(number) => self.add_num(number),
|
||||
Self::Vector(vector) => self.add_vec(vector),
|
||||
}
|
||||
}
|
||||
fn sub(&self, arg: &Self) -> CalculatorResult<Self> {
|
||||
match arg {
|
||||
Self::Number(number) => self.sub_num(number),
|
||||
Self::Vector(vector) => self.sub_vec(vector),
|
||||
}
|
||||
}
|
||||
fn mul(&self, arg: &Self) -> CalculatorResult<Self> {
|
||||
match arg {
|
||||
Self::Number(number) => self.mul_num(number),
|
||||
Self::Vector(vector) => self.mul_vec(vector),
|
||||
}
|
||||
}
|
||||
fn div(&self, arg: &Self) -> CalculatorResult<Self> {
|
||||
match arg {
|
||||
Self::Number(number) => self.div_num(number),
|
||||
Self::Vector(vector) => self.div_vec(vector),
|
||||
}
|
||||
}
|
||||
fn int_divide(&self, arg: &Self) -> CalculatorResult<Self> {
|
||||
match arg {
|
||||
Self::Number(number) => self.int_divide_num(number),
|
||||
Self::Vector(vector) => self.int_divide_vec(vector),
|
||||
}
|
||||
}
|
||||
fn modulo(&self, arg: &Self) -> CalculatorResult<Self> {
|
||||
match arg {
|
||||
Self::Number(number) => self.modulo_num(number),
|
||||
Self::Vector(vector) => self.modulo_vec(vector),
|
||||
}
|
||||
}
|
||||
fn pow(&self, arg: &Self) -> CalculatorResult<Self> {
|
||||
match arg {
|
||||
Self::Number(number) => self.pow_num(number),
|
||||
Self::Vector(vector) => self.pow_vec(vector),
|
||||
}
|
||||
}
|
||||
|
||||
fn add_vec(&self, arg: &Vector) -> CalculatorResult<Self> {
|
||||
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<Self> {
|
||||
match self {
|
||||
Self::Number(number) => number.sub_vec(arg),
|
||||
Self::Vector(vector) => vector.sub_vec(arg),
|
||||
}
|
||||
}
|
||||
fn mul_vec(&self, arg: &Vector) -> CalculatorResult<Self> {
|
||||
match self {
|
||||
Self::Number(number) => number.mul_vec(arg),
|
||||
Self::Vector(vector) => vector.mul_vec(arg),
|
||||
}
|
||||
}
|
||||
fn div_vec(&self, arg: &Vector) -> CalculatorResult<Self> {
|
||||
match self {
|
||||
Self::Number(number) => number.div_vec(arg),
|
||||
Self::Vector(vector) => vector.div_vec(arg),
|
||||
}
|
||||
}
|
||||
fn int_divide_vec(&self, arg: &Vector) -> CalculatorResult<Self> {
|
||||
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<Self> {
|
||||
match self {
|
||||
Self::Number(number) => number.modulo_vec(arg),
|
||||
Self::Vector(vector) => vector.modulo_vec(arg),
|
||||
}
|
||||
}
|
||||
fn pow_vec(&self, arg: &Vector) -> CalculatorResult<Self> {
|
||||
match self {
|
||||
Self::Number(number) => number.pow_vec(arg),
|
||||
Self::Vector(vector) => vector.pow_vec(arg),
|
||||
}
|
||||
}
|
||||
|
||||
fn add_num(&self, arg: &Number) -> CalculatorResult<Self> {
|
||||
match self {
|
||||
Self::Number(number) => number.add_num(arg),
|
||||
Self::Vector(vector) => vector.add_num(arg),
|
||||
}
|
||||
}
|
||||
fn sub_num(&self, arg: &Number) -> CalculatorResult<Self> {
|
||||
match self {
|
||||
Self::Number(number) => number.sub_num(arg),
|
||||
Self::Vector(vector) => vector.sub_num(arg),
|
||||
}
|
||||
}
|
||||
fn mul_num(&self, arg: &Number) -> CalculatorResult<Self> {
|
||||
match self {
|
||||
Self::Number(number) => number.mul_num(arg),
|
||||
Self::Vector(vector) => vector.mul_num(arg),
|
||||
}
|
||||
}
|
||||
fn div_num(&self, arg: &Number) -> CalculatorResult<Self> {
|
||||
match self {
|
||||
Self::Number(number) => number.div_num(arg),
|
||||
Self::Vector(vector) => vector.div_num(arg),
|
||||
}
|
||||
}
|
||||
fn int_divide_num(&self, arg: &Number) -> CalculatorResult<Self> {
|
||||
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<Self> {
|
||||
match self {
|
||||
Self::Number(number) => number.modulo_num(arg),
|
||||
Self::Vector(vector) => vector.modulo_num(arg),
|
||||
}
|
||||
}
|
||||
fn pow_num(&self, arg: &Number) -> CalculatorResult<Self> {
|
||||
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<String> {
|
||||
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<Entry> {
|
||||
Number::binary_op(&arg, |b| Self {
|
||||
value: b.value + self.value,
|
||||
})
|
||||
}
|
||||
fn sub(&self, arg: &Entry) -> CalculatorResult<Entry> {
|
||||
Number::binary_op(&arg, |b| Self {
|
||||
value: b.value - self.value,
|
||||
})
|
||||
}
|
||||
fn mul(&self, arg: &Entry) -> CalculatorResult<Entry> {
|
||||
Number::binary_op(&arg, |b| Self {
|
||||
value: b.value * self.value,
|
||||
})
|
||||
}
|
||||
fn div(&self, arg: &Entry) -> CalculatorResult<Entry> {
|
||||
Number::binary_op(&arg, |b| Self {
|
||||
value: b.value / self.value,
|
||||
})
|
||||
}
|
||||
fn int_divide(&self, arg: &Entry) -> CalculatorResult<Entry> {
|
||||
Number::binary_op(&arg, |b| Self {
|
||||
value: b.value.div_euclid(self.value),
|
||||
})
|
||||
}
|
||||
fn negate(&self) -> CalculatorResult<Entry> {
|
||||
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<Entry> {
|
||||
Number::binary_op(&arg, |b| Self {
|
||||
value: b.value % self.value,
|
||||
})
|
||||
}
|
||||
fn sin(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult<Entry> {
|
||||
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<Entry> {
|
||||
match arg {
|
||||
Entry::Vector(vector) => self.add_vec(vector),
|
||||
Entry::Number(number) => self.add_num(number),
|
||||
}
|
||||
}
|
||||
fn sub(&self, arg: &Entry) -> CalculatorResult<Entry> {
|
||||
match arg {
|
||||
Entry::Vector(vector) => self.sub_vec(vector),
|
||||
Entry::Number(number) => self.sub_num(number),
|
||||
}
|
||||
}
|
||||
fn mul(&self, arg: &Entry) -> CalculatorResult<Entry> {
|
||||
match arg {
|
||||
Entry::Vector(vector) => self.mul_vec(vector),
|
||||
Entry::Number(number) => self.mul_num(number),
|
||||
}
|
||||
}
|
||||
fn div(&self, arg: &Entry) -> CalculatorResult<Entry> {
|
||||
match arg {
|
||||
Entry::Vector(vector) => self.div_vec(vector),
|
||||
Entry::Number(number) => self.div_num(number),
|
||||
}
|
||||
}
|
||||
fn int_divide(&self, arg: &Entry) -> CalculatorResult<Entry> {
|
||||
match arg {
|
||||
Entry::Vector(vector) => self.int_divide_vec(vector),
|
||||
Entry::Number(number) => self.int_divide_num(number),
|
||||
}
|
||||
}
|
||||
fn modulo(&self, arg: &Entry) -> CalculatorResult<Entry> {
|
||||
match arg {
|
||||
Entry::Vector(vector) => self.modulo_vec(vector),
|
||||
Entry::Number(number) => self.modulo_num(number),
|
||||
}
|
||||
}
|
||||
fn pow(&self, arg: &Entry) -> CalculatorResult<Entry> {
|
||||
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<Entry> {
|
||||
self.iterated_binary(arg, Self::add_num)
|
||||
}
|
||||
fn sub_vec(&self, arg: &Vector) -> CalculatorResult<Entry> {
|
||||
self.iterated_binary(arg, Self::sub_num)
|
||||
}
|
||||
fn mul_vec(&self, arg: &Vector) -> CalculatorResult<Entry> {
|
||||
self.iterated_binary(arg, Self::mul_num)
|
||||
}
|
||||
fn div_vec(&self, arg: &Vector) -> CalculatorResult<Entry> {
|
||||
self.iterated_binary(arg, Self::div_num)
|
||||
}
|
||||
fn int_divide_vec(&self, arg: &Vector) -> CalculatorResult<Entry> {
|
||||
self.iterated_binary(arg, Self::int_divide_num)
|
||||
}
|
||||
fn modulo_vec(&self, arg: &Vector) -> CalculatorResult<Entry> {
|
||||
self.iterated_binary(arg, Self::modulo_num)
|
||||
}
|
||||
fn pow_vec(&self, arg: &Vector) -> CalculatorResult<Entry> {
|
||||
self.iterated_binary(arg, Self::pow_num)
|
||||
}
|
||||
|
||||
fn add_num(&self, arg: &Number) -> CalculatorResult<Entry> {
|
||||
Ok(Entry::Number(Self {
|
||||
value: arg.value + self.value,
|
||||
}))
|
||||
}
|
||||
fn sub_num(&self, arg: &Number) -> CalculatorResult<Entry> {
|
||||
Ok(Entry::Number(Self {
|
||||
value: arg.value - self.value,
|
||||
}))
|
||||
}
|
||||
fn mul_num(&self, arg: &Number) -> CalculatorResult<Entry> {
|
||||
Ok(Entry::Number(Self {
|
||||
value: arg.value * self.value,
|
||||
}))
|
||||
}
|
||||
fn div_num(&self, arg: &Number) -> CalculatorResult<Entry> {
|
||||
Ok(Entry::Number(Self {
|
||||
value: arg.value / self.value,
|
||||
}))
|
||||
}
|
||||
fn int_divide_num(&self, arg: &Number) -> CalculatorResult<Entry> {
|
||||
Ok(Entry::Number(Self {
|
||||
value: arg.value.div_euclid(self.value),
|
||||
}))
|
||||
}
|
||||
fn modulo_num(&self, arg: &Number) -> CalculatorResult<Entry> {
|
||||
Ok(Entry::Number(Self {
|
||||
value: arg.value % self.value,
|
||||
}))
|
||||
}
|
||||
fn pow_num(&self, arg: &Number) -> CalculatorResult<Entry> {
|
||||
Ok(Entry::Number(Self {
|
||||
value: arg.value.powf(self.value),
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl Number {
|
||||
fn iterated_binary(
|
||||
self,
|
||||
vector: &Vector,
|
||||
op: impl Fn(&Self, &Self) -> CalculatorResult<Entry>,
|
||||
) -> CalculatorResult<Entry> {
|
||||
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::<CalculatorResult<Vec<Self>>>()?,
|
||||
direction: vector.direction,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl CalculatorEntry for Vector {
|
||||
// Misc
|
||||
fn to_editable_string(&self) -> CalculatorResult<String> {
|
||||
// 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<Entry> {
|
||||
self.binary_op(&arg, |(a, b)| Number {
|
||||
value: b.value + a.value,
|
||||
})
|
||||
}
|
||||
fn sub(&self, arg: &Entry) -> CalculatorResult<Entry> {
|
||||
self.binary_op(&arg, |(a, b)| Number {
|
||||
value: b.value - a.value,
|
||||
})
|
||||
}
|
||||
fn mul(&self, arg: &Entry) -> CalculatorResult<Entry> {
|
||||
self.binary_op(&arg, |(a, b)| Number {
|
||||
value: b.value * a.value,
|
||||
})
|
||||
}
|
||||
fn div(&self, arg: &Entry) -> CalculatorResult<Entry> {
|
||||
self.binary_op(&arg, |(a, b)| Number {
|
||||
value: b.value / a.value,
|
||||
})
|
||||
}
|
||||
fn int_divide(&self, arg: &Entry) -> CalculatorResult<Entry> {
|
||||
self.binary_op(&arg, |(a, b)| Number {
|
||||
value: b.value.div_euclid(a.value),
|
||||
})
|
||||
}
|
||||
fn negate(&self) -> CalculatorResult<Entry> {
|
||||
Ok(self.map_into(|n| Number { value: -n.value }))
|
||||
self.iterated_unary(Number::negate)
|
||||
}
|
||||
fn abs(&self) -> CalculatorResult<Entry> {
|
||||
Ok(self.map_into(|n| Number {
|
||||
value: n.value.abs(),
|
||||
}))
|
||||
self.iterated_unary(Number::abs)
|
||||
}
|
||||
fn inverse(&self) -> CalculatorResult<Entry> {
|
||||
Ok(Entry::Vector(Vector {
|
||||
direction: !self.direction,
|
||||
..*self
|
||||
}))
|
||||
self.iterated_unary(Number::inverse)
|
||||
}
|
||||
fn sin(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult<Entry> {
|
||||
self.iterated_unary(|n| n.sin(angle_mode))
|
||||
}
|
||||
fn cos(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult<Entry> {
|
||||
self.iterated_unary(|n| n.cos(angle_mode))
|
||||
}
|
||||
fn tan(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult<Entry> {
|
||||
self.iterated_unary(|n| n.tan(angle_mode))
|
||||
}
|
||||
fn asin(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult<Entry> {
|
||||
self.iterated_unary(|n| n.asin(angle_mode))
|
||||
}
|
||||
fn acos(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult<Entry> {
|
||||
self.iterated_unary(|n| n.acos(angle_mode))
|
||||
}
|
||||
fn atan(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult<Entry> {
|
||||
self.iterated_unary(|n| n.atan(angle_mode))
|
||||
}
|
||||
fn sqrt(&self) -> CalculatorResult<Entry> {
|
||||
self.iterated_unary(Number::sqrt)
|
||||
}
|
||||
fn log(&self) -> CalculatorResult<Entry> {
|
||||
self.iterated_unary(Number::log)
|
||||
}
|
||||
fn ln(&self) -> CalculatorResult<Entry> {
|
||||
self.iterated_unary(Number::ln)
|
||||
}
|
||||
|
||||
fn add(&self, arg: &Entry) -> CalculatorResult<Entry> {
|
||||
match arg {
|
||||
Entry::Vector(vector) => self.add_vec(vector),
|
||||
Entry::Number(number) => self.add_num(number),
|
||||
}
|
||||
}
|
||||
fn sub(&self, arg: &Entry) -> CalculatorResult<Entry> {
|
||||
match arg {
|
||||
Entry::Vector(vector) => self.sub_vec(vector),
|
||||
Entry::Number(number) => self.sub_num(number),
|
||||
}
|
||||
}
|
||||
fn mul(&self, arg: &Entry) -> CalculatorResult<Entry> {
|
||||
match arg {
|
||||
Entry::Vector(vector) => self.mul_vec(vector),
|
||||
Entry::Number(number) => self.mul_num(number),
|
||||
}
|
||||
}
|
||||
fn div(&self, arg: &Entry) -> CalculatorResult<Entry> {
|
||||
match arg {
|
||||
Entry::Vector(vector) => self.div_vec(vector),
|
||||
Entry::Number(number) => self.div_num(number),
|
||||
}
|
||||
}
|
||||
fn int_divide(&self, arg: &Entry) -> CalculatorResult<Entry> {
|
||||
match arg {
|
||||
Entry::Vector(vector) => self.int_divide_vec(vector),
|
||||
Entry::Number(number) => self.int_divide_num(number),
|
||||
}
|
||||
}
|
||||
fn modulo(&self, arg: &Entry) -> CalculatorResult<Entry> {
|
||||
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<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> {}
|
||||
fn pow(&self, arg: &Entry) -> CalculatorResult<Entry> {
|
||||
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<Entry> {
|
||||
self.iterated_binary_vec(arg, Number::add_num)
|
||||
}
|
||||
fn sub_vec(&self, arg: &Self) -> CalculatorResult<Entry> {
|
||||
self.iterated_binary_vec(arg, Number::sub_num)
|
||||
}
|
||||
fn mul_vec(&self, arg: &Self) -> CalculatorResult<Entry> {
|
||||
self.iterated_binary_vec(arg, Number::mul_num)
|
||||
}
|
||||
fn div_vec(&self, arg: &Self) -> CalculatorResult<Entry> {
|
||||
self.iterated_binary_vec(arg, Number::div_num)
|
||||
}
|
||||
fn int_divide_vec(&self, arg: &Self) -> CalculatorResult<Entry> {
|
||||
self.iterated_binary_vec(arg, Number::int_divide_num)
|
||||
}
|
||||
fn modulo_vec(&self, arg: &Self) -> CalculatorResult<Entry> {
|
||||
self.iterated_binary_vec(arg, Number::modulo_num)
|
||||
}
|
||||
fn pow_vec(&self, arg: &Self) -> CalculatorResult<Entry> {
|
||||
self.iterated_binary_vec(arg, Number::pow_num)
|
||||
}
|
||||
|
||||
fn add_num(&self, arg: &Number) -> CalculatorResult<Entry> {
|
||||
self.iterated_binary_num(arg, Number::add_num)
|
||||
}
|
||||
fn sub_num(&self, arg: &Number) -> CalculatorResult<Entry> {
|
||||
self.iterated_binary_num(arg, Number::sub_num)
|
||||
}
|
||||
fn mul_num(&self, arg: &Number) -> CalculatorResult<Entry> {
|
||||
self.iterated_binary_num(arg, Number::mul_num)
|
||||
}
|
||||
fn div_num(&self, arg: &Number) -> CalculatorResult<Entry> {
|
||||
self.iterated_binary_num(arg, Number::div_num)
|
||||
}
|
||||
fn int_divide_num(&self, arg: &Number) -> CalculatorResult<Entry> {
|
||||
self.iterated_binary_num(arg, Number::int_divide_num)
|
||||
}
|
||||
fn modulo_num(&self, arg: &Number) -> CalculatorResult<Entry> {
|
||||
self.iterated_binary_num(arg, Number::modulo_num)
|
||||
}
|
||||
fn pow_num(&self, arg: &Number) -> CalculatorResult<Entry> {
|
||||
self.iterated_binary_num(arg, Number::pow_num)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait CalculatorEntry {
|
||||
impl Vector {
|
||||
fn iterated_unary(
|
||||
&self,
|
||||
op: impl Fn(&Number) -> CalculatorResult<Entry>,
|
||||
) -> CalculatorResult<Entry> {
|
||||
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::<CalculatorResult<Vec<Number>>>()?,
|
||||
direction: true,
|
||||
}))
|
||||
}
|
||||
|
||||
fn iterated_binary_vec(
|
||||
&self,
|
||||
v2: &Self,
|
||||
op: impl Fn(&Number, &Number) -> CalculatorResult<Entry>,
|
||||
) -> CalculatorResult<Entry> {
|
||||
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::<CalculatorResult<Vec<Number>>>()?,
|
||||
direction: true,
|
||||
}))
|
||||
}
|
||||
fn iterated_binary_num(
|
||||
&self,
|
||||
n2: &Number,
|
||||
op: impl Fn(&Number, &Number) -> CalculatorResult<Entry>,
|
||||
) -> CalculatorResult<Entry> {
|
||||
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::<CalculatorResult<Vec<Number>>>()?,
|
||||
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<String>;
|
||||
// Mathematical operations
|
||||
// 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>;
|
||||
|
||||
fn add_vec(&self, arg: &Vector) -> CalculatorResult<Entry>;
|
||||
fn sub_vec(&self, arg: &Vector) -> CalculatorResult<Entry>;
|
||||
fn mul_vec(&self, arg: &Vector) -> CalculatorResult<Entry>;
|
||||
fn div_vec(&self, arg: &Vector) -> CalculatorResult<Entry>;
|
||||
fn int_divide_vec(&self, arg: &Vector) -> CalculatorResult<Entry>;
|
||||
fn modulo_vec(&self, arg: &Vector) -> CalculatorResult<Entry>;
|
||||
fn pow_vec(&self, arg: &Vector) -> CalculatorResult<Entry>;
|
||||
|
||||
fn add_num(&self, arg: &Number) -> CalculatorResult<Entry>;
|
||||
fn sub_num(&self, arg: &Number) -> CalculatorResult<Entry>;
|
||||
fn mul_num(&self, arg: &Number) -> CalculatorResult<Entry>;
|
||||
fn div_num(&self, arg: &Number) -> CalculatorResult<Entry>;
|
||||
fn int_divide_num(&self, arg: &Number) -> CalculatorResult<Entry>;
|
||||
fn modulo_num(&self, arg: &Number) -> CalculatorResult<Entry>;
|
||||
fn pow_num(&self, arg: &Number) -> CalculatorResult<Entry>;
|
||||
|
||||
// Unary
|
||||
fn negate(&self) -> CalculatorResult<Entry>;
|
||||
fn abs(&self) -> CalculatorResult<Entry>;
|
||||
fn inverse(&self) -> CalculatorResult<Entry>;
|
||||
fn modulo(&self, arg: &Entry) -> 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>;
|
||||
@ -454,13 +769,13 @@ pub trait CalculatorEntry {
|
||||
fn sqrt(&self) -> CalculatorResult<Entry>;
|
||||
fn log(&self) -> CalculatorResult<Entry>;
|
||||
fn ln(&self) -> 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 {
|
||||
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::<Vec<String>>()
|
||||
.join("; ")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Based on https://stackoverflow.com/a/65266882
|
||||
fn scientific(f: f64, precision: usize) -> String {
|
||||
let mut ret = format!("{:.precision$E}", f, precision = precision);
|
||||
|
@ -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(),
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user