File: test_umath_complex.py

package info (click to toggle)
python-numpy 1%3A1.4.1-5
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 12,736 kB
  • ctags: 14,035
  • sloc: ansic: 80,776; python: 62,482; makefile: 183; fortran: 121; f90: 42; cpp: 28; perl: 19; sh: 15
file content (477 lines) | stat: -rw-r--r-- 17,728 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
from numpy.testing import *
import numpy.core.umath as ncu
import numpy as np

# TODO: branch cuts (use Pauli code)
# TODO: conj 'symmetry'
# TODO: FPU exceptions

class TestCexp(object):
    def test_simple(self):
        check = check_complex_value
        f = np.exp

        yield check, f, 1, 0, np.exp(1), 0, False
        yield check, f, 0, 1, np.cos(1), np.sin(1), False

        ref = np.exp(1) * np.complex(np.cos(1), np.sin(1))
        yield check, f, 1, 1, ref.real, ref.imag, False

    def test_special_values(self):
        # C99: Section G 6.3.1

        check = check_complex_value
        f = np.exp

        # cexp(+-0 + 0i) is 1 + 0i
        yield check, f, np.PZERO, 0, 1, 0, False
        yield check, f, np.NZERO, 0, 1, 0, False

        # cexp(x + infi) is nan + nani for finite x and raises 'invalid' FPU
        # exception
        yield check, f,  1, np.inf, np.nan, np.nan
        yield check, f, -1, np.inf, np.nan, np.nan
        yield check, f,  0, np.inf, np.nan, np.nan

        # cexp(inf + 0i) is inf + 0i
        yield check, f,  np.inf, 0, np.inf, 0

        # cexp(-inf + yi) is +0 * (cos(y) + i sin(y)) for finite y
        ref = np.complex(np.cos(1.), np.sin(1.))
        yield check, f,  -np.inf, 1, np.PZERO, np.PZERO

        ref = np.complex(np.cos(np.pi * 0.75), np.sin(np.pi * 0.75))
        yield check, f,  -np.inf, 0.75 * np.pi, np.NZERO, np.PZERO

        # cexp(inf + yi) is +inf * (cos(y) + i sin(y)) for finite y
        ref = np.complex(np.cos(1.), np.sin(1.))
        yield check, f,  np.inf, 1, np.inf, np.inf

        ref = np.complex(np.cos(np.pi * 0.75), np.sin(np.pi * 0.75))
        yield check, f,  np.inf, 0.75 * np.pi, -np.inf, np.inf

        # cexp(-inf + inf i) is +-0 +- 0i (signs unspecified)
        def _check_ninf_inf(dummy):
            z = f(np.array(np.complex(-np.inf, np.inf)))
            if z.real != 0 or z.imag != 0:
                raise AssertionError(
                        "cexp(-inf, inf) is (%f, %f), expected (+-0, +-0)" \
                        % (z.real, z.imag))
        yield _check_ninf_inf, None

        # cexp(inf + inf i) is +-inf + NaNi and raised invalid FPU ex.
        def _check_inf_inf(dummy):
            z = f(np.array(np.complex(np.inf, np.inf)))
            if not np.isinf(z.real) or not np.isnan(z.imag):
                raise AssertionError(
                        "cexp(inf, inf) is (%f, %f), expected (+-inf, nan)" \
                        % (z.real, z.imag))
        yield _check_inf_inf, None

        # cexp(-inf + nan i) is +-0 +- 0i
        def _check_ninf_nan(dummy):
            z = f(np.array(np.complex(-np.inf, np.nan)))
            if z.real != 0 or z.imag != 0:
                raise AssertionError(
                        "cexp(-inf, nan) is (%f, %f), expected (+-0, +-0)" \
                        % (z.real, z.imag))
        yield _check_ninf_nan, None

        # cexp(inf + nan i) is +-inf + nan
        def _check_inf_nan(dummy):
            z = f(np.array(np.complex(np.inf, np.nan)))
            if not np.isinf(z.real) or not np.isnan(z.imag):
                raise AssertionError(
                        "cexp(-inf, nan) is (%f, %f), expected (+-inf, nan)" \
                        % (z.real, z.imag))
        yield _check_inf_nan, None

        # cexp(nan + yi) is nan + nani for y != 0 (optional: raises invalid FPU
        # ex)
        yield check, f, np.nan, 1, np.nan, np.nan
        yield check, f, np.nan, -1, np.nan, np.nan

        yield check, f, np.nan,  np.inf, np.nan, np.nan
        yield check, f, np.nan, -np.inf, np.nan, np.nan

        # cexp(nan + nani) is nan + nani
        yield check, f, np.nan, np.nan, np.nan, np.nan

    @dec.knownfailureif(True, "cexp(nan + 0I) is wrong on most implementations")
    def test_special_values2(self):
        # XXX: most implementations get it wrong here (including glibc <= 2.10)
        # cexp(nan + 0i) is nan + 0i
        yield check, f, np.nan, 0, np.nan, 0

