mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-02 19:39:49 +09:00
Merge pull request #1239 from youknowone/fix-divmod
Fix int [r]divmod, Add rfloordiv
This commit is contained in:
@@ -3,6 +3,7 @@ from testutils import assert_raises
|
||||
assert divmod(11, 3) == (3, 2)
|
||||
assert divmod(8,11) == (0, 8)
|
||||
assert divmod(0.873, 0.252) == (3.0, 0.11699999999999999)
|
||||
assert divmod(-86340, 86400) == (-1, 60)
|
||||
|
||||
assert_raises(ZeroDivisionError, lambda: divmod(5, 0), 'divmod by zero')
|
||||
assert_raises(ZeroDivisionError, lambda: divmod(5.0, 0.0), 'divmod by zero')
|
||||
|
||||
@@ -36,7 +36,17 @@ assert (2).__rsub__(1) == -1
|
||||
assert (2).__mul__(1) == 2
|
||||
assert (2).__rmul__(1) == 2
|
||||
assert (2).__truediv__(1) == 2.0
|
||||
with assertRaises(ZeroDivisionError):
|
||||
(2).__truediv__(0)
|
||||
assert (2).__rtruediv__(1) == 0.5
|
||||
assert (-2).__floordiv__(3) == -1
|
||||
with assertRaises(ZeroDivisionError):
|
||||
(2).__floordiv__(0)
|
||||
assert (-3).__rfloordiv__(2) == -1
|
||||
assert (-2).__divmod__(3) == (-1, 1)
|
||||
with assertRaises(ZeroDivisionError):
|
||||
(2).__divmod__(0)
|
||||
assert (-3).__rdivmod__(2) == (-1, -1)
|
||||
assert (2).__pow__(3) == 8
|
||||
assert (10).__pow__(-1) == 0.1
|
||||
assert (2).__rpow__(3) == 9
|
||||
|
||||
@@ -139,10 +139,29 @@ fn inner_pow(int1: &PyInt, int2: &PyInt, vm: &VirtualMachine) -> PyResult {
|
||||
}
|
||||
|
||||
fn inner_mod(int1: &PyInt, int2: &PyInt, vm: &VirtualMachine) -> PyResult {
|
||||
if int2.value != BigInt::zero() {
|
||||
Ok(vm.ctx.new_int(&int1.value % &int2.value))
|
||||
} else {
|
||||
if int2.value.is_zero() {
|
||||
Err(vm.new_zero_division_error("integer modulo by zero".to_string()))
|
||||
} else {
|
||||
Ok(vm.ctx.new_int(&int1.value % &int2.value))
|
||||
}
|
||||
}
|
||||
|
||||
fn inner_floordiv(int1: &PyInt, int2: &PyInt, vm: &VirtualMachine) -> PyResult {
|
||||
if int2.value.is_zero() {
|
||||
Err(vm.new_zero_division_error("integer division by zero".to_string()))
|
||||
} else {
|
||||
Ok(vm.ctx.new_int(int1.value.div_floor(&int2.value)))
|
||||
}
|
||||
}
|
||||
|
||||
fn inner_divmod(int1: &PyInt, int2: &PyInt, vm: &VirtualMachine) -> PyResult {
|
||||
if int2.value.is_zero() {
|
||||
Err(vm.new_zero_division_error("integer division or modulo by zero".to_string()))
|
||||
} else {
|
||||
let (div, modulo) = int1.value.div_mod_floor(&int2.value);
|
||||
Ok(vm
|
||||
.ctx
|
||||
.new_tuple(vec![vm.ctx.new_int(div), vm.ctx.new_int(modulo)]))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,13 +288,18 @@ impl PyInt {
|
||||
#[pymethod(name = "__floordiv__")]
|
||||
fn floordiv(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
if objtype::isinstance(&other, &vm.ctx.int_type()) {
|
||||
let v2 = get_value(&other);
|
||||
if *v2 != BigInt::zero() {
|
||||
let modulo = (&self.value % v2 + v2) % v2;
|
||||
Ok(vm.ctx.new_int((&self.value - modulo) / v2))
|
||||
} else {
|
||||
Err(vm.new_zero_division_error("integer floordiv by zero".to_string()))
|
||||
}
|
||||
let other = other.payload::<PyInt>().unwrap();
|
||||
inner_floordiv(self, &other, &vm)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethod(name = "__rfloordiv__")]
|
||||
fn rfloordiv(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
if objtype::isinstance(&other, &vm.ctx.int_type()) {
|
||||
let other = other.payload::<PyInt>().unwrap();
|
||||
inner_floordiv(&other, self, &vm)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
@@ -397,15 +421,18 @@ impl PyInt {
|
||||
#[pymethod(name = "__divmod__")]
|
||||
fn divmod(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
if objtype::isinstance(&other, &vm.ctx.int_type()) {
|
||||
let v2 = get_value(&other);
|
||||
if *v2 != BigInt::zero() {
|
||||
let (r1, r2) = self.value.div_rem(v2);
|
||||
Ok(vm
|
||||
.ctx
|
||||
.new_tuple(vec![vm.ctx.new_int(r1), vm.ctx.new_int(r2)]))
|
||||
} else {
|
||||
Err(vm.new_zero_division_error("integer divmod by zero".to_string()))
|
||||
}
|
||||
let other = other.payload::<PyInt>().unwrap();
|
||||
inner_divmod(self, &other, vm)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethod(name = "__rdivmod__")]
|
||||
fn rdivmod(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
if objtype::isinstance(&other, &vm.ctx.int_type()) {
|
||||
let other = other.payload::<PyInt>().unwrap();
|
||||
inner_divmod(&other, self, vm)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user