1 //This file is part of CRAB
2 //http://www.nscl.msu.edu/~pratt/freecodes/crab/home.html
4 /*--------------------------------------------------
8 -- Some modification for speed
9 -- Some protections from overflow and underflow
10 -- Solving of equations of order 2,3,4:
11 Solve2, Solve3, Solve4;
12 --------------------------------------------------*/
14 #ifndef __COMPLEX_CXX__
15 #define __COMPLEX_CXX__
18 #define small_epsilon 1e-12
22 #define PI 3.141592653589793238462643
29 /////////////////////////// Helper Error Function
31 void ComplexError (char *msg)
33 cout << endl << msg << endl;
37 void ComplexWarning (char *msg)
39 cout << endl << msg << endl;
47 Complex (double a=0, double b=0): Re(a),Im(b) {}
49 double GetRe () { return Re; }
50 double GetIm () { return Im; }
51 void SetRe (double a) { Re = a; }
52 void SetIm (double a) { Im = a; }
53 void Set (double a, double b) { Re = a; Im = b; }
54 void SetPolar (double, double);
57 Complex operator ! () const;
58 Complex operator ! ();
59 Complex operator + () const;
60 Complex operator + ();
61 Complex operator - () const;
62 Complex operator - ();
63 Complex operator += (const Complex &);
64 Complex operator += (double);
65 Complex operator -= (const Complex &);
66 Complex operator -= (double);
67 Complex operator *= (const Complex &);
68 Complex operator *= (double);
69 Complex operator /= (const Complex &);
70 Complex operator /= (double);
72 friend ostream& operator << (ostream&, const Complex &);
73 friend istream& operator >> (istream&, Complex &);
76 const Complex ImUnit (0,1);
78 void Zero (Complex &);
79 Complex Polar (double, double);
80 double real (const Complex &);
81 double imag (const Complex &);
82 double Arg (const Complex &);
83 double phase(const Complex &);
84 double abs (const Complex &);
85 void Solve2 (Complex*, const Complex&, const Complex&);
86 void Solve3 (Complex*, const Complex&, const Complex&, const Complex&);
87 void Solve4 (Complex*, const Complex&, const Complex&, const Complex&, const Complex&);
88 Complex Solve2 (const Complex&, const Complex&, int RootNumber);
89 Complex Solve3 (const Complex&, const Complex&, const Complex&, int RootNumber);
90 Complex Solve4 (const Complex&, const Complex&, const Complex&, const Complex&, int RootNumber);
91 Complex conj (const Complex &);
92 Complex sqr (const Complex &);
93 Complex sqrt (const Complex &, int=0);
94 Complex pow (Complex, int);
95 Complex pow (Complex, double);
96 Complex pow (Complex, Complex);
97 Complex root (const Complex &, int, int=0);
98 Complex exp (const Complex &);
99 Complex log (const Complex &);
100 Complex sin (const Complex &);
101 Complex cos (const Complex &);
102 Complex tan (const Complex &);
103 Complex cot (const Complex &);
104 Complex sec (const Complex &);
105 Complex csc (const Complex &);
106 Complex sinh (const Complex &);
107 Complex cosh (const Complex &);
108 Complex tanh (const Complex &);
109 Complex coth (const Complex &);
110 Complex sech (const Complex &);
111 Complex csch (const Complex &);
112 Complex asin (const Complex &, int=0);
113 Complex acos (const Complex &, int=0);
114 Complex atan (const Complex &);
115 Complex acot (const Complex &);
116 Complex asec (const Complex &, int=0);
117 Complex acsc (const Complex &, int=0);
118 Complex asinh(const Complex &, int=0);
119 Complex acosh(const Complex &, int=0);
120 Complex atanh(const Complex &);
121 Complex acoth(const Complex &);
122 Complex asech(const Complex &, int=0);
123 Complex acsch(const Complex &, int=0);
125 Complex operator ^ (const Complex &, int);
126 Complex operator ^ (const Complex &, double);
127 Complex operator ^ (const Complex &, const Complex &);
129 double operator += (double&, const Complex &);
130 double operator -= (double&, const Complex &);
131 double operator *= (double&, const Complex &);
132 double operator /= (double&, const Complex &);
134 Complex operator + (const Complex &, const Complex &);
135 Complex operator + (const Complex &, double);
136 Complex operator + (double, const Complex &);
137 Complex operator - (const Complex &, const Complex &);
138 Complex operator - (const Complex &, double);
139 Complex operator - (double, const Complex &);
140 Complex operator * (const Complex &, const Complex &);
141 Complex operator * (const Complex &, double);
142 Complex operator * (double, const Complex &);
143 Complex operator / (const Complex &, const Complex &);
144 Complex operator / (const Complex &, double);
145 Complex operator / (double, const Complex &);
147 int operator == (const Complex &, double);
148 int operator == (double, const Complex &);
149 int operator == (const Complex &, const Complex &);
150 int operator != (const Complex &, double);
151 int operator != (double, const Complex &);
152 int operator != (const Complex &, const Complex &);
153 int operator >= (const Complex &, double);
154 int operator >= (double, const Complex &);
155 int operator >= (const Complex &, const Complex &);
156 int operator <= (const Complex &, double);
157 int operator <= (double, const Complex &);
158 int operator <= (const Complex &, const Complex &);
159 int operator > (const Complex &, double);
160 int operator > (double, const Complex &);
161 int operator > (const Complex &, const Complex &);
162 int operator < (const Complex &, double);
163 int operator < (double, const Complex &);
164 int operator < (const Complex &, const Complex &);
166 ////////////////////////////////////////////////
168 inline double sqr(double a) { return a*a; }
170 inline Complex Complex::operator + () const
175 inline Complex Complex::operator + ()
180 inline Complex Complex::operator - () const
182 return Complex (-Re, -Im);
185 inline Complex Complex::operator - ()
187 return Complex (-Re, -Im);
190 inline Complex Complex::operator ! () const // complex conjugate //
192 return Complex (Re, -Im);
195 inline Complex Complex::operator ! () // complex conjugate //
197 return Complex (Re, -Im);
200 /////////////////////// +=,-=,*=,/=
202 double operator += (double &a, const Complex &b)
204 if (fabs(b.Im) < small_epsilon) a+=b.Re;
206 ComplexError ("Error in double+=Complex: Complex is not double number");
210 double operator -= (double &a, const Complex &b)
212 if (fabs(b.Im) < small_epsilon) a-=b.Re;
214 ComplexError ("Error in double -=Complex: Complex is not double number");
218 double operator *= (double &a, const Complex &b)
220 if (fabs(b.Im) < small_epsilon) a*=b.Re;
222 ComplexError ("Error in double *=Complex: Complex is not double number");
226 double operator /= (double &a, const Complex &b)
228 if (fabs(b.Im) < small_epsilon) a/=b.Re;
230 ComplexError ("Error in double /=Complex: Complex is not double number");
234 inline Complex Complex::operator += (const Complex &a)
241 inline Complex Complex::operator += (double a)
247 inline Complex Complex::operator -= (const Complex &a)
254 inline Complex Complex::operator -= (double a)
260 Complex Complex::operator *= (const Complex &a)
262 double t1=Re*a.Re, t2=Im*a.Im;
263 Im = (Re+Im) * (a.Re+a.Im) - t1 - t2;
268 inline Complex Complex::operator *= (double a)
275 Complex Complex::operator /= (const Complex &a)
278 if (fabs(a.Re) >= fabs(a.Im))
281 t2 = a.Re + a.Im * t1;
282 temp = (Re + Im * t1) / t2;
283 Im = (Im - Re * t1) / t2;
289 t2 = a.Re * t1 + a.Im;
290 temp = (Re * t1 + Im) / t2;
291 Im = (Im * t1 - Re) / t2;
297 inline Complex Complex::operator /= (double a)
304 /////////////////////////// +,-,*,/
306 inline Complex operator + (const Complex &a, const Complex &b)
308 return Complex (a.Re+b.Re, a.Im+b.Im);
311 inline Complex operator + (const Complex &a, double b)
313 return Complex (a.Re+b, a.Im);
316 inline Complex operator + (double b, const Complex &a)
318 return Complex (a.Re+b, a.Im);
321 inline Complex operator - (const Complex &a, const Complex &b)
323 return Complex (a.Re-b.Re, a.Im-b.Im);
326 inline Complex operator - (const Complex &a, double b)
328 return Complex (a.Re-b, a.Im);
331 inline Complex operator - (double b, const Complex &a)
333 return Complex (b-a.Re, -a.Im);
336 Complex operator * (const Complex &a, const Complex &b)
338 double t1 = a.Re * b.Re;
339 double t2 = a.Im * b.Im;
340 return Complex (t1 - t2, (a.Re+a.Im) * (b.Re+b.Im) - t1 - t2);
343 inline Complex operator * (const Complex &a, double b)
345 return Complex (a.Re*b, a.Im*b);
348 inline Complex operator * (double b, const Complex &a)
350 return Complex (a.Re*b, a.Im*b);
353 inline Complex operator / (const Complex &a, double b)
355 return Complex (a.Re/b, a.Im/b);
358 inline Complex operator / (const Complex &a, const Complex &b)
361 if (fabs(b.Re) >= fabs(b.Im))
364 t2 = b.Re + b.Im * t1;
365 return Complex ((a.Re + a.Im * t1) / t2, (a.Im - a.Re * t1) / t2);
370 t2 = b.Re * t1 + b.Im;
371 return Complex ((a.Re * t1 + a.Im) / t2, (a.Im * t1 - a.Re) / t2);
375 inline Complex operator / (double b, const Complex &a)
377 return (Complex (b,0)) / a;
380 //////////////////////// <<,>>
382 ostream& operator << (ostream &stream, const Complex &a)
384 stream<<" "<<a.Re<<" "<<a.Im<<" ";
388 istream& operator >> (istream &stream, Complex &a)
394 /////////////////////// ==,!=
396 inline int operator == (const Complex &a, double b)
398 return (a.Re==b) && (fabs(a.Im)<small_epsilon);
401 inline int operator == (double b, const Complex &a)
403 return (a.Re==b) && (fabs(a.Im)<small_epsilon);
406 inline int operator == (const Complex &a, const Complex &b)
408 return (a.Re==b.Re) && (a.Im==b.Im);
411 inline int operator != (const Complex &a, double b)
413 return (a.Re!=b) || (fabs(a.Im)>small_epsilon);
416 inline int operator != (double b, const Complex &a)
418 return (a.Re!=b) || (fabs(a.Im)>small_epsilon);
421 inline int operator != (const Complex &a, const Complex &b)
423 return (a.Re!=b.Re) || (a.Im!=b.Im);
426 /////////////////////// >=,<=
428 inline int operator >= (const Complex &a, double b)
433 inline int operator >= (double b, const Complex &a)
438 inline int operator >= (const Complex &a, const Complex &b)
440 return abs(a) >= abs(b);
443 inline int operator <= (const Complex &a, double b)
448 inline int operator <= (double b, const Complex &a)
453 inline int operator <= (const Complex &a, const Complex &b)
455 return abs(a) <= abs(b);
458 /////////////////////// >,<
460 inline int operator > (const Complex &a, double b)
465 inline int operator > (double b, const Complex &a)
470 inline int operator > (const Complex &a, const Complex &b)
472 return abs(a) > abs(b);
475 inline int operator < (const Complex &a, double b)
480 inline int operator < (double b, const Complex &a)
485 inline int operator < (const Complex &a, const Complex &b)
487 return abs(a) < abs(b);
490 ///////////////////////// Functions
491 double real (const Complex &a)
495 double imag (const Complex &a)
499 double abs (const Complex &a)
501 if (a.Im == 0) return fabs(a.Re);
502 if (a.Re == 0) return fabs(a.Im);
503 double R = fabs(a.Re), I = fabs(a.Im);
505 (R * sqrt (1 + sqr(a.Im/a.Re))) :
506 (I * sqrt (1 + sqr(a.Re/a.Im))) ;
509 double Arg (const Complex &a)
511 return atan2(a.Im,a.Re);
514 double phase (const Complex &a)
516 return atan2(a.Im,a.Re);
519 inline void Zero (Complex &a) { a.Re=a.Im=0; }
521 Complex conj (const Complex &a) { return !a; }
522 Complex pow (Complex a, int n) { return a^n; }
523 Complex pow (Complex a, double n) { return a^n; }
524 Complex pow (Complex a, Complex b) { return a^b; }
526 inline Complex sqr (const Complex &a) { return a*a; }
528 Complex sqrt (const Complex &a, int flag)
530 if ((a.Re>=0) && (fabs(a.Im)<small_epsilon))
531 return flag ? -sqrt(a.Re) : sqrt(a.Re);
532 double R = fabs(a.Re), I = fabs(a.Im);
533 double w = (R >= I) ?
534 sqrt (R/2 * ( 1 + sqrt (1 + sqr(a.Im/a.Re)))):
535 sqrt (I/2 * (R/I + sqrt (1 + sqr(a.Re/a.Im))));
545 c.Im = (a.Im >= 0) ? w : -w;
547 return ((flag && (c.Re<0)) || (!flag && (c.Re>=0))) ? c : -c;
550 Complex operator ^ (const Complex &a, int n)
554 if (n>0) for (int i=0;i<n;i++) c*=a;
555 else for (int j=0;j>n;j--) c*=a;
560 Complex operator ^ (const Complex &a, double n)
562 return exp(n*log(a));
565 Complex operator ^ (const Complex &a, const Complex &b)
567 return exp(b*log(a));
570 Complex root (const Complex &z, int n, int k)
572 double c=exp(log(abs(z))/n);
573 double t=(Arg(z)+2*PI*k)/n;
574 return Complex (c*cos(t), c*sin(t));
577 Complex exp (const Complex &a)
580 return Complex (t*cos(a.Im), t*sin(a.Im));
583 Complex log (const Complex &a)
586 ComplexError("Error in function log(Complex): argument is 0");
587 return Complex (log(abs(a)), Arg(a));
590 Complex sin (const Complex &a)
592 return Complex (sin(a.Re)*cosh(a.Im), cos(a.Re)*sinh(a.Im));
595 Complex cos (const Complex &a)
597 return Complex (cos(a.Re)*cosh(a.Im), -sin(a.Re)*sinh(a.Im));
600 Complex tan (const Complex &a)
602 return sin(a)/cos(a);
605 Complex cot (const Complex &a)
607 return cos(a)/sin(a);
610 Complex sec (const Complex &a)
615 Complex csc (const Complex &a)
620 Complex sinh (const Complex &a)
622 return Complex (sinh(a.Re)*cos(a.Im), cosh(a.Re)*sin(a.Im));
625 Complex cosh (const Complex &a)
627 return Complex (cosh(a.Re)*cos(a.Im), sinh(a.Re)*sin(a.Im));
630 Complex tanh (const Complex &a)
632 return sinh(a)/cosh(a);
635 Complex coth (const Complex &a)
637 return cosh(a)/sinh(a);
640 Complex sech (const Complex &a)
645 Complex csch (const Complex &a)
649 //////////////////////// Inverce trigonometric functions
651 Complex asin (const Complex &a, int flag)
653 return -ImUnit * log(ImUnit*a + sqrt(1-sqr(a), flag));
656 Complex acos (const Complex &a, int flag)
658 return -ImUnit * log(a + ImUnit*sqrt(1-sqr(a), flag));
661 Complex atan (const Complex &a)
663 return ImUnit/2 * log((ImUnit+a)/(ImUnit-a));
666 Complex acot (const Complex &a)
668 return ImUnit/2 * log((a-ImUnit)/(a+ImUnit));
671 Complex asec (const Complex &a, int flag)
673 return acos(1/a, flag);
676 Complex acsc (const Complex &a, int flag)
678 return asin(1/a, flag);
681 Complex asinh (const Complex &a, int flag)
683 return log(a + sqrt(sqr(a)+1, flag));
686 Complex acosh (const Complex &a, int flag)
688 return log(a + sqrt(sqr(a)-1, flag));
691 Complex atanh (const Complex &a)
693 return log((1+a)/(1-a)) / 2;
696 Complex acoth (const Complex &a)
698 return log((a+1)/(a-1)) / 2;
701 Complex asech (const Complex &a, int flag)
703 return acosh(1/a, flag);
706 Complex acsch (const Complex &a, int flag)
708 return asinh(1/a, flag);
711 Complex Polar (double a, double b)
713 return Complex (a*cos(b), a*sin(b));
716 void Complex::SetPolar (double a, double b)
722 void Complex::SetAbs (double a)
729 void Complex::SetArg (double b)
736 void Solve2 (Complex* z, const Complex &b, const Complex &c)
737 // finding z of equation: z^2 + b*z + c = 0
739 Complex t = sqrt(sqr(b)-4*c);
740 Complex q = ((!b * t).Re >= 0) ? (-(b + t) / 2) : (-(b - t) / 2);
745 Complex Solve2 (const Complex &b, const Complex &c, int RootNumber)
747 if ((RootNumber < 0) || (RootNumber > 1))
748 ComplexError ("Error in Solve2: wrong root number");
751 return z[RootNumber];
754 void Solve3 (Complex* z, const Complex &a2, const Complex &a1, const Complex &a0)
755 // finding z of equation: z^3 + a2*z^2 + a1*z + a0 = 0
757 Complex q, r, t, a, b, zero(0,0);
758 q = (sqr(a2) - 3*a1) / 9;
759 r = (2*(a2^3) - 9*a2*a1 + 27*a0) / 54;
760 t = sqrt((r^2) - (q^3));
761 a = ((!r * t) >=0.0) ? -((r+t)^(1.0/3)) : -((r-t)^(1.0/3));
762 b = ((a == zero) ? zero : (q/a));
763 z[0] = -(a+b)/2 - a2/3 + ImUnit*sqrt(3)*(a-b)/2;
764 z[1] = -(a+b)/2 - a2/3 - ImUnit*sqrt(3)*(a-b)/2;
768 Complex Solve3 (const Complex &a2, const Complex &a1, const Complex &a0, int RootNumber)
770 if ((RootNumber < 0) || (RootNumber > 2))
771 ComplexError ("Error in Solve3: wrong root number");
774 return z[RootNumber];
777 void Solve4 (Complex* z, const Complex &a3, const Complex &a2, const Complex &a1, const Complex &a0)
778 // finding z of equation: z^4 + a3*z^3 + a2*z^2 + a1*z + a0 = 0
780 Complex u[3], t1, t2, t;
781 Solve3 (u, -a2, (a1*a3 - 4*a0), -((a1^2) + a0*(a3^2) - 4*a0*a2));
783 t1 = sqrt((a3^2)/4 - a2 + t);
784 t2 = sqrt((t^2)/4 - a0);
785 Solve2 ( z, (a3/2 - t1), (t/2 + t2));
786 Solve2 (&(z[2]), (a3/2 + t1), (t/2 - t2));
789 Complex Solve4 (const Complex &a3, const Complex &a2, const Complex &a1, const Complex &a0, int RootNumber)
791 if ((RootNumber < 0) || (RootNumber > 3))
792 ComplexError ("Error in Solve4: wrong root number");
794 Solve4 (z,a3,a2,a1,a0);
795 return z[RootNumber];
799 #endif // __COMPLEX_CXX__ //