class TestClog(TestCase):
    def test_simple(self):
        x = np.array([1+0j, 1+2j])
        y_r = np.log(np.abs(x)) + 1j * np.angle(x)
        y = np.log(x)
        for i in range(len(x)):
            assert_almost_equal(y[i], y_r[i])

    @dec.knownfailureif(True, "clog(- inf + i inf) fails on Windows.")
    def test_special_values(self):
        xl = []
        yl = []

        # From C99 std (Sec 6.3.2)
        # XXX: check exceptions raised

        # clog(-0 + i0) returns -inf + i pi and raises the 'divide-by-zero'
        # floating-point exception.
        x = np.array([np.NZERO], dtype=np.complex)
        y = np.complex(-np.inf, np.pi)
        assert_almost_equal(np.log(x), y)
        xl.append(x)
        yl.append(y)

        # clog(+0 + i0) returns -inf + i0 and raises the 'divide-by-zero'
        # floating-point exception.
        x = np.array([0], dtype=np.complex)
        y = np.complex(-np.inf, 0)
        assert_almost_equal(np.log(x), y)
        xl.append(x)
        yl.append(y)

        # clog(x + i inf returns +inf + i pi /2, for finite x.
        x = np.array([complex(1, np.inf)], dtype=np.complex)
        y = np.complex(np.inf, 0.5 * np.pi)
        assert_almost_equal(np.log(x), y)
        xl.append(x)
        yl.append(y)

        x = np.array([complex(-1, np.inf)], dtype=np.complex)
        assert_almost_equal(np.log(x), y)
        xl.append(x)
        yl.append(y)

        # clog(x + iNaN) returns NaN + iNaN and optionally raises the
        # 'invalid' floating- point exception, for finite x.
        x = np.array([complex(1., np.nan)], dtype=np.complex)
        y = np.complex(np.nan, np.nan)
        assert_almost_equal(np.log(x), y)
        xl.append(x)
        yl.append(y)

        x = np.array([np.inf + np.nan * 1j], dtype=np.complex)
        assert_almost_equal(np.log(x), y)
        xl.append(x)
        yl.append(y)

        # clog(- inf + iy) returns +inf + ipi , for finite positive-signed y.
        x = np.array([-np.inf + 1j], dtype=np.complex)
        y = np.complex(np.inf, np.pi)
        assert_almost_equal(np.log(x), y)
        xl.append(x)
        yl.append(y)

        # clog(+ inf + iy) returns +inf + i0, for finite positive-signed y.
        x = np.array([np.inf + 1j], dtype=np.complex)
        y = np.complex(np.inf, 0)
        assert_almost_equal(np.log(x), y)
        xl.append(x)
        yl.append(y)

        # clog(- inf + i inf) returns +inf + i3pi /4.
        x = np.array([complex(-np.inf, np.inf)], dtype=np.complex)
        y = np.complex(np.inf, 0.75 * np.pi)
        assert_almost_equal(np.log(x), y)
        xl.append(x)
        yl.append(y)

        # clog(+ inf + i inf) returns +inf + ipi /4.
        x = np.array([complex(np.inf, np.inf)], dtype=np.complex)
        y = np.complex(np.inf, 0.25 * np.pi)
        assert_almost_equal(np.log(x), y)
        xl.append(x)
        yl.append(y)

        # clog(+/- inf + iNaN) returns +inf + iNaN.
        x = np.array([complex(np.inf, np.nan)], dtype=np.complex)
        y = np.complex(np.inf, np.nan)
        assert_almost_equal(np.log(x), y)
        xl.append(x)
        yl.append(y)

        x = np.array([complex(-np.inf, np.nan)], dtype=np.complex)
        assert_almost_equal(np.log(x), y)
        xl.append(x)
        yl.append(y)

        # clog(NaN + iy) returns NaN + iNaN and optionally raises the
        # 'invalid' floating-point exception, for finite y.
        x = np.array([complex(np.nan, 1)], dtype=np.complex)
        y = np.complex(np.nan, np.nan)
        assert_almost_equal(np.log(x), y)
        xl.append(x)
        yl.append(y)

        # clog(NaN + i inf) returns +inf + iNaN.
        x = np.array([complex(np.nan, np.inf)], dtype=np.complex)
        y = np.complex(np.inf, np.nan)
        assert_almost_equal(np.log(x), y)
        xl.append(x)
        yl.append(y)

        # clog(NaN + iNaN) returns NaN + iNaN.
        x = np.array([complex(np.nan, np.nan)], dtype=np.complex)
        y = np.complex(np.nan, np.nan)
        assert_almost_equal(np.log(x), y)
        xl.append(x)
        yl.append(y)

        # clog(conj(z)) = conj(clog(z)).
        xa = np.array(xl, dtype=np.complex)
        ya = np.array(yl, dtype=np.complex)
        for i in range(len(xa)):
            assert_almost_equal(np.log(np.conj(xa[i])), np.conj(np.log(xa[i])))

