Skip to content

Commit

Permalink
Implement floor, ceil and round
Browse files Browse the repository at this point in the history
  • Loading branch information
frectonz committed Feb 15, 2024
1 parent fb02762 commit eda5977
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 0 deletions.
3 changes: 3 additions & 0 deletions core/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,9 @@ pub(crate) fn resolve_identifier<I: Interrupt>(
"unitless" => Value::Num(Box::new(Number::from(1))),
"arg" => Value::BuiltInFunction(BuiltInFunction::Arg),
"abs" => Value::BuiltInFunction(BuiltInFunction::Abs),
"floor" => Value::BuiltInFunction(BuiltInFunction::Floor),
"ceil" => Value::BuiltInFunction(BuiltInFunction::Ceil),
"round" => Value::BuiltInFunction(BuiltInFunction::Round),
"sin" => Value::BuiltInFunction(BuiltInFunction::Sin),
"cos" => Value::BuiltInFunction(BuiltInFunction::Cos),
"tan" => Value::BuiltInFunction(BuiltInFunction::Tan),
Expand Down
15 changes: 15 additions & 0 deletions core/src/num/bigrat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,21 @@ impl BigRat {
Ok(self.apply_uint_op(BigUint::factorial, int)?.into())
}

pub(crate) fn floor<I: Interrupt>(self, int: &I) -> FResult<Self> {
let float = self.into_f64(int)?.floor();
Self::from_f64(float, int)
}

pub(crate) fn ceil<I: Interrupt>(self, int: &I) -> FResult<Self> {
let float = self.into_f64(int)?.ceil();
Self::from_f64(float, int)
}

pub(crate) fn round<I: Interrupt>(self, int: &I) -> FResult<Self> {
let float = self.into_f64(int)?.round();
Self::from_f64(float, int)
}

pub(crate) fn bitwise<I: Interrupt>(
self,
rhs: Self,
Expand Down
12 changes: 12 additions & 0 deletions core/src/num/complex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,18 @@ impl Complex {
})
}

pub(crate) fn floor<I: Interrupt>(self, int: &I) -> FResult<Exact<Real>> {
Ok(Exact::new(self.expect_real()?.floor(int)?, true))
}

pub(crate) fn ceil<I: Interrupt>(self, int: &I) -> FResult<Exact<Real>> {
Ok(Exact::new(self.expect_real()?.ceil(int)?, true))
}

pub(crate) fn round<I: Interrupt>(self, int: &I) -> FResult<Exact<Real>> {
Ok(Exact::new(self.expect_real()?.round(int)?, true))
}

pub(crate) fn arg<I: Interrupt>(self, int: &I) -> FResult<Exact<Real>> {
Ok(Exact::new(self.imag.atan2(self.real, int)?, false))
}
Expand Down
12 changes: 12 additions & 0 deletions core/src/num/real.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,18 @@ impl Real {
Ok(Self::from(self.approximate(int)?.factorial(int)?))
}

pub(crate) fn floor<I: Interrupt>(self, int: &I) -> FResult<Self> {
Ok(Self::from(self.approximate(int)?.floor(int)?))
}

pub(crate) fn ceil<I: Interrupt>(self, int: &I) -> FResult<Self> {
Ok(Self::from(self.approximate(int)?.ceil(int)?))
}

pub(crate) fn round<I: Interrupt>(self, int: &I) -> FResult<Self> {
Ok(Self::from(self.approximate(int)?.round(int)?))
}

pub(crate) fn format<I: Interrupt>(
&self,
base: Base,
Expand Down
36 changes: 36 additions & 0 deletions core/src/num/unit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,42 @@ impl Value {
}
}

pub(crate) fn floor<I: Interrupt>(self, int: &I) -> FResult<Self> {
let value = self.value.one_point()?.floor(int)?;
Ok(Self {
value: Complex::from(value.value).into(),
unit: self.unit,
exact: self.exact && value.exact,
base: self.base,
format: self.format,
simplifiable: self.simplifiable,
})
}

pub(crate) fn ceil<I: Interrupt>(self, int: &I) -> FResult<Self> {
let value = self.value.one_point()?.ceil(int)?;
Ok(Self {
value: Complex::from(value.value).into(),
unit: self.unit,
exact: self.exact && value.exact,
base: self.base,
format: self.format,
simplifiable: self.simplifiable,
})
}

pub(crate) fn round<I: Interrupt>(self, int: &I) -> FResult<Self> {
let value = self.value.one_point()?.round(int)?;
Ok(Self {
value: Complex::from(value.value).into(),
unit: self.unit,
exact: self.exact && value.exact,
base: self.base,
format: self.format,
simplifiable: self.simplifiable,
})
}

pub(crate) fn real(self) -> FResult<Self> {
Ok(Self {
value: Complex::from(self.value.one_point()?.real()).into(),
Expand Down
3 changes: 3 additions & 0 deletions core/src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,9 @@ impl Value {
BuiltInFunction::Real => arg.expect_num()?.real()?,
BuiltInFunction::Imag => arg.expect_num()?.imag()?,
BuiltInFunction::Arg => arg.expect_num()?.arg(int)?,
BuiltInFunction::Floor => arg.expect_num()?.floor(int)?,
BuiltInFunction::Ceil => arg.expect_num()?.ceil(int)?,
BuiltInFunction::Round => arg.expect_num()?.round(int)?,
})))
}

Expand Down
6 changes: 6 additions & 0 deletions core/src/value/built_in_function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ pub(crate) enum BuiltInFunction {
Real,
Imag,
Arg,
Floor,
Ceil,
Round,
}

impl BuiltInFunction {
Expand Down Expand Up @@ -98,6 +101,9 @@ impl BuiltInFunction {
Self::Real => "real",
Self::Imag => "imag",
Self::Arg => "arg",
Self::Floor => "floor",
Self::Ceil => "ceil",
Self::Round => "round",
}
}

Expand Down
27 changes: 27 additions & 0 deletions core/tests/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2675,6 +2675,33 @@ fn factorial_of_three_kg() {
expect_error("(3 kg)!", None);
}

#[test]
fn test_floor() {
test_eval("floor(3)", "3");
test_eval("floor(3.9)", "3");
test_eval("floor(-3)", "-3");
test_eval("floor(-3.1)", "-4");
}

#[test]
fn test_ceil() {
test_eval("ceil(3)", "3");
test_eval("ceil(3.3)", "4");
test_eval("ceil(-3)", "-3");
test_eval("ceil(-3.3)", "-3");
}

#[test]
fn test_round() {
test_eval("round(3)", "3");

test_eval("round(3.3)", "3");
test_eval("round(3.7)", "4");

test_eval("round(-3.3)", "-3");
test_eval("round(-3.7)", "-4");
}

#[test]
fn recurring_digits_1() {
test_eval_simple("9/11 to float", "0.(81)");
Expand Down

0 comments on commit eda5977

Please sign in to comment.