diff --git a/tests/snippets/stdlib_math.py b/tests/snippets/stdlib_math.py index 9909b6e1d7..13e230e67a 100644 --- a/tests/snippets/stdlib_math.py +++ b/tests/snippets/stdlib_math.py @@ -34,6 +34,10 @@ assert math.trunc(2.2) == 2 assert math.ceil(3.3) == 4 assert math.floor(4.4) == 4 +assert isinstance(math.trunc(2.2), int) +assert isinstance(math.ceil(3.3), int) +assert isinstance(math.floor(4.4), int) + class A(object): def __trunc__(self): return 2 diff --git a/vm/src/obj/objfloat.rs b/vm/src/obj/objfloat.rs index 17eb76a9f7..896c47e65b 100644 --- a/vm/src/obj/objfloat.rs +++ b/vm/src/obj/objfloat.rs @@ -89,7 +89,7 @@ fn inner_mod(v1: f64, v2: f64, vm: &VirtualMachine) -> PyResult { } } -fn try_to_bigint(value: f64, vm: &VirtualMachine) -> PyResult { +pub fn try_to_bigint(value: f64, vm: &VirtualMachine) -> PyResult { match value.to_bigint() { Some(int) => Ok(int), None => { diff --git a/vm/src/stdlib/math.rs b/vm/src/stdlib/math.rs index d548ab8aef..da9cb983ef 100644 --- a/vm/src/stdlib/math.rs +++ b/vm/src/stdlib/math.rs @@ -214,19 +214,33 @@ fn math_trunc(value: PyObjectRef, vm: &VirtualMachine) -> PyResult { try_magic_method("__trunc__", vm, &value) } +/// Applies ceiling to a float, returning an Integral. +/// +/// # Arguments +/// +/// * `value` - Either a float or a python object which implements __ceil__ +/// * `vm` - Represents the python state. fn math_ceil(value: PyObjectRef, vm: &VirtualMachine) -> PyResult { if objtype::isinstance(&value, &vm.ctx.float_type()) { let v = objfloat::get_value(&value); - Ok(vm.ctx.new_float(v.ceil())) + let v = objfloat::try_to_bigint(v.ceil(), vm)?; + Ok(vm.ctx.new_int(v)) } else { try_magic_method("__ceil__", vm, &value) } } +/// Applies floor to a float, returning an Integral. +/// +/// # Arguments +/// +/// * `value` - Either a float or a python object which implements __ceil__ +/// * `vm` - Represents the python state. fn math_floor(value: PyObjectRef, vm: &VirtualMachine) -> PyResult { if objtype::isinstance(&value, &vm.ctx.float_type()) { let v = objfloat::get_value(&value); - Ok(vm.ctx.new_float(v.floor())) + let v = objfloat::try_to_bigint(v.floor(), vm)?; + Ok(vm.ctx.new_int(v)) } else { try_magic_method("__floor__", vm, &value) }