class TestCsqrt(object):
    def test_simple(self):
        # sqrt(1)
        yield check_complex_value, np.sqrt, 1, 0, 1, 0

        # sqrt(1i)
        yield check_complex_value, np.sqrt, 0, 1, 0.5*np.sqrt(2), 0.5*np.sqrt(2), False

        # sqrt(-1)
        yield check_complex_value, np.sqrt, -1, 0, 0, 1

    def test_simple_conjugate(self):
        ref = np.conj(np.sqrt(np.complex(1, 1)))
        def f(z):
            return np.sqrt(np.conj(z))
        yield check_complex_value, f, 1, 1, ref.real, ref.imag, False

    #def test_branch_cut(self):
    #    _check_branch_cut(f, -1, 0, 1, -1)

    def test_special_values(self):
        check = check_complex_value
        f = np.sqrt

        # C99: Sec G 6.4.2
        x, y = [], []

        # csqrt(+-0 + 0i) is 0 + 0i
        yield check, f, np.PZERO, 0, 0, 0
        yield check, f, np.NZERO, 0, 0, 0

        # csqrt(x + infi) is inf + infi for any x (including NaN)
        yield check, f,  1, np.inf, np.inf, np.inf
        yield check, f, -1, np.inf, np.inf, np.inf

        yield check, f, np.PZERO, np.inf, np.inf, np.inf
        yield check, f, np.NZERO, np.inf, np.inf, np.inf
        yield check, f,   np.inf, np.inf, np.inf, np.inf
        yield check, f,  -np.inf, np.inf, np.inf, np.inf
        yield check, f,  -np.nan, np.inf, np.inf, np.inf

        # csqrt(x + nani) is nan + nani for any finite x
        yield check, f,  1, np.nan, np.nan, np.nan
        yield check, f, -1, np.nan, np.nan, np.nan
        yield check, f,  0, np.nan, np.nan, np.nan

        # csqrt(-inf + yi) is +0 + infi for any finite y > 0
        yield check, f, -np.inf, 1, np.PZERO, np.inf

        # csqrt(inf + yi) is +inf + 0i for any finite y > 0
        yield check, f, np.inf, 1, np.inf, np.PZERO

        # csqrt(-inf + nani) is nan +- infi (both +i infi are valid)
        def _check_ninf_nan(dummy):
            z = np.sqrt(np.array(np.complex(-np.inf, np.nan)))
            if not np.isnan(z.real) or not np.isinf(z.imag):
                raise AssertionError(
                        "csqrt(-inf, nan) is (%f, %f), expected (nan, +-inf)" \
                        % (z.real, z.imag))

        yield _check_ninf_nan, None

        # csqrt(+inf + nani) is inf + nani
        yield check, f, np.inf, np.nan, np.inf, np.nan

        # csqrt(nan + yi) is nan + nani for any finite y (infinite handled in x
        # + nani)
        yield check, f, np.nan,       0, np.nan, np.nan
        yield check, f, np.nan,       1, np.nan, np.nan
        yield check, f, np.nan,  np.nan, np.nan, np.nan

        # XXX: check for conj(csqrt(z)) == csqrt(conj(z)) (need to fix branch
        # cuts first)

