14710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Complex numbers
24710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# ---------------
34710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
44710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# [Now that Python has a complex data type built-in, this is not very
54710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# useful, but it's still a nice example class]
64710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
74710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# This module represents complex numbers as instances of the class Complex.
84710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# A Complex instance z has two data attribues, z.re (the real part) and z.im
94710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# (the imaginary part).  In fact, z.re and z.im can have any value -- all
104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# arithmetic operators work regardless of the type of z.re and z.im (as long
114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# as they support numerical operations).
124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#
134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# The following functions exist (Complex is actually a class):
144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Complex([re [,im]) -> creates a complex number from a real and an imaginary part
154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# IsComplex(z) -> true iff z is a complex number (== has .re and .im attributes)
164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# ToComplex(z) -> a complex number equal to z; z itself if IsComplex(z) is true
174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#                 if z is a tuple(re, im) it will also be converted
184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# PolarToComplex([r [,phi [,fullcircle]]]) ->
194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#       the complex number z for which r == z.radius() and phi == z.angle(fullcircle)
204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#       (r and phi default to 0)
214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# exp(z) -> returns the complex exponential of z. Equivalent to pow(math.e,z).
224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#
234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Complex numbers have the following methods:
244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# z.abs() -> absolute value of z
254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# z.radius() == z.abs()
264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# z.angle([fullcircle]) -> angle from positive X axis; fullcircle gives units
274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# z.phi([fullcircle]) == z.angle(fullcircle)
284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#
294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# These standard functions and unary operators accept complex arguments:
304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# abs(z)
314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# -z
324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# +z
334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# not z
344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# repr(z) == `z`
354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# str(z)
364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# hash(z) -> a combination of hash(z.re) and hash(z.im) such that if z.im is zero
374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#            the result equals hash(z.re)
384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Note that hex(z) and oct(z) are not defined.
394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#
404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# These conversions accept complex arguments only if their imaginary part is zero:
414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# int(z)
424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# long(z)
434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# float(z)
444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#
454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# The following operators accept two complex numbers, or one complex number
464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# and one real number (int, long or float):
474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# z1 + z2
484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# z1 - z2
494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# z1 * z2
504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# z1 / z2
514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# pow(z1, z2)
524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# cmp(z1, z2)
534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Note that z1 % z2 and divmod(z1, z2) are not defined,
544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# nor are shift and mask operations.
554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#
564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# The standard module math does not support complex numbers.
574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# The cmath modules should be used instead.
584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#
594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Idea:
604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# add a class Polar(r, phi) and mixed-mode arithmetic which
614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# chooses the most appropriate type for the result:
624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Complex for +,-,cmp
634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Polar   for *,/,pow
644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport math
664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport sys
674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtwopi = math.pi*2.0
694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmhalfpi = math.pi/2.0
704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef IsComplex(obj):
724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return hasattr(obj, 're') and hasattr(obj, 'im')
734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef ToComplex(obj):
754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if IsComplex(obj):
764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return obj
774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    elif isinstance(obj, tuple):
784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return Complex(*obj)
794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else:
804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return Complex(obj)
814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef PolarToComplex(r = 0, phi = 0, fullcircle = twopi):
834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    phi = phi * (twopi / fullcircle)
844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return Complex(math.cos(phi)*r, math.sin(phi)*r)
854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef Re(obj):
874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if IsComplex(obj):
884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return obj.re
894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return obj
904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef Im(obj):
924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if IsComplex(obj):
934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return obj.im
944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0
954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass Complex:
974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __init__(self, re=0, im=0):
994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        _re = 0
1004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        _im = 0
1014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if IsComplex(re):
1024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            _re = re.re
1034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            _im = re.im
1044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else:
1054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            _re = re
1064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if IsComplex(im):
1074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            _re = _re - im.im
1084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            _im = _im + im.re
1094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else:
1104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            _im = _im + im
1114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # this class is immutable, so setting self.re directly is
1124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # not possible.
1134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.__dict__['re'] = _re
1144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.__dict__['im'] = _im
1154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __setattr__(self, name, value):
1174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        raise TypeError, 'Complex numbers are immutable'
1184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __hash__(self):
1204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if not self.im:
1214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return hash(self.re)
1224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return hash((self.re, self.im))
1234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __repr__(self):
1254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if not self.im:
1264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return 'Complex(%r)' % (self.re,)
1274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else:
1284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return 'Complex(%r, %r)' % (self.re, self.im)
1294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __str__(self):
1314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if not self.im:
1324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return repr(self.re)
1334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else:
1344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return 'Complex(%r, %r)' % (self.re, self.im)
1354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __neg__(self):
1374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return Complex(-self.re, -self.im)
1384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __pos__(self):
1404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return self
1414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __abs__(self):
1434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return math.hypot(self.re, self.im)
1444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __int__(self):
1464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if self.im:
1474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            raise ValueError, "can't convert Complex with nonzero im to int"
1484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return int(self.re)
1494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __long__(self):
1514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if self.im:
1524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            raise ValueError, "can't convert Complex with nonzero im to long"
1534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return long(self.re)
1544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __float__(self):
1564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if self.im:
1574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            raise ValueError, "can't convert Complex with nonzero im to float"
1584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return float(self.re)
1594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __cmp__(self, other):
1614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        other = ToComplex(other)
1624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return cmp((self.re, self.im), (other.re, other.im))
1634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __rcmp__(self, other):
1654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        other = ToComplex(other)
1664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return cmp(other, self)
1674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __nonzero__(self):
1694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return not (self.re == self.im == 0)
1704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    abs = radius = __abs__
1724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def angle(self, fullcircle = twopi):
1744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return (fullcircle/twopi) * ((halfpi - math.atan2(self.re, self.im)) % twopi)
1754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    phi = angle
1774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __add__(self, other):
1794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        other = ToComplex(other)
1804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return Complex(self.re + other.re, self.im + other.im)
1814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    __radd__ = __add__
1834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __sub__(self, other):
1854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        other = ToComplex(other)
1864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return Complex(self.re - other.re, self.im - other.im)
1874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __rsub__(self, other):
1894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        other = ToComplex(other)
1904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return other - self
1914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __mul__(self, other):
1934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        other = ToComplex(other)
1944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return Complex(self.re*other.re - self.im*other.im,
1954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                       self.re*other.im + self.im*other.re)
1964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    __rmul__ = __mul__
1984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __div__(self, other):
2004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        other = ToComplex(other)
2014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d = float(other.re*other.re + other.im*other.im)
2024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if not d: raise ZeroDivisionError, 'Complex division'
2034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return Complex((self.re*other.re + self.im*other.im) / d,
2044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                       (self.im*other.re - self.re*other.im) / d)
2054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __rdiv__(self, other):
2074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        other = ToComplex(other)
2084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return other / self
2094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __pow__(self, n, z=None):
2114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if z is not None:
2124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            raise TypeError, 'Complex does not support ternary pow()'
2134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if IsComplex(n):
2144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if n.im:
2154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                if self.im: raise TypeError, 'Complex to the Complex power'
2164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                else: return exp(math.log(self.re)*n)
2174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            n = n.re
2184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        r = pow(self.abs(), n)
2194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        phi = n*self.angle()
2204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return Complex(math.cos(phi)*r, math.sin(phi)*r)
2214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __rpow__(self, base):
2234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        base = ToComplex(base)
2244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return pow(base, self)
2254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef exp(z):
2274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    r = math.exp(z.re)
2284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return Complex(math.cos(z.im)*r,math.sin(z.im)*r)
2294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef checkop(expr, a, b, value, fuzz = 1e-6):
2324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    print '       ', a, 'and', b,
2334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    try:
2344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        result = eval(expr)
2354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    except:
2364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        result = sys.exc_type
2374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    print '->', result
2384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if isinstance(result, str) or isinstance(value, str):
2394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ok = (result == value)
2404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else:
2414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ok = abs(result - value) <= fuzz
2424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if not ok:
2434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        print '!!\t!!\t!! should be', value, 'diff', abs(result - value)
2444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef test():
2464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    print 'test constructors'
2474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    constructor_test = (
2484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # "expect" is an array [re,im] "got" the Complex.
2494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ( (0,0), Complex() ),
2504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ( (0,0), Complex() ),
2514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ( (1,0), Complex(1) ),
2524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ( (0,1), Complex(0,1) ),
2534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ( (1,2), Complex(Complex(1,2)) ),
2544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ( (1,3), Complex(Complex(1,2),1) ),
2554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ( (0,0), Complex(0,Complex(0,0)) ),
2564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ( (3,4), Complex(3,Complex(4)) ),
2574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ( (-1,3), Complex(1,Complex(3,2)) ),
2584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ( (-7,6), Complex(Complex(1,2),Complex(4,8)) ) )
2594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    cnt = [0,0]
2604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    for t in constructor_test:
2614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cnt[0] += 1
2624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if ((t[0][0]!=t[1].re)or(t[0][1]!=t[1].im)):
2634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            print "        expected", t[0], "got", t[1]
2644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            cnt[1] += 1
2654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    print "  ", cnt[1], "of", cnt[0], "tests failed"
2664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # test operators
2674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    testsuite = {
2684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'a+b': [
2694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (1, 10, 11),
2704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (1, Complex(0,10), Complex(1,10)),
2714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (Complex(0,10), 1, Complex(1,10)),
2724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (Complex(0,10), Complex(1), Complex(1,10)),
2734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (Complex(1), Complex(0,10), Complex(1,10)),
2744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ],
2754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'a-b': [
2764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (1, 10, -9),
2774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (1, Complex(0,10), Complex(1,-10)),
2784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (Complex(0,10), 1, Complex(-1,10)),
2794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (Complex(0,10), Complex(1), Complex(-1,10)),
2804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (Complex(1), Complex(0,10), Complex(1,-10)),
2814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ],
2824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'a*b': [
2834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (1, 10, 10),
2844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (1, Complex(0,10), Complex(0, 10)),
2854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (Complex(0,10), 1, Complex(0,10)),
2864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (Complex(0,10), Complex(1), Complex(0,10)),
2874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (Complex(1), Complex(0,10), Complex(0,10)),
2884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ],
2894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'a/b': [
2904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (1., 10, 0.1),
2914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (1, Complex(0,10), Complex(0, -0.1)),
2924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (Complex(0, 10), 1, Complex(0, 10)),
2934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (Complex(0, 10), Complex(1), Complex(0, 10)),
2944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (Complex(1), Complex(0,10), Complex(0, -0.1)),
2954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ],
2964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'pow(a,b)': [
2974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (1, 10, 1),
2984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (1, Complex(0,10), 1),
2994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (Complex(0,10), 1, Complex(0,10)),
3004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (Complex(0,10), Complex(1), Complex(0,10)),
3014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (Complex(1), Complex(0,10), 1),
3024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (2, Complex(4,0), 16),
3034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ],
3044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'cmp(a,b)': [
3054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (1, 10, -1),
3064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (1, Complex(0,10), 1),
3074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (Complex(0,10), 1, -1),
3084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (Complex(0,10), Complex(1), -1),
3094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (Complex(1), Complex(0,10), 1),
3104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ],
3114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
3124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    for expr in sorted(testsuite):
3134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        print expr + ':'
3144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = (expr,)
3154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for item in testsuite[expr]:
3164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            checkop(*(t+item))
3174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmif __name__ == '__main__':
3204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    test()
321