From c8d0360760466eb693371dc2c189fdbe8b16d8d6 Mon Sep 17 00:00:00 2001 From: Gyubong Date: Tue, 4 Oct 2022 16:29:09 +0900 Subject: [PATCH 1/3] Fix #4198 --- vm/src/builtins/int.rs | 32 ++++++-------------------------- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/vm/src/builtins/int.rs b/vm/src/builtins/int.rs index ad16506477..d5c5dca92e 100644 --- a/vm/src/builtins/int.rs +++ b/vm/src/builtins/int.rs @@ -18,8 +18,9 @@ use crate::{ use bstr::ByteSlice; use num_bigint::{BigInt, BigUint, Sign}; use num_integer::Integer; +use num_rational::Ratio; use num_traits::{One, Pow, PrimInt, Signed, ToPrimitive, Zero}; -use std::ops::Neg; +use std::ops::{Div, Neg}; use std::{fmt, ops::Not}; /// int(x=0) -> integer @@ -212,31 +213,10 @@ fn inner_truediv(i1: &BigInt, i2: &BigInt, vm: &VirtualMachine) -> PyResult { return Err(vm.new_zero_division_error("division by zero".to_owned())); } - let value = if let (Some(f1), Some(f2)) = (i2f(i1), i2f(i2)) { - f1 / f2 - } else { - let (quotient, mut rem) = i1.div_rem(i2); - let mut divisor = i2.clone(); - - if let Some(quotient) = i2f("ient) { - let rem_part = loop { - if rem.is_zero() { - break 0.0; - } else if let (Some(rem), Some(divisor)) = (i2f(&rem), i2f(&divisor)) { - break rem / divisor; - } else { - // try with smaller numbers - rem /= 2; - divisor /= 2; - } - }; - - quotient + rem_part - } else { - return Err(vm.new_overflow_error("int too large to convert to float".to_owned())); - } - }; - Ok(vm.ctx.new_float(value).into()) + Ok(vm + .ctx + .new_float(Ratio::from(i1.clone()).div(i2).to_f64().unwrap()) + .into()) } impl Constructor for PyInt { From a98288b911c7000081af0d36624e56085739e314 Mon Sep 17 00:00:00 2001 From: Gyubong Date: Tue, 4 Oct 2022 16:56:47 +0900 Subject: [PATCH 2/3] Add overflow handling logic --- vm/src/builtins/int.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/vm/src/builtins/int.rs b/vm/src/builtins/int.rs index d5c5dca92e..08f52847fd 100644 --- a/vm/src/builtins/int.rs +++ b/vm/src/builtins/int.rs @@ -213,10 +213,16 @@ fn inner_truediv(i1: &BigInt, i2: &BigInt, vm: &VirtualMachine) -> PyResult { return Err(vm.new_zero_division_error("division by zero".to_owned())); } - Ok(vm - .ctx - .new_float(Ratio::from(i1.clone()).div(i2).to_f64().unwrap()) - .into()) + let float = Ratio::from(i1.clone()).div(i2).to_f64().unwrap(); + + if float.is_infinite() { + Err(vm.new_exception_msg( + vm.ctx.exceptions.overflow_error.to_owned(), + "integer division result too large for a float".to_owned(), + )) + } else { + Ok(vm.ctx.new_float(float).into()) + } } impl Constructor for PyInt { From 773066f2ddc88d71e16a78dee9aacf8b5068ecbe Mon Sep 17 00:00:00 2001 From: Gyubong Date: Tue, 4 Oct 2022 17:28:00 +0900 Subject: [PATCH 3/3] Remove expectedFailure --- Lib/test/test_statistics.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/Lib/test/test_statistics.py b/Lib/test/test_statistics.py index 28664a4637..da81258832 100644 --- a/Lib/test/test_statistics.py +++ b/Lib/test/test_statistics.py @@ -691,8 +691,6 @@ class GlobalsTest(unittest.TestCase): 'missing name "%s" in __all__' % name) -# TODO: RUSTPYTHON -@unittest.expectedFailure class DocTests(unittest.TestCase): @unittest.skipIf(sys.flags.optimize >= 2, "Docstrings are omitted with -OO and above")