1
0

cmath.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. import math
  2. class complex:
  3. def __init__(self, real, imag=0):
  4. self._real = float(real)
  5. self._imag = float(imag)
  6. @property
  7. def real(self):
  8. return self._real
  9. @property
  10. def imag(self):
  11. return self._imag
  12. def conjugate(self):
  13. return complex(self.real, -self.imag)
  14. def __repr__(self):
  15. s = ['(', str(self.real)]
  16. s.append('-' if self.imag < 0 else '+')
  17. s.append(str(abs(self.imag)))
  18. s.append('j)')
  19. return ''.join(s)
  20. def __eq__(self, other):
  21. if type(other) is complex:
  22. return self.real == other.real and self.imag == other.imag
  23. if type(other) in (int, float):
  24. return self.real == other and self.imag == 0
  25. return NotImplemented
  26. def __ne__(self, other):
  27. res = self == other
  28. if res is NotImplemented:
  29. return res
  30. return not res
  31. def __add__(self, other):
  32. if type(other) is complex:
  33. return complex(self.real + other.real, self.imag + other.imag)
  34. if type(other) in (int, float):
  35. return complex(self.real + other, self.imag)
  36. return NotImplemented
  37. def __radd__(self, other):
  38. return self.__add__(other)
  39. def __sub__(self, other):
  40. if type(other) is complex:
  41. return complex(self.real - other.real, self.imag - other.imag)
  42. if type(other) in (int, float):
  43. return complex(self.real - other, self.imag)
  44. return NotImplemented
  45. def __rsub__(self, other):
  46. if type(other) is complex:
  47. return complex(other.real - self.real, other.imag - self.imag)
  48. if type(other) in (int, float):
  49. return complex(other - self.real, -self.imag)
  50. return NotImplemented
  51. def __mul__(self, other):
  52. if type(other) is complex:
  53. return complex(self.real * other.real - self.imag * other.imag,
  54. self.real * other.imag + self.imag * other.real)
  55. if type(other) in (int, float):
  56. return complex(self.real * other, self.imag * other)
  57. return NotImplemented
  58. def __rmul__(self, other):
  59. return self.__mul__(other)
  60. def __truediv__(self, other):
  61. if type(other) is complex:
  62. denominator = other.real ** 2 + other.imag ** 2
  63. real_part = (self.real * other.real + self.imag * other.imag) / denominator
  64. imag_part = (self.imag * other.real - self.real * other.imag) / denominator
  65. return complex(real_part, imag_part)
  66. if type(other) in (int, float):
  67. return complex(self.real / other, self.imag / other)
  68. return NotImplemented
  69. def __pow__(self, other: int | float):
  70. if type(other) in (int, float):
  71. return complex(self.__abs__() ** other * math.cos(other * phase(self)),
  72. self.__abs__() ** other * math.sin(other * phase(self)))
  73. return NotImplemented
  74. def __abs__(self) -> float:
  75. return math.sqrt(self.real ** 2 + self.imag ** 2)
  76. def __neg__(self):
  77. return complex(-self.real, -self.imag)
  78. def __hash__(self):
  79. return hash((self.real, self.imag))
  80. # Conversions to and from polar coordinates
  81. def phase(z: complex):
  82. return math.atan2(z.imag, z.real)
  83. def polar(z: complex):
  84. return z.__abs__(), phase(z)
  85. def rect(r: float, phi: float):
  86. return r * math.cos(phi) + r * math.sin(phi) * 1j
  87. # Power and logarithmic functions
  88. def exp(z: complex):
  89. return math.exp(z.real) * rect(1, z.imag)
  90. def log(z: complex, base=2.718281828459045):
  91. return math.log(z.__abs__(), base) + phase(z) * 1j
  92. def log10(z: complex):
  93. return log(z, 10)
  94. def sqrt(z: complex):
  95. return z ** 0.5
  96. # Trigonometric functions
  97. def acos(z: complex):
  98. return -1j * log(z + sqrt(z * z - 1))
  99. def asin(z: complex):
  100. return -1j * log(1j * z + sqrt(1 - z * z))
  101. def atan(z: complex):
  102. return 1j / 2 * log((1 - 1j * z) / (1 + 1j * z))
  103. def cos(z: complex):
  104. return (exp(z) + exp(-z)) / 2
  105. def sin(z: complex):
  106. return (exp(z) - exp(-z)) / (2 * 1j)
  107. def tan(z: complex):
  108. return sin(z) / cos(z)
  109. # Hyperbolic functions
  110. def acosh(z: complex):
  111. return log(z + sqrt(z * z - 1))
  112. def asinh(z: complex):
  113. return log(z + sqrt(z * z + 1))
  114. def atanh(z: complex):
  115. return 1 / 2 * log((1 + z) / (1 - z))
  116. def cosh(z: complex):
  117. return (exp(z) + exp(-z)) / 2
  118. def sinh(z: complex):
  119. return (exp(z) - exp(-z)) / 2
  120. def tanh(z: complex):
  121. return sinh(z) / cosh(z)
  122. # Classification functions
  123. def isfinite(z: complex):
  124. return math.isfinite(z.real) and math.isfinite(z.imag)
  125. def isinf(z: complex):
  126. return math.isinf(z.real) or math.isinf(z.imag)
  127. def isnan(z: complex):
  128. return math.isnan(z.real) or math.isnan(z.imag)
  129. def isclose(a: complex, b: complex):
  130. return math.isclose(a.real, b.real) and math.isclose(a.imag, b.imag)
  131. # Constants
  132. pi = math.pi
  133. e = math.e
  134. tau = 2 * pi
  135. inf = math.inf
  136. infj = complex(0, inf)
  137. nan = math.nan
  138. nanj = complex(0, nan)