Merge pull request #3555 from Snowapril/remove_complex_methods

Remove several special method of complex class
This commit is contained in:
Jeong YunWon
2022-02-19 02:31:54 +09:00
committed by GitHub
2 changed files with 102 additions and 59 deletions

View File

@@ -1,6 +1,6 @@
import unittest
import sys
from test import support
from test.support import os_helper
from test.test_grammar import (VALID_UNDERSCORE_LITERALS,
INVALID_UNDERSCORE_LITERALS)
@@ -12,6 +12,14 @@ INF = float("inf")
NAN = float("nan")
# These tests ensure that complex math does the right thing
ZERO_DIVISION = (
(1+1j, 0+0j),
(1+1j, 0.0),
(1+1j, 0),
(1.0, 0+0j),
(1, 0+0j),
)
class ComplexTest(unittest.TestCase):
def assertAlmostEqual(self, a, b):
@@ -100,20 +108,34 @@ class ComplexTest(unittest.TestCase):
self.check_div(complex(random(), random()),
complex(random(), random()))
self.assertRaises(ZeroDivisionError, complex.__truediv__, 1+1j, 0+0j)
self.assertRaises(OverflowError, pow, 1e200+1j, 1e200+1j)
self.assertAlmostEqual(complex.__truediv__(2+0j, 1+1j), 1-1j)
self.assertRaises(ZeroDivisionError, complex.__truediv__, 1+1j, 0+0j)
for denom_real, denom_imag in [(0, NAN), (NAN, 0), (NAN, NAN)]:
z = complex(0, 0) / complex(denom_real, denom_imag)
self.assertTrue(isnan(z.real))
self.assertTrue(isnan(z.imag))
def test_truediv_zero_division(self):
for a, b in ZERO_DIVISION:
with self.assertRaises(ZeroDivisionError):
a / b
def test_floordiv(self):
self.assertRaises(TypeError, complex.__floordiv__, 3+0j, 1.5+0j)
self.assertRaises(TypeError, complex.__floordiv__, 3+0j, 0+0j)
with self.assertRaises(TypeError):
(1+1j) // (1+0j)
with self.assertRaises(TypeError):
(1+1j) // 1.0
with self.assertRaises(TypeError):
(1+1j) // 1
with self.assertRaises(TypeError):
1.0 // (1+0j)
with self.assertRaises(TypeError):
1 // (1+0j)
def test_floordiv_zero_division(self):
for a, b in ZERO_DIVISION:
with self.assertRaises(TypeError):
a // b
def test_richcompare(self):
self.assertIs(complex.__eq__(1+1j, 1<<10000), False)
@@ -162,13 +184,32 @@ class ComplexTest(unittest.TestCase):
def test_mod(self):
# % is no longer supported on complex numbers
self.assertRaises(TypeError, (1+1j).__mod__, 0+0j)
self.assertRaises(TypeError, lambda: (3.33+4.43j) % 0)
self.assertRaises(TypeError, (1+1j).__mod__, 4.3j)
with self.assertRaises(TypeError):
(1+1j) % (1+0j)
with self.assertRaises(TypeError):
(1+1j) % 1.0
with self.assertRaises(TypeError):
(1+1j) % 1
with self.assertRaises(TypeError):
1.0 % (1+0j)
with self.assertRaises(TypeError):
1 % (1+0j)
def test_mod_zero_division(self):
for a, b in ZERO_DIVISION:
with self.assertRaises(TypeError):
a % b
def test_divmod(self):
self.assertRaises(TypeError, divmod, 1+1j, 1+0j)
self.assertRaises(TypeError, divmod, 1+1j, 0+0j)
self.assertRaises(TypeError, divmod, 1+1j, 1.0)
self.assertRaises(TypeError, divmod, 1+1j, 1)
self.assertRaises(TypeError, divmod, 1.0, 1+0j)
self.assertRaises(TypeError, divmod, 1, 1+0j)
def test_divmod_zero_division(self):
for a, b in ZERO_DIVISION:
self.assertRaises(TypeError, divmod, a, b)
def test_pow(self):
self.assertAlmostEqual(pow(1+1j, 0+0j), 1.0)
@@ -177,6 +218,7 @@ class ComplexTest(unittest.TestCase):
self.assertAlmostEqual(pow(1j, -1), 1/1j)
self.assertAlmostEqual(pow(1j, 200), 1)
self.assertRaises(ValueError, pow, 1+1j, 1+1j, 1+1j)
self.assertRaises(OverflowError, pow, 1e200+1j, 1e200+1j)
a = 3.33+4.43j
self.assertEqual(a ** 0j, 1)
@@ -209,6 +251,54 @@ class ComplexTest(unittest.TestCase):
b = 5.1+2.3j
self.assertRaises(ValueError, pow, a, b, 0)
# Check some boundary conditions; some of these used to invoke
# undefined behaviour (https://bugs.python.org/issue44698). We're
# not actually checking the results of these operations, just making
# sure they don't crash (for example when using clang's
# UndefinedBehaviourSanitizer).
values = (sys.maxsize, sys.maxsize+1, sys.maxsize-1,
-sys.maxsize, -sys.maxsize+1, -sys.maxsize+1)
for real in values:
for imag in values:
with self.subTest(real=real, imag=imag):
c = complex(real, imag)
try:
c ** real
except OverflowError:
pass
try:
c ** c
except OverflowError:
pass
def test_pow_with_small_integer_exponents(self):
# Check that small integer exponents are handled identically
# regardless of their type.
values = [
complex(5.0, 12.0),
complex(5.0e100, 12.0e100),
complex(-4.0, INF),
complex(INF, 0.0),
]
exponents = [-19, -5, -3, -2, -1, 0, 1, 2, 3, 5, 19]
for value in values:
for exponent in exponents:
with self.subTest(value=value, exponent=exponent):
try:
int_pow = value**exponent
except OverflowError:
int_pow = "overflow"
try:
float_pow = value**float(exponent)
except OverflowError:
float_pow = "overflow"
try:
complex_pow = value**complex(exponent)
except OverflowError:
complex_pow = "overflow"
self.assertEqual(str(float_pow), str(int_pow))
self.assertEqual(str(complex_pow), str(int_pow))
def test_boolcontext(self):
for i in range(100):
self.assertTrue(complex(random() + 1e-6, random() + 1e-6))
@@ -509,22 +599,6 @@ class ComplexTest(unittest.TestCase):
def test_neg(self):
self.assertEqual(-(1+6j), -1-6j)
def test_file(self):
a = 3.33+4.43j
b = 5.1+2.3j
fo = None
try:
fo = open(os_helper.TESTFN, "w")
print(a, b, file=fo)
fo.close()
fo = open(os_helper.TESTFN, "r")
self.assertEqual(fo.read(), ("%s %s\n" % (a, b)))
finally:
if (fo is not None) and (not fo.closed):
fo.close()
os_helper.unlink(os_helper.TESTFN)
def test_getnewargs(self):
self.assertEqual((1+2j).__getnewargs__(), (1.0, 2.0))
self.assertEqual((1-2j).__getnewargs__(), (1.0, -2.0))
@@ -715,8 +789,6 @@ class ComplexTest(unittest.TestCase):
self.assertEqual(format(complex(INF, 1), 'F'), 'INF+1.000000j')
self.assertEqual(format(complex(INF, -1), 'F'), 'INF-1.000000j')
def test_main():
support.run_unittest(ComplexTest)
if __name__ == "__main__":
test_main()
unittest.main()

