codon/test/stdlib/cmath_test.codon

1111 lines
27 KiB
Python
Raw Normal View History

2021-10-04 12:05:24 +08:00
import math
import cmath
2022-01-24 18:32:33 +08:00
INF = float("inf")
NAN = float("nan")
2021-10-04 12:05:24 +08:00
2021-10-05 01:07:11 +08:00
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
2022-01-24 18:32:33 +08:00
2021-10-05 01:07:11 +08:00
def complex_identical(x, y):
return float_identical(x.real, y.real) and float_identical(x.imag, y.imag)
2022-01-24 18:32:33 +08:00
2021-10-05 01:07:11 +08:00
###########
# complex #
###########
ZERO_DIVISION = (
2022-01-24 18:32:33 +08:00
(1 + 1j, 0 + 0j),
(1 + 1j, 0.0 + 0j),
(1 + 1j, 0 + 0j),
(1.0 + 0j, 0 + 0j),
(1 + 0j, 0 + 0j),
2021-10-05 01:07:11 +08:00
)
2022-01-24 18:32:33 +08:00
2021-10-05 01:07:11 +08:00
def close_abs(x, y, eps=1e-9):
"""Return true iff floats x and y "are close"."""
# put the one with larger magnitude second
if abs(x) > abs(y):
x, y = y, x
if y == 0:
return abs(x) < eps
if x == 0:
return abs(y) < eps
# check that relative difference < eps
2022-01-24 18:32:33 +08:00
return abs((x - y) / y) < eps
2021-10-05 01:07:11 +08:00
def close_complex(x, y, eps=1e-9):
a = complex(x)
b = complex(y)
return close_abs(a.real, b.real, eps) and close_abs(a.imag, b.imag, eps)
2022-01-24 18:32:33 +08:00
2021-10-05 01:07:11 +08:00
def check_div(x, y):
"""Compute complex z=x*y, and check that z/x==y and z/y==x."""
z = x * y
if x != 0:
q = z / x
if not close_complex(q, y):
return False
q = z.__truediv__(x)
if not close_complex(q, y):
return False
if y != 0:
q = z / y
if not close_complex(q, x):
return False
q = z.__truediv__(y)
if not close_complex(q, x):
return False
return True
2022-01-24 18:32:33 +08:00
2021-10-05 01:07:11 +08:00
@test
def test_truediv():
from random import random
2022-01-24 18:32:33 +08:00
2021-10-05 01:07:11 +08:00
simple_real = [float(i) for i in range(-5, 6)]
simple_complex = [complex(x, y) for x in simple_real for y in simple_real]
for x in simple_complex:
for y in simple_complex:
assert check_div(x, y)
# A naive complex division algorithm (such as in 2.0) is very prone to
# nonsense errors for these (overflows and underflows).
2022-01-24 18:32:33 +08:00
assert check_div(complex(1e200, 1e200), 1 + 0j)
assert check_div(complex(1e-200, 1e-200), 1 + 0j)
2021-10-05 01:07:11 +08:00
# Just for fun.
for i in range(100):
check_div(complex(random(), random()), complex(random(), random()))
2022-01-24 18:32:33 +08:00
assert close_complex(complex.__truediv__(2 + 0j, 1 + 1j), 1 - 1j)
2021-10-05 01:07:11 +08:00
2022-01-24 18:32:33 +08:00
for denom_real, denom_imag in [(0.0, NAN), (NAN, 0.0), (NAN, NAN)]:
2021-10-05 01:07:11 +08:00
z = complex(0, 0) / complex(denom_real, denom_imag)
assert math.isnan(z.real)
assert math.isnan(z.imag)
2022-01-24 18:32:33 +08:00
2021-10-05 01:07:11 +08:00
test_truediv()
2022-01-24 18:32:33 +08:00
2021-10-05 01:07:11 +08:00
@test
def test_richcompare():
2022-01-24 18:32:33 +08:00
assert not complex.__eq__(1 + 1j, 1 << 10000)
assert complex.__eq__(1 + 1j, 1 + 1j)
assert not complex.__eq__(1 + 1j, 2 + 2j)
assert not complex.__ne__(1 + 1j, 1 + 1j)
assert complex.__ne__(1 + 1j, 2 + 2j), True
2021-10-05 01:07:11 +08:00
for i in range(1, 100):
f = i / 100.0
2022-01-24 18:32:33 +08:00
assert complex.__eq__(f + 0j, f)
assert not complex.__ne__(f + 0j, f)
2021-10-05 01:07:11 +08:00
assert not complex.__eq__(complex(f, f), f)
assert complex.__ne__(complex(f, f), f)
import operator
2022-01-24 18:32:33 +08:00
assert operator.eq(1 + 1j, 1 + 1j) == True
assert operator.eq(1 + 1j, 2 + 2j) == False
assert operator.ne(1 + 1j, 1 + 1j) == False
assert operator.ne(1 + 1j, 2 + 2j) == True
2021-10-05 01:07:11 +08:00
test_richcompare()
2022-01-24 18:32:33 +08:00
2021-10-05 01:07:11 +08:00
@test
def test_pow():
2022-01-24 18:32:33 +08:00
def pow(a, b):
return a ** b
assert close_complex(pow(1 + 1j, 0 + 0j), 1.0)
assert close_complex(pow(0 + 0j, 2 + 0j), 0.0)
assert close_complex(pow(1j, -1), 1 / (1j))
assert close_complex(pow(1j, 200), 1)
2021-10-05 01:07:11 +08:00
2022-01-24 18:32:33 +08:00
a = 3.33 + 4.43j
assert a ** (0j) == 1
2022-01-24 18:32:33 +08:00
assert a ** (0.0 + 0.0j) == 1
2021-10-05 01:07:11 +08:00
assert (3j) ** (0j) == 1
assert (3j) ** 0 == 1
2021-10-05 01:07:11 +08:00
# The following is used to exercise certain code paths
assert a ** 105 == a ** 105
assert a ** -105 == a ** -105
assert a ** -30 == a ** -30
assert (0.0j) ** 0 == 1
2022-01-24 18:32:33 +08:00
2021-10-05 01:07:11 +08:00
test_pow()
2022-01-24 18:32:33 +08:00
2021-10-05 01:07:11 +08:00
@test
def test_conjugate():
2022-01-24 18:32:33 +08:00
assert close_complex(complex(5.3, 9.8).conjugate(), 5.3 - 9.8j)
2021-10-05 01:07:11 +08:00
test_conjugate()
2022-01-24 18:32:33 +08:00
2021-10-05 01:07:11 +08:00
@test
def test_cabs():
2022-01-24 18:32:33 +08:00
nums = [complex(x / 3.0, y / 7.0) for x in range(-9, 9) for y in range(-9, 9)]
2021-10-05 01:07:11 +08:00
for num in nums:
2022-01-24 18:32:33 +08:00
assert close_complex((num.real ** 2 + num.imag ** 2) ** 0.5, abs(num))
2021-10-05 01:07:11 +08:00
test_cabs()
2022-01-24 18:32:33 +08:00
2021-10-05 01:07:11 +08:00
@test
def test_negative_zero_repr_str():
def test(v, expected):
return str(v) == expected
2022-01-24 18:32:33 +08:00
assert test(complex(0.0, 1.0), "1j")
assert test(complex(-0.0, 1.0), "(-0+1j)")
assert test(complex(0.0, -1.0), "-1j")
assert test(complex(-0.0, -1.0), "(-0-1j)")
assert test(complex(0.0, 0.0), "0j")
assert test(complex(0.0, -0.0), "-0j")
assert test(complex(-0.0, 0.0), "(-0+0j)")
assert test(complex(-0.0, -0.0), "(-0-0j)")
2021-10-05 01:07:11 +08:00
test_negative_zero_repr_str()
#########
# cmath #
#########
2021-10-04 23:08:28 +08:00
complex_zeros = [complex(x, y) for x in [0.0, -0.0] for y in [0.0, -0.0]]
2022-01-24 18:32:33 +08:00
complex_infinities = [
complex(x, y)
for x, y in [
2021-10-04 23:08:28 +08:00
(INF, 0.0), # 1st quadrant
(INF, 2.3),
(INF, INF),
(2.3, INF),
(0.0, INF),
2022-01-24 18:32:33 +08:00
(-0.0, INF), # 2nd quadrant
2021-10-04 23:08:28 +08:00
(-2.3, INF),
(-INF, INF),
(-INF, 2.3),
(-INF, 0.0),
2022-01-24 18:32:33 +08:00
(-INF, -0.0), # 3rd quadrant
2021-10-04 23:08:28 +08:00
(-INF, -2.3),
(-INF, -INF),
(-2.3, -INF),
(-0.0, -INF),
2022-01-24 18:32:33 +08:00
(0.0, -INF), # 4th quadrant
2021-10-04 23:08:28 +08:00
(2.3, -INF),
(INF, -INF),
(INF, -2.3),
2022-01-24 18:32:33 +08:00
(INF, -0.0),
]
]
complex_nans = [
complex(x, y)
for x, y in [
2021-10-04 23:08:28 +08:00
(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),
2022-01-24 18:32:33 +08:00
(INF, NAN),
]
]
2021-10-04 12:05:24 +08:00
2021-10-04 23:08:28 +08:00
@llvm
@pure
def small() -> float:
ret double 4.940660e-323
2022-01-24 18:32:33 +08:00
def almost_equal(a, b, rel_err=2e-15, abs_err=small()):
2021-10-04 23:08:28 +08:00
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:
2022-01-24 18:32:33 +08:00
if math.copysign(1.0, a) != math.copysign(1.0, b):
2021-10-04 23:08:28 +08:00
return False
2022-01-24 18:32:33 +08:00
absolute_error = abs(b - a)
2021-10-04 23:08:28 +08:00
if absolute_error <= max(abs_err, rel_err * abs(a)):
return True
return False
2022-01-24 18:32:33 +08:00
2021-10-04 23:08:28 +08:00
@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)
2022-01-24 18:32:33 +08:00
2021-10-04 23:08:28 +08:00
test_constants()
2022-01-24 18:32:33 +08:00
2021-10-04 23:08:28 +08:00
@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"
2022-01-24 18:32:33 +08:00
2021-10-04 23:08:28 +08:00
test_infinity_and_nan_constants()
2022-01-24 18:32:33 +08:00
2021-10-04 23:08:28 +08:00
@test
def test_user_object():
2022-01-24 18:32:33 +08:00
class MyComplexOS:
2021-10-04 23:08:28 +08:00
value: T
2022-02-16 23:51:16 +08:00
T: type
2022-01-24 18:32:33 +08:00
2021-10-04 23:08:28 +08:00
def __init__(self, value: T):
self.value = value
2022-01-24 18:32:33 +08:00
2021-10-04 23:08:28 +08:00
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)
2022-01-24 18:32:33 +08:00
2021-10-04 23:08:28 +08:00
test_user_object()
2022-01-24 18:32:33 +08:00
2021-10-04 23:08:28 +08:00
@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)
2022-01-24 18:32:33 +08:00
2021-10-04 23:08:28 +08:00
test_input_type()
@test
def test_cmath_matches_math():
test_values = [0.01, 0.1, 0.2, 0.5, 0.9, 0.99]
2022-01-24 18:32:33 +08:00
unit_interval = test_values + [-x for x in test_values] + [0.0, 1.0, -1.0]
positive = test_values + [1.0] + [1.0 / x for x in test_values]
nonnegative = [0.0] + positive
real_line = [0.0] + positive + [-x for x in positive]
2021-10-04 23:08:28 +08:00
test_functions = {
2022-01-24 18:32:33 +08:00
"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"]:
2021-10-04 23:08:28 +08:00
z = cmath.acos(v)
assert almost_equal(z.real, math.acos(v))
2022-01-24 18:32:33 +08:00
assert z.imag == 0.0
2021-10-04 23:08:28 +08:00
2022-01-24 18:32:33 +08:00
for v in test_functions["asin"]:
2021-10-04 23:08:28 +08:00
z = cmath.asin(v)
assert almost_equal(z.real, math.asin(v))
2022-01-24 18:32:33 +08:00
assert z.imag == 0.0
2021-10-04 23:08:28 +08:00
2022-01-24 18:32:33 +08:00
for v in test_functions["atan"]:
2021-10-04 23:08:28 +08:00
z = cmath.atan(v)
assert almost_equal(z.real, math.atan(v))
2022-01-24 18:32:33 +08:00
assert z.imag == 0.0
2021-10-04 23:08:28 +08:00
2022-01-24 18:32:33 +08:00
for v in test_functions["cos"]:
2021-10-04 23:08:28 +08:00
z = cmath.cos(v)
assert almost_equal(z.real, math.cos(v))
2022-01-24 18:32:33 +08:00
assert z.imag == 0.0
2021-10-04 23:08:28 +08:00
2022-01-24 18:32:33 +08:00
for v in test_functions["cosh"]:
2021-10-04 23:08:28 +08:00
z = cmath.cosh(v)
assert almost_equal(z.real, math.cosh(v))
2022-01-24 18:32:33 +08:00
assert z.imag == 0.0
2021-10-04 23:08:28 +08:00
2022-01-24 18:32:33 +08:00
for v in test_functions["exp"]:
2021-10-04 23:08:28 +08:00
z = cmath.exp(v)
assert almost_equal(z.real, math.exp(v))
2022-01-24 18:32:33 +08:00
assert z.imag == 0.0
2021-10-04 23:08:28 +08:00
2022-01-24 18:32:33 +08:00
for v in test_functions["log"]:
2021-10-04 23:08:28 +08:00
z = cmath.log(v)
assert almost_equal(z.real, math.log(v))
2022-01-24 18:32:33 +08:00
assert z.imag == 0.0
2021-10-04 23:08:28 +08:00
2022-01-24 18:32:33 +08:00
for v in test_functions["log10"]:
2021-10-04 23:08:28 +08:00
z = cmath.log10(v)
assert almost_equal(z.real, math.log10(v))
2022-01-24 18:32:33 +08:00
assert z.imag == 0.0
2021-10-04 23:08:28 +08:00
2022-01-24 18:32:33 +08:00
for v in test_functions["sin"]:
2021-10-04 23:08:28 +08:00
z = cmath.sin(v)
assert almost_equal(z.real, math.sin(v))
2022-01-24 18:32:33 +08:00
assert z.imag == 0.0
2021-10-04 23:08:28 +08:00
2022-01-24 18:32:33 +08:00
for v in test_functions["sinh"]:
2021-10-04 23:08:28 +08:00
z = cmath.sinh(v)
assert almost_equal(z.real, math.sinh(v))
2022-01-24 18:32:33 +08:00
assert z.imag == 0.0
2021-10-04 12:05:24 +08:00
2022-01-24 18:32:33 +08:00
for v in test_functions["sqrt"]:
2021-10-04 23:08:28 +08:00
z = cmath.sqrt(v)
assert almost_equal(z.real, math.sqrt(v))
2022-01-24 18:32:33 +08:00
assert z.imag == 0.0
2021-10-04 12:05:24 +08:00
2022-01-24 18:32:33 +08:00
for v in test_functions["tan"]:
2021-10-04 23:08:28 +08:00
z = cmath.tan(v)
assert almost_equal(z.real, math.tan(v))
2022-01-24 18:32:33 +08:00
assert z.imag == 0.0
2021-10-04 12:05:24 +08:00
2022-01-24 18:32:33 +08:00
for v in test_functions["tanh"]:
2021-10-04 23:08:28 +08:00
z = cmath.tanh(v)
assert almost_equal(z.real, math.tanh(v))
2022-01-24 18:32:33 +08:00
assert z.imag == 0.0
2021-10-04 23:08:28 +08:00
2022-01-24 18:32:33 +08:00
for base in [0.5, 2.0, 10.0]:
2021-10-04 23:08:28 +08:00
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
2022-01-24 18:32:33 +08:00
assert z.imag == 0.0
2021-10-04 23:08:28 +08:00
test_cmath_matches_math()
2022-01-24 18:32:33 +08:00
2021-10-04 23:08:28 +08:00
@test
def test_polar():
def check(arg, expected):
got = cmath.polar(arg)
2022-01-24 18:32:33 +08:00
return all(almost_equal(e, g) for e, g in zip(expected, got))
2021-10-04 23:08:28 +08:00
pi = cmath.pi
2022-01-24 18:32:33 +08:00
assert check(0, (0.0, 0.0))
assert check(1, (1.0, 0.0))
assert check(-1, (1.0, pi))
assert check(1j, (1.0, pi / 2))
assert check(-3j, (3.0, -pi / 2))
inf = float("inf")
assert check(complex(inf, 0), (inf, 0.0))
2021-10-04 23:08:28 +08:00
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))
2022-01-24 18:32:33 +08:00
nan = float("nan")
2021-10-04 23:08:28 +08:00
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))
2022-01-24 18:32:33 +08:00
2021-10-04 23:08:28 +08:00
test_polar()
2022-01-24 18:32:33 +08:00
2021-10-04 23:08:28 +08:00
@test
def test_phase():
from cmath import phase, pi
2022-01-24 18:32:33 +08:00
assert almost_equal(phase(0), 0.0)
assert almost_equal(phase(1.0), 0.0)
assert almost_equal(phase(-1.0), pi)
assert almost_equal(phase(-1.0 + 1e-300j), pi)
assert almost_equal(phase(-1.0 - 1e-300j), -pi)
assert almost_equal(phase(1j), pi / 2)
assert almost_equal(phase(-1j), -pi / 2)
2021-10-04 23:08:28 +08:00
# 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)
2022-01-24 18:32:33 +08:00
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)
2021-10-04 23:08:28 +08:00
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
2022-01-24 18:32:33 +08:00
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)
2021-10-04 23:08:28 +08:00
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))
2022-01-24 18:32:33 +08:00
2021-10-04 23:08:28 +08:00
test_phase()
2022-01-24 18:32:33 +08:00
2021-10-04 23:08:28 +08:00
@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)))
2022-01-24 18:32:33 +08:00
2021-10-04 23:08:28 +08:00
test_abs()
2022-01-24 18:32:33 +08:00
2021-10-04 23:08:28 +08:00
def c_equal(a, b):
2022-01-24 18:32:33 +08:00
eps = 1e-7
2021-10-04 23:08:28 +08:00
if abs(a.real - b[0]) > eps or abs(a.imag - b[1]) > eps:
return False
return True
2022-01-24 18:32:33 +08:00
2021-10-04 23:08:28 +08:00
@test
def test_rect():
from cmath import rect, pi
2022-01-24 18:32:33 +08:00
2021-10-04 23:08:28 +08:00
assert c_equal(rect(0, 0), (0, 0))
2022-01-24 18:32:33 +08:00
assert c_equal(rect(1, 0), (1.0, 0))
assert c_equal(rect(1, -pi), (-1.0, 0))
assert c_equal(rect(1, pi / 2), (0, 1.0))
assert c_equal(rect(1, -pi / 2), (0, -1.0))
2021-10-04 23:08:28 +08:00
test_rect()
2022-01-24 18:32:33 +08:00
2021-10-04 23:08:28 +08:00
@test
def test_isfinite():
2022-01-24 18:32:33 +08:00
real_vals = [float("-inf"), -2.3, -0.0, 0.0, 2.3, float("inf"), float("nan")]
2021-10-04 23:08:28 +08:00
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))
2022-01-24 18:32:33 +08:00
2021-10-04 23:08:28 +08:00
test_isfinite()
2022-01-24 18:32:33 +08:00
2021-10-04 23:08:28 +08:00
@test
def test_isnan():
assert not cmath.isnan(1)
assert not cmath.isnan(1j)
2021-10-04 23:08:28 +08:00
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))
2022-01-24 18:32:33 +08:00
2021-10-04 23:08:28 +08:00
test_isnan()
2022-01-24 18:32:33 +08:00
2021-10-04 23:08:28 +08:00
@test
def test_isinf():
assert not cmath.isinf(1)
assert not cmath.isinf(1j)
2021-10-04 23:08:28 +08:00
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))
2022-01-24 18:32:33 +08:00
2021-10-04 23:08:28 +08:00
test_isinf()
2022-01-24 18:32:33 +08:00
2021-10-04 23:08:28 +08:00
@test
def test_tanh_sign():
for z in complex_zeros:
assert complex_identical(cmath.tanh(z), z)
2022-01-24 18:32:33 +08:00
2021-10-04 23:08:28 +08:00
test_tanh_sign()
2022-01-24 18:32:33 +08:00
2021-10-04 23:08:28 +08:00
@test
def test_atan_sign():
for z in complex_zeros:
assert complex_identical(cmath.atan(z), z)
2022-01-24 18:32:33 +08:00
2021-10-04 23:08:28 +08:00
test_atan_sign()
2022-01-24 18:32:33 +08:00
2021-10-04 23:08:28 +08:00
@test
def test_atanh_sign():
for z in complex_zeros:
assert complex_identical(cmath.atanh(z), z)
2022-01-24 18:32:33 +08:00
2021-10-04 23:08:28 +08:00
test_atanh_sign()
2022-01-24 18:32:33 +08:00
2021-10-04 23:08:28 +08:00
@test
def test_is_close():
# test complex values that are close to within 12 decimal places
2022-01-24 18:32:33 +08:00
complex_examples = [
(1.0 + 1.0j, 1.000000000001 + 1.0j),
(1.0 + 1.0j, 1.0 + 1.000000000001j),
(-1.0 + 1.0j, -1.000000000001 + 1.0j),
(1.0 - 1.0j, 1.0 - 0.999999999999j),
]
for a, b in complex_examples:
2021-10-04 23:08:28 +08:00
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
2022-01-24 18:32:33 +08:00
near_zero_examples = [
(0.001j, 0),
(0.001 + 0j, 0),
(0.001 + 0.001j, 0),
(-0.001 + 0.001j, 0),
(0.001 - 0.001j, 0),
(-0.001 - 0.001j, 0),
]
for a, b in near_zero_examples:
2021-10-04 23:08:28 +08:00
assert cmath.isclose(a, b, abs_tol=1.5e-03)
assert not cmath.isclose(a, b, abs_tol=0.5e-03)
2022-01-24 18:32:33 +08:00
assert cmath.isclose(0.001 - 0.001j, 0.001 + 0.001j, abs_tol=2e-03)
assert not cmath.isclose(0.001 - 0.001j, 0.001 + 0.001j, abs_tol=1e-03)
2021-10-04 23:08:28 +08:00
test_is_close()
2021-10-04 12:05:24 +08:00
2022-01-24 18:32:33 +08:00
2021-10-04 12:05:24 +08:00
@test
def test_cmath_testcases():
2021-10-04 23:08:28 +08:00
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)
2022-01-24 18:32:33 +08:00
return math.isclose(a, b, rel_tol=1e-10, abs_tol=1e-15)
2021-10-04 23:08:28 +08:00
x1 = exp.real
y1 = exp.imag
x2 = got.real
y2 = got.imag
2022-01-24 18:32:33 +08:00
if "ignore-real-sign" in flags:
2021-10-04 23:08:28 +08:00
x1 = math.fabs(x1)
x2 = math.fabs(x2)
2022-01-24 18:32:33 +08:00
if "ignore-imag-sign" in flags:
2021-10-04 23:08:28 +08:00
y1 = math.fabs(y1)
y2 = math.fabs(y2)
return close(x1, x2) and close(y1, y2)
2021-10-04 12:05:24 +08:00
def run_test(test):
v = test.split()
if not v:
return True
name = v[0]
func = v[1]
inp = complex(float(v[2]), float(v[3]))
exp = complex(float(v[5]), float(v[6]))
flags = v[7:]
got = complex()
2022-01-24 18:32:33 +08:00
if func == "rect":
2021-10-04 12:05:24 +08:00
got = cmath.rect(inp.real, inp.imag)
2022-01-24 18:32:33 +08:00
elif func == "polar":
2021-10-04 12:05:24 +08:00
got = complex(*cmath.polar(inp))
2022-01-24 18:32:33 +08:00
elif func == "exp":
2021-10-04 12:05:24 +08:00
got = cmath.exp(inp)
2022-01-24 18:32:33 +08:00
elif func == "log":
2021-10-04 12:05:24 +08:00
got = cmath.log(inp)
2022-01-24 18:32:33 +08:00
elif func == "log10":
2021-10-04 12:05:24 +08:00
got = cmath.log10(inp)
2022-01-24 18:32:33 +08:00
elif func == "sqrt":
2021-10-04 12:05:24 +08:00
got = cmath.sqrt(inp)
2022-01-24 18:32:33 +08:00
elif func == "acos":
2021-10-04 12:05:24 +08:00
got = cmath.acos(inp)
2022-01-24 18:32:33 +08:00
elif func == "asin":
2021-10-04 12:05:24 +08:00
got = cmath.asin(inp)
2022-01-24 18:32:33 +08:00
elif func == "atan":
2021-10-04 12:05:24 +08:00
got = cmath.atan(inp)
2022-01-24 18:32:33 +08:00
elif func == "cos":
2021-10-04 12:05:24 +08:00
got = cmath.cos(inp)
2022-01-24 18:32:33 +08:00
elif func == "sin":
2021-10-04 12:05:24 +08:00
got = cmath.sin(inp)
2022-01-24 18:32:33 +08:00
elif func == "tan":
2021-10-04 12:05:24 +08:00
got = cmath.tan(inp)
2022-01-24 18:32:33 +08:00
elif func == "acosh":
2021-10-04 12:05:24 +08:00
got = cmath.acosh(inp)
2022-01-24 18:32:33 +08:00
elif func == "asinh":
2021-10-04 12:05:24 +08:00
got = cmath.asinh(inp)
2022-01-24 18:32:33 +08:00
elif func == "atanh":
2021-10-04 12:05:24 +08:00
got = cmath.atanh(inp)
2022-01-24 18:32:33 +08:00
elif func == "cosh":
2021-10-04 12:05:24 +08:00
got = cmath.cosh(inp)
2022-01-24 18:32:33 +08:00
elif func == "sinh":
2021-10-04 12:05:24 +08:00
got = cmath.sinh(inp)
2022-01-24 18:32:33 +08:00
elif func == "tanh":
2021-10-04 12:05:24 +08:00
got = cmath.tanh(inp)
else:
2022-01-24 18:32:33 +08:00
assert False, f"ERROR: unknown function: {func}"
2021-10-04 12:05:24 +08:00
if not check(exp, got, flags):
2022-01-24 18:32:33 +08:00
print(f"{name} {func} {inp=} {got=} {exp=} {flags=}")
2021-10-04 12:05:24 +08:00
return False
return True
tests = []
2022-01-24 18:32:33 +08:00
with open("test/stdlib/cmath_testcases.txt") as f:
2021-10-04 12:05:24 +08:00
for line in f:
line = line.strip()
2022-01-24 18:32:33 +08:00
if not line.startswith("--"):
2021-10-04 12:05:24 +08:00
tests.append(line)
for test in tests:
assert run_test(test)
2022-01-24 18:32:33 +08:00
2021-10-04 12:05:24 +08:00
test_cmath_testcases()
v0.16 (#335) * Add Python extension lowering pass * Add DocstringAttribute * Add extension module codegen * Handle different argument counts efficiently * Add warnings to extension lowering * Fix module name * Fix extension codegen * Fix argument check * Auto-convert Codon exceptions to Python exceptions * Fix #183 * Fix #162; Fix #135 * Fix #155 * Fix CPython interface in codegen * Fix #191 * Fix #187 * Fix #189 * Generate object file in pyext mode * Convert Codon exceptions to Python exceptions * Fix vtable init; Fix failing tests on Linux * Fix #190 * Fix #156 * Fix union routing * Remove need for import python * Automatic @export and wrapping for toplevel functions * Reorganize API * Add Python extension IR structs * Add special calls for no-suspend yield-expr * Add special calls for no-suspend yield-expr * pyextension.h support [wip] * pyextension.h support [wip] * pyextension.h support * pyextension.h support for toplevel functions * clang-format * Add PyFunction::nargs field * Update pyextension codegen (WIP) * SUpport nargs * Add support for @pycapture * PyType codegen (WIP) * Py method codegen (WIP) * Add type ptr hook * Add getset codegen * Add type alloc function * Add type pointer hook codegen * Re-organize codegen * Add member codegen * Update module init codegen * Update module init codegen * Add support for typePtrHook and new to/from_py hooks * Fix extension codegen * Fix init codegen * Fix init codegen; add "tp_new" slot * Fix type hook * Add extra flags * Specialized wrappers (PyType specs) * Add static Python link option * Fix C imports * Add guards * Remove unused field * Python mode only when pyExt set * Update python module * Fix assert * Update codegen/passes * Fix tuple parsing in index expression * Fix empty tuple unification * Do not Cythonize underscore fns * clang-format * Fix switch * Add Py support for cmp/setitem * Add Py support for cmp/setitem * Add type is support * GetSet support * clang-format * GetSet support (fixes) * Avoid useless vtable alloc * Add iter support * Fix size_t capture bug * clang-format * Fix POD type unification with tuples * Add __try_from_py__ API * Fix annotation * Add static reflection methods (setattr; internal.static.*); refactor PyExt to python.codon; handle errors and kwargs in PyExt * Python compat fixes * Update Python object conversions * Fix PyErrors * clang-format; add copyright * Add PyFunction::keywords field * Fix JIT MRO handling; Refactor out Jupyter support * Refactor out Jupyter support * Add support for custom linking args (link=[]) to TOML plugins * Fix tests * Use g++ instead of gcc * Fix Jupyter CMAKE * Fix Jupyter CMAKE * Add _PyArg_Parser definition * Add complex64 type * Add extra complex64 tests * Fix Python calls; add staticenumerate * Fix call * Fix calls * Update pyext wrappers * Fix staticenumerate; Support static calls in tuple() * Fix pyext routing * Add add/mul for tuples * clang-format * Fix pyext codegen * Fix wrap_multiple * Add seq_alloc_atomic_uncollectable * Fix default generics issue * Add binary/ternary ops * Fix missing generic issue * Fix number slots * Update pow * Remove unnecessary pyobj * Fix allocation * Refactor errors * Add test extension * Fix formatting * clang-format * Fix getitem/setitem/delitem in pyext * Fix pyext iterators * Add builtin pow() (fix #294) * Fix #244 * Fix #231 * Fix #229 * Fix #205 * Update docs * Fix error message * Add pyext tests * Add pyext support for @property * Add pyext support for toplevel fns and @tuple classes * More pyext tests * More pyext tests * Fix file error checking * More pyext tests * Update pyext tests * Update docs * Add pyext test to CI * Add pyext support for @tuple.__new__ * Add pyext support for @tuple.__new__ * Fix hetero-tuple issue with fn_overloads * More pyext tests * Bump versions * Fix del magic in pyext * Fix init magic for tuples in pyext * Have test-pypi only run on develop branch * Make exception type indices unnamed-addr * Fix #316; Fix #317 (slash issue) * Use uncollectible-alloc for vtable * Fix #249 * Add pyext docs * Fix #249; Fix clashing vtables; Fix super() and class_copy * Add content-atomic type property instruction * __contents_atomic__ support * Update internal functions * Use PIC when generating Python extension * Cleanup * Add Dockerfile & fix -fPIC * Cleanup * Fix setup.py * Fix pyext fn iteration * Fix CI * clang-format * Update long conversions in Py bridge * Support wide-int to str conversions * Fix test * Add pow for arbitrary-width ints * Fix Linux backtraces * Cleanup * Add more tests * Fix docs; Remove tuple.__add__ for scalars * Update docs --------- Co-authored-by: Ibrahim Numanagić <ibrahimpasa@gmail.com>
2023-04-13 06:13:54 +08:00
2023-08-01 01:02:29 +08:00
@test
def test_complex_bool():
z = complex(0, 0)
assert not bool(z)
z = complex(1, 0)
assert bool(z)
z = complex(0, -1)
assert bool(z)
z = complex(1, -1)
assert bool(z)
test_complex_bool()
v0.16 (#335) * Add Python extension lowering pass * Add DocstringAttribute * Add extension module codegen * Handle different argument counts efficiently * Add warnings to extension lowering * Fix module name * Fix extension codegen * Fix argument check * Auto-convert Codon exceptions to Python exceptions * Fix #183 * Fix #162; Fix #135 * Fix #155 * Fix CPython interface in codegen * Fix #191 * Fix #187 * Fix #189 * Generate object file in pyext mode * Convert Codon exceptions to Python exceptions * Fix vtable init; Fix failing tests on Linux * Fix #190 * Fix #156 * Fix union routing * Remove need for import python * Automatic @export and wrapping for toplevel functions * Reorganize API * Add Python extension IR structs * Add special calls for no-suspend yield-expr * Add special calls for no-suspend yield-expr * pyextension.h support [wip] * pyextension.h support [wip] * pyextension.h support * pyextension.h support for toplevel functions * clang-format * Add PyFunction::nargs field * Update pyextension codegen (WIP) * SUpport nargs * Add support for @pycapture * PyType codegen (WIP) * Py method codegen (WIP) * Add type ptr hook * Add getset codegen * Add type alloc function * Add type pointer hook codegen * Re-organize codegen * Add member codegen * Update module init codegen * Update module init codegen * Add support for typePtrHook and new to/from_py hooks * Fix extension codegen * Fix init codegen * Fix init codegen; add "tp_new" slot * Fix type hook * Add extra flags * Specialized wrappers (PyType specs) * Add static Python link option * Fix C imports * Add guards * Remove unused field * Python mode only when pyExt set * Update python module * Fix assert * Update codegen/passes * Fix tuple parsing in index expression * Fix empty tuple unification * Do not Cythonize underscore fns * clang-format * Fix switch * Add Py support for cmp/setitem * Add Py support for cmp/setitem * Add type is support * GetSet support * clang-format * GetSet support (fixes) * Avoid useless vtable alloc * Add iter support * Fix size_t capture bug * clang-format * Fix POD type unification with tuples * Add __try_from_py__ API * Fix annotation * Add static reflection methods (setattr; internal.static.*); refactor PyExt to python.codon; handle errors and kwargs in PyExt * Python compat fixes * Update Python object conversions * Fix PyErrors * clang-format; add copyright * Add PyFunction::keywords field * Fix JIT MRO handling; Refactor out Jupyter support * Refactor out Jupyter support * Add support for custom linking args (link=[]) to TOML plugins * Fix tests * Use g++ instead of gcc * Fix Jupyter CMAKE * Fix Jupyter CMAKE * Add _PyArg_Parser definition * Add complex64 type * Add extra complex64 tests * Fix Python calls; add staticenumerate * Fix call * Fix calls * Update pyext wrappers * Fix staticenumerate; Support static calls in tuple() * Fix pyext routing * Add add/mul for tuples * clang-format * Fix pyext codegen * Fix wrap_multiple * Add seq_alloc_atomic_uncollectable * Fix default generics issue * Add binary/ternary ops * Fix missing generic issue * Fix number slots * Update pow * Remove unnecessary pyobj * Fix allocation * Refactor errors * Add test extension * Fix formatting * clang-format * Fix getitem/setitem/delitem in pyext * Fix pyext iterators * Add builtin pow() (fix #294) * Fix #244 * Fix #231 * Fix #229 * Fix #205 * Update docs * Fix error message * Add pyext tests * Add pyext support for @property * Add pyext support for toplevel fns and @tuple classes * More pyext tests * More pyext tests * Fix file error checking * More pyext tests * Update pyext tests * Update docs * Add pyext test to CI * Add pyext support for @tuple.__new__ * Add pyext support for @tuple.__new__ * Fix hetero-tuple issue with fn_overloads * More pyext tests * Bump versions * Fix del magic in pyext * Fix init magic for tuples in pyext * Have test-pypi only run on develop branch * Make exception type indices unnamed-addr * Fix #316; Fix #317 (slash issue) * Use uncollectible-alloc for vtable * Fix #249 * Add pyext docs * Fix #249; Fix clashing vtables; Fix super() and class_copy * Add content-atomic type property instruction * __contents_atomic__ support * Update internal functions * Use PIC when generating Python extension * Cleanup * Add Dockerfile & fix -fPIC * Cleanup * Fix setup.py * Fix pyext fn iteration * Fix CI * clang-format * Update long conversions in Py bridge * Support wide-int to str conversions * Fix test * Add pow for arbitrary-width ints * Fix Linux backtraces * Cleanup * Add more tests * Fix docs; Remove tuple.__add__ for scalars * Update docs --------- Co-authored-by: Ibrahim Numanagić <ibrahimpasa@gmail.com>
2023-04-13 06:13:54 +08:00
@test
def test_complex64():
c64 = complex64
z = c64(.5 + .5j)
2024-07-31 07:35:27 +08:00
assert c64() == z * float32(0.)
assert z + float32(1) == c64(1.5, .5)
v0.16 (#335) * Add Python extension lowering pass * Add DocstringAttribute * Add extension module codegen * Handle different argument counts efficiently * Add warnings to extension lowering * Fix module name * Fix extension codegen * Fix argument check * Auto-convert Codon exceptions to Python exceptions * Fix #183 * Fix #162; Fix #135 * Fix #155 * Fix CPython interface in codegen * Fix #191 * Fix #187 * Fix #189 * Generate object file in pyext mode * Convert Codon exceptions to Python exceptions * Fix vtable init; Fix failing tests on Linux * Fix #190 * Fix #156 * Fix union routing * Remove need for import python * Automatic @export and wrapping for toplevel functions * Reorganize API * Add Python extension IR structs * Add special calls for no-suspend yield-expr * Add special calls for no-suspend yield-expr * pyextension.h support [wip] * pyextension.h support [wip] * pyextension.h support * pyextension.h support for toplevel functions * clang-format * Add PyFunction::nargs field * Update pyextension codegen (WIP) * SUpport nargs * Add support for @pycapture * PyType codegen (WIP) * Py method codegen (WIP) * Add type ptr hook * Add getset codegen * Add type alloc function * Add type pointer hook codegen * Re-organize codegen * Add member codegen * Update module init codegen * Update module init codegen * Add support for typePtrHook and new to/from_py hooks * Fix extension codegen * Fix init codegen * Fix init codegen; add "tp_new" slot * Fix type hook * Add extra flags * Specialized wrappers (PyType specs) * Add static Python link option * Fix C imports * Add guards * Remove unused field * Python mode only when pyExt set * Update python module * Fix assert * Update codegen/passes * Fix tuple parsing in index expression * Fix empty tuple unification * Do not Cythonize underscore fns * clang-format * Fix switch * Add Py support for cmp/setitem * Add Py support for cmp/setitem * Add type is support * GetSet support * clang-format * GetSet support (fixes) * Avoid useless vtable alloc * Add iter support * Fix size_t capture bug * clang-format * Fix POD type unification with tuples * Add __try_from_py__ API * Fix annotation * Add static reflection methods (setattr; internal.static.*); refactor PyExt to python.codon; handle errors and kwargs in PyExt * Python compat fixes * Update Python object conversions * Fix PyErrors * clang-format; add copyright * Add PyFunction::keywords field * Fix JIT MRO handling; Refactor out Jupyter support * Refactor out Jupyter support * Add support for custom linking args (link=[]) to TOML plugins * Fix tests * Use g++ instead of gcc * Fix Jupyter CMAKE * Fix Jupyter CMAKE * Add _PyArg_Parser definition * Add complex64 type * Add extra complex64 tests * Fix Python calls; add staticenumerate * Fix call * Fix calls * Update pyext wrappers * Fix staticenumerate; Support static calls in tuple() * Fix pyext routing * Add add/mul for tuples * clang-format * Fix pyext codegen * Fix wrap_multiple * Add seq_alloc_atomic_uncollectable * Fix default generics issue * Add binary/ternary ops * Fix missing generic issue * Fix number slots * Update pow * Remove unnecessary pyobj * Fix allocation * Refactor errors * Add test extension * Fix formatting * clang-format * Fix getitem/setitem/delitem in pyext * Fix pyext iterators * Add builtin pow() (fix #294) * Fix #244 * Fix #231 * Fix #229 * Fix #205 * Update docs * Fix error message * Add pyext tests * Add pyext support for @property * Add pyext support for toplevel fns and @tuple classes * More pyext tests * More pyext tests * Fix file error checking * More pyext tests * Update pyext tests * Update docs * Add pyext test to CI * Add pyext support for @tuple.__new__ * Add pyext support for @tuple.__new__ * Fix hetero-tuple issue with fn_overloads * More pyext tests * Bump versions * Fix del magic in pyext * Fix init magic for tuples in pyext * Have test-pypi only run on develop branch * Make exception type indices unnamed-addr * Fix #316; Fix #317 (slash issue) * Use uncollectible-alloc for vtable * Fix #249 * Add pyext docs * Fix #249; Fix clashing vtables; Fix super() and class_copy * Add content-atomic type property instruction * __contents_atomic__ support * Update internal functions * Use PIC when generating Python extension * Cleanup * Add Dockerfile & fix -fPIC * Cleanup * Fix setup.py * Fix pyext fn iteration * Fix CI * clang-format * Update long conversions in Py bridge * Support wide-int to str conversions * Fix test * Add pow for arbitrary-width ints * Fix Linux backtraces * Cleanup * Add more tests * Fix docs; Remove tuple.__add__ for scalars * Update docs --------- Co-authored-by: Ibrahim Numanagić <ibrahimpasa@gmail.com>
2023-04-13 06:13:54 +08:00
assert bool(z) == True
assert bool(0 * z) == False
assert +z == z
assert -z == c64(-.5 - .5j)
assert abs(z) == float32(0.7071067811865476)
2024-07-31 07:35:27 +08:00
assert z + c64(1) == c64(1.5 + .5j)
assert c64(1j) + z == c64(.5 + 1.5j)
assert z * c64(2) == c64(1 + 1j)
assert c64(2j) * z == c64(-1 + 1j)
assert z / c64(.5) == c64(1 + 1j)
assert c64(1j) / z == c64(1 + 1j)
assert z ** c64(2) == c64(.5j)
assert z + 1 == 1.5 + .5j
assert 1j + z == .5 + 1.5j
assert z * 2 == 1 + 1j
assert 2j * z == -1 + 1j
assert z / .5 == 1 + 1j
assert 1j / z == 1 + 1j
assert z ** 2 == .5j
y = c64(1j) ** z
assert math.isclose(float(y.real), 0.32239694194483454, rel_tol=1e-7)
assert math.isclose(float(y.imag), 0.32239694194483454, rel_tol=1e-7)
v0.16 (#335) * Add Python extension lowering pass * Add DocstringAttribute * Add extension module codegen * Handle different argument counts efficiently * Add warnings to extension lowering * Fix module name * Fix extension codegen * Fix argument check * Auto-convert Codon exceptions to Python exceptions * Fix #183 * Fix #162; Fix #135 * Fix #155 * Fix CPython interface in codegen * Fix #191 * Fix #187 * Fix #189 * Generate object file in pyext mode * Convert Codon exceptions to Python exceptions * Fix vtable init; Fix failing tests on Linux * Fix #190 * Fix #156 * Fix union routing * Remove need for import python * Automatic @export and wrapping for toplevel functions * Reorganize API * Add Python extension IR structs * Add special calls for no-suspend yield-expr * Add special calls for no-suspend yield-expr * pyextension.h support [wip] * pyextension.h support [wip] * pyextension.h support * pyextension.h support for toplevel functions * clang-format * Add PyFunction::nargs field * Update pyextension codegen (WIP) * SUpport nargs * Add support for @pycapture * PyType codegen (WIP) * Py method codegen (WIP) * Add type ptr hook * Add getset codegen * Add type alloc function * Add type pointer hook codegen * Re-organize codegen * Add member codegen * Update module init codegen * Update module init codegen * Add support for typePtrHook and new to/from_py hooks * Fix extension codegen * Fix init codegen * Fix init codegen; add "tp_new" slot * Fix type hook * Add extra flags * Specialized wrappers (PyType specs) * Add static Python link option * Fix C imports * Add guards * Remove unused field * Python mode only when pyExt set * Update python module * Fix assert * Update codegen/passes * Fix tuple parsing in index expression * Fix empty tuple unification * Do not Cythonize underscore fns * clang-format * Fix switch * Add Py support for cmp/setitem * Add Py support for cmp/setitem * Add type is support * GetSet support * clang-format * GetSet support (fixes) * Avoid useless vtable alloc * Add iter support * Fix size_t capture bug * clang-format * Fix POD type unification with tuples * Add __try_from_py__ API * Fix annotation * Add static reflection methods (setattr; internal.static.*); refactor PyExt to python.codon; handle errors and kwargs in PyExt * Python compat fixes * Update Python object conversions * Fix PyErrors * clang-format; add copyright * Add PyFunction::keywords field * Fix JIT MRO handling; Refactor out Jupyter support * Refactor out Jupyter support * Add support for custom linking args (link=[]) to TOML plugins * Fix tests * Use g++ instead of gcc * Fix Jupyter CMAKE * Fix Jupyter CMAKE * Add _PyArg_Parser definition * Add complex64 type * Add extra complex64 tests * Fix Python calls; add staticenumerate * Fix call * Fix calls * Update pyext wrappers * Fix staticenumerate; Support static calls in tuple() * Fix pyext routing * Add add/mul for tuples * clang-format * Fix pyext codegen * Fix wrap_multiple * Add seq_alloc_atomic_uncollectable * Fix default generics issue * Add binary/ternary ops * Fix missing generic issue * Fix number slots * Update pow * Remove unnecessary pyobj * Fix allocation * Refactor errors * Add test extension * Fix formatting * clang-format * Fix getitem/setitem/delitem in pyext * Fix pyext iterators * Add builtin pow() (fix #294) * Fix #244 * Fix #231 * Fix #229 * Fix #205 * Update docs * Fix error message * Add pyext tests * Add pyext support for @property * Add pyext support for toplevel fns and @tuple classes * More pyext tests * More pyext tests * Fix file error checking * More pyext tests * Update pyext tests * Update docs * Add pyext test to CI * Add pyext support for @tuple.__new__ * Add pyext support for @tuple.__new__ * Fix hetero-tuple issue with fn_overloads * More pyext tests * Bump versions * Fix del magic in pyext * Fix init magic for tuples in pyext * Have test-pypi only run on develop branch * Make exception type indices unnamed-addr * Fix #316; Fix #317 (slash issue) * Use uncollectible-alloc for vtable * Fix #249 * Add pyext docs * Fix #249; Fix clashing vtables; Fix super() and class_copy * Add content-atomic type property instruction * __contents_atomic__ support * Update internal functions * Use PIC when generating Python extension * Cleanup * Add Dockerfile & fix -fPIC * Cleanup * Fix setup.py * Fix pyext fn iteration * Fix CI * clang-format * Update long conversions in Py bridge * Support wide-int to str conversions * Fix test * Add pow for arbitrary-width ints * Fix Linux backtraces * Cleanup * Add more tests * Fix docs; Remove tuple.__add__ for scalars * Update docs --------- Co-authored-by: Ibrahim Numanagić <ibrahimpasa@gmail.com>
2023-04-13 06:13:54 +08:00
assert z != -z
assert z != 0
assert z.real == float32(.5)
2024-07-31 07:35:27 +08:00
assert (z + c64(1j)).imag == float32(1.5)
v0.16 (#335) * Add Python extension lowering pass * Add DocstringAttribute * Add extension module codegen * Handle different argument counts efficiently * Add warnings to extension lowering * Fix module name * Fix extension codegen * Fix argument check * Auto-convert Codon exceptions to Python exceptions * Fix #183 * Fix #162; Fix #135 * Fix #155 * Fix CPython interface in codegen * Fix #191 * Fix #187 * Fix #189 * Generate object file in pyext mode * Convert Codon exceptions to Python exceptions * Fix vtable init; Fix failing tests on Linux * Fix #190 * Fix #156 * Fix union routing * Remove need for import python * Automatic @export and wrapping for toplevel functions * Reorganize API * Add Python extension IR structs * Add special calls for no-suspend yield-expr * Add special calls for no-suspend yield-expr * pyextension.h support [wip] * pyextension.h support [wip] * pyextension.h support * pyextension.h support for toplevel functions * clang-format * Add PyFunction::nargs field * Update pyextension codegen (WIP) * SUpport nargs * Add support for @pycapture * PyType codegen (WIP) * Py method codegen (WIP) * Add type ptr hook * Add getset codegen * Add type alloc function * Add type pointer hook codegen * Re-organize codegen * Add member codegen * Update module init codegen * Update module init codegen * Add support for typePtrHook and new to/from_py hooks * Fix extension codegen * Fix init codegen * Fix init codegen; add "tp_new" slot * Fix type hook * Add extra flags * Specialized wrappers (PyType specs) * Add static Python link option * Fix C imports * Add guards * Remove unused field * Python mode only when pyExt set * Update python module * Fix assert * Update codegen/passes * Fix tuple parsing in index expression * Fix empty tuple unification * Do not Cythonize underscore fns * clang-format * Fix switch * Add Py support for cmp/setitem * Add Py support for cmp/setitem * Add type is support * GetSet support * clang-format * GetSet support (fixes) * Avoid useless vtable alloc * Add iter support * Fix size_t capture bug * clang-format * Fix POD type unification with tuples * Add __try_from_py__ API * Fix annotation * Add static reflection methods (setattr; internal.static.*); refactor PyExt to python.codon; handle errors and kwargs in PyExt * Python compat fixes * Update Python object conversions * Fix PyErrors * clang-format; add copyright * Add PyFunction::keywords field * Fix JIT MRO handling; Refactor out Jupyter support * Refactor out Jupyter support * Add support for custom linking args (link=[]) to TOML plugins * Fix tests * Use g++ instead of gcc * Fix Jupyter CMAKE * Fix Jupyter CMAKE * Add _PyArg_Parser definition * Add complex64 type * Add extra complex64 tests * Fix Python calls; add staticenumerate * Fix call * Fix calls * Update pyext wrappers * Fix staticenumerate; Support static calls in tuple() * Fix pyext routing * Add add/mul for tuples * clang-format * Fix pyext codegen * Fix wrap_multiple * Add seq_alloc_atomic_uncollectable * Fix default generics issue * Add binary/ternary ops * Fix missing generic issue * Fix number slots * Update pow * Remove unnecessary pyobj * Fix allocation * Refactor errors * Add test extension * Fix formatting * clang-format * Fix getitem/setitem/delitem in pyext * Fix pyext iterators * Add builtin pow() (fix #294) * Fix #244 * Fix #231 * Fix #229 * Fix #205 * Update docs * Fix error message * Add pyext tests * Add pyext support for @property * Add pyext support for toplevel fns and @tuple classes * More pyext tests * More pyext tests * Fix file error checking * More pyext tests * Update pyext tests * Update docs * Add pyext test to CI * Add pyext support for @tuple.__new__ * Add pyext support for @tuple.__new__ * Fix hetero-tuple issue with fn_overloads * More pyext tests * Bump versions * Fix del magic in pyext * Fix init magic for tuples in pyext * Have test-pypi only run on develop branch * Make exception type indices unnamed-addr * Fix #316; Fix #317 (slash issue) * Use uncollectible-alloc for vtable * Fix #249 * Add pyext docs * Fix #249; Fix clashing vtables; Fix super() and class_copy * Add content-atomic type property instruction * __contents_atomic__ support * Update internal functions * Use PIC when generating Python extension * Cleanup * Add Dockerfile & fix -fPIC * Cleanup * Fix setup.py * Fix pyext fn iteration * Fix CI * clang-format * Update long conversions in Py bridge * Support wide-int to str conversions * Fix test * Add pow for arbitrary-width ints * Fix Linux backtraces * Cleanup * Add more tests * Fix docs; Remove tuple.__add__ for scalars * Update docs --------- Co-authored-by: Ibrahim Numanagić <ibrahimpasa@gmail.com>
2023-04-13 06:13:54 +08:00
assert z.conjugate() == c64(.5 - .5j)
assert z.__copy__() == z
assert hash(z)
assert c64(complex(z)) == z
2023-07-24 23:30:46 +08:00
z = c64(1.5, 2.5)
assert z.real == f32(1.5)
assert z.imag == f32(2.5)
z = c64(3.5)
assert z.real == f32(3.5)
assert z.imag == f32(0.0)
z = c64(f32(4.5), f32(5.5))
assert z.real == f32(4.5)
assert z.imag == f32(5.5)
z = c64(f32(6.5))
assert z.real == f32(6.5)
assert z.imag == f32(0.0)
2023-08-01 01:02:29 +08:00
z = c64(0, 0)
assert not bool(z)
z = c64(1, 0)
assert bool(z)
z = c64(0, -1)
assert bool(z)
z = c64(1, -1)
assert bool(z)
v0.16 (#335) * Add Python extension lowering pass * Add DocstringAttribute * Add extension module codegen * Handle different argument counts efficiently * Add warnings to extension lowering * Fix module name * Fix extension codegen * Fix argument check * Auto-convert Codon exceptions to Python exceptions * Fix #183 * Fix #162; Fix #135 * Fix #155 * Fix CPython interface in codegen * Fix #191 * Fix #187 * Fix #189 * Generate object file in pyext mode * Convert Codon exceptions to Python exceptions * Fix vtable init; Fix failing tests on Linux * Fix #190 * Fix #156 * Fix union routing * Remove need for import python * Automatic @export and wrapping for toplevel functions * Reorganize API * Add Python extension IR structs * Add special calls for no-suspend yield-expr * Add special calls for no-suspend yield-expr * pyextension.h support [wip] * pyextension.h support [wip] * pyextension.h support * pyextension.h support for toplevel functions * clang-format * Add PyFunction::nargs field * Update pyextension codegen (WIP) * SUpport nargs * Add support for @pycapture * PyType codegen (WIP) * Py method codegen (WIP) * Add type ptr hook * Add getset codegen * Add type alloc function * Add type pointer hook codegen * Re-organize codegen * Add member codegen * Update module init codegen * Update module init codegen * Add support for typePtrHook and new to/from_py hooks * Fix extension codegen * Fix init codegen * Fix init codegen; add "tp_new" slot * Fix type hook * Add extra flags * Specialized wrappers (PyType specs) * Add static Python link option * Fix C imports * Add guards * Remove unused field * Python mode only when pyExt set * Update python module * Fix assert * Update codegen/passes * Fix tuple parsing in index expression * Fix empty tuple unification * Do not Cythonize underscore fns * clang-format * Fix switch * Add Py support for cmp/setitem * Add Py support for cmp/setitem * Add type is support * GetSet support * clang-format * GetSet support (fixes) * Avoid useless vtable alloc * Add iter support * Fix size_t capture bug * clang-format * Fix POD type unification with tuples * Add __try_from_py__ API * Fix annotation * Add static reflection methods (setattr; internal.static.*); refactor PyExt to python.codon; handle errors and kwargs in PyExt * Python compat fixes * Update Python object conversions * Fix PyErrors * clang-format; add copyright * Add PyFunction::keywords field * Fix JIT MRO handling; Refactor out Jupyter support * Refactor out Jupyter support * Add support for custom linking args (link=[]) to TOML plugins * Fix tests * Use g++ instead of gcc * Fix Jupyter CMAKE * Fix Jupyter CMAKE * Add _PyArg_Parser definition * Add complex64 type * Add extra complex64 tests * Fix Python calls; add staticenumerate * Fix call * Fix calls * Update pyext wrappers * Fix staticenumerate; Support static calls in tuple() * Fix pyext routing * Add add/mul for tuples * clang-format * Fix pyext codegen * Fix wrap_multiple * Add seq_alloc_atomic_uncollectable * Fix default generics issue * Add binary/ternary ops * Fix missing generic issue * Fix number slots * Update pow * Remove unnecessary pyobj * Fix allocation * Refactor errors * Add test extension * Fix formatting * clang-format * Fix getitem/setitem/delitem in pyext * Fix pyext iterators * Add builtin pow() (fix #294) * Fix #244 * Fix #231 * Fix #229 * Fix #205 * Update docs * Fix error message * Add pyext tests * Add pyext support for @property * Add pyext support for toplevel fns and @tuple classes * More pyext tests * More pyext tests * Fix file error checking * More pyext tests * Update pyext tests * Update docs * Add pyext test to CI * Add pyext support for @tuple.__new__ * Add pyext support for @tuple.__new__ * Fix hetero-tuple issue with fn_overloads * More pyext tests * Bump versions * Fix del magic in pyext * Fix init magic for tuples in pyext * Have test-pypi only run on develop branch * Make exception type indices unnamed-addr * Fix #316; Fix #317 (slash issue) * Use uncollectible-alloc for vtable * Fix #249 * Add pyext docs * Fix #249; Fix clashing vtables; Fix super() and class_copy * Add content-atomic type property instruction * __contents_atomic__ support * Update internal functions * Use PIC when generating Python extension * Cleanup * Add Dockerfile & fix -fPIC * Cleanup * Fix setup.py * Fix pyext fn iteration * Fix CI * clang-format * Update long conversions in Py bridge * Support wide-int to str conversions * Fix test * Add pow for arbitrary-width ints * Fix Linux backtraces * Cleanup * Add more tests * Fix docs; Remove tuple.__add__ for scalars * Update docs --------- Co-authored-by: Ibrahim Numanagić <ibrahimpasa@gmail.com>
2023-04-13 06:13:54 +08:00
test_complex64()
2023-12-06 04:48:34 +08:00
def test_complex_from_string():
# for tests when string is not zero-terminated
def f(s):
return complex(s[1:-1])
def g(s):
return complex(' ' * 50 + s[1:-1] + ' ' * 50)
assert complex("1") == 1+0j
assert complex("1j") == 1j
assert complex("-1") == -1
assert complex("+1") == +1
assert complex("(1+2j)") == 1+2j
assert complex("(1.3+2.2j)") == 1.3+2.2j
assert complex("3.14+1J") == 3.14+1j
assert complex(" ( +3.14-6J )") == 3.14-6j
assert complex(" ( +3.14-J )") == 3.14-1j
assert complex(" ( +3.14+j )") == 3.14+1j
assert complex("J") == 1j
assert complex("( j )") == 1j
assert complex("+J") == 1j
assert complex("( -j)") == -1j
assert complex('1e-500') == 0.0 + 0.0j
assert complex('-1e-500j') == 0.0 - 0.0j
assert complex('-1e-500+1e-500j') == -0.0 + 0.0j
assert complex('1-1j') == 1.0 - 1j
assert complex('1J') == 1j
assert f("x1x") == 1+0j
assert f("x1jx") == 1j
assert f("x-1x") == -1
assert f("x+1x") == +1
assert f("x(1+2j)x") == 1+2j
assert f("x(1.3+2.2j)x") == 1.3+2.2j
assert f("x3.14+1Jx") == 3.14+1j
assert f("x ( +3.14-6J )x") == 3.14-6j
assert f("x ( +3.14-J )x") == 3.14-1j
assert f("x ( +3.14+j )x") == 3.14+1j
assert f("xJx") == 1j
assert f("x( j )x") == 1j
assert f("x+Jx") == 1j
assert f("x( -j)x") == -1j
assert f('x1e-500x') == 0.0 + 0.0j
assert f('x-1e-500jx') == 0.0 - 0.0j
assert f('x-1e-500+1e-500jx') == -0.0 + 0.0j
assert f('x1-1jx') == 1.0 - 1j
assert f('x1Jx') == 1j
assert g("x1x") == 1+0j
assert g("x1jx") == 1j
assert g("x-1x") == -1
assert g("x+1x") == +1
assert g("x(1+2j)x") == 1+2j
assert g("x(1.3+2.2j)x") == 1.3+2.2j
assert g("x3.14+1Jx") == 3.14+1j
assert g("x ( +3.14-6J )x") == 3.14-6j
assert g("x ( +3.14-J )x") == 3.14-1j
assert g("x ( +3.14+j )x") == 3.14+1j
assert g("xJx") == 1j
assert g("x( j )x") == 1j
assert g("x+Jx") == 1j
assert g("x( -j)x") == -1j
assert g('x1e-500x') == 0.0 + 0.0j
assert g('x-1e-500jx') == 0.0 - 0.0j
assert g('x-1e-500+1e-500jx') == -0.0 + 0.0j
assert g('x1-1jx') == 1.0 - 1j
assert g('x1Jx') == 1j
try:
complex("\0")
assert False
except ValueError:
pass
try:
complex("3\09")
assert False
except ValueError:
pass
try:
complex("1+")
assert False
except ValueError:
pass
try:
complex("1+1j+1j")
assert False
except ValueError:
pass
try:
complex("--")
assert False
except ValueError:
pass
try:
complex("(1+2j")
assert False
except ValueError:
pass
try:
complex("1+2j)")
assert False
except ValueError:
pass
try:
complex("1+(2j)")
assert False
except ValueError:
pass
try:
complex("(1+2j)123")
assert False
except ValueError:
pass
try:
complex("x")
assert False
except ValueError:
pass
try:
complex("1j+2")
assert False
except ValueError:
pass
try:
complex("1e1ej")
assert False
except ValueError:
pass
try:
complex("1e++1ej")
assert False
except ValueError:
pass
try:
complex(")1+2j(")
assert False
except ValueError:
pass
try:
complex("")
assert False
except ValueError:
pass
try:
f(" 1+2j")
assert False
except ValueError:
pass
try:
f("1..1j")
assert False
except ValueError:
pass
try:
f("1.11.1j")
assert False
except ValueError:
pass
try:
f("1e1.1j")
assert False
except ValueError:
pass
try:
f(" ")
assert False
except ValueError:
pass
try:
f(" J")
assert False
except ValueError:
pass
try:
g(" 1+2j")
assert False
except ValueError:
pass
try:
g("1..1j")
assert False
except ValueError:
pass
try:
g("1.11.1j")
assert False
except ValueError:
pass
try:
g("1e1.1j")
assert False
except ValueError:
pass
try:
g(" ")
assert False
except ValueError:
pass
try:
g(" J")
assert False
except ValueError:
pass
test_complex_from_string()