From db10a82cbe3cd59b436899080fbe0a838e78ede0 Mon Sep 17 00:00:00 2001 From: "johan.park" Date: Sun, 22 Sep 2019 16:12:41 +0900 Subject: [PATCH] Update copysign module of math - Implement copysign function with test case - Add constants of NAN, INF, NINF on top of `math_module.py` --- tests/snippets/math_module.py | 39 +++++++++++++++++++++++++++++++++-- vm/src/stdlib/math.rs | 11 ++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/tests/snippets/math_module.py b/tests/snippets/math_module.py index f85a7337a..48d612da4 100644 --- a/tests/snippets/math_module.py +++ b/tests/snippets/math_module.py @@ -1,6 +1,10 @@ import math from testutils import assert_raises +NAN = float('nan') +INF = float('inf') +NINF = float('-inf') + # assert(math.exp(2) == math.exp(2.0)) # assert(math.exp(True) == math.exp(1.0)) # @@ -30,6 +34,37 @@ assert math.trunc(2.2) == 2 assert math.ceil(3.3) == 4 assert math.floor(4.4) == 4 +assert math.copysign(1, 42) == 1.0 +assert math.copysign(0., 42) == 0.0 +assert math.copysign(1., -42) == -1.0 +assert math.copysign(3, 0.) == 3.0 +assert math.copysign(4., -0.) == -4.0 +assert_raises(TypeError, math.copysign) +# copysign should let us distinguish signs of zeros +assert math.copysign(1., 0.) == 1. +assert math.copysign(1., -0.) == -1. +assert math.copysign(INF, 0.) == INF +assert math.copysign(INF, -0.) == NINF +assert math.copysign(NINF, 0.) == INF +assert math.copysign(NINF, -0.) == NINF +# and of infinities +assert math.copysign(1., INF) == 1. +assert math.copysign(1., NINF) == -1. +assert math.copysign(INF, INF) == INF +assert math.copysign(INF, NINF) == NINF +assert math.copysign(NINF, INF) == INF +assert math.copysign(NINF, NINF) == NINF +assert math.isnan(math.copysign(NAN, 1.)) +assert math.isnan(math.copysign(NAN, INF)) +assert math.isnan(math.copysign(NAN, NINF)) +assert math.isnan(math.copysign(NAN, NAN)) +# copysign(INF, NAN) may be INF or it may be NINF, since +# we don't know whether the sign bit of NAN is set on any +# given platform. +assert math.isinf(math.copysign(INF, NAN)) +# similarly, copysign(2., NAN) could be 2. or -2. +assert abs(math.copysign(2., NAN)) == 2. + class A(object): def __trunc__(self): return 2 @@ -91,8 +126,8 @@ 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 math.frexp(INF) == (INF, 0) +assert str(math.frexp(NAN)) == str((NAN, 0)) assert_raises(TypeError, lambda: math.frexp(None)) assert math.gcd(0, 0) == 0 diff --git a/vm/src/stdlib/math.rs b/vm/src/stdlib/math.rs index e111e74fb..253028a5e 100644 --- a/vm/src/stdlib/math.rs +++ b/vm/src/stdlib/math.rs @@ -40,6 +40,16 @@ make_math_func_bool!(math_isfinite, is_finite); make_math_func_bool!(math_isinf, is_infinite); make_math_func_bool!(math_isnan, is_nan); +fn math_copysign(a: IntoPyFloat, b: IntoPyFloat, _vm: &VirtualMachine) -> f64 { + let a = a.to_f64(); + let b = b.to_f64(); + if a.is_nan() || b.is_nan(){ + a + } else { + a.copysign(b) + } +} + // Power and logarithmic functions: make_math_func!(math_exp, exp); make_math_func!(math_expm1, exp_m1); @@ -213,6 +223,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { "isfinite" => ctx.new_rustfunc(math_isfinite), "isinf" => ctx.new_rustfunc(math_isinf), "isnan" => ctx.new_rustfunc(math_isnan), + "copysign" => ctx.new_rustfunc(math_copysign), // Power and logarithmic functions: "exp" => ctx.new_rustfunc(math_exp),