home *** CD-ROM | disk | FTP | other *** search
- /* -------------------------------------------------------------------- */
- /* complex.cpp */
- /* */
- /* Z++ Version 1.0 Last revised 04/03/92 */
- /* */
- /* Complex number class for Turbo C++/Borland C++. */
- /* Copyright 1992 by Carl W. Moreland */
- /* This source code may be freely distributed as long as the copyright */
- /* notice remains intact. */
- /* -------------------------------------------------------------------- */
-
- #include "complex.h"
-
- unsigned char complex::zArgMode = Z_RADIANS;
- unsigned char complex::zPrintMode = Z_COMMA;
- unsigned char complex::zLetter = 'i';
-
- /* ----- Constructors ------------------------------------------------- */
-
- complex::complex(void)
- {
- re = 0;
- im = 0;
- }
-
- complex::complex(const double real, const double imag)
- {
- re = real;
- im = imag;
- }
-
- complex::complex(const complex& z)
- {
- re = z.re;
- im = z.im;
- }
-
- /* -------------------------------------------------------------------- */
-
- double re(const complex& z) // friend version
- {
- return z.re;
- }
-
- double im(const complex& z) // friend version
- {
- return z.im;
- }
-
- double real(const complex& z) // friend version
- {
- return z.re;
- }
-
- double imag(const complex& z) // friend version
- {
- return z.im;
- }
-
- double mag(const complex& z) // magnitude |z|
- {
- return sqrt(z.re*z.re + z.im*z.im);
- }
-
- double arg(const complex& z) // argument (angle)
- {
- if(z.re == 0 && z.im == 0) // this is actually a domain error
- return 0;
- if(complex::zArgMode == Z_RADIANS)
- return atan2(z.im, z.re);
- return atan2(z.im, z.re)/M_PI*180;
- }
-
- complex conj(const complex& z) // complex conjugate
- {
- return complex(z.re, -z.im);
- }
-
- double norm(const complex& z)
- {
- return z.re*z.re + z.im*z.im;
- }
-
- complex ptor(double mag, double angle) // polar-to-rectangular
- {
- if(complex::zArgMode == Z_RADIANS)
- return complex(mag*cos(angle), mag*sin(angle));
- return complex(mag*cos(angle/180*M_PI), mag*sin(angle/180*M_PI));
- }
-
- complex rtop(double x, double y) // rectangular-to-polar
- {
- if(x == 0 && y == 0) // this is actually a domain error
- return Z0;
- if(complex::zArgMode == Z_RADIANS)
- return complex(sqrt(x*x + y*y), atan2(y, x));
- return complex(sqrt(x*x + y*y), atan2(y, x)*180/M_PI);
- }
-
- complex& complex::topolar(void)
- {
- double re_tmp = re;
-
- if(re != 0 || im != 0) // z = (0,0) is a domain error
- {
- re = sqrt(re*re + im*im);
- im = atan2(im, re_tmp);
- }
-
- if(complex::zArgMode == Z_DEGREES)
- im *= (180/M_PI);
-
- return *this;
- }
-
- complex& complex::torect(void)
- {
- double re_tmp = re;
-
- re = re_tmp*cos(im);
- im = re_tmp*sin(im);
-
- return *this;
- }
-
- /* ----- Operators ---------------------------------------------------- */
-
- void complex::operator=(const complex& z)
- {
- re = z.re;
- im = z.im;
- }
-
- complex& complex::operator+=(const complex& z)
- {
- re += z.re;
- im += z.im;
- return *this;
- }
-
- complex& complex::operator-=(const complex& z)
- {
- re -= z.re;
- im -= z.im;
- return *this;
- }
-
- complex& complex::operator*=(const complex& z)
- {
- *this = *this * z;
- return *this;
- }
-
- complex& complex::operator/=(const complex& z)
- {
- *this = *this / z;
- return *this;
- }
-
- complex complex::operator+() const
- {
- return *this;
- }
-
- complex complex::operator-() const
- {
- return complex(-re, -im);
- }
-
- complex operator+(const complex& z1, const complex& z2)
- {
- return complex(z1.re + z2.re, z1.im + z2.im);
- }
-
- complex operator+(const complex& z, const double x)
- {
- return complex(z.re+x, z.im);
- }
-
- complex operator+(const double x, const complex& z)
- {
- return complex(z.re+x, z.im);
- }
-
- complex operator-(const complex& z1, const complex& z2)
- {
- return complex(z1.re - z2.re, z1.im - z2.im);
- }
-
- complex operator-(const complex& z, const double x)
- {
- return complex(z.re-x, z.im);
- }
-
- complex operator-(const double x, const complex& z)
- {
- return complex(x-z.re, -z.im);
- }
-
- complex operator*(const complex& z1, const complex& z2)
- {
- double re = z1.re*z2.re - z1.im*z2.im;
- double im = z1.re*z2.im + z1.im*z2.re;
- return complex(re, im);
- }
-
- complex operator*(const complex& z, const double x)
- {
- return complex(z.re*x, z.im*x);
- }
-
- complex operator*(const double x, const complex& z)
- {
- return complex(z.re*x, z.im*x);
- }
-
- complex operator/(const complex& z1, const complex& z2)
- {
- if(z2 == Z0)
- return complex(Zinf); // z2 = Z0 is an error!
-
- double denom = z2.re*z2.re + z2.im*z2.im;
- double re = (z1.re*z2.re + z1.im*z2.im)/denom;
- double im = (z2.re*z1.im - z2.im*z1.re)/denom;
- return complex(re, im);
- }
-
- complex operator/(const complex& z, const double x)
- {
- return complex(z.re/x, z.im/x);
- }
-
- complex operator/(const double x, const complex& z)
- {
- if(z == Z0)
- return complex(Zinf); // z = Z0 is an error!
-
- double denom = z.re*z.re + z.im*z.im;
- return complex(x*z.re/denom, -z.im*x/denom);
- }
-
- complex operator^(const complex& z1, const complex& z2)
- {
- return pow(z1, z2);
- }
-
- int operator==(const complex& z1, const complex& z2)
- {
- return (z1.re == z2.re) && (z1.im == z2.im);
- }
-
- int operator!=(const complex& z1, const complex& z2)
- {
- return (z1.re != z2.re) || (z1.im != z2.im);
- }
-
- /* ----- Math functions ----------------------------------------------- */
-
- double abs(const complex& z)
- {
- return sqrt(z.re*z.re + z.im*z.im);
- }
-
- complex sqrt(const complex& z)
- {
- return ptor(sqrt(abs(z)), arg(z)/2);
- }
-
- complex pow(const complex& base, const double exponent)
- {
- if(base != Z0 && exponent == 0.0)
- return complex(1,0);
-
- if (base == Z0 && exponent > 0)
- return Z0;
-
- // base == Z0 && exponent == 0 is undefined!
-
- return ptor(pow(abs(base), exponent), exponent*arg(base));
- }
-
- complex pow(const double base, const complex& exponent)
- {
- if(base != 0.0 && exponent == Z0)
- return complex(1,0);
-
- if (base == 0 && re(exponent) > 0)
- return complex(0,0);
-
- // base == 0 && re(exponent) == 0 is undefined!
-
- if(base > 0.0)
- return exp(exponent * log(fabs(base)));
-
- return exp(exponent * complex(log(fabs(base)), M_PI));
- }
-
- complex pow(const complex& base, const complex& exponent)
- {
- if(base != Z0 && exponent == Z0)
- return complex(1,0);
-
- if(base == Z0 && re(exponent) > 0)
- return complex(0,0);
-
- // base == Z0 && re(exponent) == 0 is undefined!
-
- return exp(exponent * log(base));
- }
-
- /* ----- Trig functions ----------------------------------------------- */
-
- complex exp(const complex& z)
- {
- double mag = exp(z.re);
- return complex(mag*cos(z.im), mag*sin(z.im));
- }
-
- complex log(const complex& z)
- {
- return complex(log(mag(z)), atan2(z.im, z.re));
- }
-
- complex log10(const complex& z)
- {
- return log(z) * M_LOG10E;
- }
-
- complex sin(const complex& z)
- {
- return (exp(Zi*z) - exp(-Zi*z))/(2*Zi);
- }
-
- complex cos(const complex& z)
- {
- return (exp(Zi*z) + exp(-Zi*z))/2;
- }
-
- complex tan(const complex& z)
- {
- return sin(z)/cos(z);
- }
-
- complex asin(const complex& z)
- {
- return -Zi*log(Zi*z+sqrt(1-z*z));
- }
-
- complex acos(const complex& z)
- {
- return -Zi*log(z+Zi*sqrt(1-z*z));
- }
-
- complex atan(const complex& z)
- {
- return -0.5*Zi * log((1+Zi*z)/(1-Zi*z));
- }
-
- complex sinh(const complex& z)
- {
- return (exp(z) - exp(-z))/2;
- }
-
- complex cosh(const complex& z)
- {
- return (exp(z) + exp(-z))/2;
- }
-
- complex tanh(const complex& z)
- {
- return sinh(z)/cosh(z);
- }
-
- /* ----- Misc functions ----------------------------------------------- */
-
- void complex::SetArgMode(unsigned char mode) const
- {
- if(mode == Z_RADIANS || mode == Z_DEGREES)
- zArgMode = mode;
- }
-
- void complex::SetPrintMode(unsigned char mode) const
- {
- if(mode == Z_COMMA || mode == Z_LETTER)
- zPrintMode = mode;
- }
-
- void complex::SetLetter(unsigned char letter) const
- {
- zLetter = letter;
- }
-
- /* ----- Stream I/O --------------------------------------------------- */
-
- ostream& operator<<(ostream& s, const complex& z)
- {
- char sign[] = " ";
-
- if(complex::zPrintMode == Z_COMMA)
- return s << "(" << z.re << ", " << z.im << ")";
-
- if(z.im == 0 || z.im/fabs(z.im) == 1)
- sign[1] = '+';
- else
- sign[1] = '-';
- return s << z.re << sign << complex::zLetter << fabs(z.im);
-
- }
-
- istream& operator>>(istream& s, complex& z)
- {
- char ch;
- double real=0, imag=0;
-
- s >> ch;
- if(ch == '(')
- {
- s >> real >> ch;
- if(ch == ',')
- s >> imag >> ch;
- if(ch != ')')
- s.clear(ios::badbit | s.rdstate());
- }
- else
- {
- s.putback(ch);
- s >> real;
- }
-
- z = complex(real, imag);
- return s;
- }
-
-