// Complex.cpp: implementation of the Complex class.
//
//////////////////////////////////////////////////////////////////////

#include <assert.h>
#include "Complex.h"
#include <math.h>
#include <iostream>

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

Complex::Complex(double real, double imaginary)
    : m_real(real), m_imaginary(imaginary)
{
    m_real = real;
	m_imaginary = imaginary;
}


Complex::~Complex()
{

}

void Complex::add(Complex rhs)
{
    m_real += rhs.m_real;
	m_imaginary += rhs.m_imaginary;
}

void Complex::subtract(Complex rhs)
{
    m_real -= rhs.m_real;
	m_imaginary -= rhs.m_imaginary;
}

// (a + b i) * (c + d i) = (ac-bd) + (ad+bc) i
void Complex::multiply(Complex rhs)
{
	double real = m_real, imaginary = m_imaginary;
    m_real = real*rhs.m_real-imaginary*rhs.m_imaginary;
	m_imaginary = real*rhs.m_imaginary+imaginary*rhs.m_real;
}

// (a + b i) / (c + d i) = (ac+bd)/(c*c+d*d) + (-ad+bc)/(c*c+d*d) i 
bool Complex::divide(Complex rhs)
{
    double divisor = rhs.m_real*rhs.m_real+
		             rhs.m_imaginary*rhs.m_imaginary;
	if (divisor < 1e-10) return false;
	double real = m_real, imaginary = m_imaginary;

    m_real = (real*rhs.m_real+imaginary*rhs.m_imaginary)/divisor;
	m_imaginary = (-real*rhs.m_imaginary+imaginary*rhs.m_real)/divisor;
	return true;
}

// | a + b i | = (a*a+b*b)^0.5
double Complex::magnitue()
{
    return sqrt(m_real*m_real+m_imaginary*m_imaginary);
}

bool Complex::equal(Complex rhs, double precision)
{
    double dx = m_real - rhs.m_real;
	double dy = m_imaginary - rhs.m_imaginary;
	if (dx*dx+dy*dy < precision*precision)
		return true;
	else
		return false;
}

void Complex::print(ostream& os)
{
	os << '(' << m_real << " + " << m_imaginary << " i)";
}

void Complex::unitTest()
{
    Complex x1(7, 3), x2(1, 1), x3(5, -2);
    assert(x1.divide(x2));
    assert(x1.equal(x3, 1e-10));
    x2 = Complex(0, 0);
    assert(!x1.divide(x2));
}


Complex::Complex(void):m_real(0), m_imaginary(0)
{
}

ostream &operator<<(ostream& os, Complex &x)
{
    x.print(os);
    return os;
}

istream &operator>>(istream& is, Complex &x)
{
    double real, imaginary;
    char op, charI, lbr, rbr;
    is >> lbr >> real >> op >> imaginary >> charI >> rbr;
    if (op == '-')
        imaginary = -imaginary;
    x = Complex(real, imaginary);
    return is;
}
