From c9e62002ec87c5fe56c3f77791ba8473f1fdcd0e Mon Sep 17 00:00:00 2001 From: Hanif Ariffin Date: Tue, 11 Feb 2025 16:09:38 +0800 Subject: [PATCH] Fixed the implementation of some math functions to match CPython closer. (#5510) Signed-off-by: Hanif Ariffin --- Lib/test/test_random.py | 2 -- stdlib/src/math.rs | 27 ++++++++++++++++++++++----- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py index 70bfbf09b..5bd92f32c 100644 --- a/Lib/test/test_random.py +++ b/Lib/test/test_random.py @@ -1012,8 +1012,6 @@ def gamma(z, sqrt2pi=(2.0*pi)**0.5): ]) class TestDistributions(unittest.TestCase): - # TODO: RUSTPYTHON ValueError: math domain error - @unittest.expectedFailure def test_zeroinputs(self): # Verify that distributions can handle a series of zero inputs' g = random.Random() diff --git a/stdlib/src/math.rs b/stdlib/src/math.rs index c1abc1a6f..30b088f71 100644 --- a/stdlib/src/math.rs +++ b/stdlib/src/math.rs @@ -132,6 +132,9 @@ mod math { #[pyfunction] fn log(x: PyObjectRef, base: OptionalArg, vm: &VirtualMachine) -> PyResult { let base = base.map(|b| *b).unwrap_or(std::f64::consts::E); + if base.is_sign_negative() { + return Err(vm.new_value_error("math domain error".to_owned())); + } log2(x, vm).map(|logx| logx / base.log2()) } @@ -192,16 +195,18 @@ mod math { let x = *x; let y = *y; - if x < 0.0 && x.is_finite() && y.fract() != 0.0 && y.is_finite() { - return Err(vm.new_value_error("math domain error".to_owned())); - } - - if x == 0.0 && y < 0.0 && y != f64::NEG_INFINITY { + if x < 0.0 && x.is_finite() && y.fract() != 0.0 && y.is_finite() + || x == 0.0 && y < 0.0 && y != f64::NEG_INFINITY + { return Err(vm.new_value_error("math domain error".to_owned())); } let value = x.powf(y); + if x.is_finite() && y.is_finite() && value.is_infinite() { + return Err(vm.new_overflow_error("math range error".to_string())); + } + Ok(value) } @@ -212,6 +217,9 @@ mod math { return Ok(value); } if value.is_sign_negative() { + if value.is_zero() { + return Ok(-0.0f64); + } return Err(vm.new_value_error("math domain error".to_owned())); } Ok(value.sqrt()) @@ -260,6 +268,9 @@ mod math { #[pyfunction] fn cos(x: ArgIntoFloat, vm: &VirtualMachine) -> PyResult { + if x.is_infinite() { + return Err(vm.new_value_error("math domain error".to_owned())); + } call_math_func!(cos, x, vm) } @@ -394,11 +405,17 @@ mod math { #[pyfunction] fn sin(x: ArgIntoFloat, vm: &VirtualMachine) -> PyResult { + if x.is_infinite() { + return Err(vm.new_value_error("math domain error".to_owned())); + } call_math_func!(sin, x, vm) } #[pyfunction] fn tan(x: ArgIntoFloat, vm: &VirtualMachine) -> PyResult { + if x.is_infinite() { + return Err(vm.new_value_error("math domain error".to_owned())); + } call_math_func!(tan, x, vm) }