/*
 *  fpfpComplex.cpp
 *  fp
 *
 *  Created by Robert Delaney on 11/7/09.
 *  Copyright 2009 Bob Delaney's Science Software. All rights reserved.
 *
 */

#include "fpComplex.h"

fpComplex::fpComplex()
{
	re = im = 0;
}


fpComplex::~fpComplex()
{   /*
    if((*this).re.i.nn && (*this).re.i.b)
        free((*this).re.i.b);
    if((*this).im.i.nn && (*this).im.i.b)
        free((*this).im.i.b);
     */
}


fpComplex::fpComplex(const char *inStringRe, const char *inStringIm)
{
	if(fpConvFromString(*this, inStringRe, inStringIm))
		return;
	
	re = im = 0;
}


fpComplex::fpComplex(const char *inString)
{
	if(fpConvFromString(*this, inString))
		return;
	
	re = im = 0;
}


fpComplex::fpComplex(const fp& x, const fp& y)
{
	re = x;
	im = y;
}


fpComplex::fpComplex(double x)
{
	re = x;
	im = 0.;
}


fpComplex::fpComplex(double x, double y)
{
	re = x;
	im = y;
}


fpComplex fpComplex::operator- ()
{
	fpComplex	z;
	
	equate(z.re, re);
	equate(z.im, im);
	
	z.re.i.n = -z.re.i.n;
	z.im.i.n = -z.im.i.n;
	
	return z;
}


fpComplex fpComplex::operator- () const
{
	fpComplex	z;
	
	equate(z.re, re);
	equate(z.im, im);
	
	z.re.i.n = -z.re.i.n;
	z.im.i.n = -z.im.i.n;
	
	return z;
}


fpComplex& fpComplex::operator= (const fpComplex& x)
{
    if(this==&x)
        return *this;
    
	re = x.re;
	im = x.im;
	return *this;
}


fpComplex& fpComplex::operator= (const char* inString)
{
	
	if(fpConvFromString(*this, inString))
		return *this;
	
	re = im = 0;
	
	return *this;
}


fpComplex& fpComplex::operator= (const fp& x)
{
	re = x;
	im = 0;
	return *this;
}


fpComplex& fpComplex::operator= (const mb& x)
{
	re = x;
	im = 0;
	return *this;
}


fpComplex& fpComplex::operator= (double x)
{
	re = x;
	im = 0;
	return *this;
}

fpComplex& fpComplex::operator= (const Complex& x)
{
    re = x.Re;
    im = x.Im;
    return *this;
}


bool fpComplex::operator== (const fpComplex& x)
{
	if(re==x.re && im==x.im)
		return true;
	
	return false;
}


bool fpComplex::operator!= (const fpComplex& x)
{
	if(re!=x.re || im!=x.im)
		return true;
	
	return false;
}


bool fpComplex::operator! ()
{
	if(!re && !im)
		return true;
	
	return false;
}


bool fpComplex::operator== (const fpComplex& x) const
{
	if(re==x.re && im==x.im)
		return true;
	
	return false;
}


bool fpComplex::operator!= (const fpComplex& x) const
{
	if(re!=x.re || im!=x.im)
		return true;
	
	return false;
}


bool fpComplex::operator! () const
{
	if(!re && !im)
		return true;
	
	return false;
}


bool fpComplex::operator== (const fp& x)
{
	if(re==x && !im)
		return true;
	
	return false;
}


bool fpComplex::operator!= (const fp& x)
{
	if(re!=x || im.i.n)
		return true;
	
	return false;
}


bool fpComplex::operator== (const fp& x) const
{
	if(re==x && !im)
		return true;
	
	return false;
}


bool fpComplex::operator!= (const fp& x) const
{
	if(re!=x || im.i.n)
		return true;
	
	return false;
}


bool fpComplex::operator== (const mb& x)
{
	if(re==x && !im)
		return true;
	
	return false;
}


bool fpComplex::operator!= (const mb& x)
{
	if(re!=x || im.i.n)
		return true;
	
	return false;
}


bool fpComplex::operator== (const mb& x) const
{
	if(re==x && !im)
		return true;
	
	return false;
}


bool fpComplex::operator!= (const mb& x) const
{
	if(re!=x || im.i.n)
		return true;
	
	return false;
}


bool fpComplex::operator== (double x)
{
	if(re==x && !im)
		return true;
	
	return false;
}


bool fpComplex::operator!= (double x)
{
	if(re!=x || im.i.n)
		return true;
	
	return false;
}


bool fpComplex::operator== (double x) const
{
	if(re==x && !im)
		return true;
	
	return false;
}


bool fpComplex::operator!= (double x) const
{
	if(re!=x || im.i.n)
		return true;
	
	return false;
}


fpComplex fpComplex::operator+ (const fpComplex& y)
{
	fpComplex		z;
	
	z.re = re + y.re;
	z.im = im + y.im;
	
	return z;
}


fpComplex fpComplex::operator- (const fpComplex& y)
{
	fpComplex		z;
	
	z.re = re - y.re;
	z.im = im - y.im;
	
	return z;
}


