#+title: Task 1: Complex Numbers

#+author: JirR02
* Task
:PROPERTIES:
:CUSTOM_ID: task
:END:
Create your own data type for complex numbers that can be used as a
drop-in replacement for double. The definition of the data type and the
forward declarations of operators must be in file =complex.h=, while the
implementation of operators must be in file =complex.cpp=.

1. Define a struct named =Complex= that represents a complex number in
   the cartesian form. As data type use floating point numbers with
   =double= precision.

2. Implement input and output =(>>, <<)= operators for reading and
   writing of complex numbers.

A complex number \((x pm yi)\) is represented in the format =[x,y]=,
where =x= and =y= follows the format of floating point numbers with
=double= precision.

E.g., =[-2,5]= represents \((-2 + 5i)\) . *Important: No spaces*.

*Note*: You can assume that your input value is a well-formatted complex
number.

3. [@3] Implement arithmetic operators for addition, subtraction,
   multiplication, and division \((+,-,*,/)\) of complex numbers. For
   the division, you may assume that the squared modulus of the divisor
   is not zero, even after rounding it to a floating point number.
   Finally, you do not need to treat the case of division by zero.

4. Implement the negation operator \((-)\) of complex numbers.

5. Implement comparison operators for equality and inequality
   \((==,!=)\) of complex numbers.

*Hint*: recall from Exercise 5 how to correctly compare floating point
numbers.

* Solution
:PROPERTIES:
:CUSTOM_ID: solution
:END:
** =complex.h=
:PROPERTIES:
:CUSTOM_ID: complex.h
:END:
#+begin_src cpp
#pragma once

#include <cmath>
#include <iostream>

struct Complex {
  double a;
  double b;
};

// arithmetic operators
Complex operator+(const Complex &cn1, const Complex &cn2);
Complex operator-(const Complex &cn1, const Complex &cn2);
Complex operator*(const Complex &cn1, const Complex &cn2);
Complex operator/(const Complex &cn1, const Complex &cn2);

// negation operator

Complex operator-(const Complex &cn1);

// equality and inequality operators

bool operator==(const Complex &cn1, const Complex &cn2);
bool operator!=(const Complex &cn1, const Complex &cn2);

// reads a complex number from input
std::istream &operator>>(std::istream &in, Complex &a);
std::ostream &operator<<(std::ostream &out, const Complex &a);
#+end_src

** =complex.cpp=
:PROPERTIES:
:CUSTOM_ID: complex.cpp
:END:
#+begin_src cpp
#include "complex.h"
#include <cstdlib>

std::istream &operator>>(std::istream &in, Complex &a) {
  char open;
  char comma;
  char close;
  double aa;
  double ab;
  in >> open;
  if (open == '[') {
    in >> aa >> comma >> ab >> close;
    if (comma == ',' && close == ']') {
      a.a = aa;
      a.b = ab;
    } else {
      std::cerr << "Invalid Input!";
  }
  } else {
    std::cerr << "Invalid Input!";
  }
  return in;
}

std::ostream &operator<<(std::ostream &out, const Complex &a) {
  return out << "[" << a.a << "," << a.b << "]";
}

Complex operator+(const Complex &cn1, const Complex &cn2) {
  Complex res;
  double a = cn1.a + cn2.a;
  double b = cn1.b + cn2.b;
  res.a = a;
  res.b = b;
  return res;
}

Complex operator-(const Complex &cn1, const Complex &cn2) {
  Complex res;
  double a = cn1.a - cn2.a;
  double b = cn1.b - cn2.b;
  res.a = a;
  res.b = b;
  return res;
}

Complex operator*(const Complex &cn1, const Complex &cn2) {
  Complex res;
  double a = (cn1.a * cn2.a) - (cn1.b * cn2.b);
  double b = (cn1.a * cn2.b) + (cn1.b * cn2.a);
  res.a = a;
  res.b = b;
  return res;
}

Complex operator/(const Complex &cn1, const Complex &cn2) {
  Complex res;
  double a = (cn1.a * cn2.a + cn1.b * cn2.b) / (cn2.a * cn2.a + cn2.b * cn2.b);
  double b = (cn1.b * cn2.a - cn1.a * cn2.b) / (cn2.a * cn2.a + cn2.b * cn2.b);
  res.a = a;
  res.b = b;
  return res;
}

Complex operator-(const Complex &cn1) {
  Complex res;
  double a = -cn1.a;
  double b = -cn1.b;
  res.a = a;
  res.b = b;
  return res;
}

bool operator==(const Complex &cn1, const Complex &cn2) {
  double epsilon = 0.1;
  return (std::abs(cn1.a - cn2.a) < epsilon) &&
  (std::abs(cn1.b - cn2.b) < epsilon);
}

bool operator!=(const Complex &cn1, const Complex &cn2) {
  double epsilon = 0.1;
  return (std::abs(cn1.a - cn2.a) > epsilon) ||
  (std::abs(cn1.b - cn2.b) > epsilon);
}
#+end_src

--------------

Made by JirR02 in Switzerland 🇨🇭
