From 47daaf555f8bd4172a3c54d3e249199700076a49 Mon Sep 17 00:00:00 2001 From: Adolfo Gonzalez III Date: Fri, 8 Nov 2019 16:13:11 -0600 Subject: [PATCH 1/7] Rebasing branch --- tests/snippets/math_module.py | 125 ++++++++++++++++++++++++++++++++++ vm/src/stdlib/math.rs | 30 +++++++- 2 files changed, 153 insertions(+), 2 deletions(-) create mode 100644 tests/snippets/math_module.py diff --git a/tests/snippets/math_module.py b/tests/snippets/math_module.py new file mode 100644 index 000000000..42ae6b955 --- /dev/null +++ b/tests/snippets/math_module.py @@ -0,0 +1,125 @@ +import math +from testutils import assert_raises + +# assert(math.exp(2) == math.exp(2.0)) +# assert(math.exp(True) == math.exp(1.0)) +# +# class Conversible(): +# def __float__(self): +# print("Converting to float now!") +# return 1.1111 +# +# assert math.log(1.1111) == math.log(Conversible()) + +# roundings +assert int.__trunc__ +assert int.__floor__ +assert int.__ceil__ + +# assert float.__trunc__ +with assert_raises(AttributeError): + assert float.__floor__ +with assert_raises(AttributeError): + assert float.__ceil__ + +assert math.trunc(2) == 2 +assert math.ceil(3) == 3 +assert math.floor(4) == 4 + +assert math.trunc(2.2) == 2 +assert math.ceil(3.3) == 4 +assert math.floor(4.4) == 4 + +# Check if the type of the resulting number is correct +assert type(math.trunc(2.2)) == int +assert type(math.ceil(3.3)) == int +assert type(math.floor(4.4)) == int + +class A(object): + def __trunc__(self): + return 2 + + def __ceil__(self): + return 3 + + def __floor__(self): + return 4 + +assert math.trunc(A()) == 2 +assert math.ceil(A()) == 3 +assert math.floor(A()) == 4 + +class A(object): + def __trunc__(self): + return 2.2 + + def __ceil__(self): + return 3.3 + + def __floor__(self): + return 4.4 + +assert math.trunc(A()) == 2.2 +assert math.ceil(A()) == 3.3 +assert math.floor(A()) == 4.4 + +class A(object): + def __trunc__(self): + return 'trunc' + + def __ceil__(self): + return 'ceil' + + def __floor__(self): + return 'floor' + +assert math.trunc(A()) == 'trunc' +assert math.ceil(A()) == 'ceil' +assert math.floor(A()) == 'floor' + +with assert_raises(TypeError): + math.trunc(object()) +with assert_raises(TypeError): + math.ceil(object()) +with assert_raises(TypeError): + math.floor(object()) + +assert str(math.frexp(0.0)) == str((+0.0, 0)) +assert str(math.frexp(-0.0)) == str((-0.0, 0)) +assert math.frexp(1) == (0.5, 1) +assert math.frexp(1.5) == (0.75, 1) +assert_raises(TypeError, lambda: math.frexp(None)) + +assert str(math.ldexp(+0.0, 0)) == str(0.0) +assert str(math.ldexp(-0.0, 0)) == str(-0.0) +assert math.ldexp(0.5, 1) == 1 +assert math.ldexp(0.75, 1) == 1.5 +assert_raises(TypeError, lambda: math.ldexp(None, None)) + +assert math.frexp(float('inf')) == (float('inf'), 0) +assert str(math.frexp(float('nan'))) == str((float('nan'), 0)) +assert_raises(TypeError, lambda: math.frexp(None)) + +assert math.gcd(0, 0) == 0 +assert math.gcd(1, 0) == 1 +assert math.gcd(0, 1) == 1 +assert math.gcd(1, 1) == 1 +assert math.gcd(-1, 1) == 1 +assert math.gcd(1, -1) == 1 +assert math.gcd(-1, -1) == 1 +assert math.gcd(125, -255) == 5 +assert_raises(TypeError, lambda: math.gcd(1.1, 2)) + +assert math.factorial(0) == 1 +assert math.factorial(1) == 1 +assert math.factorial(2) == 2 +assert math.factorial(3) == 6 +assert math.factorial(10) == 3628800 +assert math.factorial(20) == 2432902008176640000 +assert_raises(ValueError, lambda: math.factorial(-1)) + +assert math.modf(1.25) == (0.25, 1.0) +assert math.modf(-1.25) == (-0.25, -1.0) +assert math.modf(2.56) == (0.56, 2.0) +assert math.modf(-2.56) == (-0.56, -2.0) +assert math.modf(1) == (0.0, 1.0) diff --git a/vm/src/stdlib/math.rs b/vm/src/stdlib/math.rs index d548ab8ae..9627ce6cc 100644 --- a/vm/src/stdlib/math.rs +++ b/vm/src/stdlib/math.rs @@ -214,19 +214,45 @@ 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. +/// +/// # Remarks +/// +/// Currently the code is applying ceil to the float using rust's builtin +/// method and then converts to integral using python float's __int__ method. +/// 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 = vm.ctx.new_float(v.ceil()); + try_magic_method("__int__", vm, &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. +/// +/// # Remarks +/// +/// Currently the code is applying floor to the float using rust's builtin +/// method and then converts to integral using python float's __int__ method. +/// 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 = vm.ctx.new_float(v.floor()); + try_magic_method("__int__", vm, &v) } else { try_magic_method("__floor__", vm, &value) } From 6d73dac56d2ef150c518b5c4f972020ecb60a2e6 Mon Sep 17 00:00:00 2001 From: Adolfo Gonzalez III Date: Fri, 8 Nov 2019 16:14:13 -0600 Subject: [PATCH 2/7] Removed tests --- tests/snippets/math_module.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/snippets/math_module.py b/tests/snippets/math_module.py index 42ae6b955..f85a7337a 100644 --- a/tests/snippets/math_module.py +++ b/tests/snippets/math_module.py @@ -30,11 +30,6 @@ assert math.trunc(2.2) == 2 assert math.ceil(3.3) == 4 assert math.floor(4.4) == 4 -# Check if the type of the resulting number is correct -assert type(math.trunc(2.2)) == int -assert type(math.ceil(3.3)) == int -assert type(math.floor(4.4)) == int - class A(object): def __trunc__(self): return 2 From 256f3562c2f8802099bb170f284b8ae62cb35134 Mon Sep 17 00:00:00 2001 From: Adolfo Gonzalez III Date: Thu, 7 Nov 2019 12:07:02 -0600 Subject: [PATCH 3/7] Changed to use existing method Made try_to_bigint public and then used for math.ceil and math.floor --- vm/src/obj/objfloat.rs | 2 +- vm/src/stdlib/math.rs | 20 ++++---------------- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/vm/src/obj/objfloat.rs b/vm/src/obj/objfloat.rs index 17eb76a9f..896c47e65 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 9627ce6cc..da9cb983e 100644 --- a/vm/src/stdlib/math.rs +++ b/vm/src/stdlib/math.rs @@ -220,17 +220,11 @@ fn math_trunc(value: PyObjectRef, vm: &VirtualMachine) -> PyResult { /// /// * `value` - Either a float or a python object which implements __ceil__ /// * `vm` - Represents the python state. -/// -/// # Remarks -/// -/// Currently the code is applying ceil to the float using rust's builtin -/// method and then converts to integral using python float's __int__ method. -/// fn math_ceil(value: PyObjectRef, vm: &VirtualMachine) -> PyResult { if objtype::isinstance(&value, &vm.ctx.float_type()) { let v = objfloat::get_value(&value); - let v = vm.ctx.new_float(v.ceil()); - try_magic_method("__int__", vm, &v) + let v = objfloat::try_to_bigint(v.ceil(), vm)?; + Ok(vm.ctx.new_int(v)) } else { try_magic_method("__ceil__", vm, &value) } @@ -242,17 +236,11 @@ fn math_ceil(value: PyObjectRef, vm: &VirtualMachine) -> PyResult { /// /// * `value` - Either a float or a python object which implements __ceil__ /// * `vm` - Represents the python state. -/// -/// # Remarks -/// -/// Currently the code is applying floor to the float using rust's builtin -/// method and then converts to integral using python float's __int__ method. -/// fn math_floor(value: PyObjectRef, vm: &VirtualMachine) -> PyResult { if objtype::isinstance(&value, &vm.ctx.float_type()) { let v = objfloat::get_value(&value); - let v = vm.ctx.new_float(v.floor()); - try_magic_method("__int__", vm, &v) + let v = objfloat::try_to_bigint(v.floor(), vm)?; + Ok(vm.ctx.new_int(v)) } else { try_magic_method("__floor__", vm, &value) } From 8c876bc8eae5f3923a2911ceb4d9b1e1b49c5971 Mon Sep 17 00:00:00 2001 From: Adolfo Gonzalez III Date: Mon, 2 Dec 2019 11:26:00 -0600 Subject: [PATCH 4/7] Merging changes --- tests/snippets/math_module.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/snippets/math_module.py b/tests/snippets/math_module.py index f85a7337a..42ae6b955 100644 --- a/tests/snippets/math_module.py +++ b/tests/snippets/math_module.py @@ -30,6 +30,11 @@ assert math.trunc(2.2) == 2 assert math.ceil(3.3) == 4 assert math.floor(4.4) == 4 +# Check if the type of the resulting number is correct +assert type(math.trunc(2.2)) == int +assert type(math.ceil(3.3)) == int +assert type(math.floor(4.4)) == int + class A(object): def __trunc__(self): return 2 From 67c7fef22e2e3729c7ef9d5f3a0064a5219f189d Mon Sep 17 00:00:00 2001 From: Adolfo Gonzalez III Date: Fri, 8 Nov 2019 16:14:13 -0600 Subject: [PATCH 5/7] Removed tests --- tests/snippets/math_module.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/snippets/math_module.py b/tests/snippets/math_module.py index 42ae6b955..f85a7337a 100644 --- a/tests/snippets/math_module.py +++ b/tests/snippets/math_module.py @@ -30,11 +30,6 @@ assert math.trunc(2.2) == 2 assert math.ceil(3.3) == 4 assert math.floor(4.4) == 4 -# Check if the type of the resulting number is correct -assert type(math.trunc(2.2)) == int -assert type(math.ceil(3.3)) == int -assert type(math.floor(4.4)) == int - class A(object): def __trunc__(self): return 2 From 4e4be1c40a7f1e6e01d07624b49357235848ab6b Mon Sep 17 00:00:00 2001 From: Adolfo Gonzalez III Date: Fri, 6 Dec 2019 13:20:25 -0600 Subject: [PATCH 6/7] Removed file --- tests/snippets/math_module.py | 120 ---------------------------------- 1 file changed, 120 deletions(-) delete mode 100644 tests/snippets/math_module.py diff --git a/tests/snippets/math_module.py b/tests/snippets/math_module.py deleted file mode 100644 index f85a7337a..000000000 --- a/tests/snippets/math_module.py +++ /dev/null @@ -1,120 +0,0 @@ -import math -from testutils import assert_raises - -# assert(math.exp(2) == math.exp(2.0)) -# assert(math.exp(True) == math.exp(1.0)) -# -# class Conversible(): -# def __float__(self): -# print("Converting to float now!") -# return 1.1111 -# -# assert math.log(1.1111) == math.log(Conversible()) - -# roundings -assert int.__trunc__ -assert int.__floor__ -assert int.__ceil__ - -# assert float.__trunc__ -with assert_raises(AttributeError): - assert float.__floor__ -with assert_raises(AttributeError): - assert float.__ceil__ - -assert math.trunc(2) == 2 -assert math.ceil(3) == 3 -assert math.floor(4) == 4 - -assert math.trunc(2.2) == 2 -assert math.ceil(3.3) == 4 -assert math.floor(4.4) == 4 - -class A(object): - def __trunc__(self): - return 2 - - def __ceil__(self): - return 3 - - def __floor__(self): - return 4 - -assert math.trunc(A()) == 2 -assert math.ceil(A()) == 3 -assert math.floor(A()) == 4 - -class A(object): - def __trunc__(self): - return 2.2 - - def __ceil__(self): - return 3.3 - - def __floor__(self): - return 4.4 - -assert math.trunc(A()) == 2.2 -assert math.ceil(A()) == 3.3 -assert math.floor(A()) == 4.4 - -class A(object): - def __trunc__(self): - return 'trunc' - - def __ceil__(self): - return 'ceil' - - def __floor__(self): - return 'floor' - -assert math.trunc(A()) == 'trunc' -assert math.ceil(A()) == 'ceil' -assert math.floor(A()) == 'floor' - -with assert_raises(TypeError): - math.trunc(object()) -with assert_raises(TypeError): - math.ceil(object()) -with assert_raises(TypeError): - math.floor(object()) - -assert str(math.frexp(0.0)) == str((+0.0, 0)) -assert str(math.frexp(-0.0)) == str((-0.0, 0)) -assert math.frexp(1) == (0.5, 1) -assert math.frexp(1.5) == (0.75, 1) -assert_raises(TypeError, lambda: math.frexp(None)) - -assert str(math.ldexp(+0.0, 0)) == str(0.0) -assert str(math.ldexp(-0.0, 0)) == str(-0.0) -assert math.ldexp(0.5, 1) == 1 -assert math.ldexp(0.75, 1) == 1.5 -assert_raises(TypeError, lambda: math.ldexp(None, None)) - -assert math.frexp(float('inf')) == (float('inf'), 0) -assert str(math.frexp(float('nan'))) == str((float('nan'), 0)) -assert_raises(TypeError, lambda: math.frexp(None)) - -assert math.gcd(0, 0) == 0 -assert math.gcd(1, 0) == 1 -assert math.gcd(0, 1) == 1 -assert math.gcd(1, 1) == 1 -assert math.gcd(-1, 1) == 1 -assert math.gcd(1, -1) == 1 -assert math.gcd(-1, -1) == 1 -assert math.gcd(125, -255) == 5 -assert_raises(TypeError, lambda: math.gcd(1.1, 2)) - -assert math.factorial(0) == 1 -assert math.factorial(1) == 1 -assert math.factorial(2) == 2 -assert math.factorial(3) == 6 -assert math.factorial(10) == 3628800 -assert math.factorial(20) == 2432902008176640000 -assert_raises(ValueError, lambda: math.factorial(-1)) - -assert math.modf(1.25) == (0.25, 1.0) -assert math.modf(-1.25) == (-0.25, -1.0) -assert math.modf(2.56) == (0.56, 2.0) -assert math.modf(-2.56) == (-0.56, -2.0) -assert math.modf(1) == (0.0, 1.0) From 1519c326d8c96c39e5ae7160b45ac47325856f6d Mon Sep 17 00:00:00 2001 From: Adolfo Gonzalez III Date: Fri, 6 Dec 2019 14:17:30 -0600 Subject: [PATCH 7/7] Added test --- tests/snippets/stdlib_math.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/snippets/stdlib_math.py b/tests/snippets/stdlib_math.py index 9909b6e1d..13e230e67 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