View File

@@ -10,7 +10,6 @@ use crate::{
use num_complex::Complex64;
use num_traits::Zero;
use rustpython_common::{float_ops, hash};
use std::convert::Infallible as Never;
/// Create a complex number from a real part and an optional imaginary part.
///
@@ -272,16 +271,6 @@ impl PyComplex {
self.value.conj()
}
#[pymethod(magic)]
fn float(&self, vm: &VirtualMachine) -> PyResult<Never> {
Err(vm.new_type_error(String::from("Can't convert complex to float")))
}
#[pymethod(magic)]
fn int(&self, vm: &VirtualMachine) -> PyResult<Never> {
Err(vm.new_type_error(String::from("Can't convert complex to int")))
}
#[pymethod(name = "__rmul__")]
#[pymethod(magic)]
fn mul(
@@ -310,24 +299,6 @@ impl PyComplex {
self.op(other, |a, b| inner_div(b, a, vm), vm)
}
#[pymethod(name = "__mod__")]
#[pymethod(name = "__rmod__")]
fn mod_(&self, _other: PyObjectRef, vm: &VirtualMachine) -> PyResult<Never> {
Err(vm.new_type_error("can't mod complex numbers.".to_owned()))
}
#[pymethod(name = "__rfloordiv__")]
#[pymethod(magic)]
fn floordiv(&self, _other: PyObjectRef, vm: &VirtualMachine) -> PyResult<Never> {
Err(vm.new_type_error("can't take floor of complex number.".to_owned()))
}
#[pymethod(name = "__rdivmod__")]
#[pymethod(magic)]
fn divmod(&self, _other: PyObjectRef, vm: &VirtualMachine) -> PyResult<Never> {
Err(vm.new_type_error("can't take floor or mod of complex number.".to_owned()))
}
#[pymethod(magic)]
fn pos(&self) -> Complex64 {
self.value