A   complex number   is a number which can be written as:




a
+
b
×
i


{\displaystyle a+b\times i}


(sometimes shown as:




b
+
a
×
i


{\displaystyle b+a\times i}


where   



a


{\displaystyle a}

   and   



b


{\displaystyle b}

  are real numbers,   and   



i


{\displaystyle i}

   is   √ -1 



Typically, complex numbers are represented as a pair of real numbers called the "imaginary part" and "real part",   where the imaginary part is the number to be multiplied by 



i


{\displaystyle i}

.



Task

 Show addition, multiplication, negation, and inversion of complex numbers in separate functions. (Subtraction and division operations can be made with pairs of these operations.) 
 Print the results for each operation tested.
 Optional: Show complex conjugation.


By definition, the   complex conjugate   of




a
+
b
i


{\displaystyle a+bi}


is




a
−
b
i


{\displaystyle a-bi}





Some languages have complex number libraries available.   If your language does, show the operations.   If your language does not, also show the definition of this type.




c1 = .complex~new(1, 2)
c2 = .complex~new(3, 4)
r = 7
 
say "c1           =" c1
say "c2           =" c2
say "r            =" r
say "-c1          =" (-c1)
say "c1 + r       =" c1 + r
say "c1 + c2      =" c1 + c2
say "c1 - r       =" c1 - r
say "c1 - c2      =" c1 - c2
say "c1 * r       =" c1 * r
say "c1 * c2      =" c1 * c2
say "inv(c1)      =" c1~inv
say "conj(c1)     =" c1~conjugate
say "c1 / r       =" c1 / r
say "c1 / c2      =" c1 / c2
say "c1 == c1     =" (c1 == c1)
say "c1 == c2     =" (c1 == c2)
 
 
::class complex
::method init
  expose r i
  use strict arg r, i = 0
 
-- complex instances are immutable, so these are
-- read only attributes
::attribute r GET
::attribute i GET
 
::method negative
  expose r i
  return self~class~new(-r, -i)
 
::method add
  expose r i
  use strict arg other
  if other~isa(.complex) then
     return self~class~new(r + other~r, i + other~i)
  else return self~class~new(r + other, i)
 
::method subtract
  expose r i
  use strict arg other
  if other~isa(.complex) then
     return self~class~new(r - other~r, i - other~i)
  else return self~class~new(r - other, i)
 
::method times
  expose r i
  use strict arg other
  if other~isa(.complex) then
     return self~class~new(r * other~r - i * other~i, r * other~i + i * other~r)
  else return self~class~new(r * other, i * other)
 
::method inv
  expose r i
  denom = r * r + i * i
  return self~class~new(r/denom,-i/denom)
 
::method conjugate
  expose r i
  return self~class~new(r, -i)
 
::method divide
  use strict arg other
  -- this is easier if everything is a complex number
  if \other~isA(.complex) then other = .complex~new(other)
  -- division is multiplication with the inversion
  return self * other~inv
 
::method "=="
  expose r i
  use strict arg other
 
  if \other~isa(.complex) then return .false
  -- Note:  these are numeric comparisons, so we're using the "="
  -- method so those are handled correctly
  return r = other~r & i = other~i
 
::method "\=="
  use strict arg other
  return \self~"\=="(other)
 
::method "="
  -- this is equivalent of "=="
  forward message("==")
 
::method "\="
  -- this is equivalent of "\=="
  forward message("\==")
 
::method "<>"
  -- this is equivalent of "\=="
  forward message("\==")
 
::method "><"
  -- this is equivalent of "\=="
  forward message("\==")
 
-- some operator overrides -- these only work if the left-hand-side of the
-- subexpression is a quaternion
::method "*"
  forward message("TIMES")
 
::method "/"
  forward message("DIVIDE")
 
::method "-"
  -- need to check if this is a prefix minus or a subtract
  if arg() == 0 then
      forward message("NEGATIVE")
  else
      forward message("SUBTRACT")
 
::method "+"
  -- need to check if this is a prefix plus or an addition
  if arg() == 0 then
      return self  -- we can return this copy since it is immutable
  else
      forward message("ADD")
 
::method string
  expose r i
  return r self~formatnumber(i)"i"
 
::method formatnumber private
  use arg value
  if value > 0 then return "+" value
  else return "-" value~abs
 
-- override hashcode for collection class hash uses
::method hashCode
  expose r i
  return r~hashcode~bitxor(i~hashcode)