#ifndef COMPLEX_HPP
#define COMPLEX_HPP

#include <iostream>

class complex {
	public:
	double re;
	double im;

	complex() {
	}

	complex(const double& x) {
		re = x;
		im = 0.;
	}
	complex(const double& x, const double& y) {
		re = x;
		im = y;
	}

	friend complex operator+(const complex& x, const complex& y) {
		complex r;

		r.re = x.re + y.re;
		r.im = x.im + y.im;

		return r;
	}

	friend complex operator+(const complex& x, const double& y) {
		complex r;

		r.re = x.re + y;
		r.im = x.im;

		return r;
	}

	friend complex operator+(const double& x, const complex& y) {
		complex r;

		r.re = x + y.re;
		r.im = y.im;

		return r;
	}

	friend complex& operator+=(complex& x, const complex& y) {
		x = x + y;
		return x;
	}

	friend complex& operator+=(complex& x, const double& y) {
		x.re += y;
		return x;
	}

	friend complex operator-(const complex& x, const complex& y) {
		complex r;

		r.re = x.re - y.re;
		r.im = x.im - y.im;

		return r;
	}

	friend complex operator-(const complex& x, const double& y) {
		complex r;

		r.re = x.re - y;
		r.im = x.im;

		return r;
	}

	friend complex operator-(const double& x, const complex& y) {
		complex r;

		r.re = x - y.re;
		r.im = - y.im;

		return r;
	}

	friend complex& operator-=(complex& x, const complex& y) {
		x = x - y;
		return x;
	}

	friend complex& operator-=(complex& x, const double& y) {
		x.re -= y;
		return x;
	}

	friend complex operator-(const complex& x) {
		complex r;

		r.re = - x.re;
		r.im = - x.im;

		return r;
	}

	friend complex operator*(const complex& x, const complex& y) {
		complex r;

		r.re = x.re * y.re - x.im * y.im;
		r.im = x.re * y.im + x.im * y.re;

		return r;
	}

	friend complex operator*(const complex& x, const double& y) {
		complex r;

		r.re = x.re * y;
		r.im = x.im * y;

		return r;
	}

	friend complex operator*(const double& x, const complex& y) {
		complex r;

		r.re = x * y.re;
		r.im = x * y.im;

		return r;
	}

	friend complex& operator*=(complex& x, const complex& y) {
		x = x * y;
		return x;
	}

	friend complex& operator*=(complex& x, const double& y) {
		x.re *= y;
		x.im *= y;
		return x;
	}

	friend complex sqr(const complex& x) {
		complex r;

		r.re = x.re * x.re - x.im * x.im;
		r.im = 2. * x.re * x.im;

		return r;
	}

	friend std::ostream& operator<<(std::ostream& s, const complex& x) {
		s << '(' << x.re << '+' << x.im << "i)";
		return s;
	}
};

#endif // COMPLEX_HPP
