RPN calculator
This commit is contained in:
68
src/calc.rs
Normal file
68
src/calc.rs
Normal file
@@ -0,0 +1,68 @@
|
||||
use num_traits::{PrimInt, Unsigned};
|
||||
|
||||
use crate::{Decimal, DecimalError};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RPNCalc<const SS: usize = 2, const DS: usize = 5, E = u16> {
|
||||
stack: [Decimal<DS, E>; SS],
|
||||
cur: usize,
|
||||
}
|
||||
|
||||
impl<const SS: usize, const DS: usize, E: PrimInt> Default for RPNCalc<SS, DS, E> {
|
||||
fn default() -> Self {
|
||||
RPNCalc {
|
||||
stack: [Decimal::default(); SS],
|
||||
cur: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<const SS: usize, const DS: usize, E: PrimInt + Unsigned> RPNCalc<SS, DS, E> {
|
||||
pub fn enter(&mut self, val: Decimal<DS, E>) {
|
||||
self.stack[self.cur] = val;
|
||||
if self.cur == SS - 1 {
|
||||
self.cur = 0;
|
||||
} else {
|
||||
self.cur += 1;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pop(&mut self) -> Decimal<DS, E> {
|
||||
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<Decimal<DS, E>, 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(())
|
||||
}
|
||||
}
|
||||
@@ -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<const S: usize = 5, E = u16> {
|
||||
pub minus: bool,
|
||||
pub significant: [u8; S],
|
||||
|
||||
Reference in New Issue
Block a user