class TestCpow(TestCase):
    def test_simple(self):
        x = np.array([1+1j, 0+2j, 1+2j, np.inf, np.nan])
        y_r = x ** 2
        y = np.power(x, 2)
        for i in range(len(x)):
            assert_almost_equal(y[i], y_r[i])

    def test_scalar(self):
        x = np.array([1, 1j,         2,  2.5+.37j, np.inf, np.nan])
        y = np.array([1, 1j, -0.5+1.5j, -0.5+1.5j,      2,      3])
        lx = range(len(x))
        # Compute the values for complex type in python
        p_r = [complex(x[i]) ** complex(y[i]) for i in lx]
        # Substitute a result allowed by C99 standard
        p_r[4] = complex(np.inf, np.nan)
        # Do the same with numpy complex scalars
        n_r = [x[i] ** y[i] for i in lx]
        for i in lx:
            assert_almost_equal(n_r[i], p_r[i], err_msg='Loop %d\n' % i)

    def test_array(self):
        x = np.array([1, 1j,         2,  2.5+.37j, np.inf, np.nan])
        y = np.array([1, 1j, -0.5+1.5j, -0.5+1.5j,      2,      3])
        lx = range(len(x))
        # Compute the values for complex type in python
        p_r = [complex(x[i]) ** complex(y[i]) for i in lx]
        # Substitute a result allowed by C99 standard
        p_r[4] = complex(np.inf, np.nan)
        # Do the same with numpy arrays
        n_r = x ** y
        for i in lx:
            assert_almost_equal(n_r[i], p_r[i], err_msg='Loop %d\n' % i)

class TestCabs(object):
    def test_simple(self):
        x = np.array([1+1j, 0+2j, 1+2j, np.inf, np.nan])
        y_r = np.array([np.sqrt(2.), 2, np.sqrt(5), np.inf, np.nan])
        y = np.abs(x)
        for i in range(len(x)):
            assert_almost_equal(y[i], y_r[i])

    def test_fabs(self):
        # Test that np.abs(x +- 0j) == np.abs(x) (as mandated by C99 for cabs)
        x = np.array([1+0j], dtype=np.complex)
        assert_array_equal(np.abs(x), np.real(x))

        x = np.array([complex(1, np.NZERO)], dtype=np.complex)
        assert_array_equal(np.abs(x), np.real(x))

        x = np.array([complex(np.inf, np.NZERO)], dtype=np.complex)
        assert_array_equal(np.abs(x), np.real(x))

        x = np.array([complex(np.nan, np.NZERO)], dtype=np.complex)
        assert_array_equal(np.abs(x), np.real(x))

    def test_cabs_inf_nan(self):
        x, y = [], []

        # cabs(+-nan + nani) returns nan
        x.append(np.nan)
        y.append(np.nan)
        yield check_real_value, np.abs,  np.nan, np.nan, np.nan

        x.append(np.nan)
        y.append(-np.nan)
        yield check_real_value, np.abs, -np.nan, np.nan, np.nan

        # According to C99 standard, if exactly one of the real/part is inf and
        # the other nan, then cabs should return inf
        x.append(np.inf)
        y.append(np.nan)
        yield check_real_value, np.abs,  np.inf, np.nan, np.inf

        x.append(-np.inf)
        y.append(np.nan)
        yield check_real_value, np.abs, -np.inf, np.nan, np.inf

        # cabs(conj(z)) == conj(cabs(z)) (= cabs(z))
        def f(a):
            return np.abs(np.conj(a))
        def g(a, b):
            return np.abs(np.complex(a, b))

        xa = np.array(x, dtype=np.complex)
        ya = np.array(x, dtype=np.complex)
        for i in range(len(xa)):
            ref = g(x[i], y[i])
            yield check_real_value, f, x[i], y[i], ref

