//-------------------------------------------------- // vs_complex.h // /*! \brief Template class for complex numbers \class complex complex.h this routines are based on volya_complex.h (Volya at MSU) Version 1.0.1, he did \verbatim -- Some modification for speed -- Some protections from overflow and underflow -- Solving of equations of order 2,3,4: Solve2, Solve3, Solve4; \endverbatim this routine extends Volyas routine by using templates for more flexibility. Even it is tried to get as close as possible to Volyas routine, it is not the same. Where a scalar x = {int, long int, float, double, long double} occured, those spezializations are implemented . But only where it is useful eg. complex += x but not x += complex (integers are skipped) */ // // Carsten Schwarz (C.Schwarz@gsi.de) // GSI // Plankstr. 1 // 64291 Darmstadt // Germany // // 21.7.99 // //--------------------------------------------------- // $Id: complex.hxx,v 1.2 2003/05/01 13:11:48 carsten Exp $ // cvs log at end of file #ifndef __COMPLEX_CXX__ #define __COMPLEX_CXX__ // endif at end of file #ifndef small_epsilon #define small_epsilon 1e-12 #endif #ifndef PI #define PI 3.141592653589793238462643 #endif #include #include #include #include template class complex { public: complex() { re=0.0; im=0.0; } complex(scalar r,scalar i) : re(r),im(i){} public: scalar re; scalar im; }; //!specialization of complex numbers template template <> class complex { public: complex(float r=0.0, float i=0.0) : re(r), im(i) {} explicit complex(const complex& a); explicit complex(const complex& a); public: float re,im; }; //-------- //!specialization of complex numbers template template <> class complex { public: complex(double r=0.0, double i=0.0) : re(r), im(i) {} complex (const complex& a); explicit complex (const complex& a); public: double re,im; }; //-------- //!specialization of complex numbers template template <> class complex { public: complex(long double r=0.0, long double i=0.0) : re(r), im(i) {} complex (const complex& a); complex (const complex& a); public: long double re,im; }; //-------------------------------------------------------------- // += -= *= /= //-------------------------------------------------------------- // complex += complex template inline complex& operator += (complex& a, const complex& b) { a.re += b.re; a.im += b.im; return a; } // scalar += complex template inline scalar& operator += (float &a, const complex& b) { assert(fabs(b.im) < small_epsilon); a+=b.re; return a; } template inline scalar& operator += (double &a, const complex& b) { assert(fabs(b.im) < small_epsilon); a+=b.re; return a; } template inline scalar& operator += (long double &a, const complex& b) { assert(fabs(b.im) < small_epsilon); a+=b.re; return a; } // complex += scalar template inline complex& operator += (complex& a, const int &b) { a.re += b; return a; } template inline complex& operator += (complex& a, const long int &b) { a.re += b; return a; } template inline complex& operator += (complex& a, const float &b) { a.re += b; return a; } template inline complex& operator += (complex& a, const double &b) { a.re += b; return a; } template inline complex& operator += (complex& a, const long double &b) { a.re += b; return a; } // complex -= complex template inline complex& operator -= (complex& a, const complex& b) { a.re -= b.re; a.im -= b.im; return a; } // scalar -= complex template inline scalar& operator -= (float &a, const complex& b) { assert(fabs(b.im) < small_epsilon); a-=b.re; return a; } template inline scalar& operator -= (double &a, const complex& b) { assert(fabs(b.im) < small_epsilon); a-=b.re; return a; } template inline scalar& operator -= (long double &a, const complex& b) { assert(fabs(b.im) < small_epsilon); a-=b.re; return a; } // complex -= scalar template inline complex& operator -= (complex& a, const int &b) { a.re -= b; return a; } template inline complex& operator -= (complex& a, const long int &b) { a.re -= b; return a; } template inline complex& operator -= (complex& a, const float &b) { a.re -= b; return a; } template inline complex& operator -= (complex& a, const double &b) { a.re -= b; return a; } template inline complex& operator -= (complex& a, const long double &b) { a.re -= b; return a; } // complex *= complex template inline complex& operator *= (complex& a, const complex& b) { scalar t1=a.re*b.re, t2=a.im*b.im; a.im = ((a.re+a.im)*(b.re+b.im)-t1-t2); a.re = (t1 - t2); return a; } // scalar *= complex template inline scalar& operator *= (float &a, const complex& b) { assert(fabs(b.im) < small_epsilon); a *= b.re; return a; } template inline scalar& operator *= (double &a, const complex& b) { assert(fabs(b.im) < small_epsilon); a *= b.re; return a; } template inline scalar& operator *= (long double &a, const complex& b) { assert(fabs(b.im) < small_epsilon); a *= b.re; return a; } // complex *= scalar template inline complex& operator *= (complex& a, const int &b) { a.re *= b; a.im *= b; return a; } template inline complex& operator *= (complex& a, const long int &b) { a.re *= b; a.im *= b; return a; } template inline complex& operator *= (complex& a, const float &b) { a.re *= b; a.im *= b; return a; } template inline complex& operator *= (complex& a, const double &b) { a.re *= b; a.im *= b; return a; } template inline complex& operator *= (complex& a, const long double &b) { a.re *= b; a.im *= b; return a; } // complex /= complex template inline complex& operator /= (complex& a, const complex& b) { scalar t1, t2, temp; if (fabs(b.re) >= fabs(b.im)) { t1 = b.im / b.re; t2 = b.re + b.im * t1; temp = (a.re + a.im * t1) / t2; a.im = (a.im - a.re * t1) / t2; a.re = temp; } else { t1 = b.re / b.im; t2 = b.re * t1 + b.im; temp = (a.re * t1 + a.im) / t2; a.im = (a.im * t1 - a.re) / t2; a.re = temp; } return a; } // scalar /= complex template inline scalar& operator /= (float &a, const complex& b) { assert(fabs(b.im) < small_epsilon); a /= b.re; return a; } template inline scalar& operator /= (double &a, const complex& b) { assert(fabs(b.im) < small_epsilon); a /= b.re; return a; } template inline scalar& operator /= (long double &a, const complex& b) { assert(fabs(b.im) < small_epsilon); a /= b.re; return a; } // complex /= scalar template inline complex& operator /= (complex& a, const int &b) { a.re /= b; a.im /= b; return a; } template inline complex& operator /= (complex& a, const long int &b) { a.re /= b; a.im /= b; return a; } template inline complex& operator /= (complex& a, const float &b) { a.re /= b; a.im /= b; return a; } template inline complex& operator /= (complex& a, const double &b) { a.re /= b; a.im /= b; return a; } template inline complex& operator /= (complex& a, const long double &b) { a.re /= b; a.im /= b; return a; } //-------------------------------------------------------------- // unary operators ! + - //-------------------------------------------------------------- template inline complex operator! (const complex& a) //complex conj. {return complex(a.re,-a.im);} template inline complex operator+ (const complex& a) //complex conj. {return complex(a.re,a.im);} template inline complex operator- (const complex& a) //complex conj. {return complex(-a.re,-a.im);} //--------------------------------------------------------------- // binary operators + - * / template inline complex operator+ (const complex &a, const complex &b) {return complex(a.re+b.re, a.im+b.im);} //.. template inline complex operator+ (const complex &a, const int &b) {return complex(a.re+b, a.im);} template inline complex operator+ (const complex &a, const long int &b) {return complex(a.re+b, a.im);} template inline complex operator+ (const complex &a, const float &b) {return complex(a.re+b, a.im);} template inline complex operator+ (const complex &a, const double &b) {return complex(a.re+b, a.im);} template inline complex operator+ (const complex &a, const long double &b) {return complex(a.re+b, a.im);} //.. template inline complex operator+ (const int &a, const complex &b) {return complex(a+b.re, b.im);} template inline complex operator+ (const long int &a, const complex &b) {return complex(a+b.re, b.im);} template inline complex operator+ (const float &a, const complex &b) {return complex(a+b.re, b.im);} template inline complex operator+ (const double &a, const complex &b) {return complex(a+b.re, b.im);} template inline complex operator+ (const long double &a, const complex &b) {return complex(a+b.re, b.im);} //--------- template inline complex operator- (const complex &a, const complex &b) {return complex(a.re-b.re, a.im-b.im);} //.. template inline complex operator- (const complex &a, const int &b) {return complex(a.re-b, a.im);} template inline complex operator- (const complex &a, const long int &b) {return complex(a.re-b, a.im);} template inline complex operator- (const complex &a, const float &b) {return complex(a.re-b, a.im);} template inline complex operator- (const complex &a, const double &b) {return complex(a.re-b, a.im);} template inline complex operator- (const complex &a, const long double &b) {return complex(a.re-b, a.im);} //.. template inline complex operator- (const int &a, const complex &b) {return complex(a-b.re, -b.im);} template inline complex operator- (const long int &a, const complex &b) {return complex(a-b.re, -b.im);} template inline complex operator- (const float &a, const complex &b) {return complex(a-b.re, -b.im);} template inline complex operator- (const double &a, const complex &b) {return complex(a-b.re, -b.im);} template inline complex operator- (const long double &a, const complex &b) {return complex(a-b.re, -b.im);} //--------- template inline complex operator* (const complex& a, const complex& b) { scalar t1 = a.re * b.re; scalar t2 = a.im * b.im; return complex(t1-t2, (a.re+a.im)* (b.re+b.im)- (t1+t2) ); // why this trick? imag = a.r*b.i + b.r*a.i } //... template inline complex operator* (const complex& a, const int &b) {return complex(a.re*b, a.im*b);} template inline complex operator* (const complex& a, const long int &b) {return complex(a.re*b, a.im*b);} template inline complex operator* (const complex& a, const float &b) {return complex(a.re*b, a.im*b);} template inline complex operator* (const complex& a, const double &b) {return complex(a.re*b, a.im*b);} template inline complex operator* (const complex& a, const long double &b) {return complex(a.re*b, a.im*b);} //... template inline complex operator* (const int &a, const complex& b) {return complex(a*b.re, a*b.im);} template inline complex operator* (const long int &a, const complex& b) {return complex(a*b.re, a*b.im);} template inline complex operator* (const float &a, const complex& b) {return complex(a*b.re, a*b.im);} template inline complex operator* (const double &a, const complex& b) {return complex(a*b.re, a*b.im);} template inline complex operator* (const long double &a, const complex& b) {return complex(a*b.re, a*b.im);} //------------ template inline complex operator/ (const complex& a, const complex& b) { scalar t1, t2; if (fabs(b.re) >= fabs(b.im)) { t1 = b.im / b.re; t2 = b.re + b.im * t1; return complex((a.re+a.im*t1)/t2, (a.im-a.re*t1)/t2); } else { t1 = b.re / b.im; t2 = b.re*t1 + b.im; return complex((a.re*t1 + a.im) /t2, (a.im*t1 - a.re) /t2); } } //.. template inline complex operator/ (const int &a, const complex& b) {return complex(a,0)/b;} template inline complex operator/ (const long int &a, const complex& b) {return complex(a,0)/b;} template inline complex operator/ (const float &a, const complex& b) {return complex(a,0)/b;} template inline complex operator/ (const double &a, const complex& b) {return complex(a,0)/b;} template inline complex operator/ (const long double &a, const complex& b) {return complex(a,0)/b;} //.. template inline complex operator/ (const complex& a, const int &b) {return complex(a.re/b,a.im/b);} template inline complex operator/ (const complex& a, const long int &b) {return complex(a.re/b,a.im/b);} template inline complex operator/ (const complex& a, const float &b) {return complex(a.re/b,a.im/b);} template inline complex operator/ (const complex& a, const double &b) {return complex(a.re/b,a.im/b);} template inline complex operator/ (const complex& a, const long double &b) {return complex(a.re/b,a.im/b);} //------------------------------------------------------------------ // stream operators //------------------------------------------------------------------ template std::ostream& operator << (std::ostream &stream, const complex &a) { stream<<"("< std::istream& operator >> (std::istream &stream, complex &a) { stream>>a.re>>a.im; return stream; } //--------------------------------------------------------------------- // bool operators == != //--------------------------------------------------------------------- template inline bool operator == (const complex& a, const complex& b) { return (a.re==b.re) && (a.im==b.im); } //... template inline bool operator == (const int &a, const complex& b) { return (a==b.re) && (b.im inline bool operator == (const long int &a, const complex& b) { return (a==b.re) && (b.im inline bool operator == (const float &a, const complex& b) { return (a==b.re) && (b.im inline bool operator == (const double &a, const complex& b) { return (a==b.re) && (b.im inline bool operator == (const long double &a, const complex& b) { return (a==b.re) && (b.im inline bool operator == (const complex& a, const int &b) { return (a.re==b) && (a.im inline bool operator == (const complex& a, const long int &b) { return (a.re==b) && (a.im inline bool operator == (const complex& a, const float &b) { return (a.re==b) && (a.im inline bool operator == (const complex& a, const double &b) { return (a.re==b) && (a.im inline bool operator == (const complex& a, const long double &b) { return (a.re==b) && (a.im inline bool operator != (const complex& a, const complex& b) { return (a.re!=b.re) || (a.im!=b.im); } //... template inline bool operator != (const int &a, const complex& b) { return (a!=b.re) || (b.im>=small_epsilon); } template inline bool operator != (const long int &a, const complex& b) { return (a!=b.re) || (b.im>=small_epsilon); } template inline bool operator != (const float &a, const complex& b) { return (a!=b.re) || (b.im>=small_epsilon); } template inline bool operator != (const double &a, const complex& b) { return (a!=b.re) || (b.im>=small_epsilon); } template inline bool operator != (const long double &a, const complex& b) { return (a!=b.re) || (b.im>=small_epsilon); } //... template inline bool operator != (const complex& a, const int &b) { return (a.re!=b) || (a.im>=small_epsilon); } template inline bool operator != (const complex& a, const long int &b) { return (a.re!=b) || (a.im>=small_epsilon); } template inline bool operator != (const complex& a, const float &b) { return (a.re!=b) || (a.im>=small_epsilon); } template inline bool operator != (const complex& a, const double &b) { return (a.re!=b) || (a.im>=small_epsilon); } template inline bool operator != (const complex& a, const long double &b) { return (a.re!=b) || (a.im>=small_epsilon); } //--------------------------------------------------------------------- // bool operators >= <= //--------------------------------------------------------------------- template inline bool operator >= (const complex& a, const complex& b) { return (abs(a) >= abs(b)); } //... template inline bool operator >= (const int &a, const complex& b) { return (a >= abs(b)); } template inline bool operator >= (const long int &a, const complex& b) { return (a >= abs(b)); } template inline bool operator >= (const float &a, const complex& b) { return (a >= abs(b)); } template inline bool operator >= (const double &a, const complex& b) { return (a >= abs(b)); } template inline bool operator >= (const long double &a, const complex& b) { return (a >= abs(b)); } //... template inline bool operator >= (const complex& a, const int &b) { return (abs(a) >= b); } template inline bool operator >= (const complex& a, const long int &b) { return (abs(a) >= b); } template inline bool operator >= (const complex& a, const float &b) { return (abs(a) >= b); } template inline bool operator >= (const complex& a, const double &b) { return (abs(a) >= b); } template inline bool operator >= (const complex& a, const long double &b) { return (abs(a) >= b); } //... template inline bool operator <= (const complex& a, const complex& b) { return (abs(a) <= abs(b)); } //... template inline bool operator <= (const int &a, const complex& b) { return (a <= abs(b)); } template inline bool operator <= (const long int &a, const complex& b) { return (a <= abs(b)); } template inline bool operator <= (const float &a, const complex& b) { return (a <= abs(b)); } template inline bool operator <= (const double &a, const complex& b) { return (a <= abs(b)); } template inline bool operator <= (const long double &a, const complex& b) { return (a <= abs(b)); } //... template inline bool operator <= (const complex& a, const int &b) { return (abs(a) <= b); } template inline bool operator <= (const complex& a, const long int &b) { return (abs(a) <= b); } template inline bool operator <= (const complex& a, const float &b) { return (abs(a) <= b); } template inline bool operator <= (const complex& a, const double &b) { return (abs(a) <= b); } template inline bool operator <= (const complex& a, const long double &b) { return (abs(a) <= b); } //--------------------------------------------------------------------- // bool operators > < //--------------------------------------------------------------------- template inline bool operator > (const complex& a, const complex& b) { return (abs(a) > abs(b)); } //... template inline bool operator > (const int &a, const complex& b) { return (a > abs(b)); } template inline bool operator > (const long int &a, const complex& b) { return (a > abs(b)); } template inline bool operator > (const float &a, const complex& b) { return (a > abs(b)); } template inline bool operator > (const double &a, const complex& b) { return (a > abs(b)); } template inline bool operator > (const long double &a, const complex& b) { return (a > abs(b)); } //... template inline bool operator > (const complex& a, const int &b) { return (abs(a) > b); } template inline bool operator > (const complex& a, const long int &b) { return (abs(a) > b); } template inline bool operator > (const complex& a, const float &b) { return (abs(a) > b); } template inline bool operator > (const complex& a, const double &b) { return (abs(a) > b); } template inline bool operator > (const complex& a, const long double &b) { return (abs(a) > b); } //... template inline bool operator < (const complex& a, const complex& b) { return (abs(a) < abs(b)); } //... template inline bool operator < (const int &a, const complex& b) { return (a < abs(b)); } template inline bool operator < (const long int &a, const complex& b) { return (a < abs(b)); } template inline bool operator < (const float &a, const complex& b) { return (a < abs(b)); } template inline bool operator < (const double &a, const complex& b) { return (a < abs(b)); } template inline bool operator < (const long double &a, const complex& b) { return (a < abs(b)); } //... template inline bool operator < (const complex& a, const int &b) { return (abs(a) < b); } template inline bool operator < (const complex& a, const long int &b) { return (abs(a) < b); } template inline bool operator < (const complex& a, const float &b) { return (abs(a) < b); } template inline bool operator < (const complex& a, const double &b) { return (abs(a) < b); } template inline bool operator < (const complex& a, const long double &b) { return (abs(a) < b); } //--------------------------------------------------------------------- // functions //--------------------------------------------------------------------- //----------------------------------------------------- // real(), imag(), conj(), abs(), arg(), phase(), Arg() //----------------------------------------------------- template inline const scalar real(const complex& a) {return a.re;} template inline const scalar imag(const complex& a) {return a.im;} template inline const complex conj(const complex& a) {return complex(a.re,-a.im);} template inline const scalar abs(const complex& a) { if (a.im == 0) return fabs(a.re); if (a.re == 0) return fabs(a.im); scalar rr = fabs(a.re); scalar ri = fabs(a.im); return (rr >= ri) ? (rr * sqrt (1 + (ri*ri/(rr*rr)))) : (ri * sqrt (1 + (rr*rr/(ri*ri)))) ; } template inline const scalar arg(const complex& a) { return atan2(a.im,a.re); } template inline const scalar phase(const complex& a) { return atan2(a.im,a.re); } template inline const scalar Arg(const complex& a) { return atan2(a.im,a.re); } //----------------------------------------------------------------- // sqr(), // complex^int // complex^(long int) // complex^scalar // complex^complex // pow(complex,int) // pow(complex,long int) // pow(complex,scalar) // pow(complex,complex) // // results checked with mathematica: fun(0.5+i*0.4) //------- template inline complex sqr(complex z) {return z*z;} //already defined in physfun.cxx //template //inline scalar sqr(scalar z){return z*z;} template complex operator ^ (const complex& a, const int n) { complex c(1,0); if (n==0) return c; if (n>0) { for (int i=0;in;j--) { c*=a; } } if (n>0) { return c; } else { return 1/c; } } template complex operator ^ (const complex& a, const long int n) { complex c(1,0); if (n==0) return c; if (n>0) { for (int i=0;in;j--) { c*=a; } } if (n>0) { return c; } else { return 1/c; } } template complex operator ^ (const complex& a, const float &r) { return exp(r*log(a)); } template complex operator ^ (const complex& a, const double &r) { return exp(r*log(a)); } template complex operator ^ (const complex& a, const long double &r) { return exp(r*log(a)); } template complex operator ^ (const complex& a, const complex& b) { return exp(b*log(a)); } template complex pow(const complex& a, const int& i) { return a^i; } template complex pow(const complex& a, const long int& i) { return a^i; } template complex pow(const complex& a, const float &r) { return a^r; } template complex pow(const complex& a, const double &r) { return a^r; } template complex pow(const complex& a, const long double &r) { return a^r; } template complex pow(const complex& a, const complex& b) { return a^b; } //---------------------------------------------------------------------- // sqrt(z) // results checked with mathematica: fun(0.5+i*0.4) //---------------------------------------------------------------------- template complex sqrt(const complex& a) { if ((a.re>=0) && (fabs(a.im)(sqrt(a.re),0); } scalar rr = fabs(a.re); scalar ii = fabs(a.im); scalar w = (rr >= ii) ? sqrt (rr/2 * ( 1 + sqrt (1 + sqr(a.im/a.re)))): sqrt (ii/2 * (rr/ii + sqrt (1 + sqr(a.re/a.im)))); complex c; if (a.re >= 0) { c.re = w; c.im = a.imag()/(2*w); } else { c.re = ii / (2*w); c.im = (a.im >= 0) ? w : -w; } return (c.re>=0) ? c : -c; } template complex root (const complex& z, int n, int k) { scalar c=exp(log(abs(z))/n); scalar t=(Arg(z)+2*PI*k)/n; return complex(c*cos(t), c*sin(t)); } //---------------------------------------------------------------------- // exp() log() //---------------------------------------------------------------------- template complex exp (const complex& a) { scalar t=exp(a.re); return complex(t*cos(a.im), t*sin(a.im)); } template complex log (const complex& a) { assert(abs(a)!=0); return complex(log(abs(a)),Arg(a)); } //---------------------------------------------------------------------- // sin() cos() tan() cot() // results checked with mathematica: fun(0.5+i*0.4) //---------------------------------------------------------------------- template complex sin (const complex& a) { return complex(sin(a.re)*cosh(a.im), cos(a.re)*sinh(a.im)); } template complex cos (const complex& a) { return complex (cos(a.re)*cosh(a.im), -sin(a.re)*sinh(a.im)); } template complex tan (const complex& a) { return sin(a)/cos(a); } template complex cot (const complex& a) { return cos(a)/sin(a); } template complex sec (const complex& a) { return 1/cos(a); } template complex csc (const complex& a) { return 1/sin(a); } //--------------------------------------------------------------------- // sinh cosh tanh coth sech csch // results checked with mathematica: fun(0.5+i*0.4) //--------------------------------------------------------------------- template complex sinh (const complex& a) { return complex(sinh(a.re)*cos(a.im), cosh(a.re)*sin(a.im)); } template complex cosh (const complex& a) { return complex(cosh(a.re)*cos(a.im), sinh(a.re)*sin(a.im)); } template complex tanh (const complex& a) { return sinh(a)/cosh(a); } template complex coth (const complex& a) { return cosh(a)/sinh(a); } template complex sech (const complex& a) { return 1/cosh(a); } template complex csch (const complex& a) { return 1/sinh(a); } //--------------------------------------------------------------------- // asin acos atan acot asec acsc // results checked with mathematica: fun(0.5+i*0.4) //--------------------------------------------------------------------- template complex asin(const complex &a) { const complex ImUnit(0,1); return -ImUnit * log(ImUnit*a + sqrt(1-sqr(a))); } template complex acos(const complex &a) { const complex ImUnit(0,1); return -ImUnit * log(a + ImUnit*sqrt(1-sqr(a))); } template complex atan(const complex &a) { const complex ImUnit(0,1); return ImUnit/2 * log((ImUnit+a)/(ImUnit-a)); } template complex acot(const complex &a) { const complex ImUnit(0,1); return ImUnit/2 * log((a-ImUnit)/(a+ImUnit)); } template complex asec(const complex &a) { return acos(1/a); } template complex acsc(const complex &a) { return asin(1/a); } //-------------------------------------------------------------------- // asinh acosh atanh acoth asech acsch // results checked with mathematica: fun(0.5+i*0.4) //-------------------------------------------------------------------- template complex asinh(const complex &a) { return log(a + sqrt(sqr(a)+1)); } template complex acosh(const complex &a) { return log(a + sqrt(sqr(a)-1)); } template complex atanh(const complex &a) { return log((1+a)/(1-a))/2; } template complex acoth(const complex &a) { return log((a+1)/(a-1))/2; } template complex asech(const complex &a) { return acosh(1/a); } template complex acsch(const complex &a) { return asinh(1/a); } //--------------------------------------------------------------------- // divers //--------------------------------------------------------------------- template complex Polar(scalar a,scalar b) { return complex(a*cos(b),a*sin(b)); } //---------------------------------------------------------------------- // solve Equations z^2 + b*z + c = 0 //---------------------------------------------------------------------- template void Solve2 (complex* z, const complex& b, const complex& c) { complex t = sqrt(sqr(b)-4*c); complex p = !b * t; complex q = (p.re >= 0) ? (-(b + t) / 2) : (-(b - t) / 2); z[0] = q; z[1] = c/q; } template complex Solve2(const complex& b, const complex& c, int RootNumber) { assert((RootNumber >=0) && (RootNumber <= 1)); complex z[2]; Solve2(z,b,c); return z[RootNumber]; } //---------------------------------------------------------------------- // solve Equations z^3 + a2*z^2 + a1*z + a0 = 0 //---------------------------------------------------------------------- template void Solve3(complex* z, const complex& a2, const complex& a1, const complex& a0) { const complex ImUnit(0,1); complex q, r, t, a, b, zero(0,0); q = (sqr(a2) - 3*a1) / 9; r = (2*(a2^3)-9*a2*a1+27*a0)/54; t = sqrt(sqr(r) - (q^3)); a = ((!r * t) >=0.0) ? -((r+t)^(1.0/3)) : -((r-t)^(1.0/3)); b = ((a == zero) ? zero : (q/a)); z[0] = -(a+b)/2-a2/3+ImUnit*sqrt(3)*(a-b)/2; z[1] = -(a+b)/2-a2/3-ImUnit*sqrt(3)*(a-b)/2; z[2] = a + b - a2/scalar(3); } template complex Solve3(const complex& a2, const complex& a1, const complex& a0, int RootNumber) { assert((RootNumber >= 0) && (RootNumber <= 2)); complex z[3]; Solve3 (z,a2,a1,a0); return z[RootNumber]; } //---------------------------------------------------------------------- // solve Equations z^4 + a3*z^3 + a2*z^2 + a1*z + a0 = 0 //---------------------------------------------------------------------- template void Solve4(complex* z, const complex& a3, const complex& a2, const complex& a1, const complex& a0) { complex u[3], t1, t2, t; Solve3 (u,-a2,(a1*a3 - 4*a0), -(sqr(a1)+a0*sqr(a3)-4*a0*a2)); t = *u; t1 = sqrt(sqr(a3)/4 - a2 + t); t2 = sqrt(sqr(t) /4 - a0); Solve2 ( z, (a3/2 - t1), (t/2 + t2)); Solve2 (&(z[2]), (a3/2 + t1), (t/2 - t2)); } template complex Solve4(const complex& a3, const complex& a2, const complex& a1, const complex& a0, int RootNumber) { assert((RootNumber >= 0) && (RootNumber <= 3)); complex z[4]; Solve4 (z,a3,a2,a1,a0); return z[RootNumber]; } #endif // __COMPLEX_CXX__ // // $Log: complex.hxx,v $ // Revision 1.2 2003/05/01 13:11:48 carsten // headerfiles without .h // // Revision 1.1 2002/04/12 11:56:14 carsten // moved from indracorr // // Revision 1.1 2001/10/09 19:50:49 carsten // added // // Revision 1.4 2001/10/09 19:48:22 carsten // added comments //