3
from cpython.object cimport Py_EQ, Py_NE
14
>>> Complex3j() == Complex3j()
20
>>> Complex3j() != Complex3j()
23
def __richcmp__(a, b, int op):
24
if op == Py_EQ or op == Py_NE:
25
if isinstance(a, Complex3j):
26
eq = isinstance(b, Complex3j) or b == 3j
28
eq = isinstance(b, Complex3j) and a == 3j
29
return eq if op == Py_EQ else not eq
33
def test_object_conversion(o):
35
>>> test_object_conversion(2)
37
>>> test_object_conversion(2j - 0.5)
38
((-0.5+2j), (-0.5+2j))
40
cdef float complex a = o
41
cdef double complex b = o
45
def test_arithmetic(double complex z, double complex w):
47
>>> test_arithmetic(2j, 4j)
48
(2j, -2j, 6j, -2j, (-8+0j), (0.5+0j))
49
>>> test_arithmetic(6+12j, 3j)
50
((6+12j), (-6-12j), (6+15j), (6+9j), (-36+18j), (4-2j))
51
>>> test_arithmetic(5-10j, 3+4j)
52
((5-10j), (-5+10j), (8-6j), (2-14j), (55-10j), (-1-2j))
54
return +z, -z+0, z+w, z-w, z*w, z/w
57
def test_div(double complex a, double complex b, expected):
60
>>> test_div(1 + 1j, 1 + big*1j, 1/big - 1j/big)
61
>>> test_div(1 + 1j, 1/big + 1j/big, big)
63
# Can't count on good c99 complex division :(
64
if '_c99_' not in __name__:
65
assert a / b == expected, (a / b, expected)
68
def test_pow(double complex z, double complex w, tol=None):
70
Various implementations produce slightly different results...
73
>>> test_pow(a, 1, 1e-15)
75
>>> test_pow(a, 2, 1e-15)
77
>>> test_pow(a, a, 1e-15)
79
>>> test_pow(complex(0.5, -.25), complex(3, 4), 1e-15)
81
>>> test_pow(-0.5, 1j, tol=1e-15)
83
>>> test_pow(-1, 0.5, tol=1e-15)
89
return abs(z**w / <object>z ** <object>w - 1) < tol
92
def test_int_pow(double complex z, int n, tol=None):
94
>>> [test_int_pow(complex(0, 1), k, 1e-15) for k in range(-4, 5)]
95
[True, True, True, True, True, True, True, True, True]
96
>>> [test_int_pow(complex(0, 2), k, 1e-15) for k in range(-4, 5)]
97
[True, True, True, True, True, True, True, True, True]
98
>>> [test_int_pow(complex(2, 0.5), k, 1e-14) for k in range(0, 10)]
99
[True, True, True, True, True, True, True, True, True, True]
100
>>> test_int_pow(-0.5, 5, tol=1e-15)
104
return z**n + <object>0 # add zero to normalize zero sign
106
return abs(z**n / <object>z ** <object>n - 1) < tol
109
@cython.cdivision(False)
110
def test_div_by_zero(double complex z):
112
>>> test_div_by_zero(4j)
114
>>> test_div_by_zero(0)
115
Traceback (most recent call last):
117
ZeroDivisionError: float division
122
def test_coercion(int a, float b, double c, float complex d, double complex e):
124
>>> test_coercion(1, 1.5, 2.5, 4+1j, 10j)
132
cdef double complex z
138
return z + a + b + c + d + e
141
def test_compare(double complex a, double complex b):
143
>>> test_compare(3, 3)
144
(True, False, False, False, False, True, False)
145
>>> test_compare(3j, 3j)
146
(True, False, True, True, True, False, False)
147
>>> test_compare(3j, 4j)
148
(False, True, True, False, True, True, False)
149
>>> test_compare(3, 4)
150
(False, True, False, False, False, True, False)
151
>>> test_compare(2-1j, 4)
152
(False, True, False, False, False, True, True)
154
return a == b, a != b, a == 3j, 3j == b, a == Complex3j(), Complex3j() != b, a == C21
157
def test_compare_coerce(double complex a, int b):
159
>>> test_compare_coerce(3, 4)
160
(False, True, False, False, False, True)
161
>>> test_compare_coerce(4+1j, 4)
162
(False, True, False, True, False, True)
163
>>> test_compare_coerce(4, 4)
164
(True, False, False, False, False, True)
165
>>> test_compare_coerce(3j, 4)
166
(False, True, True, False, True, False)
168
return a == b, a != b, a == 3j, 4+1j == a, a == Complex3j(), Complex3j() != a
174
(5j, (1-2.5j), (2-1j))
176
return 5j, 1-2.5j, C21
179
def test_real_imag(double complex z):
181
>>> test_real_imag(1-3j)
183
>>> test_real_imag(5)
185
>>> test_real_imag(1.5j)
188
return z.real, z.imag
190
def test_real_imag_assignment(object a, double b):
192
>>> test_real_imag_assignment(1, 2)
194
>>> test_real_imag_assignment(1.5, -3.5)
197
cdef double complex z
202
def test_conjugate(float complex z):
204
>>> test_conjugate(2+3j)
209
def test_conjugate_double(double complex z):
211
>>> test_conjugate_double(2+3j)
216
ctypedef double complex cdouble
217
def test_conjugate_typedef(cdouble z):
219
>>> test_conjugate_typedef(2+3j)
224
cdef cdouble test_conjugate_nogil(cdouble z) nogil:
225
# Really just a compile test.
227
test_conjugate_nogil(0) # use it
229
## cdef extern from "complex_numbers_T305.h":
230
## ctypedef double double_really_float "myfloat"
231
## ctypedef float float_really_double "mydouble"
232
## ctypedef float real_float "myfloat"
233
## ctypedef double real_double "mydouble"
235
## def test_conjugate_nosizeassumptions(double_really_float x,
236
## float_really_double y,
237
## real_float z, real_double w):
239
## >>> test_conjugate_nosizeassumptions(1, 1, 1, 1)
240
## (-1j, -1j, -1j, -1j)
241
## >>> ["%.2f" % x.imag for x in test_conjugate_nosizeassumptions(2e300, 2e300, 2e300, 2e300)]
242
## ['-inf', '-2e+300', '-inf', '-2e+300']
244
## cdef double complex I = 1j
245
## return ((x*I).conjugate(), (y*I).conjugate(), (z*I).conjugate(), (w*I).conjugate())
247
ctypedef double mydouble
248
def test_coerce_typedef_multiply(mydouble x, double complex z):
250
>>> test_coerce_typedef_multiply(3, 1+1j)
256
def test_coerce_typedef_multiply_int(myint x, double complex z):
258
>>> test_coerce_typedef_multiply_int(3, 1+1j)
263
cpdef double complex complex_retval():
272
Run the main operations on 1000 pseudo-random numbers to
273
try to spot anything accidentally missed from the test cases
274
(doesn't cover inf and NaN as inputs though)
277
cdef double complex x
278
cdef double complex y
280
from random import Random
281
from math import ldexp
283
r.seed("I'm a seed") # try to make the test somewhat reproducible
285
# copied from https://docs.python.org/3/library/random.html#recipes
286
# gets evenly distributed random numbers
288
mantissa = 0x10_0000_0000_0000 | r.getrandbits(52)
292
x = r.getrandbits(32)
293
exponent += x.bit_length() - 32
294
return ldexp(mantissa, exponent)
296
for n in range(1, 1001):
298
# strategical insert some 0 values
317
py_dict = dict(x=x, y=y)
320
sum_py = eval("x+y", py_dict)
321
delta_sum = abs(sum_/sum_py - 1)
322
assert delta_sum < 1e-15, f"{x} {y} {sum_} {sum_py} {delta_sum}"
325
minus_py = eval("x-y", py_dict)
326
delta_minus = abs(minus/minus_py - 1)
327
assert delta_minus < 1e-15, f"{x} {y} {minus} {minus_py} {delta_minus}"
330
times_py = eval("x*y", py_dict)
331
delta_times = abs(times/times_py - 1)
332
assert delta_times < 1e-15, f"{x} {y} {times} {times_py} {delta_times}"
335
divide_py = eval("x/y", py_dict)
336
delta_divide = abs(divide/divide_py - 1)
337
assert delta_divide < 1e-15, f"{x} {y} {divide} {divide_py} {delta_divide}"
340
divide2_py = eval("y/x", py_dict)
341
delta_divide2 = abs(divide2/divide2_py - 1)
342
assert delta_divide2 < 1e-15, f"{x} {y} {divide2} {divide2_py} {delta_divide2}"
345
pow_py = eval("x**y", py_dict)
346
delta_pow = abs(pow_/pow_py - 1)
347
assert delta_pow < 1e-15, f"{x} {y} {pow_} {pow_py} {delta_pow}"
350
pow2_py = eval("y**x", py_dict)
351
delta_pow2 = abs(pow2/pow2_py - 1)
352
assert delta_pow2 < 1e-15, f"{x} {y} {pow2} {pow2_py} {delta_pow2}"