4 # [Now that Python has a complex data type built-in, this is not very
5 # useful, but it's still a nice example class]
7 # This module represents complex numbers as instances of the class Complex.
8 # A Complex instance z has two data attribues, z.re (the real part) and z.im
9 # (the imaginary part). In fact, z.re and z.im can have any value -- all
10 # arithmetic operators work regardless of the type of z.re and z.im (as long
11 # as they support numerical operations).
13 # The following functions exist (Complex is actually a class):
14 # Complex([re [,im]) -> creates a complex number from a real and an imaginary part
15 # IsComplex(z) -> true iff z is a complex number (== has .re and .im attributes)
16 # ToComplex(z) -> a complex number equal to z; z itself if IsComplex(z) is true
17 # if z is a tuple(re, im) it will also be converted
18 # PolarToComplex([r [,phi [,fullcircle]]]) ->
19 # the complex number z for which r == z.radius() and phi == z.angle(fullcircle)
20 # (r and phi default to 0)
21 # exp(z) -> returns the complex exponential of z. Equivalent to pow(math.e,z).
23 # Complex numbers have the following methods:
24 # z.abs() -> absolute value of z
25 # z.radius() == z.abs()
26 # z.angle([fullcircle]) -> angle from positive X axis; fullcircle gives units
27 # z.phi([fullcircle]) == z.angle(fullcircle)
29 # These standard functions and unary operators accept complex arguments:
36 # hash(z) -> a combination of hash(z.re) and hash(z.im) such that if z.im is zero
37 # the result equals hash(z.re)
38 # Note that hex(z) and oct(z) are not defined.
40 # These conversions accept complex arguments only if their imaginary part is zero:
45 # The following operators accept two complex numbers, or one complex number
46 # and one real number (int, long or float):
53 # Note that z1 % z2 and divmod(z1, z2) are not defined,
54 # nor are shift and mask operations.
56 # The standard module math does not support complex numbers.
57 # The cmath modules should be used instead.
60 # add a class Polar(r, phi) and mixed-mode arithmetic which
61 # chooses the most appropriate type for the result:
72 return hasattr(obj
, 're') and hasattr(obj
, 'im')
77 elif isinstance(obj
, tuple):
82 def PolarToComplex(r
= 0, phi
= 0, fullcircle
= twopi
):
83 phi
= phi
* (twopi
/ fullcircle
)
84 return Complex(math
.cos(phi
)*r
, math
.sin(phi
)*r
)
98 def __init__(self
, re
=0, im
=0):
111 # this class is immutable, so setting self.re directly is
113 self
.__dict
__['re'] = _re
114 self
.__dict
__['im'] = _im
116 def __setattr__(self
, name
, value
):
117 raise TypeError, 'Complex numbers are immutable'
122 return hash((self
.re
, self
.im
))
126 return 'Complex(%r)' % (self
.re
,)
128 return 'Complex(%r, %r)' % (self
.re
, self
.im
)
134 return 'Complex(%r, %r)' % (self
.re
, self
.im
)
137 return Complex(-self
.re
, -self
.im
)
143 return math
.hypot(self
.re
, self
.im
)
147 raise ValueError, "can't convert Complex with nonzero im to int"
152 raise ValueError, "can't convert Complex with nonzero im to long"
157 raise ValueError, "can't convert Complex with nonzero im to float"
158 return float(self
.re
)
160 def __cmp__(self
, other
):
161 other
= ToComplex(other
)
162 return cmp((self
.re
, self
.im
), (other
.re
, other
.im
))
164 def __rcmp__(self
, other
):
165 other
= ToComplex(other
)
166 return cmp(other
, self
)
168 def __nonzero__(self
):
169 return not (self
.re
== self
.im
== 0)
171 abs = radius
= __abs__
173 def angle(self
, fullcircle
= twopi
):
174 return (fullcircle
/twopi
) * ((halfpi
- math
.atan2(self
.re
, self
.im
)) % twopi
)
178 def __add__(self
, other
):
179 other
= ToComplex(other
)
180 return Complex(self
.re
+ other
.re
, self
.im
+ other
.im
)
184 def __sub__(self
, other
):
185 other
= ToComplex(other
)
186 return Complex(self
.re
- other
.re
, self
.im
- other
.im
)
188 def __rsub__(self
, other
):
189 other
= ToComplex(other
)
192 def __mul__(self
, other
):
193 other
= ToComplex(other
)
194 return Complex(self
.re
*other
.re
- self
.im
*other
.im
,
195 self
.re
*other
.im
+ self
.im
*other
.re
)
199 def __div__(self
, other
):
200 other
= ToComplex(other
)
201 d
= float(other
.re
*other
.re
+ other
.im
*other
.im
)
202 if not d
: raise ZeroDivisionError, 'Complex division'
203 return Complex((self
.re
*other
.re
+ self
.im
*other
.im
) / d
,
204 (self
.im
*other
.re
- self
.re
*other
.im
) / d
)
206 def __rdiv__(self
, other
):
207 other
= ToComplex(other
)
210 def __pow__(self
, n
, z
=None):
212 raise TypeError, 'Complex does not support ternary pow()'
215 if self
.im
: raise TypeError, 'Complex to the Complex power'
216 else: return exp(math
.log(self
.re
)*n
)
218 r
= pow(self
.abs(), n
)
220 return Complex(math
.cos(phi
)*r
, math
.sin(phi
)*r
)
222 def __rpow__(self
, base
):
223 base
= ToComplex(base
)
224 return pow(base
, self
)
228 return Complex(math
.cos(z
.im
)*r
,math
.sin(z
.im
)*r
)
231 def checkop(expr
, a
, b
, value
, fuzz
= 1e-6):
232 print ' ', a
, 'and', b
,
236 result
= sys
.exc_type
238 if isinstance(result
, str) or isinstance(value
, str):
239 ok
= (result
== value
)
241 ok
= abs(result
- value
) <= fuzz
243 print '!!\t!!\t!! should be', value
, 'diff', abs(result
- value
)
246 print 'test constructors'
248 # "expect" is an array [re,im] "got" the Complex.
249 ( (0,0), Complex() ),
250 ( (0,0), Complex() ),
251 ( (1,0), Complex(1) ),
252 ( (0,1), Complex(0,1) ),
253 ( (1,2), Complex(Complex(1,2)) ),
254 ( (1,3), Complex(Complex(1,2),1) ),
255 ( (0,0), Complex(0,Complex(0,0)) ),
256 ( (3,4), Complex(3,Complex(4)) ),
257 ( (-1,3), Complex(1,Complex(3,2)) ),
258 ( (-7,6), Complex(Complex(1,2),Complex(4,8)) ) )
260 for t
in constructor_test
:
262 if ((t
[0][0]!=t
[1].re
)or(t
[0][1]!=t
[1].im
)):
263 print " expected", t
[0], "got", t
[1]
265 print " ", cnt
[1], "of", cnt
[0], "tests failed"
270 (1, Complex(0,10), Complex(1,10)),
271 (Complex(0,10), 1, Complex(1,10)),
272 (Complex(0,10), Complex(1), Complex(1,10)),
273 (Complex(1), Complex(0,10), Complex(1,10)),
277 (1, Complex(0,10), Complex(1,-10)),
278 (Complex(0,10), 1, Complex(-1,10)),
279 (Complex(0,10), Complex(1), Complex(-1,10)),
280 (Complex(1), Complex(0,10), Complex(1,-10)),
284 (1, Complex(0,10), Complex(0, 10)),
285 (Complex(0,10), 1, Complex(0,10)),
286 (Complex(0,10), Complex(1), Complex(0,10)),
287 (Complex(1), Complex(0,10), Complex(0,10)),
291 (1, Complex(0,10), Complex(0, -0.1)),
292 (Complex(0, 10), 1, Complex(0, 10)),
293 (Complex(0, 10), Complex(1), Complex(0, 10)),
294 (Complex(1), Complex(0,10), Complex(0, -0.1)),
298 (1, Complex(0,10), 1),
299 (Complex(0,10), 1, Complex(0,10)),
300 (Complex(0,10), Complex(1), Complex(0,10)),
301 (Complex(1), Complex(0,10), 1),
302 (2, Complex(4,0), 16),
306 (1, Complex(0,10), 1),
307 (Complex(0,10), 1, -1),
308 (Complex(0,10), Complex(1), -1),
309 (Complex(1), Complex(0,10), 1),
312 for expr
in sorted(testsuite
):
315 for item
in testsuite
[expr
]:
319 if __name__
== '__main__':