diff --git a/src/calc.rs b/src/calc.rs new file mode 100644 index 0000000..0d49217 --- /dev/null +++ b/src/calc.rs @@ -0,0 +1,68 @@ +use num_traits::{PrimInt, Unsigned}; + +use crate::{Decimal, DecimalError}; + +#[derive(Debug, Clone)] +pub struct RPNCalc { + stack: [Decimal; SS], + cur: usize, +} + +impl Default for RPNCalc { + fn default() -> Self { + RPNCalc { + stack: [Decimal::default(); SS], + cur: 0, + } + } +} + +impl RPNCalc { + pub fn enter(&mut self, val: Decimal) { + self.stack[self.cur] = val; + if self.cur == SS - 1 { + self.cur = 0; + } else { + self.cur += 1; + } + } + + pub fn pop(&mut self) -> Decimal { + self.cur = if self.cur == 0 { SS - 1 } else { self.cur - 1 }; + let ret = self.stack[self.cur]; + self.stack[self.cur] = Decimal::default(); + ret + } + + pub fn add(&mut self) -> Result, DecimalError> { + let a = self.pop(); + let b = self.pop(); + let a = f64::try_from(a)?; + let b = f64::try_from(b)?; + let res = Decimal::try_from(a + b)?; + self.enter(res); + Ok(res) + } +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_add() -> Result<(), DecimalError> { + let mut calc = RPNCalc::<3, 5>::default(); + calc.enter(Decimal::try_from(1337.42)?); + assert_eq!(calc.add()?, Decimal::try_from(1337.42)?); + calc.enter(Decimal::try_from(1337.42)?); + assert_eq!(calc.add()?, Decimal::try_from(1337.42 * 2.0)?); + calc.enter(Decimal::try_from(2.0)?); + calc.enter(Decimal::try_from(3.0)?); + assert_eq!(calc.add()?, Decimal::try_from(5.0)?); + assert_eq!(calc.add()?, Decimal::try_from(1337.42 * 2.0 + 5.0)?); + assert_eq!(calc.add()?, Decimal::try_from(1337.42 * 2.0 + 5.0)?); + assert_eq!(calc.add()?, Decimal::try_from(1337.42 * 2.0 + 5.0)?); + assert_eq!(calc.add()?, Decimal::try_from(1337.42 * 2.0 + 5.0)?); + assert_eq!(calc.add()?, Decimal::try_from(1337.42 * 2.0 + 5.0)?); + Ok(()) + } +} diff --git a/src/lib.rs b/src/lib.rs index c8262af..1e3e90c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,7 @@ #![no_std] +pub mod calc; + use core::{error::Error, fmt::Display}; #[cfg(not(test))] use num_traits::float::FloatCore; @@ -21,7 +23,7 @@ impl Display for DecimalError { } } -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct Decimal { pub minus: bool, pub significant: [u8; S],