class TestCarg(object):
    def test_simple(self):
        check_real_value(ncu._arg, 1, 0, 0, False)
        check_real_value(ncu._arg, 0, 1, 0.5*np.pi, False)

        check_real_value(ncu._arg, 1, 1, 0.25*np.pi, False)
        check_real_value(ncu._arg, np.PZERO, np.PZERO, np.PZERO)

    @dec.knownfailureif(True,
        "Complex arithmetic with signed zero is buggy on most implementation")
    def test_zero(self):
        # carg(-0 +- 0i) returns +- pi
        yield check_real_value, ncu._arg, np.NZERO, np.PZERO,  np.pi, False
        yield check_real_value, ncu._arg, np.NZERO, np.NZERO, -np.pi, False

        # carg(+0 +- 0i) returns +- 0
        yield check_real_value, ncu._arg, np.PZERO, np.PZERO, np.PZERO
        yield check_real_value, ncu._arg, np.PZERO, np.NZERO, np.NZERO

        # carg(x +- 0i) returns +- 0 for x > 0
        yield check_real_value, ncu._arg, 1, np.PZERO, np.PZERO, False
        yield check_real_value, ncu._arg, 1, np.NZERO, np.NZERO, False

        # carg(x +- 0i) returns +- pi for x < 0
        yield check_real_value, ncu._arg, -1, np.PZERO,  np.pi, False
        yield check_real_value, ncu._arg, -1, np.NZERO, -np.pi, False

        # carg(+- 0 + yi) returns pi/2 for y > 0
        yield check_real_value, ncu._arg, np.PZERO, 1, 0.5 * np.pi, False
        yield check_real_value, ncu._arg, np.NZERO, 1, 0.5 * np.pi, False

        # carg(+- 0 + yi) returns -pi/2 for y < 0
        yield check_real_value, ncu._arg, np.PZERO, -1, 0.5 * np.pi, False
        yield check_real_value, ncu._arg, np.NZERO, -1,-0.5 * np.pi, False

    #def test_branch_cuts(self):
    #    _check_branch_cut(ncu._arg, -1, 1j, -1, 1)

    def test_special_values(self):
        # carg(-np.inf +- yi) returns +-pi for finite y > 0
        yield check_real_value, ncu._arg, -np.inf,  1,  np.pi, False
        yield check_real_value, ncu._arg, -np.inf, -1, -np.pi, False

        # carg(np.inf +- yi) returns +-0 for finite y > 0
        yield check_real_value, ncu._arg, np.inf,  1, np.PZERO, False
        yield check_real_value, ncu._arg, np.inf, -1, np.NZERO, False

        # carg(x +- np.infi) returns +-pi/2 for finite x
        yield check_real_value, ncu._arg, 1,  np.inf,  0.5 * np.pi, False
        yield check_real_value, ncu._arg, 1, -np.inf, -0.5 * np.pi, False

        # carg(-np.inf +- np.infi) returns +-3pi/4
        yield check_real_value, ncu._arg, -np.inf,  np.inf,  0.75 * np.pi, False
        yield check_real_value, ncu._arg, -np.inf, -np.inf, -0.75 * np.pi, False

        # carg(np.inf +- np.infi) returns +-pi/4
        yield check_real_value, ncu._arg, np.inf,  np.inf,  0.25 * np.pi, False
        yield check_real_value, ncu._arg, np.inf, -np.inf, -0.25 * np.pi, False

        # carg(x + yi) returns np.nan if x or y is nan
        yield check_real_value, ncu._arg, np.nan,      0, np.nan, False
        yield check_real_value, ncu._arg,      0, np.nan, np.nan, False

        yield check_real_value, ncu._arg, np.nan, np.inf, np.nan, False
        yield check_real_value, ncu._arg, np.inf, np.nan, np.nan, False

def check_real_value(f, x1, y1, x, exact=True):
    z1 = np.array([complex(x1, y1)])
    if exact:
        assert_equal(f(z1), x)
    else:
        assert_almost_equal(f(z1), x)

def check_complex_value(f, x1, y1, x2, y2, exact=True):
    z1 = np.array([complex(x1, y1)])
    z2 = np.complex(x2, y2)
    if exact:
        assert_equal(f(z1), z2)
    else:
        assert_almost_equal(f(z1), z2)

if __name__ == "__main__":
    run_module_suite()