calc accessors and reset

This commit is contained in:
2025-07-18 21:19:30 +01:00
parent 27f745ee6d
commit 33dda0d6ea

View File

@@ -55,11 +55,38 @@ impl From<Infallible> for StackCalcError {
impl<F: FloatCore, const STACK: usize, const DSIZE: usize, EXP: PrimInt + Unsigned>
StackCalc<F, STACK, DSIZE, EXP>
{
pub fn is_full(&self) -> bool {
self.index == STACK
}
pub fn is_empty(&self) -> bool {
self.index == 0
}
pub fn len(&self) -> usize {
self.index
}
pub fn reset(&mut self) {
self.index = 0;
}
pub fn last(&self) -> Option<Decimal<DSIZE, EXP>> {
if self.is_empty() {
return None;
}
Some(self.stack[self.index - 1])
}
pub fn iter(&self) -> impl Iterator<Item = &Decimal<DSIZE, EXP>> {
self.stack.iter().take(self.index)
}
pub fn push(
&mut self,
val: impl TryInto<Decimal<DSIZE, EXP>, Error: Into<StackCalcError>>,
) -> Result<(), StackCalcError> {
if self.index == STACK {
if self.is_full() {
return Err(StackCalcError::StackOverflow);
}
self.stack[self.index] = val.try_into().map_err(Into::into)?;
@@ -68,22 +95,46 @@ impl<F: FloatCore, const STACK: usize, const DSIZE: usize, EXP: PrimInt + Unsign
}
pub fn pop(&mut self) -> Result<Decimal<DSIZE, EXP>, StackCalcError> {
if self.index == 0 {
if self.is_empty() {
return Err(StackCalcError::StackUnderflow);
}
self.index -= 1;
Ok(self.stack[self.index])
}
pub fn add(&mut self) -> Result<Decimal<DSIZE, EXP>, StackCalcError> {
fn pop_pair_float(&mut self) -> Result<(F, F), StackCalcError> {
let a = self.pop()?;
let b = self.pop()?;
let a = a.to_float::<F>()?;
let b = b.to_float::<F>()?;
let res = Decimal::from_float(a + b)?;
Ok((a, b))
}
fn calc_pair_float(
&mut self,
f: impl FnOnce(F, F) -> Result<F, StackCalcError>,
) -> Result<Decimal<DSIZE, EXP>, StackCalcError> {
let (a, b) = self.pop_pair_float()?;
let res = Decimal::from_float(f(a, b)?)?;
self.push(res)?;
Ok(res)
}
pub fn add(&mut self) -> Result<Decimal<DSIZE, EXP>, StackCalcError> {
self.calc_pair_float(|a, b| Ok(b + a))
}
pub fn sub(&mut self) -> Result<Decimal<DSIZE, EXP>, StackCalcError> {
self.calc_pair_float(|a, b| Ok(b - a))
}
pub fn mul(&mut self) -> Result<Decimal<DSIZE, EXP>, StackCalcError> {
self.calc_pair_float(|a, b| Ok(b * a))
}
pub fn div(&mut self) -> Result<Decimal<DSIZE, EXP>, StackCalcError> {
self.calc_pair_float(|a, b| Ok(b / a))
}
}
#[cfg(test)]
@@ -103,8 +154,13 @@ mod tests {
calc.push(3.0).unwrap_err(),
StackCalcError::StackOverflow
));
assert_eq!(calc.add()?, Decimal::try_from(5.0)?);
assert_eq!(calc.add()?, Decimal::try_from(1337.42 * 2.0 + 5.0)?);
calc.add()?;
assert_eq!(calc.last().unwrap(), Decimal::try_from(5.0)?);
calc.add()?;
assert_eq!(
calc.last().unwrap(),
Decimal::try_from(1337.42 * 2.0 + 5.0)?
);
assert!(matches!(
calc.add().unwrap_err(),
StackCalcError::StackUnderflow