mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Use improved log2() implementation for log10()
This also fixes a bug in the log2() implementation, where very large negative integer arguments would not raise an exception (and instead would turn into NaNs).
This commit is contained in:
1 parent
247072c2cc
commit
82b4990224
3 files changed
+11
-26
No files matched your search
Vendored
-2
@@ -514,8 +514,6 @@ class LongTest(unittest.TestCase):
|
||||
self.assertNotEqual(float(shuge), int(shuge),
|
||||
"float(shuge) should not equal int(shuge)")
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_logs(self):
|
||||
LOG10E = math.log10(math.e)
|
||||
|
||||
|
||||
Vendored
-4
@@ -1137,8 +1137,6 @@ class MathTests(unittest.TestCase):
|
||||
self.assertEqual(math.ldexp(NINF, n), NINF)
|
||||
self.assertTrue(math.isnan(math.ldexp(NAN, n)))
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def testLog(self):
|
||||
self.assertRaises(TypeError, math.log)
|
||||
self.ftest('log(1/e)', math.log(1/math.e), -1)
|
||||
@@ -1190,8 +1188,6 @@ class MathTests(unittest.TestCase):
|
||||
expected = [float(n) for n in range(-1074, 1024)]
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def testLog10(self):
|
||||
self.assertRaises(TypeError, math.log10)
|
||||
self.ftest('log10(0.1)', math.log10(0.1), -1)
|
||||
|
||||
+11
-20
@@ -132,18 +132,9 @@ mod math {
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn log(x: ArgIntoFloat, base: OptionalArg<ArgIntoFloat>, vm: &VirtualMachine) -> PyResult<f64> {
|
||||
let x = *x;
|
||||
base.map_or_else(
|
||||
|| {
|
||||
if x.is_nan() || x > 0.0_f64 {
|
||||
Ok(x.ln())
|
||||
} else {
|
||||
Err(vm.new_value_error("math domain error".to_owned()))
|
||||
}
|
||||
},
|
||||
|base| Ok(x.log(*base)),
|
||||
)
|
||||
fn log(x: PyObjectRef, base: OptionalArg<ArgIntoFloat>, vm: &VirtualMachine) -> PyResult<f64> {
|
||||
let base = base.map(|b| *b).unwrap_or(std::f64::consts::E);
|
||||
log2(x, vm).map(|logx| logx / base.log2())
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
@@ -179,7 +170,12 @@ mod math {
|
||||
}
|
||||
Err(float_err) => {
|
||||
if let Ok(x) = x.try_int(vm) {
|
||||
Ok(int_log2(x.as_bigint()))
|
||||
let x = x.as_bigint();
|
||||
if x > &BigInt::zero() {
|
||||
Ok(int_log2(x))
|
||||
} else {
|
||||
Err(vm.new_value_error("math domain error".to_owned()))
|
||||
}
|
||||
} else {
|
||||
// Return the float error, as it will be more intuitive to users
|
||||
Err(float_err)
|
||||
@@ -189,13 +185,8 @@ mod math {
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn log10(x: ArgIntoFloat, vm: &VirtualMachine) -> PyResult<f64> {
|
||||
let x = *x;
|
||||
if x.is_nan() || x > 0.0_f64 {
|
||||
Ok(x.log10())
|
||||
} else {
|
||||
Err(vm.new_value_error("math domain error".to_owned()))
|
||||
}
|
||||
fn log10(x: PyObjectRef, vm: &VirtualMachine) -> PyResult<f64> {
|
||||
log2(x, vm).map(|logx| logx / 10f64.log2())
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
|
||||
Reference in new issue
Block a user