#ifndef __COMPLEX_AMV
#define __COMPLEX_AMV
#include <iostream>
#include "REEvaluator.h"
#include "stringAMV.h"
#include "algorithm.h"
#include "binaryTree.h"
#include "deque.h"
namespace amv {
template<class type>
class complex {
type re;
type im;
bool polar;
type magnitude;
type angle;
public:
complex(const type &r=type(), const type &i=type(), bool p=false):
re(r), im(i), polar(p), magnitude(r), angle(i)
{
}
complex toPolar() const
{
if(polar)
return *this;
return complex(norm(*this).re,atan(im/re),true);
}
complex toBinomic() const
{
if(polar)
return complex(magnitude*cos(angle),magnitude*sin(angle));
return *this;
}
complex &operator+=(const complex &c)
{
if(polar)
{
*this=toBinomic();
}
if(c.polar)
{
complex temp(c.toBinomic());
re+=temp.re;
im+=temp.im;
}
else
{
re+=c.re;
im+=c.im;
}
return *this;
}
complex &operator+=(const type &t)
{
if(polar)
{
*this=toBinomic();
}
re+=t;
return *this;
}
complex &operator-=(const complex &c)
{
if(polar)
{
*this=toBinomic();
}
if(c.polar)
{
complex temp(c.toBinomic());
re-=temp.re;
im-=temp.im;
}
else
{
re-=c.re;
im-=c.im;
}
return *this;
}
complex &operator-=(const type &t)
{
if(polar)
{
*this=toBinomic();
}
re-=t;
return *this;
}
complex &operator*=(const complex &c)
{
if(polar && c.polar)
{
magnitude*=c.magnitude;
angle+=c.angle;
}
else if(polar && !c.polar)
{
complex temp(c.toPolar());
magnitude*=temp.magnitude;
angle+=temp.angle;
}
else if(!polar && c.polar)
{
*this=toPolar();
magnitude*=c.magnitude;
angle+=c.angle;
}
else
{
type r(re*c.re-im*c.im),i(re*c.im+im*c.re);
re=r;
im=i;
}
return *this;
}
complex &operator*=(const type &t)
{
if(polar)
magnitude*=t;
else
{
re*=t;
im*=t;
}
return *this;
}
friend complex inv(const complex &c)
{
return complex(c.re/((c.re^2)+(c.im^2)),-c.im/((c.re^2)+(c.im^2)));
}
complex &operator/=(const complex &c)
{
if(polar && c.polar)
{
magnitude/=c.magnitude;
angle-=c.angle;
return *this;
}
else if(polar && !c.polar)
{
complex temp(c.toPolar());
magnitude/=temp.magnitude;
angle-=temp.angle;
return *this;
}
else if(!polar && c.polar)
{
*this=toPolar();
magnitude/=c.magnitude;
angle-=c.angle;
return *this;
}
return (*this*=inv(c));
}
complex &operator/=(const type &t)
{
if(polar)
magnitude/=t;
else
{
re/=t;
im/=t;
}
return *this;
}
complex &operator^=(const complex &c)
{
type n(c.re);
if(c.polar)
n=c.magnitude;
if(polar)
{
magnitude^=n;
angle*=n;
}
else
{
complex temp(toPolar());
temp.magnitude^=n;
temp.angle*=n;
*this=temp;
}
return *this;
}
complex &operator^=(const type &t)
{
if(polar)
{
magnitude^=t;
angle*=t;
}
else
{
complex temp(toPolar());
temp.magnitude^=t;
temp.angle*=t;
*this=temp;
}
return *this;
}
complex &operator%=(const complex &c)
{
re%=c.re;
return *this;
}
complex &operator%=(const type &t)
{
re%=t;
return *this;
}
complex operator+() const
{
return *this;
}
complex operator-() const
{
return complex(-re,-im);
}
friend complex<type> fact(const complex<type> &n);
friend complex<type> exp(const complex<type> &n);
friend complex<type> log(const complex<type> &n);
friend complex<type> ln(const complex<type> &n);
friend complex<type> sin(const complex<type> &n);
friend complex<type> sinh(const complex<type> &n);
friend complex<type> asin(const complex<type> &n);
friend complex<type> cos(const complex<type> &n);
friend complex<type> cosh(const complex<type> &n);
friend complex<type> acos(const complex<type> &n);
friend complex<type> tan(const complex<type> &n);
friend complex<type> tanh(const complex<type> &n);
friend complex<type> atan(const complex<type> &n);
friend complex<type> ctg(const complex<type> &n);
friend complex<type> actg(const complex<type> &n);
friend complex<type> sec(const complex<type> &n);
friend complex<type> asec(const complex<type> &n);
friend complex<type> csc(const complex<type> &n);
friend complex<type> acsc(const complex<type> &n);
friend complex<type> pow(const complex<type> &n, const complex<type> &nth);
friend complex<type> root(const complex<type> &nth, const complex<type> &n);
friend deque<complex<type> > roots(const complex<type> &nth, const complex<type> &n);
friend ostream &operator<<(ostream &os, const complex &c)
{
type zero, one(1), mone(-1);
if(c.polar)
{
if(c.magnitude==one)
os<<"cis "<<c.angle;
else if(c.magnitude==mone)
os<<"-cis "<<c.angle;
else
os<<c.magnitude<<" cis "<<c.angle;
return os;
}
os<<c.re;
if(!(c.im==zero))
{
if(c.im==one)
os<<'+'<<'i';
else if(c.im==mone)
os<<'-'<<'i';
else if(c.im<zero)
os<<c.im<<'i';
else
os<<'+'<<c.im<<'i';
}
return os;
}
friend istream &operator>>(istream &is, complex &c)
{
static REEvaluator REEnospace="#*";
string s;
type r; static string re=string("(")+type::getRE()+")<i";
static char *p1=re.str();
static REEvaluator ipart=p1, onlyi="(\\+|\\-)?<i";
static REEvaluator &REEtype=type::getREE();
static REEvaluator REEpolar=" *<cis <((\\+|\\-)?<[0-9]+<(.<[0-9]+)?)"; delete p1;
p1=0;
REEnospace.skipNoSymbols(is);
if(onlyi.getLexema(is,s))
{
if(s.front()=='+' || s.front()=='i')
c=complex(0,type(1));
else
c=complex(0,type(-1));
}
else if(ipart.getLexema(is,s))
{
s.pop_back();
c=complex(0,type(s));
}
else if(REEtype.getLexema(is,s))
{
r=type(s);
if(onlyi.getLexema(is,s))
{
if(s.front()=='+' || s.front()=='i')
c=complex(r,type(1));
else
c=complex(r,type(-1));
}
else if(REEpolar.getLexema(is,s))
{
string::iterator pos=find(s,'s');
string s1(pos+2,s.end());
c.polar=true;
c.magnitude=r;
c.angle=type(s1);
}
else
{
if(ipart.getLexema(is,s))
{
s.pop_back();
c=complex(r,type(s));
}
else
c=complex(r);
}
}
else if(REEpolar.getLexema(is,s))
{
string::iterator pos=find(s,'s');
string s1(pos+2,s.end());
c.polar=true;
c.magnitude=type(1); c.angle=type(s1);
}
return is;
}
static binaryTree<function<complex<type> > > getFunctionsTree(const complex<type> &f)
{
binaryTree<function<complex<type> > > t;
t.insert(function<complex<type> >("abs",abs)),
t.insert(function<complex<type> >("fact",fact)),
t.insert(function<complex<type> >("exp",exp)),
t.insert(function<complex<type> >("log",log)),
t.insert(function<complex<type> >("ln",ln)),
t.insert(function<complex<type> >("sin",sin)),
t.insert(function<complex<type> >("sinh",sinh)),
t.insert(function<complex<type> >("asin",asin)),
t.insert(function<complex<type> >("cos",cos)),
t.insert(function<complex<type> >("cosh",cosh)),
t.insert(function<complex<type> >("acos",acos)),
t.insert(function<complex<type> >("tan",tan)),
t.insert(function<complex<type> >("tanh",tanh)),
t.insert(function<complex<type> >("atan",atan)),
t.insert(function<complex<type> >("ctg",ctg)),
t.insert(function<complex<type> >("actg",actg)),
t.insert(function<complex<type> >("sec",sec)),
t.insert(function<complex<type> >("asec",asec)),
t.insert(function<complex<type> >("csc",csc)),
t.insert(function<complex<type> >("acsc",acsc)),
t.insert(function<complex<type> >("min",min,function<complex<type> >::BINARY)),
t.insert(function<complex<type> >("max",max,function<complex<type> >::BINARY)),
t.insert(function<complex<type> >("pow",pow,function<complex<type> >::BINARY)),
t.insert(function<complex<type> >("root",root,function<complex<type> >::BINARY));
return t;
}
friend type real(const complex &c); friend type imag(const complex &c); friend complex conj(const complex &c); friend complex norm(const complex &c);
friend complex operator+(const complex &c1, const complex &c2)
{
complex temp(c1);
return temp+=c2;
}
friend complex operator+(const complex &c, const type &t)
{
complex temp(c);
return temp+=t;
}
friend complex operator+(const type &t, const complex &c)
{
complex temp(c);
return temp+=t;
}
friend complex operator-(const complex &c1, const complex &c2)
{
complex temp(c1);
return temp-=c2;
}
friend complex operator-(const complex &c, const type &t)
{
complex temp(c);
return temp-=t;
}
friend complex operator-(const type &t, const complex &c)
{
complex temp(c);
return temp-=t;
}
friend complex operator*(const complex &c1, const complex &c2)
{
complex temp(c1);
return temp*=c2;
}
friend complex operator*(const complex &c, const type &t)
{
return complex(c.re*t,c.im*t);
}
friend complex operator*(const type &t, const complex &c)
{
return complex(c.re*t,c.im*t);
}
friend complex operator/(const complex &c1, const complex &c2)
{
complex temp(c1);
return temp/=c2;
}
friend complex operator/(const complex &c, const type &t)
{
return complex(c.re/t,c.im/t);
}
friend complex operator/(const type &t, const complex &c)
{
complex temp(c);
return temp/=t;
}
friend bool operator==(const complex &c1, const complex &c2)
{
return (c1.re==c2.re && c1.im==c2.im);
}
friend bool operator!=(const complex &c1, const complex &c2)
{
return !(c1==c2);
}
};
template <class type>
inline type real(const complex<type> &c)
{
return c.re;
}
template <class type>
inline type imag(const complex<type> &c)
{
return c.im;
}
template <class type>
inline complex<type> conj(const complex<type> &c)
{
return complex<type>(c.re,-c.im);
}
template <class type>
inline complex<type> norm(const complex<type> &c)
{
return root(type(2),(c.re*c.re+c.im*c.im));}
template <class type>
inline complex<type> polar(const type &mag, const type &angle=type(0))
{
return complex(mag*cos(angle),mag*sin(angle));
}
template <class type>
complex<type> abs(const complex<type> &n)
{
return norm(n);
}
template <class type>
complex<type> fact(const complex<type> &n)
{
complex<type> temp(1), i(2);
for(; i<n || i==n; ++i)
temp*=i;
return temp;
}
template <class type>
complex<type> exp(const complex<type> &n)
{
complex<type> temp(1), i(2), limit(10);
temp+=n;
for(; i<limit; ++i)
{
temp+=(n^i)/fact(i);
}
return temp;
}
template <class type>
complex<type> log(const complex<type> &n)
{
complex<type> temp;
return temp;
}
template <class type>
complex<type> ln(const complex<type> &n)
{
complex<type> temp;
return temp;
}
template <class type>
complex<type> sin(const complex<type> &n)
{
complex<type> newAngle(reduce(n)), temp(newAngle), i(3), limit(10*2);
bool s=false;
for(; i<limit; i+=2)
{
if(s)
temp+=(newAngle^i)/fact(i);
else
temp+=-((newAngle^i)/fact(i));
s=!s;
}
return temp;
}
template <class type>
complex<type> sinh(const complex<type> &n)
{
complex<type> temp;
return temp;
}
template <class type>
complex<type> asin(const complex<type> &n)
{
complex<type> temp;
return temp;
}
template <class type>
complex<type> cos(const complex<type> &n)
{
complex<type> newAngle(reduce(n)), temp(1), i(2), limit(10*2);
bool s=false;
for(; i<limit; i+=2)
{
if(s)
temp+=(newAngle^i)/fact(i);
else
temp+=-((newAngle^i)/fact(i));
s=!s;
}
return temp;
}
template <class type>
complex<type> cosh(const complex<type> &n)
{
complex<type> temp;
return temp;
}
template <class type>
complex<type> acos(const complex<type> &n)
{
complex<type> temp;
return temp;
}
template <class type>
complex<type> tan(const complex<type> &n)
{
complex<type> temp(sin(n)/cos(n));
return temp;
}
template <class type>
complex<type> tanh(const complex<type> &n)
{
complex<type> temp(sin(n)/cos(n));
return temp;
}
template <class type>
complex<type> atan(const complex<type> &n)
{
complex<type> temp(sin(n)/cos(n));
return temp;
}
template <class type>
complex<type> ctg(const complex<type> &n)
{
complex<type> temp(cos(n)/sin(n));
return temp;
}
template <class type>
complex<type> actg(const complex<type> &n)
{
complex<type> temp(sin(n)/cos(n));
return temp;
}
template <class type>
complex<type> sec(const complex<type> &n)
{
complex<type> temp(complex<type>(1)/cos(n));
return temp;
}
template <class type>
complex<type> asec(const complex<type> &n)
{
complex<type> temp(sin(n)/cos(n));
return temp;
}
template <class type>
complex<type> csc(const complex<type> &n)
{
complex<type> temp(complex<type>(1)/sin(n));
return temp;
}
template <class type>
complex<type> acsc(const complex<type> &n)
{
complex<type> temp(sin(n)/cos(n));
return temp;
}
template <class type>
complex<type> pow(const complex<type> &n, const complex<type> &nth)
{
return (n^nth);
}
template <class type>
complex<type> root(const complex<type> &nth, const complex<type> &n)
{
return (roots(nth,n))[0];
}
template <class type>
deque<complex<type> > roots(const complex<type> &nth, const complex<type> &n)
{
deque<complex<type> > droots;
type i(0);
if(n.polar)
{
for(; i<nth.re; ++i)
droots.push_back(complex<type>(rootGomezMorin(n.magnitude,nth.re),(n.angle+type(360)*i)/nth.re,true));
}
else
{
type magnitude=norm(n).re;
type angle=atan(n.im/n.re);
for(; i<nth.re; ++i)
droots.push_back(complex<type>(rootGomezMorin(magnitude,nth.re),(angle+type(360)*i)/nth.re,true));
}
return droots;
}
}
#endif