fpComplex fpComplex::operator* (const fpComplex& y)
{
	fpComplex		z;
	
	mul(z, *this, y);
	
	return z;
}


fpComplex fpComplex::operator/ (const fpComplex& y)
{
	fpComplex		z;
	
	div(z, *this, y);
	
	return z;
}


fpComplex fpComplex::operator+ (const fpComplex& y) const
{
	fpComplex		z;
	
	z.re = re + y.re;
	z.im = im + y.im;
	
	return z;
}


fpComplex fpComplex::operator- (const fpComplex& y) const
{
	fpComplex		z;
	
	z.re = re - y.re;
	z.im = im - y.im;
	
	return z;
}


fpComplex fpComplex::operator* (const fpComplex& y) const
{
	fpComplex		z;
	
	mul(z, *this, y);
	
	return z;
}


fpComplex fpComplex::operator/ (const fpComplex& y) const
{
	fpComplex		z;
	
	div(z, *this, y);
	
	return z;
}


fpComplex& fpComplex::operator+= (const fpComplex& x)
{
	re = re + x.re;
	im = im + x.im;
	
	return *this;
}


fpComplex& fpComplex::operator-= (const fpComplex& x)
{
	re = re - x.re;
	im = im - x.im;
	
	return *this;
}


fpComplex& fpComplex::operator*= (const fpComplex& x)
{
	mul(*this, *this, x);
	
	return *this;
}


fpComplex& fpComplex::operator/= (const fpComplex& x)
{
	div(*this, *this, x);
	
	return *this;
}


fpComplex fpComplex::operator+ (const fp& y)
{
	fpComplex		z;
	
	z.re = re + y;
	z.im = im;
	
	return z;
}


fpComplex fpComplex::operator- (const fp& y)
{
	fpComplex		z;
	
	z.re = re - y;
	z.im = im;
	
	return z;
}


fpComplex fpComplex::operator* (const fp& y)
{
	fpComplex		z;
	
	z.re = re*y;
	z.im = im*y;
	
	return z;
}


fpComplex fpComplex::operator/ (const fp& y)
{
	fpComplex		z;
	
	if(!y.i.n)
	{
		z.re = z.im = 0;
		return z;
	}
	
	z.re = re/y;
	z.im = im/y;
	
	return z;
}


fpComplex fpComplex::operator+ (const fp& y) const
{
	fpComplex		z;
	
	z.re = re + y;
	z.im = im;
	
	return z;
}


fpComplex fpComplex::operator- (const fp& y) const
{
	fpComplex		z;
	
	z.re = re - y;
	z.im = im;
	
	return z;
}


fpComplex fpComplex::operator* (const fp& y) const
{
	fpComplex		z;
	
	z.re = re*y;
	z.im = im*y;
	
	return z;
}


fpComplex fpComplex::operator/ (const fp& y) const
{
	fpComplex		z;
	
	if(!y.i.n)
	{
		z.re = z.im = 0;
		return z;
	}
	
	z.re = re/y;
	z.im = im/y;
	
	return z;
}


fpComplex& fpComplex::operator+= (const fp& y)
{
	
	re = re + y;
	
	return *this;
}


fpComplex& fpComplex::operator-= (const fp& y)
{
	
	re = re - y;
	
	return *this;
}


fpComplex& fpComplex::operator*= (const fp& y)
{
	
	re = re*y;
	im = im*y;
	
	return *this;
}


fpComplex& fpComplex::operator/= (const fp& y)
{
	
	if(!y.i.n)
	{
		re = im = 0;
		return *this;
	}
	
	re = re/y;
	im = im/y;
	
	return *this;
}


fpComplex fpComplex::operator+ (const mb& y)
{
	fpComplex		z;
	
	z.re = re + y;
	z.im = im;
	
	return z;
}


fpComplex fpComplex::operator- (const mb& y)
{
	fpComplex		z;
	
	z.re = re - y;
	z.im = im;
	
	return z;
}


fpComplex fpComplex::operator* (const mb& y)
{
	fpComplex		z;
	
	z.re = re*y;
	z.im = im*y;
	
	return z;
}


fpComplex fpComplex::operator/ (const mb& y)
{
	fpComplex		z;
	
	if(!y.n)
	{
		z.re = z.im = 0;
		return z;
	}
	
	z.re = re/y;
	z.im = im/y;
	
	return z;
}


fpComplex fpComplex::operator+ (const mb& y) const
{
	fpComplex		z;
	
	z.re = re + y;
	z.im = im;
	
	return z;
}


fpComplex fpComplex::operator- (const mb& y) const
{
	fpComplex		z;
	
	z.re = re - y;
	z.im = im;
	
	return z;
}


fpComplex fpComplex::operator* (const mb& y) const
{
	fpComplex		z;
	
	z.re = re*y;
	z.im = im*y;
	
	return z;
}


fpComplex fpComplex::operator/ (const mb& y) const
{
	fpComplex		z;
	
	if(!y.n)
	{
		z.re = z.im = 0;
		return z;
	}
	
	z.re = re/y;
	z.im = im/y;
	
	return z;
}


fpComplex& fpComplex::operator+= (const mb& y)
{
	
	re = re + y;
	
	return *this;
}


