mirror of https://github.com/exaloop/codon.git
Add more cmath tests
parent
132593a36e
commit
587ce851c4
|
@ -245,15 +245,15 @@ def _rect_special():
|
|||
C(INF,-0.), C(INF,0.), C(U,U), C(INF,N), C(INF,N), C(N,N), C(N,N), C(N,0.), C(N,0.), C(N,N), C(N,N), C(N,N))
|
||||
return v
|
||||
|
||||
def _is_special(z: complex):
|
||||
def _is_special(z):
|
||||
return (not math.isfinite(z.real)) or (not math.isfinite(z.imag))
|
||||
|
||||
def _special_get(z: complex, table):
|
||||
def _special_get(z, table):
|
||||
t1 = _special_type(z.real)
|
||||
t2 = _special_type(z.imag)
|
||||
return table[7*t1 + t2]
|
||||
|
||||
def _sqrt_impl(z: complex):
|
||||
def _sqrt_impl(z):
|
||||
if _is_special(z):
|
||||
return _special_get(z, _sqrt_special())
|
||||
|
||||
|
@ -285,7 +285,7 @@ def _sqrt_impl(z: complex):
|
|||
# errno = 0
|
||||
return complex(r_real, r_imag)
|
||||
|
||||
def _acos_impl(z: complex):
|
||||
def _acos_impl(z):
|
||||
if _is_special(z):
|
||||
return _special_get(z, _acos_special())
|
||||
|
||||
|
@ -307,7 +307,7 @@ def _acos_impl(z: complex):
|
|||
r_imag = math.asinh(s2.real*s1.imag - s2.imag*s1.real)
|
||||
return complex(r_real, r_imag)
|
||||
|
||||
def _acosh_impl(z: complex):
|
||||
def _acosh_impl(z):
|
||||
if _is_special(z):
|
||||
return _special_get(z, _acosh_special())
|
||||
|
||||
|
@ -324,7 +324,7 @@ def _acosh_impl(z: complex):
|
|||
r_imag = 2.*math.atan2(s1.imag, s2.real)
|
||||
return complex(r_real, r_imag)
|
||||
|
||||
def _asinh_impl(z: complex):
|
||||
def _asinh_impl(z):
|
||||
if _is_special(z):
|
||||
return _special_get(z, _asinh_special())
|
||||
|
||||
|
@ -343,13 +343,13 @@ def _asinh_impl(z: complex):
|
|||
r_imag = math.atan2(z.imag, s1.real*s2.real - s1.imag*s2.imag)
|
||||
return complex(r_real, r_imag)
|
||||
|
||||
def _asin_impl(z: complex):
|
||||
def _asin_impl(z):
|
||||
s = _asinh_impl(complex(-z.imag, z.real))
|
||||
r_real = s.imag
|
||||
r_imag = -s.real
|
||||
return complex(r_real, r_imag)
|
||||
|
||||
def _atanh_impl(z: complex):
|
||||
def _atanh_impl(z):
|
||||
if _is_special(z):
|
||||
return _special_get(z, _atanh_special())
|
||||
|
||||
|
@ -388,13 +388,13 @@ def _atanh_impl(z: complex):
|
|||
# errno = 0
|
||||
return complex(r_real, r_imag)
|
||||
|
||||
def _atan_impl(z: complex):
|
||||
def _atan_impl(z):
|
||||
s = _atanh_impl(complex(-z.imag, z.real))
|
||||
r_real = s.imag
|
||||
r_imag = -s.real
|
||||
return complex(r_real, r_imag)
|
||||
|
||||
def _cosh_impl(z: complex):
|
||||
def _cosh_impl(z):
|
||||
r_real = 0.
|
||||
r_imag = 0.
|
||||
# special treatment for cosh(+/-inf + iy) if y is not a NaN
|
||||
|
@ -438,11 +438,11 @@ def _cosh_impl(z: complex):
|
|||
'''
|
||||
return complex(r_real, r_imag)
|
||||
|
||||
def _cos_impl(z: complex):
|
||||
def _cos_impl(z):
|
||||
r = _cosh_impl(complex(-z.imag, z.real))
|
||||
return r
|
||||
|
||||
def _exp_impl(z: complex):
|
||||
def _exp_impl(z):
|
||||
r_real = 0.
|
||||
r_imag = 0.
|
||||
if (not math.isfinite(z.real)) or (not math.isfinite(z.imag)):
|
||||
|
@ -486,7 +486,7 @@ def _exp_impl(z: complex):
|
|||
'''
|
||||
return complex(r_real, r_imag)
|
||||
|
||||
def _c_log(z: complex):
|
||||
def _c_log(z):
|
||||
if _is_special(z):
|
||||
return _special_get(z, _log_special())
|
||||
|
||||
|
@ -519,11 +519,11 @@ def _c_log(z: complex):
|
|||
# errno = 0
|
||||
return complex(r_real, r_imag)
|
||||
|
||||
def _log10_impl(z: complex):
|
||||
def _log10_impl(z):
|
||||
s = _c_log(z)
|
||||
return complex(s.real / _M_LN10, s.imag / _M_LN10)
|
||||
|
||||
def _sinh_impl(z: complex):
|
||||
def _sinh_impl(z):
|
||||
r_real = 0.
|
||||
r_imag = 0.
|
||||
if (not math.isfinite(z.real)) or (not math.isfinite(z.imag)):
|
||||
|
@ -564,12 +564,12 @@ def _sinh_impl(z: complex):
|
|||
'''
|
||||
return complex(r_real, r_imag)
|
||||
|
||||
def _sin_impl(z: complex):
|
||||
def _sin_impl(z):
|
||||
s = _sinh_impl(complex(-z.imag, z.real))
|
||||
r = complex(s.imag, -s.real)
|
||||
return r
|
||||
|
||||
def _tanh_impl(z: complex):
|
||||
def _tanh_impl(z):
|
||||
r_real = 0.
|
||||
r_imag = 0.
|
||||
# special treatment for tanh(+/-inf + iy) if y is finite and
|
||||
|
@ -611,17 +611,11 @@ def _tanh_impl(z: complex):
|
|||
# errno = 0
|
||||
return complex(r_real, r_imag)
|
||||
|
||||
def _tan_impl(z: complex):
|
||||
def _tan_impl(z):
|
||||
s = _tanh_impl(complex(-z.imag, z.real))
|
||||
r = complex(s.imag, -s.real)
|
||||
return r
|
||||
|
||||
def _log_impl(x: complex, y: complex):
|
||||
x = _c_log(x)
|
||||
y = _c_log(y)
|
||||
x /= y
|
||||
return x
|
||||
|
||||
def phase(x):
|
||||
z = complex(x)
|
||||
return z._phase()
|
||||
|
@ -672,10 +666,14 @@ def exp(x):
|
|||
z = complex(x)
|
||||
return _exp_impl(z)
|
||||
|
||||
def log(x):
|
||||
# TODO: base
|
||||
def log(x, base = e):
|
||||
z = complex(x)
|
||||
return _c_log(z)
|
||||
y = complex(base)
|
||||
r = _c_log(z)
|
||||
if y == complex(e, 0.0):
|
||||
return r
|
||||
else:
|
||||
return r/_c_log(y)
|
||||
|
||||
def log10(x):
|
||||
z = complex(x)
|
||||
|
@ -683,7 +681,7 @@ def log10(x):
|
|||
|
||||
def sqrt(x):
|
||||
z = complex(x)
|
||||
return _sqrt_impl(x)
|
||||
return _sqrt_impl(z)
|
||||
|
||||
def asin(x):
|
||||
z = complex(x)
|
||||
|
|
|
@ -331,5 +331,9 @@ class float:
|
|||
return result
|
||||
def __match__(self, i: float):
|
||||
return self == i
|
||||
def __suffix_j__(s: str):
|
||||
return complex(0.0, float(s))
|
||||
@property
|
||||
def real(self):
|
||||
return self
|
||||
@property
|
||||
def imag(self):
|
||||
return 0.0
|
||||
|
|
|
@ -329,5 +329,9 @@ class int:
|
|||
ret i64 %tmp
|
||||
def __match__(self, i: int):
|
||||
return self == i
|
||||
def __suffix_j__(s: str):
|
||||
return complex(0, int(s))
|
||||
@property
|
||||
def real(self):
|
||||
return self
|
||||
@property
|
||||
def imag(self):
|
||||
return 0
|
||||
|
|
|
@ -135,7 +135,7 @@ def ldexp(x: float, i: int) -> float:
|
|||
"""
|
||||
return _C.ldexp(x, i)
|
||||
|
||||
def log(x: float) -> float:
|
||||
def log(x: float, base: float = e) -> float:
|
||||
"""
|
||||
log(float) -> float
|
||||
|
||||
|
@ -148,7 +148,10 @@ def log(x: float) -> float:
|
|||
%y = call double @llvm.log.f64(double %x)
|
||||
ret double %y
|
||||
|
||||
return f(x)
|
||||
if base == e:
|
||||
return f(x)
|
||||
else:
|
||||
return f(x)/f(base)
|
||||
|
||||
def log2(x: float) -> float:
|
||||
"""
|
||||
|
|
|
@ -1,32 +1,491 @@
|
|||
import math
|
||||
import cmath
|
||||
|
||||
def check(exp, got, flags):
|
||||
def close(a, b):
|
||||
if math.isnan(a):
|
||||
return math.isnan(b)
|
||||
elif math.isnan(b):
|
||||
return math.isnan(a)
|
||||
return math.isclose(a, b, rel_tol = 1e-10, abs_tol=1e-15)
|
||||
INF = float('inf')
|
||||
NAN = float('nan')
|
||||
j = complex(0, 1)
|
||||
|
||||
x1 = exp.real
|
||||
y1 = exp.imag
|
||||
complex_zeros = [complex(x, y) for x in [0.0, -0.0] for y in [0.0, -0.0]]
|
||||
complex_infinities = [complex(x, y) for x, y in [
|
||||
(INF, 0.0), # 1st quadrant
|
||||
(INF, 2.3),
|
||||
(INF, INF),
|
||||
(2.3, INF),
|
||||
(0.0, INF),
|
||||
(-0.0, INF), # 2nd quadrant
|
||||
(-2.3, INF),
|
||||
(-INF, INF),
|
||||
(-INF, 2.3),
|
||||
(-INF, 0.0),
|
||||
(-INF, -0.0), # 3rd quadrant
|
||||
(-INF, -2.3),
|
||||
(-INF, -INF),
|
||||
(-2.3, -INF),
|
||||
(-0.0, -INF),
|
||||
(0.0, -INF), # 4th quadrant
|
||||
(2.3, -INF),
|
||||
(INF, -INF),
|
||||
(INF, -2.3),
|
||||
(INF, -0.0)
|
||||
]]
|
||||
complex_nans = [complex(x, y) for x, y in [
|
||||
(NAN, -INF),
|
||||
(NAN, -2.3),
|
||||
(NAN, -0.0),
|
||||
(NAN, 0.0),
|
||||
(NAN, 2.3),
|
||||
(NAN, INF),
|
||||
(-INF, NAN),
|
||||
(-2.3, NAN),
|
||||
(-0.0, NAN),
|
||||
(0.0, NAN),
|
||||
(2.3, NAN),
|
||||
(INF, NAN)
|
||||
]]
|
||||
|
||||
x2 = got.real
|
||||
y2 = got.imag
|
||||
def float_identical(x, y):
|
||||
if math.isnan(x) or math.isnan(y):
|
||||
if math.isnan(x) and math.isnan(y):
|
||||
return True
|
||||
elif x == y:
|
||||
if x != 0.0:
|
||||
return True
|
||||
# both zero; check that signs match
|
||||
elif math.copysign(1.0, x) == math.copysign(1.0, y):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
return False
|
||||
|
||||
if 'ignore-real-sign' in flags:
|
||||
x1 = math.fabs(x1)
|
||||
x2 = math.fabs(x2)
|
||||
def complex_identical(x, y):
|
||||
return float_identical(x.real, y.real) and float_identical(x.imag, y.imag)
|
||||
|
||||
if 'ignore-imag-sign' in flags:
|
||||
y1 = math.fabs(y1)
|
||||
y2 = math.fabs(y2)
|
||||
@llvm
|
||||
@pure
|
||||
def small() -> float:
|
||||
ret double 4.940660e-323
|
||||
|
||||
return close(x1, x2) and close(y1, y2)
|
||||
def almost_equal(a, b, rel_err = 2e-15, abs_err = small()):
|
||||
if math.isnan(a):
|
||||
if math.isnan(b):
|
||||
return True
|
||||
return False
|
||||
|
||||
if math.isinf(a):
|
||||
if a == b:
|
||||
return True
|
||||
return False
|
||||
|
||||
if not a and not b:
|
||||
if math.copysign(1., a) != math.copysign(1., b):
|
||||
return False
|
||||
|
||||
absolute_error = abs(b-a)
|
||||
if absolute_error <= max(abs_err, rel_err * abs(a)):
|
||||
return True
|
||||
return False
|
||||
|
||||
@test
|
||||
def test_constants():
|
||||
e_expected = 2.71828182845904523536
|
||||
pi_expected = 3.14159265358979323846
|
||||
assert math.isclose(cmath.pi, pi_expected)
|
||||
assert math.isclose(cmath.e, e_expected)
|
||||
test_constants()
|
||||
|
||||
@test
|
||||
def test_infinity_and_nan_constants():
|
||||
assert cmath.inf.real == math.inf
|
||||
assert cmath.inf.imag == 0.0
|
||||
assert cmath.infj.real == 0.0
|
||||
assert cmath.infj.imag == math.inf
|
||||
|
||||
assert math.isnan(cmath.nan.real)
|
||||
assert cmath.nan.imag == 0.0
|
||||
assert cmath.nanj.real == 0.0
|
||||
assert math.isnan(cmath.nanj.imag)
|
||||
|
||||
assert str(cmath.inf) == "inf"
|
||||
assert str(cmath.infj) == "infj"
|
||||
assert str(cmath.nan) == "nan"
|
||||
assert str(cmath.nanj) == "nanj"
|
||||
test_infinity_and_nan_constants()
|
||||
|
||||
@test
|
||||
def test_user_object():
|
||||
class MyComplexOS[T]:
|
||||
value: T
|
||||
def __init__(self, value: T):
|
||||
self.value = value
|
||||
def __complex__(self):
|
||||
return self.value
|
||||
|
||||
x = MyComplexOS(4.2)
|
||||
assert cmath.acos(x) == cmath.acos(x.value)
|
||||
assert cmath.acosh(x) == cmath.acosh(x.value)
|
||||
assert cmath.asin(x) == cmath.asin(x.value)
|
||||
assert cmath.asinh(x) == cmath.asinh(x.value)
|
||||
assert cmath.atan(x) == cmath.atan(x.value)
|
||||
assert cmath.atanh(x) == cmath.atanh(x.value)
|
||||
assert cmath.cos(x) == cmath.cos(x.value)
|
||||
assert cmath.cosh(x) == cmath.cosh(x.value)
|
||||
assert cmath.exp(x) == cmath.exp(x.value)
|
||||
assert cmath.log(x) == cmath.log(x.value)
|
||||
assert cmath.log10(x) == cmath.log10(x.value)
|
||||
assert cmath.sin(x) == cmath.sin(x.value)
|
||||
assert cmath.sinh(x) == cmath.sinh(x.value)
|
||||
assert cmath.sqrt(x) == cmath.sqrt(x.value)
|
||||
assert cmath.tan(x) == cmath.tan(x.value)
|
||||
assert cmath.tanh(x) == cmath.tanh(x.value)
|
||||
test_user_object()
|
||||
|
||||
@test
|
||||
def test_input_type():
|
||||
x = 42
|
||||
y = float(x)
|
||||
assert cmath.acos(x) == cmath.acos(y)
|
||||
assert cmath.acosh(x) == cmath.acosh(y)
|
||||
assert cmath.asin(x) == cmath.asin(y)
|
||||
assert cmath.asinh(x) == cmath.asinh(y)
|
||||
assert cmath.atan(x) == cmath.atan(y)
|
||||
assert cmath.atanh(x) == cmath.atanh(y)
|
||||
assert cmath.cos(x) == cmath.cos(y)
|
||||
assert cmath.cosh(x) == cmath.cosh(y)
|
||||
assert cmath.exp(x) == cmath.exp(y)
|
||||
assert cmath.log(x) == cmath.log(y)
|
||||
assert cmath.log10(x) == cmath.log10(y)
|
||||
assert cmath.sin(x) == cmath.sin(y)
|
||||
assert cmath.sinh(x) == cmath.sinh(y)
|
||||
assert cmath.sqrt(x) == cmath.sqrt(y)
|
||||
assert cmath.tan(x) == cmath.tan(y)
|
||||
assert cmath.tanh(x) == cmath.tanh(y)
|
||||
test_input_type()
|
||||
|
||||
|
||||
@test
|
||||
def test_cmath_matches_math():
|
||||
test_values = [0.01, 0.1, 0.2, 0.5, 0.9, 0.99]
|
||||
unit_interval = test_values + [-x for x in test_values] + \
|
||||
[0., 1., -1.]
|
||||
positive = test_values + [1.] + [1./x for x in test_values]
|
||||
nonnegative = [0.] + positive
|
||||
real_line = [0.] + positive + [-x for x in positive]
|
||||
|
||||
test_functions = {
|
||||
'acos' : unit_interval,
|
||||
'asin' : unit_interval,
|
||||
'atan' : real_line,
|
||||
'cos' : real_line,
|
||||
'cosh' : real_line,
|
||||
'exp' : real_line,
|
||||
'log' : positive,
|
||||
'log10' : positive,
|
||||
'sin' : real_line,
|
||||
'sinh' : real_line,
|
||||
'sqrt' : nonnegative,
|
||||
'tan' : real_line,
|
||||
'tanh' : real_line}
|
||||
|
||||
for v in test_functions['acos']:
|
||||
z = cmath.acos(v)
|
||||
assert almost_equal(z.real, math.acos(v))
|
||||
assert z.imag == 0.
|
||||
|
||||
for v in test_functions['asin']:
|
||||
z = cmath.asin(v)
|
||||
assert almost_equal(z.real, math.asin(v))
|
||||
assert z.imag == 0.
|
||||
|
||||
for v in test_functions['atan']:
|
||||
z = cmath.atan(v)
|
||||
assert almost_equal(z.real, math.atan(v))
|
||||
assert z.imag == 0.
|
||||
|
||||
for v in test_functions['cos']:
|
||||
z = cmath.cos(v)
|
||||
assert almost_equal(z.real, math.cos(v))
|
||||
assert z.imag == 0.
|
||||
|
||||
for v in test_functions['cosh']:
|
||||
z = cmath.cosh(v)
|
||||
assert almost_equal(z.real, math.cosh(v))
|
||||
assert z.imag == 0.
|
||||
|
||||
for v in test_functions['exp']:
|
||||
z = cmath.exp(v)
|
||||
assert almost_equal(z.real, math.exp(v))
|
||||
assert z.imag == 0.
|
||||
|
||||
for v in test_functions['log']:
|
||||
z = cmath.log(v)
|
||||
assert almost_equal(z.real, math.log(v))
|
||||
assert z.imag == 0.
|
||||
|
||||
for v in test_functions['log10']:
|
||||
z = cmath.log10(v)
|
||||
assert almost_equal(z.real, math.log10(v))
|
||||
assert z.imag == 0.
|
||||
|
||||
for v in test_functions['sin']:
|
||||
z = cmath.sin(v)
|
||||
assert almost_equal(z.real, math.sin(v))
|
||||
assert z.imag == 0.
|
||||
|
||||
for v in test_functions['sinh']:
|
||||
z = cmath.sinh(v)
|
||||
assert almost_equal(z.real, math.sinh(v))
|
||||
assert z.imag == 0.
|
||||
|
||||
for v in test_functions['sqrt']:
|
||||
z = cmath.sqrt(v)
|
||||
assert almost_equal(z.real, math.sqrt(v))
|
||||
assert z.imag == 0.
|
||||
|
||||
for v in test_functions['tan']:
|
||||
z = cmath.tan(v)
|
||||
assert almost_equal(z.real, math.tan(v))
|
||||
assert z.imag == 0.
|
||||
|
||||
for v in test_functions['tanh']:
|
||||
z = cmath.tanh(v)
|
||||
assert almost_equal(z.real, math.tanh(v))
|
||||
assert z.imag == 0.
|
||||
|
||||
for base in [0.5, 2., 10.]:
|
||||
for v in positive:
|
||||
z = cmath.log(v, base)
|
||||
s = math.log(v, base)
|
||||
# added 'or z.real == s' since Codon version gives -0 vs. +0 in one test
|
||||
assert almost_equal(z.real, math.log(v, base)) or z.real == s
|
||||
assert z.imag == 0.
|
||||
test_cmath_matches_math()
|
||||
|
||||
@test
|
||||
def test_polar():
|
||||
def check(arg, expected):
|
||||
got = cmath.polar(arg)
|
||||
return all(almost_equal(e, g) for e,g in zip(expected, got))
|
||||
pi = cmath.pi
|
||||
assert check(0, (0., 0.))
|
||||
assert check(1, (1., 0.))
|
||||
assert check(-1, (1., pi))
|
||||
assert check(1*j, (1., pi / 2))
|
||||
assert check(-3*j, (3., -pi / 2))
|
||||
inf = float('inf')
|
||||
assert check(complex(inf, 0), (inf, 0.))
|
||||
assert check(complex(-inf, 0), (inf, pi))
|
||||
assert check(complex(3, inf), (inf, pi / 2))
|
||||
assert check(complex(5, -inf), (inf, -pi / 2))
|
||||
assert check(complex(inf, inf), (inf, pi / 4))
|
||||
assert check(complex(inf, -inf), (inf, -pi / 4))
|
||||
assert check(complex(-inf, inf), (inf, 3 * pi / 4))
|
||||
assert check(complex(-inf, -inf), (inf, -3 * pi / 4))
|
||||
nan = float('nan')
|
||||
assert check(complex(nan, 0), (nan, nan))
|
||||
assert check(complex(0, nan), (nan, nan))
|
||||
assert check(complex(nan, nan), (nan, nan))
|
||||
assert check(complex(inf, nan), (inf, nan))
|
||||
assert check(complex(-inf, nan), (inf, nan))
|
||||
assert check(complex(nan, inf), (inf, nan))
|
||||
assert check(complex(nan, -inf), (inf, nan))
|
||||
test_polar()
|
||||
|
||||
@test
|
||||
def test_phase():
|
||||
from cmath import phase, pi
|
||||
assert almost_equal(phase(0), 0.)
|
||||
assert almost_equal(phase(1.), 0.)
|
||||
assert almost_equal(phase(-1.), pi)
|
||||
assert almost_equal(phase(-1.+1E-300*j), pi)
|
||||
assert almost_equal(phase(-1.-1E-300*j), -pi)
|
||||
assert almost_equal(phase(1*j), pi/2)
|
||||
assert almost_equal(phase(-1*j), -pi/2)
|
||||
|
||||
# zeros
|
||||
assert phase(complex(0.0, 0.0)) == 0.0
|
||||
assert phase(complex(0.0, -0.0)) == -0.0
|
||||
assert phase(complex(-0.0, 0.0)) == pi
|
||||
assert phase(complex(-0.0, -0.0)) == -pi
|
||||
|
||||
# infinities
|
||||
assert almost_equal(phase(complex(-INF, -0.0)), -pi)
|
||||
assert almost_equal(phase(complex(-INF, -2.3)), -pi)
|
||||
assert almost_equal(phase(complex(-INF, -INF)), -0.75*pi)
|
||||
assert almost_equal(phase(complex(-2.3, -INF)), -pi/2)
|
||||
assert almost_equal(phase(complex(-0.0, -INF)), -pi/2)
|
||||
assert almost_equal(phase(complex(0.0, -INF)), -pi/2)
|
||||
assert almost_equal(phase(complex(2.3, -INF)), -pi/2)
|
||||
assert almost_equal(phase(complex(INF, -INF)), -pi/4)
|
||||
assert phase(complex(INF, -2.3)) == -0.0
|
||||
assert phase(complex(INF, -0.0)) == -0.0
|
||||
assert phase(complex(INF, 0.0)) == 0.0
|
||||
assert phase(complex(INF, 2.3)) == 0.0
|
||||
assert almost_equal(phase(complex(INF, INF)), pi/4)
|
||||
assert almost_equal(phase(complex(2.3, INF)), pi/2)
|
||||
assert almost_equal(phase(complex(0.0, INF)), pi/2)
|
||||
assert almost_equal(phase(complex(-0.0, INF)), pi/2)
|
||||
assert almost_equal(phase(complex(-2.3, INF)), pi/2)
|
||||
assert almost_equal(phase(complex(-INF, INF)), 0.75*pi)
|
||||
assert almost_equal(phase(complex(-INF, 2.3)), pi)
|
||||
assert almost_equal(phase(complex(-INF, 0.0)), pi)
|
||||
|
||||
# real or imaginary part NaN
|
||||
for z in complex_nans:
|
||||
assert math.isnan(phase(z))
|
||||
test_phase()
|
||||
|
||||
@test
|
||||
def test_abs():
|
||||
# zeros
|
||||
for z in complex_zeros:
|
||||
assert abs(z) == 0.0
|
||||
|
||||
# infinities
|
||||
for z in complex_infinities:
|
||||
assert abs(z) == INF
|
||||
|
||||
# real or imaginary part NaN
|
||||
assert abs(complex(NAN, -INF)) == INF
|
||||
assert math.isnan(abs(complex(NAN, -2.3)))
|
||||
assert math.isnan(abs(complex(NAN, -0.0)))
|
||||
assert math.isnan(abs(complex(NAN, 0.0)))
|
||||
assert math.isnan(abs(complex(NAN, 2.3)))
|
||||
assert abs(complex(NAN, INF)) == INF
|
||||
assert abs(complex(-INF, NAN)) == INF
|
||||
assert math.isnan(abs(complex(-2.3, NAN)))
|
||||
assert math.isnan(abs(complex(-0.0, NAN)))
|
||||
assert math.isnan(abs(complex(0.0, NAN)))
|
||||
assert math.isnan(abs(complex(2.3, NAN)))
|
||||
assert abs(complex(INF, NAN)) == INF
|
||||
assert math.isnan(abs(complex(NAN, NAN)))
|
||||
test_abs()
|
||||
|
||||
def c_equal(a, b):
|
||||
eps = 1E-7
|
||||
if abs(a.real - b[0]) > eps or abs(a.imag - b[1]) > eps:
|
||||
return False
|
||||
return True
|
||||
|
||||
@test
|
||||
def test_rect():
|
||||
from cmath import rect, pi
|
||||
assert c_equal(rect(0, 0), (0, 0))
|
||||
assert c_equal(rect(1, 0), (1., 0))
|
||||
assert c_equal(rect(1, -pi), (-1., 0))
|
||||
assert c_equal(rect(1, pi/2), (0, 1.))
|
||||
assert c_equal(rect(1, -pi/2), (0, -1.))
|
||||
test_rect()
|
||||
|
||||
@test
|
||||
def test_isfinite():
|
||||
real_vals = [float('-inf'), -2.3, -0.0,
|
||||
0.0, 2.3, float('inf'), float('nan')]
|
||||
for x in real_vals:
|
||||
for y in real_vals:
|
||||
z = complex(x, y)
|
||||
assert cmath.isfinite(z) == (math.isfinite(x) and math.isfinite(y))
|
||||
test_isfinite()
|
||||
|
||||
@test
|
||||
def test_isnan():
|
||||
assert not cmath.isnan(1)
|
||||
assert not cmath.isnan(1*j)
|
||||
assert not cmath.isnan(INF)
|
||||
assert cmath.isnan(NAN)
|
||||
assert cmath.isnan(complex(NAN, 0))
|
||||
assert cmath.isnan(complex(0, NAN))
|
||||
assert cmath.isnan(complex(NAN, NAN))
|
||||
assert cmath.isnan(complex(NAN, INF))
|
||||
assert cmath.isnan(complex(INF, NAN))
|
||||
test_isnan()
|
||||
|
||||
@test
|
||||
def test_isinf():
|
||||
assert not cmath.isinf(1)
|
||||
assert not cmath.isinf(1*j)
|
||||
assert not cmath.isinf(NAN)
|
||||
assert cmath.isinf(INF)
|
||||
assert cmath.isinf(complex(INF, 0))
|
||||
assert cmath.isinf(complex(0, INF))
|
||||
assert cmath.isinf(complex(INF, INF))
|
||||
assert cmath.isinf(complex(NAN, INF))
|
||||
assert cmath.isinf(complex(INF, NAN))
|
||||
test_isinf()
|
||||
|
||||
@test
|
||||
def test_tanh_sign():
|
||||
for z in complex_zeros:
|
||||
assert complex_identical(cmath.tanh(z), z)
|
||||
test_tanh_sign()
|
||||
|
||||
@test
|
||||
def test_atan_sign():
|
||||
for z in complex_zeros:
|
||||
assert complex_identical(cmath.atan(z), z)
|
||||
test_atan_sign()
|
||||
|
||||
@test
|
||||
def test_atanh_sign():
|
||||
for z in complex_zeros:
|
||||
assert complex_identical(cmath.atanh(z), z)
|
||||
test_atanh_sign()
|
||||
|
||||
@test
|
||||
def test_is_close():
|
||||
# test complex values that are close to within 12 decimal places
|
||||
complex_examples = [(1.0+1.0*j, 1.000000000001+1.0*j),
|
||||
(1.0+1.0*j, 1.0+1.000000000001*j),
|
||||
(-1.0+1.0*j, -1.000000000001+1.0*j),
|
||||
(1.0-1.0*j, 1.0-0.999999999999*j),
|
||||
]
|
||||
|
||||
for a,b in complex_examples:
|
||||
assert cmath.isclose(a, b, rel_tol=1e-12)
|
||||
assert not cmath.isclose(a, b, rel_tol=1e-13)
|
||||
|
||||
# test values near zero that are near to within three decimal places
|
||||
near_zero_examples = [(0.001*j, 0),
|
||||
(0.001 + 0*j, 0),
|
||||
(0.001+0.001*j, 0),
|
||||
(-0.001+0.001*j, 0),
|
||||
(0.001-0.001*j, 0),
|
||||
(-0.001-0.001*j, 0),
|
||||
]
|
||||
|
||||
for a,b in near_zero_examples:
|
||||
assert cmath.isclose(a, b, abs_tol=1.5e-03)
|
||||
assert not cmath.isclose(a, b, abs_tol=0.5e-03)
|
||||
|
||||
assert cmath.isclose(0.001-0.001*j, 0.001+0.001*j, abs_tol=2e-03)
|
||||
assert not cmath.isclose(0.001-0.001*j, 0.001+0.001*j, abs_tol=1e-03)
|
||||
test_is_close()
|
||||
|
||||
@test
|
||||
def test_cmath_testcases():
|
||||
def check(exp, got, flags):
|
||||
def close(a, b):
|
||||
if math.isnan(a):
|
||||
return math.isnan(b)
|
||||
elif math.isnan(b):
|
||||
return math.isnan(a)
|
||||
return math.isclose(a, b, rel_tol = 1e-10, abs_tol=1e-15)
|
||||
|
||||
x1 = exp.real
|
||||
y1 = exp.imag
|
||||
|
||||
x2 = got.real
|
||||
y2 = got.imag
|
||||
|
||||
if 'ignore-real-sign' in flags:
|
||||
x1 = math.fabs(x1)
|
||||
x2 = math.fabs(x2)
|
||||
|
||||
if 'ignore-imag-sign' in flags:
|
||||
y1 = math.fabs(y1)
|
||||
y2 = math.fabs(y2)
|
||||
|
||||
return close(x1, x2) and close(y1, y2)
|
||||
|
||||
def run_test(test):
|
||||
v = test.split()
|
||||
if not v:
|
||||
|
@ -91,5 +550,4 @@ def test_cmath_testcases():
|
|||
|
||||
for test in tests:
|
||||
assert run_test(test)
|
||||
|
||||
test_cmath_testcases()
|
||||
|
|
Loading…
Reference in New Issue