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> impl<F: FloatCore, const STACK: usize, const DSIZE: usize, EXP: PrimInt + Unsigned>
StackCalc<F, STACK, DSIZE, EXP> 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( pub fn push(
&mut self, &mut self,
val: impl TryInto<Decimal<DSIZE, EXP>, Error: Into<StackCalcError>>, val: impl TryInto<Decimal<DSIZE, EXP>, Error: Into<StackCalcError>>,
) -> Result<(), StackCalcError> { ) -> Result<(), StackCalcError> {
if self.index == STACK { if self.is_full() {
return Err(StackCalcError::StackOverflow); return Err(StackCalcError::StackOverflow);
} }
self.stack[self.index] = val.try_into().map_err(Into::into)?; 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> { pub fn pop(&mut self) -> Result<Decimal<DSIZE, EXP>, StackCalcError> {
if self.index == 0 { if self.is_empty() {
return Err(StackCalcError::StackUnderflow); return Err(StackCalcError::StackUnderflow);
} }
self.index -= 1; self.index -= 1;
Ok(self.stack[self.index]) 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 a = self.pop()?;
let b = self.pop()?; let b = self.pop()?;
let a = a.to_float::<F>()?; let a = a.to_float::<F>()?;
let b = b.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)?; self.push(res)?;
Ok(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)] #[cfg(test)]
@@ -103,8 +154,13 @@ mod tests {
calc.push(3.0).unwrap_err(), calc.push(3.0).unwrap_err(),
StackCalcError::StackOverflow StackCalcError::StackOverflow
)); ));
assert_eq!(calc.add()?, Decimal::try_from(5.0)?); calc.add()?;
assert_eq!(calc.add()?, Decimal::try_from(1337.42 * 2.0 + 5.0)?); 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!( assert!(matches!(
calc.add().unwrap_err(), calc.add().unwrap_err(),
StackCalcError::StackUnderflow StackCalcError::StackUnderflow