fpComplex& fpComplex::operator-= (const mb& y)
{
	
	re = re - y;
	
	return *this;
}


fpComplex& fpComplex::operator*= (const mb& y)
{
	
	re = re*y;
	im = im*y;
	
	return *this;
}


fpComplex& fpComplex::operator/= (const mb& y)
{
	
	if(!y.n)
	{
		re = im = 0;
		return *this;
	}
	
	re = re/y;
	im = im/y;
	
	return *this;
}


fpComplex fpComplex::operator+ (double y)
{
	fpComplex		z;
	
	z.re = re + y;
	z.im = im;
	
	return z;
}


fpComplex fpComplex::operator- (double y)
{
	fpComplex		z;
	
	z.re = re - y;
	z.im = im;
	
	return z;
}


fpComplex fpComplex::operator* (double y)
{
	fpComplex		z;
	
	z.re = re*y;
	z.im = im*y;
	
	return z;
}


fpComplex fpComplex::operator/ (double y)
{
	fpComplex		z;
	
	if(!y)
	{
		z.re = z.im = 0;
		return z;
	}
	
	z.re = re/y;
	z.im = im/y;
	
	return z;
}


fpComplex fpComplex::operator+ (double y) const
{
	fpComplex		z;
	
	z.re = re + y;
	z.im = im;
	
	return z;
}


fpComplex fpComplex::operator- (double y) const
{
	fpComplex		z;
	
	z.re = re - y;
	z.im = im;
	
	return z;
}


fpComplex fpComplex::operator* (double y) const
{
	fpComplex		z;
	
	z.re = re*y;
	z.im = im*y;
	
	return z;
}


fpComplex fpComplex::operator/ (double y) const
{
	fpComplex		z;
	
	if(!y)
	{
		z.re = z.im = 0;
		return z;
	}
	
	z.re = re/y;
	z.im = im/y;
	
	return z;
}


fpComplex& fpComplex::operator+= (double y)
{
	
	re = re + y;
	
	return *this;
}


fpComplex& fpComplex::operator-= (double y)
{
	
	re = re - y;
	
	return *this;
}


fpComplex& fpComplex::operator*= (double y)
{
	
	re = re*y;
	im = im*y;
	
	return *this;
}


fpComplex& fpComplex::operator/= (double y)
{
	
	if(!y)
	{
		re = im = 0;
		return *this;
	}
	
	re = re/y;
	im = im/y;
	
	return *this;
}


fpComplex operator+ (const fp& x, const fpComplex& y)
{
	fpComplex		z;
	
	z.re = x + y.re;
	z.im = y.im;
	
	return z;
}


fpComplex operator- (const fp& x, const fpComplex& y)
{
	fpComplex		z;
	
	z.re = x - y.re;
	z.im = -y.im;
	
	return z;
}


fpComplex operator* (const fp& x, const fpComplex& y)
{
	fpComplex		z;
	
	z.re = x*y.re;
	z.im = x*y.im;
	
	return z;
}


fpComplex operator/ (const fp& x, const fpComplex& y)
{
	fpComplex		xC, z;
	
	if(!y)
	{
		z.re = z.im = 0;
		return z;
	}
	
	xC.re = x;
	xC.im = 0;
	
	div(z, xC, y);
	
	return z;
}


fpComplex operator+ (const mb& x, const fpComplex& y)
{
	fpComplex		z;
	
	z.re = x + y.re;
	z.im = y.im;
	
	return z;
}


fpComplex operator- (const mb& x, const fpComplex& y)
{
	fpComplex		z;
	
	z.re = x - y.re;
	z.im = -y.im;
	
	return z;
}


fpComplex operator* (const mb& x, const fpComplex& y)
{
	fpComplex		z;
	
	z.re = x*y.re;
	z.im = x*y.im;
	
	return z;
}


fpComplex operator/ (const mb& x, const fpComplex& y)
{
	fpComplex		xC, z;
	
	if(!y)
	{
		z.re = z.im = 0;
		return z;
	}
	
	xC.re = x;
	xC.im = 0;
	
	div(z, xC, y);
	
	return z;
}


fpComplex operator+ (double x, const fpComplex& y)
{
	fpComplex		z;
	
	z.re = x + y.re;
	z.im = y.im;
	
	return z;
}


fpComplex operator- (double x, const fpComplex& y)
{
	fpComplex		z;
	
	z.re = x - y.re;
	z.im = -y.im;
	
	return z;
}


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


fpComplex operator/ (double x, const fpComplex& y)
{
	fpComplex		xC, z;
	
	if(!y)
	{
		z.re = z.im = 0;
		return z;
	}
	
	xC.re = x;
	xC.im = 0;
	
	div(z, xC, y);
	
	return z;
}



ostream& operator <<(ostream &s, const fpComplex& x)
{
	char	*outString;
	
	outString = fpToStr(x.re, getDecPrec());
	s << "(" << outString;
	free(outString);
	
	s << ", ";
	
	outString = fpToStr(x.im, getDecPrec());
	s << outString;
	free(outString);
	
	s << ")";
	
	return s;
}




