1 | n/a | from test.support import requires_IEEE_754, cpython_only |
---|
2 | n/a | from test.test_math import parse_testfile, test_file |
---|
3 | n/a | import test.test_math as test_math |
---|
4 | n/a | import unittest |
---|
5 | n/a | import cmath, math |
---|
6 | n/a | from cmath import phase, polar, rect, pi |
---|
7 | n/a | import platform |
---|
8 | n/a | import sys |
---|
9 | n/a | import sysconfig |
---|
10 | n/a | |
---|
11 | n/a | INF = float('inf') |
---|
12 | n/a | NAN = float('nan') |
---|
13 | n/a | |
---|
14 | n/a | complex_zeros = [complex(x, y) for x in [0.0, -0.0] for y in [0.0, -0.0]] |
---|
15 | n/a | complex_infinities = [complex(x, y) for x, y in [ |
---|
16 | n/a | (INF, 0.0), # 1st quadrant |
---|
17 | n/a | (INF, 2.3), |
---|
18 | n/a | (INF, INF), |
---|
19 | n/a | (2.3, INF), |
---|
20 | n/a | (0.0, INF), |
---|
21 | n/a | (-0.0, INF), # 2nd quadrant |
---|
22 | n/a | (-2.3, INF), |
---|
23 | n/a | (-INF, INF), |
---|
24 | n/a | (-INF, 2.3), |
---|
25 | n/a | (-INF, 0.0), |
---|
26 | n/a | (-INF, -0.0), # 3rd quadrant |
---|
27 | n/a | (-INF, -2.3), |
---|
28 | n/a | (-INF, -INF), |
---|
29 | n/a | (-2.3, -INF), |
---|
30 | n/a | (-0.0, -INF), |
---|
31 | n/a | (0.0, -INF), # 4th quadrant |
---|
32 | n/a | (2.3, -INF), |
---|
33 | n/a | (INF, -INF), |
---|
34 | n/a | (INF, -2.3), |
---|
35 | n/a | (INF, -0.0) |
---|
36 | n/a | ]] |
---|
37 | n/a | complex_nans = [complex(x, y) for x, y in [ |
---|
38 | n/a | (NAN, -INF), |
---|
39 | n/a | (NAN, -2.3), |
---|
40 | n/a | (NAN, -0.0), |
---|
41 | n/a | (NAN, 0.0), |
---|
42 | n/a | (NAN, 2.3), |
---|
43 | n/a | (NAN, INF), |
---|
44 | n/a | (-INF, NAN), |
---|
45 | n/a | (-2.3, NAN), |
---|
46 | n/a | (-0.0, NAN), |
---|
47 | n/a | (0.0, NAN), |
---|
48 | n/a | (2.3, NAN), |
---|
49 | n/a | (INF, NAN) |
---|
50 | n/a | ]] |
---|
51 | n/a | |
---|
52 | n/a | class CMathTests(unittest.TestCase): |
---|
53 | n/a | # list of all functions in cmath |
---|
54 | n/a | test_functions = [getattr(cmath, fname) for fname in [ |
---|
55 | n/a | 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atanh', |
---|
56 | n/a | 'cos', 'cosh', 'exp', 'log', 'log10', 'sin', 'sinh', |
---|
57 | n/a | 'sqrt', 'tan', 'tanh']] |
---|
58 | n/a | # test first and second arguments independently for 2-argument log |
---|
59 | n/a | test_functions.append(lambda x : cmath.log(x, 1729. + 0j)) |
---|
60 | n/a | test_functions.append(lambda x : cmath.log(14.-27j, x)) |
---|
61 | n/a | |
---|
62 | n/a | def setUp(self): |
---|
63 | n/a | self.test_values = open(test_file) |
---|
64 | n/a | |
---|
65 | n/a | def tearDown(self): |
---|
66 | n/a | self.test_values.close() |
---|
67 | n/a | |
---|
68 | n/a | def assertFloatIdentical(self, x, y): |
---|
69 | n/a | """Fail unless floats x and y are identical, in the sense that: |
---|
70 | n/a | (1) both x and y are nans, or |
---|
71 | n/a | (2) both x and y are infinities, with the same sign, or |
---|
72 | n/a | (3) both x and y are zeros, with the same sign, or |
---|
73 | n/a | (4) x and y are both finite and nonzero, and x == y |
---|
74 | n/a | |
---|
75 | n/a | """ |
---|
76 | n/a | msg = 'floats {!r} and {!r} are not identical' |
---|
77 | n/a | |
---|
78 | n/a | if math.isnan(x) or math.isnan(y): |
---|
79 | n/a | if math.isnan(x) and math.isnan(y): |
---|
80 | n/a | return |
---|
81 | n/a | elif x == y: |
---|
82 | n/a | if x != 0.0: |
---|
83 | n/a | return |
---|
84 | n/a | # both zero; check that signs match |
---|
85 | n/a | elif math.copysign(1.0, x) == math.copysign(1.0, y): |
---|
86 | n/a | return |
---|
87 | n/a | else: |
---|
88 | n/a | msg += ': zeros have different signs' |
---|
89 | n/a | self.fail(msg.format(x, y)) |
---|
90 | n/a | |
---|
91 | n/a | def assertComplexIdentical(self, x, y): |
---|
92 | n/a | """Fail unless complex numbers x and y have equal values and signs. |
---|
93 | n/a | |
---|
94 | n/a | In particular, if x and y both have real (or imaginary) part |
---|
95 | n/a | zero, but the zeros have different signs, this test will fail. |
---|
96 | n/a | |
---|
97 | n/a | """ |
---|
98 | n/a | self.assertFloatIdentical(x.real, y.real) |
---|
99 | n/a | self.assertFloatIdentical(x.imag, y.imag) |
---|
100 | n/a | |
---|
101 | n/a | def rAssertAlmostEqual(self, a, b, rel_err = 2e-15, abs_err = 5e-323, |
---|
102 | n/a | msg=None): |
---|
103 | n/a | """Fail if the two floating-point numbers are not almost equal. |
---|
104 | n/a | |
---|
105 | n/a | Determine whether floating-point values a and b are equal to within |
---|
106 | n/a | a (small) rounding error. The default values for rel_err and |
---|
107 | n/a | abs_err are chosen to be suitable for platforms where a float is |
---|
108 | n/a | represented by an IEEE 754 double. They allow an error of between |
---|
109 | n/a | 9 and 19 ulps. |
---|
110 | n/a | """ |
---|
111 | n/a | |
---|
112 | n/a | # special values testing |
---|
113 | n/a | if math.isnan(a): |
---|
114 | n/a | if math.isnan(b): |
---|
115 | n/a | return |
---|
116 | n/a | self.fail(msg or '{!r} should be nan'.format(b)) |
---|
117 | n/a | |
---|
118 | n/a | if math.isinf(a): |
---|
119 | n/a | if a == b: |
---|
120 | n/a | return |
---|
121 | n/a | self.fail(msg or 'finite result where infinity expected: ' |
---|
122 | n/a | 'expected {!r}, got {!r}'.format(a, b)) |
---|
123 | n/a | |
---|
124 | n/a | # if both a and b are zero, check whether they have the same sign |
---|
125 | n/a | # (in theory there are examples where it would be legitimate for a |
---|
126 | n/a | # and b to have opposite signs; in practice these hardly ever |
---|
127 | n/a | # occur). |
---|
128 | n/a | if not a and not b: |
---|
129 | n/a | if math.copysign(1., a) != math.copysign(1., b): |
---|
130 | n/a | self.fail(msg or 'zero has wrong sign: expected {!r}, ' |
---|
131 | n/a | 'got {!r}'.format(a, b)) |
---|
132 | n/a | |
---|
133 | n/a | # if a-b overflows, or b is infinite, return False. Again, in |
---|
134 | n/a | # theory there are examples where a is within a few ulps of the |
---|
135 | n/a | # max representable float, and then b could legitimately be |
---|
136 | n/a | # infinite. In practice these examples are rare. |
---|
137 | n/a | try: |
---|
138 | n/a | absolute_error = abs(b-a) |
---|
139 | n/a | except OverflowError: |
---|
140 | n/a | pass |
---|
141 | n/a | else: |
---|
142 | n/a | # test passes if either the absolute error or the relative |
---|
143 | n/a | # error is sufficiently small. The defaults amount to an |
---|
144 | n/a | # error of between 9 ulps and 19 ulps on an IEEE-754 compliant |
---|
145 | n/a | # machine. |
---|
146 | n/a | if absolute_error <= max(abs_err, rel_err * abs(a)): |
---|
147 | n/a | return |
---|
148 | n/a | self.fail(msg or |
---|
149 | n/a | '{!r} and {!r} are not sufficiently close'.format(a, b)) |
---|
150 | n/a | |
---|
151 | n/a | def test_constants(self): |
---|
152 | n/a | e_expected = 2.71828182845904523536 |
---|
153 | n/a | pi_expected = 3.14159265358979323846 |
---|
154 | n/a | self.assertAlmostEqual(cmath.pi, pi_expected, places=9, |
---|
155 | n/a | msg="cmath.pi is {}; should be {}".format(cmath.pi, pi_expected)) |
---|
156 | n/a | self.assertAlmostEqual(cmath.e, e_expected, places=9, |
---|
157 | n/a | msg="cmath.e is {}; should be {}".format(cmath.e, e_expected)) |
---|
158 | n/a | |
---|
159 | n/a | def test_infinity_and_nan_constants(self): |
---|
160 | n/a | self.assertEqual(cmath.inf.real, math.inf) |
---|
161 | n/a | self.assertEqual(cmath.inf.imag, 0.0) |
---|
162 | n/a | self.assertEqual(cmath.infj.real, 0.0) |
---|
163 | n/a | self.assertEqual(cmath.infj.imag, math.inf) |
---|
164 | n/a | |
---|
165 | n/a | self.assertTrue(math.isnan(cmath.nan.real)) |
---|
166 | n/a | self.assertEqual(cmath.nan.imag, 0.0) |
---|
167 | n/a | self.assertEqual(cmath.nanj.real, 0.0) |
---|
168 | n/a | self.assertTrue(math.isnan(cmath.nanj.imag)) |
---|
169 | n/a | |
---|
170 | n/a | # Check consistency with reprs. |
---|
171 | n/a | self.assertEqual(repr(cmath.inf), "inf") |
---|
172 | n/a | self.assertEqual(repr(cmath.infj), "infj") |
---|
173 | n/a | self.assertEqual(repr(cmath.nan), "nan") |
---|
174 | n/a | self.assertEqual(repr(cmath.nanj), "nanj") |
---|
175 | n/a | |
---|
176 | n/a | def test_user_object(self): |
---|
177 | n/a | # Test automatic calling of __complex__ and __float__ by cmath |
---|
178 | n/a | # functions |
---|
179 | n/a | |
---|
180 | n/a | # some random values to use as test values; we avoid values |
---|
181 | n/a | # for which any of the functions in cmath is undefined |
---|
182 | n/a | # (i.e. 0., 1., -1., 1j, -1j) or would cause overflow |
---|
183 | n/a | cx_arg = 4.419414439 + 1.497100113j |
---|
184 | n/a | flt_arg = -6.131677725 |
---|
185 | n/a | |
---|
186 | n/a | # a variety of non-complex numbers, used to check that |
---|
187 | n/a | # non-complex return values from __complex__ give an error |
---|
188 | n/a | non_complexes = ["not complex", 1, 5, 2., None, |
---|
189 | n/a | object(), NotImplemented] |
---|
190 | n/a | |
---|
191 | n/a | # Now we introduce a variety of classes whose instances might |
---|
192 | n/a | # end up being passed to the cmath functions |
---|
193 | n/a | |
---|
194 | n/a | # usual case: new-style class implementing __complex__ |
---|
195 | n/a | class MyComplex(object): |
---|
196 | n/a | def __init__(self, value): |
---|
197 | n/a | self.value = value |
---|
198 | n/a | def __complex__(self): |
---|
199 | n/a | return self.value |
---|
200 | n/a | |
---|
201 | n/a | # old-style class implementing __complex__ |
---|
202 | n/a | class MyComplexOS: |
---|
203 | n/a | def __init__(self, value): |
---|
204 | n/a | self.value = value |
---|
205 | n/a | def __complex__(self): |
---|
206 | n/a | return self.value |
---|
207 | n/a | |
---|
208 | n/a | # classes for which __complex__ raises an exception |
---|
209 | n/a | class SomeException(Exception): |
---|
210 | n/a | pass |
---|
211 | n/a | class MyComplexException(object): |
---|
212 | n/a | def __complex__(self): |
---|
213 | n/a | raise SomeException |
---|
214 | n/a | class MyComplexExceptionOS: |
---|
215 | n/a | def __complex__(self): |
---|
216 | n/a | raise SomeException |
---|
217 | n/a | |
---|
218 | n/a | # some classes not providing __float__ or __complex__ |
---|
219 | n/a | class NeitherComplexNorFloat(object): |
---|
220 | n/a | pass |
---|
221 | n/a | class NeitherComplexNorFloatOS: |
---|
222 | n/a | pass |
---|
223 | n/a | class MyInt(object): |
---|
224 | n/a | def __int__(self): return 2 |
---|
225 | n/a | def __index__(self): return 2 |
---|
226 | n/a | class MyIntOS: |
---|
227 | n/a | def __int__(self): return 2 |
---|
228 | n/a | def __index__(self): return 2 |
---|
229 | n/a | |
---|
230 | n/a | # other possible combinations of __float__ and __complex__ |
---|
231 | n/a | # that should work |
---|
232 | n/a | class FloatAndComplex(object): |
---|
233 | n/a | def __float__(self): |
---|
234 | n/a | return flt_arg |
---|
235 | n/a | def __complex__(self): |
---|
236 | n/a | return cx_arg |
---|
237 | n/a | class FloatAndComplexOS: |
---|
238 | n/a | def __float__(self): |
---|
239 | n/a | return flt_arg |
---|
240 | n/a | def __complex__(self): |
---|
241 | n/a | return cx_arg |
---|
242 | n/a | class JustFloat(object): |
---|
243 | n/a | def __float__(self): |
---|
244 | n/a | return flt_arg |
---|
245 | n/a | class JustFloatOS: |
---|
246 | n/a | def __float__(self): |
---|
247 | n/a | return flt_arg |
---|
248 | n/a | |
---|
249 | n/a | for f in self.test_functions: |
---|
250 | n/a | # usual usage |
---|
251 | n/a | self.assertEqual(f(MyComplex(cx_arg)), f(cx_arg)) |
---|
252 | n/a | self.assertEqual(f(MyComplexOS(cx_arg)), f(cx_arg)) |
---|
253 | n/a | # other combinations of __float__ and __complex__ |
---|
254 | n/a | self.assertEqual(f(FloatAndComplex()), f(cx_arg)) |
---|
255 | n/a | self.assertEqual(f(FloatAndComplexOS()), f(cx_arg)) |
---|
256 | n/a | self.assertEqual(f(JustFloat()), f(flt_arg)) |
---|
257 | n/a | self.assertEqual(f(JustFloatOS()), f(flt_arg)) |
---|
258 | n/a | # TypeError should be raised for classes not providing |
---|
259 | n/a | # either __complex__ or __float__, even if they provide |
---|
260 | n/a | # __int__ or __index__. An old-style class |
---|
261 | n/a | # currently raises AttributeError instead of a TypeError; |
---|
262 | n/a | # this could be considered a bug. |
---|
263 | n/a | self.assertRaises(TypeError, f, NeitherComplexNorFloat()) |
---|
264 | n/a | self.assertRaises(TypeError, f, MyInt()) |
---|
265 | n/a | self.assertRaises(Exception, f, NeitherComplexNorFloatOS()) |
---|
266 | n/a | self.assertRaises(Exception, f, MyIntOS()) |
---|
267 | n/a | # non-complex return value from __complex__ -> TypeError |
---|
268 | n/a | for bad_complex in non_complexes: |
---|
269 | n/a | self.assertRaises(TypeError, f, MyComplex(bad_complex)) |
---|
270 | n/a | self.assertRaises(TypeError, f, MyComplexOS(bad_complex)) |
---|
271 | n/a | # exceptions in __complex__ should be propagated correctly |
---|
272 | n/a | self.assertRaises(SomeException, f, MyComplexException()) |
---|
273 | n/a | self.assertRaises(SomeException, f, MyComplexExceptionOS()) |
---|
274 | n/a | |
---|
275 | n/a | def test_input_type(self): |
---|
276 | n/a | # ints should be acceptable inputs to all cmath |
---|
277 | n/a | # functions, by virtue of providing a __float__ method |
---|
278 | n/a | for f in self.test_functions: |
---|
279 | n/a | for arg in [2, 2.]: |
---|
280 | n/a | self.assertEqual(f(arg), f(arg.__float__())) |
---|
281 | n/a | |
---|
282 | n/a | # but strings should give a TypeError |
---|
283 | n/a | for f in self.test_functions: |
---|
284 | n/a | for arg in ["a", "long_string", "0", "1j", ""]: |
---|
285 | n/a | self.assertRaises(TypeError, f, arg) |
---|
286 | n/a | |
---|
287 | n/a | def test_cmath_matches_math(self): |
---|
288 | n/a | # check that corresponding cmath and math functions are equal |
---|
289 | n/a | # for floats in the appropriate range |
---|
290 | n/a | |
---|
291 | n/a | # test_values in (0, 1) |
---|
292 | n/a | test_values = [0.01, 0.1, 0.2, 0.5, 0.9, 0.99] |
---|
293 | n/a | |
---|
294 | n/a | # test_values for functions defined on [-1., 1.] |
---|
295 | n/a | unit_interval = test_values + [-x for x in test_values] + \ |
---|
296 | n/a | [0., 1., -1.] |
---|
297 | n/a | |
---|
298 | n/a | # test_values for log, log10, sqrt |
---|
299 | n/a | positive = test_values + [1.] + [1./x for x in test_values] |
---|
300 | n/a | nonnegative = [0.] + positive |
---|
301 | n/a | |
---|
302 | n/a | # test_values for functions defined on the whole real line |
---|
303 | n/a | real_line = [0.] + positive + [-x for x in positive] |
---|
304 | n/a | |
---|
305 | n/a | test_functions = { |
---|
306 | n/a | 'acos' : unit_interval, |
---|
307 | n/a | 'asin' : unit_interval, |
---|
308 | n/a | 'atan' : real_line, |
---|
309 | n/a | 'cos' : real_line, |
---|
310 | n/a | 'cosh' : real_line, |
---|
311 | n/a | 'exp' : real_line, |
---|
312 | n/a | 'log' : positive, |
---|
313 | n/a | 'log10' : positive, |
---|
314 | n/a | 'sin' : real_line, |
---|
315 | n/a | 'sinh' : real_line, |
---|
316 | n/a | 'sqrt' : nonnegative, |
---|
317 | n/a | 'tan' : real_line, |
---|
318 | n/a | 'tanh' : real_line} |
---|
319 | n/a | |
---|
320 | n/a | for fn, values in test_functions.items(): |
---|
321 | n/a | float_fn = getattr(math, fn) |
---|
322 | n/a | complex_fn = getattr(cmath, fn) |
---|
323 | n/a | for v in values: |
---|
324 | n/a | z = complex_fn(v) |
---|
325 | n/a | self.rAssertAlmostEqual(float_fn(v), z.real) |
---|
326 | n/a | self.assertEqual(0., z.imag) |
---|
327 | n/a | |
---|
328 | n/a | # test two-argument version of log with various bases |
---|
329 | n/a | for base in [0.5, 2., 10.]: |
---|
330 | n/a | for v in positive: |
---|
331 | n/a | z = cmath.log(v, base) |
---|
332 | n/a | self.rAssertAlmostEqual(math.log(v, base), z.real) |
---|
333 | n/a | self.assertEqual(0., z.imag) |
---|
334 | n/a | |
---|
335 | n/a | @requires_IEEE_754 |
---|
336 | n/a | def test_specific_values(self): |
---|
337 | n/a | # Some tests need to be skipped on ancient OS X versions. |
---|
338 | n/a | # See issue #27953. |
---|
339 | n/a | SKIP_ON_TIGER = {'tan0064'} |
---|
340 | n/a | |
---|
341 | n/a | osx_version = None |
---|
342 | n/a | if sys.platform == 'darwin': |
---|
343 | n/a | version_txt = platform.mac_ver()[0] |
---|
344 | n/a | try: |
---|
345 | n/a | osx_version = tuple(map(int, version_txt.split('.'))) |
---|
346 | n/a | except ValueError: |
---|
347 | n/a | pass |
---|
348 | n/a | |
---|
349 | n/a | def rect_complex(z): |
---|
350 | n/a | """Wrapped version of rect that accepts a complex number instead of |
---|
351 | n/a | two float arguments.""" |
---|
352 | n/a | return cmath.rect(z.real, z.imag) |
---|
353 | n/a | |
---|
354 | n/a | def polar_complex(z): |
---|
355 | n/a | """Wrapped version of polar that returns a complex number instead of |
---|
356 | n/a | two floats.""" |
---|
357 | n/a | return complex(*polar(z)) |
---|
358 | n/a | |
---|
359 | n/a | for id, fn, ar, ai, er, ei, flags in parse_testfile(test_file): |
---|
360 | n/a | arg = complex(ar, ai) |
---|
361 | n/a | expected = complex(er, ei) |
---|
362 | n/a | |
---|
363 | n/a | # Skip certain tests on OS X 10.4. |
---|
364 | n/a | if osx_version is not None and osx_version < (10, 5): |
---|
365 | n/a | if id in SKIP_ON_TIGER: |
---|
366 | n/a | continue |
---|
367 | n/a | |
---|
368 | n/a | if fn == 'rect': |
---|
369 | n/a | function = rect_complex |
---|
370 | n/a | elif fn == 'polar': |
---|
371 | n/a | function = polar_complex |
---|
372 | n/a | else: |
---|
373 | n/a | function = getattr(cmath, fn) |
---|
374 | n/a | if 'divide-by-zero' in flags or 'invalid' in flags: |
---|
375 | n/a | try: |
---|
376 | n/a | actual = function(arg) |
---|
377 | n/a | except ValueError: |
---|
378 | n/a | continue |
---|
379 | n/a | else: |
---|
380 | n/a | self.fail('ValueError not raised in test ' |
---|
381 | n/a | '{}: {}(complex({!r}, {!r}))'.format(id, fn, ar, ai)) |
---|
382 | n/a | |
---|
383 | n/a | if 'overflow' in flags: |
---|
384 | n/a | try: |
---|
385 | n/a | actual = function(arg) |
---|
386 | n/a | except OverflowError: |
---|
387 | n/a | continue |
---|
388 | n/a | else: |
---|
389 | n/a | self.fail('OverflowError not raised in test ' |
---|
390 | n/a | '{}: {}(complex({!r}, {!r}))'.format(id, fn, ar, ai)) |
---|
391 | n/a | |
---|
392 | n/a | actual = function(arg) |
---|
393 | n/a | |
---|
394 | n/a | if 'ignore-real-sign' in flags: |
---|
395 | n/a | actual = complex(abs(actual.real), actual.imag) |
---|
396 | n/a | expected = complex(abs(expected.real), expected.imag) |
---|
397 | n/a | if 'ignore-imag-sign' in flags: |
---|
398 | n/a | actual = complex(actual.real, abs(actual.imag)) |
---|
399 | n/a | expected = complex(expected.real, abs(expected.imag)) |
---|
400 | n/a | |
---|
401 | n/a | # for the real part of the log function, we allow an |
---|
402 | n/a | # absolute error of up to 2e-15. |
---|
403 | n/a | if fn in ('log', 'log10'): |
---|
404 | n/a | real_abs_err = 2e-15 |
---|
405 | n/a | else: |
---|
406 | n/a | real_abs_err = 5e-323 |
---|
407 | n/a | |
---|
408 | n/a | error_message = ( |
---|
409 | n/a | '{}: {}(complex({!r}, {!r}))\n' |
---|
410 | n/a | 'Expected: complex({!r}, {!r})\n' |
---|
411 | n/a | 'Received: complex({!r}, {!r})\n' |
---|
412 | n/a | 'Received value insufficiently close to expected value.' |
---|
413 | n/a | ).format(id, fn, ar, ai, |
---|
414 | n/a | expected.real, expected.imag, |
---|
415 | n/a | actual.real, actual.imag) |
---|
416 | n/a | self.rAssertAlmostEqual(expected.real, actual.real, |
---|
417 | n/a | abs_err=real_abs_err, |
---|
418 | n/a | msg=error_message) |
---|
419 | n/a | self.rAssertAlmostEqual(expected.imag, actual.imag, |
---|
420 | n/a | msg=error_message) |
---|
421 | n/a | |
---|
422 | n/a | def check_polar(self, func): |
---|
423 | n/a | def check(arg, expected): |
---|
424 | n/a | got = func(arg) |
---|
425 | n/a | for e, g in zip(expected, got): |
---|
426 | n/a | self.rAssertAlmostEqual(e, g) |
---|
427 | n/a | check(0, (0., 0.)) |
---|
428 | n/a | check(1, (1., 0.)) |
---|
429 | n/a | check(-1, (1., pi)) |
---|
430 | n/a | check(1j, (1., pi / 2)) |
---|
431 | n/a | check(-3j, (3., -pi / 2)) |
---|
432 | n/a | inf = float('inf') |
---|
433 | n/a | check(complex(inf, 0), (inf, 0.)) |
---|
434 | n/a | check(complex(-inf, 0), (inf, pi)) |
---|
435 | n/a | check(complex(3, inf), (inf, pi / 2)) |
---|
436 | n/a | check(complex(5, -inf), (inf, -pi / 2)) |
---|
437 | n/a | check(complex(inf, inf), (inf, pi / 4)) |
---|
438 | n/a | check(complex(inf, -inf), (inf, -pi / 4)) |
---|
439 | n/a | check(complex(-inf, inf), (inf, 3 * pi / 4)) |
---|
440 | n/a | check(complex(-inf, -inf), (inf, -3 * pi / 4)) |
---|
441 | n/a | nan = float('nan') |
---|
442 | n/a | check(complex(nan, 0), (nan, nan)) |
---|
443 | n/a | check(complex(0, nan), (nan, nan)) |
---|
444 | n/a | check(complex(nan, nan), (nan, nan)) |
---|
445 | n/a | check(complex(inf, nan), (inf, nan)) |
---|
446 | n/a | check(complex(-inf, nan), (inf, nan)) |
---|
447 | n/a | check(complex(nan, inf), (inf, nan)) |
---|
448 | n/a | check(complex(nan, -inf), (inf, nan)) |
---|
449 | n/a | |
---|
450 | n/a | def test_polar(self): |
---|
451 | n/a | self.check_polar(polar) |
---|
452 | n/a | |
---|
453 | n/a | @cpython_only |
---|
454 | n/a | def test_polar_errno(self): |
---|
455 | n/a | # Issue #24489: check a previously set C errno doesn't disturb polar() |
---|
456 | n/a | from _testcapi import set_errno |
---|
457 | n/a | def polar_with_errno_set(z): |
---|
458 | n/a | set_errno(11) |
---|
459 | n/a | try: |
---|
460 | n/a | return polar(z) |
---|
461 | n/a | finally: |
---|
462 | n/a | set_errno(0) |
---|
463 | n/a | self.check_polar(polar_with_errno_set) |
---|
464 | n/a | |
---|
465 | n/a | def test_phase(self): |
---|
466 | n/a | self.assertAlmostEqual(phase(0), 0.) |
---|
467 | n/a | self.assertAlmostEqual(phase(1.), 0.) |
---|
468 | n/a | self.assertAlmostEqual(phase(-1.), pi) |
---|
469 | n/a | self.assertAlmostEqual(phase(-1.+1E-300j), pi) |
---|
470 | n/a | self.assertAlmostEqual(phase(-1.-1E-300j), -pi) |
---|
471 | n/a | self.assertAlmostEqual(phase(1j), pi/2) |
---|
472 | n/a | self.assertAlmostEqual(phase(-1j), -pi/2) |
---|
473 | n/a | |
---|
474 | n/a | # zeros |
---|
475 | n/a | self.assertEqual(phase(complex(0.0, 0.0)), 0.0) |
---|
476 | n/a | self.assertEqual(phase(complex(0.0, -0.0)), -0.0) |
---|
477 | n/a | self.assertEqual(phase(complex(-0.0, 0.0)), pi) |
---|
478 | n/a | self.assertEqual(phase(complex(-0.0, -0.0)), -pi) |
---|
479 | n/a | |
---|
480 | n/a | # infinities |
---|
481 | n/a | self.assertAlmostEqual(phase(complex(-INF, -0.0)), -pi) |
---|
482 | n/a | self.assertAlmostEqual(phase(complex(-INF, -2.3)), -pi) |
---|
483 | n/a | self.assertAlmostEqual(phase(complex(-INF, -INF)), -0.75*pi) |
---|
484 | n/a | self.assertAlmostEqual(phase(complex(-2.3, -INF)), -pi/2) |
---|
485 | n/a | self.assertAlmostEqual(phase(complex(-0.0, -INF)), -pi/2) |
---|
486 | n/a | self.assertAlmostEqual(phase(complex(0.0, -INF)), -pi/2) |
---|
487 | n/a | self.assertAlmostEqual(phase(complex(2.3, -INF)), -pi/2) |
---|
488 | n/a | self.assertAlmostEqual(phase(complex(INF, -INF)), -pi/4) |
---|
489 | n/a | self.assertEqual(phase(complex(INF, -2.3)), -0.0) |
---|
490 | n/a | self.assertEqual(phase(complex(INF, -0.0)), -0.0) |
---|
491 | n/a | self.assertEqual(phase(complex(INF, 0.0)), 0.0) |
---|
492 | n/a | self.assertEqual(phase(complex(INF, 2.3)), 0.0) |
---|
493 | n/a | self.assertAlmostEqual(phase(complex(INF, INF)), pi/4) |
---|
494 | n/a | self.assertAlmostEqual(phase(complex(2.3, INF)), pi/2) |
---|
495 | n/a | self.assertAlmostEqual(phase(complex(0.0, INF)), pi/2) |
---|
496 | n/a | self.assertAlmostEqual(phase(complex(-0.0, INF)), pi/2) |
---|
497 | n/a | self.assertAlmostEqual(phase(complex(-2.3, INF)), pi/2) |
---|
498 | n/a | self.assertAlmostEqual(phase(complex(-INF, INF)), 0.75*pi) |
---|
499 | n/a | self.assertAlmostEqual(phase(complex(-INF, 2.3)), pi) |
---|
500 | n/a | self.assertAlmostEqual(phase(complex(-INF, 0.0)), pi) |
---|
501 | n/a | |
---|
502 | n/a | # real or imaginary part NaN |
---|
503 | n/a | for z in complex_nans: |
---|
504 | n/a | self.assertTrue(math.isnan(phase(z))) |
---|
505 | n/a | |
---|
506 | n/a | def test_abs(self): |
---|
507 | n/a | # zeros |
---|
508 | n/a | for z in complex_zeros: |
---|
509 | n/a | self.assertEqual(abs(z), 0.0) |
---|
510 | n/a | |
---|
511 | n/a | # infinities |
---|
512 | n/a | for z in complex_infinities: |
---|
513 | n/a | self.assertEqual(abs(z), INF) |
---|
514 | n/a | |
---|
515 | n/a | # real or imaginary part NaN |
---|
516 | n/a | self.assertEqual(abs(complex(NAN, -INF)), INF) |
---|
517 | n/a | self.assertTrue(math.isnan(abs(complex(NAN, -2.3)))) |
---|
518 | n/a | self.assertTrue(math.isnan(abs(complex(NAN, -0.0)))) |
---|
519 | n/a | self.assertTrue(math.isnan(abs(complex(NAN, 0.0)))) |
---|
520 | n/a | self.assertTrue(math.isnan(abs(complex(NAN, 2.3)))) |
---|
521 | n/a | self.assertEqual(abs(complex(NAN, INF)), INF) |
---|
522 | n/a | self.assertEqual(abs(complex(-INF, NAN)), INF) |
---|
523 | n/a | self.assertTrue(math.isnan(abs(complex(-2.3, NAN)))) |
---|
524 | n/a | self.assertTrue(math.isnan(abs(complex(-0.0, NAN)))) |
---|
525 | n/a | self.assertTrue(math.isnan(abs(complex(0.0, NAN)))) |
---|
526 | n/a | self.assertTrue(math.isnan(abs(complex(2.3, NAN)))) |
---|
527 | n/a | self.assertEqual(abs(complex(INF, NAN)), INF) |
---|
528 | n/a | self.assertTrue(math.isnan(abs(complex(NAN, NAN)))) |
---|
529 | n/a | |
---|
530 | n/a | |
---|
531 | n/a | @requires_IEEE_754 |
---|
532 | n/a | def test_abs_overflows(self): |
---|
533 | n/a | # result overflows |
---|
534 | n/a | self.assertRaises(OverflowError, abs, complex(1.4e308, 1.4e308)) |
---|
535 | n/a | |
---|
536 | n/a | def assertCEqual(self, a, b): |
---|
537 | n/a | eps = 1E-7 |
---|
538 | n/a | if abs(a.real - b[0]) > eps or abs(a.imag - b[1]) > eps: |
---|
539 | n/a | self.fail((a ,b)) |
---|
540 | n/a | |
---|
541 | n/a | def test_rect(self): |
---|
542 | n/a | self.assertCEqual(rect(0, 0), (0, 0)) |
---|
543 | n/a | self.assertCEqual(rect(1, 0), (1., 0)) |
---|
544 | n/a | self.assertCEqual(rect(1, -pi), (-1., 0)) |
---|
545 | n/a | self.assertCEqual(rect(1, pi/2), (0, 1.)) |
---|
546 | n/a | self.assertCEqual(rect(1, -pi/2), (0, -1.)) |
---|
547 | n/a | |
---|
548 | n/a | def test_isfinite(self): |
---|
549 | n/a | real_vals = [float('-inf'), -2.3, -0.0, |
---|
550 | n/a | 0.0, 2.3, float('inf'), float('nan')] |
---|
551 | n/a | for x in real_vals: |
---|
552 | n/a | for y in real_vals: |
---|
553 | n/a | z = complex(x, y) |
---|
554 | n/a | self.assertEqual(cmath.isfinite(z), |
---|
555 | n/a | math.isfinite(x) and math.isfinite(y)) |
---|
556 | n/a | |
---|
557 | n/a | def test_isnan(self): |
---|
558 | n/a | self.assertFalse(cmath.isnan(1)) |
---|
559 | n/a | self.assertFalse(cmath.isnan(1j)) |
---|
560 | n/a | self.assertFalse(cmath.isnan(INF)) |
---|
561 | n/a | self.assertTrue(cmath.isnan(NAN)) |
---|
562 | n/a | self.assertTrue(cmath.isnan(complex(NAN, 0))) |
---|
563 | n/a | self.assertTrue(cmath.isnan(complex(0, NAN))) |
---|
564 | n/a | self.assertTrue(cmath.isnan(complex(NAN, NAN))) |
---|
565 | n/a | self.assertTrue(cmath.isnan(complex(NAN, INF))) |
---|
566 | n/a | self.assertTrue(cmath.isnan(complex(INF, NAN))) |
---|
567 | n/a | |
---|
568 | n/a | def test_isinf(self): |
---|
569 | n/a | self.assertFalse(cmath.isinf(1)) |
---|
570 | n/a | self.assertFalse(cmath.isinf(1j)) |
---|
571 | n/a | self.assertFalse(cmath.isinf(NAN)) |
---|
572 | n/a | self.assertTrue(cmath.isinf(INF)) |
---|
573 | n/a | self.assertTrue(cmath.isinf(complex(INF, 0))) |
---|
574 | n/a | self.assertTrue(cmath.isinf(complex(0, INF))) |
---|
575 | n/a | self.assertTrue(cmath.isinf(complex(INF, INF))) |
---|
576 | n/a | self.assertTrue(cmath.isinf(complex(NAN, INF))) |
---|
577 | n/a | self.assertTrue(cmath.isinf(complex(INF, NAN))) |
---|
578 | n/a | |
---|
579 | n/a | @requires_IEEE_754 |
---|
580 | n/a | @unittest.skipIf(sysconfig.get_config_var('TANH_PRESERVES_ZERO_SIGN') == 0, |
---|
581 | n/a | "system tanh() function doesn't copy the sign") |
---|
582 | n/a | def testTanhSign(self): |
---|
583 | n/a | for z in complex_zeros: |
---|
584 | n/a | self.assertComplexIdentical(cmath.tanh(z), z) |
---|
585 | n/a | |
---|
586 | n/a | # The algorithm used for atan and atanh makes use of the system |
---|
587 | n/a | # log1p function; If that system function doesn't respect the sign |
---|
588 | n/a | # of zero, then atan and atanh will also have difficulties with |
---|
589 | n/a | # the sign of complex zeros. |
---|
590 | n/a | @requires_IEEE_754 |
---|
591 | n/a | def testAtanSign(self): |
---|
592 | n/a | for z in complex_zeros: |
---|
593 | n/a | self.assertComplexIdentical(cmath.atan(z), z) |
---|
594 | n/a | |
---|
595 | n/a | @requires_IEEE_754 |
---|
596 | n/a | def testAtanhSign(self): |
---|
597 | n/a | for z in complex_zeros: |
---|
598 | n/a | self.assertComplexIdentical(cmath.atanh(z), z) |
---|
599 | n/a | |
---|
600 | n/a | |
---|
601 | n/a | class IsCloseTests(test_math.IsCloseTests): |
---|
602 | n/a | isclose = cmath.isclose |
---|
603 | n/a | |
---|
604 | n/a | def test_reject_complex_tolerances(self): |
---|
605 | n/a | with self.assertRaises(TypeError): |
---|
606 | n/a | self.isclose(1j, 1j, rel_tol=1j) |
---|
607 | n/a | |
---|
608 | n/a | with self.assertRaises(TypeError): |
---|
609 | n/a | self.isclose(1j, 1j, abs_tol=1j) |
---|
610 | n/a | |
---|
611 | n/a | with self.assertRaises(TypeError): |
---|
612 | n/a | self.isclose(1j, 1j, rel_tol=1j, abs_tol=1j) |
---|
613 | n/a | |
---|
614 | n/a | def test_complex_values(self): |
---|
615 | n/a | # test complex values that are close to within 12 decimal places |
---|
616 | n/a | complex_examples = [(1.0+1.0j, 1.000000000001+1.0j), |
---|
617 | n/a | (1.0+1.0j, 1.0+1.000000000001j), |
---|
618 | n/a | (-1.0+1.0j, -1.000000000001+1.0j), |
---|
619 | n/a | (1.0-1.0j, 1.0-0.999999999999j), |
---|
620 | n/a | ] |
---|
621 | n/a | |
---|
622 | n/a | self.assertAllClose(complex_examples, rel_tol=1e-12) |
---|
623 | n/a | self.assertAllNotClose(complex_examples, rel_tol=1e-13) |
---|
624 | n/a | |
---|
625 | n/a | def test_complex_near_zero(self): |
---|
626 | n/a | # test values near zero that are near to within three decimal places |
---|
627 | n/a | near_zero_examples = [(0.001j, 0), |
---|
628 | n/a | (0.001, 0), |
---|
629 | n/a | (0.001+0.001j, 0), |
---|
630 | n/a | (-0.001+0.001j, 0), |
---|
631 | n/a | (0.001-0.001j, 0), |
---|
632 | n/a | (-0.001-0.001j, 0), |
---|
633 | n/a | ] |
---|
634 | n/a | |
---|
635 | n/a | self.assertAllClose(near_zero_examples, abs_tol=1.5e-03) |
---|
636 | n/a | self.assertAllNotClose(near_zero_examples, abs_tol=0.5e-03) |
---|
637 | n/a | |
---|
638 | n/a | self.assertIsClose(0.001-0.001j, 0.001+0.001j, abs_tol=2e-03) |
---|
639 | n/a | self.assertIsNotClose(0.001-0.001j, 0.001+0.001j, abs_tol=1e-03) |
---|
640 | n/a | |
---|
641 | n/a | |
---|
642 | n/a | if __name__ == "__main__": |
---|
643 | n/a | unittest.main() |
---|