Download: complex.zip
This is a class for complex numbers.
See: complex.h complex.cpp ctest.cpp (test program)
complex.h
/* Complex.h Complex Number Library - Include File class Complex: declarations for Complex numbers. All function names, member names, and operators have been borrowed from AT&T C++, except for the addition of: friend Complex acos(Complex &); friend Complex asin(Complex &); friend Complex atan(Complex &); friend Complex log10(Complex &); friend Complex tan(Complex &); friend Complex tanh(Complex &); Complex operator+(); Complex operator-(); */ #pragma once #include <math.h> #include <string> #include <iostream> using namespace std; class Complex { public: // constructors Complex(double re_val, double im_val=0); Complex(); // member access double &real() { return re; } double &imag() { return im; } static const double dgrad; // object manipulation double mag() { return sqrt(re*re+im*im); } double angle() { return dgrad*atan2(im,re); } // Complex manipulations friend double real(Complex &); // the real part friend double imag(Complex &); // the imaginary part friend Complex conj(Complex &); // the Complex conjugate friend double norm(Complex &); // the square of the magnitude friend double arg(Complex &); // the angle in the plane // Create a Complex object given polar coordinates static Complex polar(double mag, double angle=0); // Overloaded ANSI C math functions friend double abs(Complex &); friend Complex acos(Complex &); friend Complex asin(Complex &); friend Complex atan(Complex &); friend Complex cos(Complex &); friend Complex cosh(Complex &); friend Complex exp(Complex &); friend Complex log(Complex &); friend Complex log10(Complex &); friend Complex pow(Complex &base, double expon); friend Complex pow(double base, Complex &expon); friend Complex pow(Complex &base, Complex &expon); friend Complex sin(Complex &); friend Complex sinh(Complex &); friend Complex sqrt(Complex &); friend Complex tan(Complex &); friend Complex tanh(Complex &); // Binary Operator Functions friend Complex operator+(Complex const &, Complex const &); friend Complex operator+(double , Complex const &); friend Complex operator+(Complex const &, double); friend Complex operator-(Complex const &, Complex const &); friend Complex operator-(double, Complex const &); friend Complex operator-(Complex const &, double); friend Complex operator*(Complex const &, Complex const &); friend Complex operator*(double , Complex const &); friend Complex operator*(Complex const &, double); friend Complex operator/(Complex const &, Complex const &); friend Complex operator/(Complex const &, double); friend Complex operator/(double, Complex const &); friend int operator==(Complex const &, Complex const &); friend int operator!=(Complex const &, Complex const &); Complex & operator+=(Complex &); Complex & operator+=(double); Complex & operator-=(Complex &); Complex & operator-=(double); Complex & operator*=(Complex &); Complex & operator*=(double); Complex & operator/=(Complex &); Complex & operator/=(double); Complex operator+(); Complex operator-(); string format(); string phasor(); // Implementation private: double re, im; }; // Inline Complex functions inline Complex::Complex(double re_val, double im_val) { re = re_val; im = im_val; } inline Complex::Complex() { /* if you want your Complex numbers initialized ... re = im = 0; */ } inline Complex Complex::operator+() { return *this; } inline Complex Complex::operator-() { return Complex(-re, -im); } // Definitions of compound-assignment operator member functions inline Complex & Complex::operator+=(Complex & z2) { re += z2.re; im += z2.im; return *this; } inline Complex & Complex::operator+=(double re_val2) { re += re_val2; return *this; } inline Complex & Complex::operator-=(Complex & z2) { re -= z2.re; im -= z2.im; return *this; } inline Complex & Complex::operator-=(double re_val2) { re -= re_val2; return *this; } inline Complex & Complex::operator*=(double re_val2) { re *= re_val2; im *= re_val2; return *this; } inline Complex & Complex::operator/=(double re_val2) { re /= re_val2; im /= re_val2; return *this; } // Definitions of non-member Complex functions inline double real(Complex & z) { return z.re; } inline double imag(Complex & z) { return z.im; } inline Complex conj(Complex & z) { return Complex(z.re, -z.im); } inline double norm(Complex &x) // z = x*conj(x) or |x|^2 { return x.re*x.re+x.im*x.im; } inline Complex Complex::polar(double mag, double angle) { angle /= dgrad; return Complex(mag*cos(angle), mag*sin(angle)); } // Definitions of non-member binary operator functions inline Complex operator+(Complex const & z1, Complex const & z2) { return Complex(z1.re + z2.re, z1.im + z2.im); } inline Complex operator+(double re_val1, Complex const & z2) { return Complex(re_val1 + z2.re, z2.im); } inline Complex operator+(Complex const & z1, double re_val2) { return Complex(z1.re + re_val2, z1.im); } inline Complex operator-(Complex const & z1, Complex const & z2) { return Complex(z1.re - z2.re, z1.im - z2.im); } inline Complex operator-(double re_val1, Complex const & z2) { return Complex(re_val1 - z2.re, -z2.im); } inline Complex operator-(Complex const & z1, double re_val2) { return Complex(z1.re - re_val2, z1.im); } inline Complex operator*(Complex const & z1, double re_val2) { return Complex(z1.re*re_val2, z1.im*re_val2); } inline Complex operator*(double re_val1, Complex const & z2) { return Complex(z2.re*re_val1, z2.im*re_val1); } inline Complex operator/(Complex const & z1, double re_val2) { return Complex(z1.re/re_val2, z1.im/re_val2); } inline int operator==(Complex const & z1, Complex const & z2) { return z1.re == z2.re && z1.im == z2.im; } inline int operator!=(Complex const & z1, Complex const & z2) { return z1.re != z2.re || z1.im != z2.im; } #if defined(STREAM_IO) // Complex stream I/O ostream & operator<<(ostream &, Complex &); istream & operator>>(istream &, Complex &); #endif
/*** complex.cpp $Revision$ $Date$ * * Complex math routines * ***/ #include <stdio.h> #define _USE_MATH_DEFINES #include <math.h> #include "complex.h" const double Complex::dgrad = 180.0/M_PI; Complex operator *(Complex const &x, Complex const &y) // Complex multiplication { Complex z; z.re = x.re * y.re - x.im * y.im; z.im = x.re * y.im + x.im * y.re; return z; } Complex operator /(Complex const &x, Complex const &y) // Complex division { Complex z; double denom; denom = y.re * y.re + y.im *y.im; if (denom == 0.0) denom = 1e-30; z.re = (y.re * x.re + y.im * x.im) / denom; z.im = (y.re * x.im - y.im * x.re) / denom; return z; } Complex sqrt(Complex &x) /* z = Complex sqrt(x) */ { Complex z; double h, tmpc; if ( x.im == 0.0 ) { /*argument is pure real*/ if (x.re >= 0.0 ) z = Complex(sqrt(x.re)); else z = Complex(0.0,sqrt(-x.re)); } else if (x.re == 0.0) { /*argument is pure imaginary*/ if ( x.im >= 0.0 ) { z.re = sqrt(0.5*x.im); z.im = z.re; } else { z.re = sqrt(-0.5*x.im); z.im = -z.re; } } else { /* argument is mixed */ h = sqrt(x.re*x.re + x.im * x.im); tmpc = sqrt(0.5 * (fabs(x.re) + h)); z.re = tmpc; z.im = 0.5 * x.im / tmpc; if ( x.re < 0.0 ) { z.re = fabs(z.im); z.im = ( x.im >= 0.0 ) ? tmpc : -tmpc; } } return z; } string Complex::format() { double x, y; const int LEN = 64; char out[LEN]; x = (fabs(real())>1e-10? real(): 0.0); y = (fabs(imag())>1e-10? imag(): 0.0); if (!y) sprintf_s(out,LEN-1,"%g",x); else if (!x) sprintf_s(out,LEN-1,"%g j",y); else if (y<0.0) sprintf_s(out,LEN-1,"%.4g - %.4g j",x,-y); else sprintf_s(out,LEN-1,"%.4g + %.4g j",x,y); return string(out); } string Complex::phasor() { const int LEN = 64; char out[LEN]; double r,theta; r = mag(); theta = angle(); if (fabs(theta)<1e-9) theta = 0.0; if (!theta) sprintf_s(out,LEN-1,"%g",r); else sprintf_s(out,LEN-1,"%g at %g dg",r,theta); return string(out); }
ctest.cpp
#include <stdio.h> #include <iostream> #include "complex.h" void test_cmul(Complex x, Complex y); void test_phasor(); void test_polar(); void main() { Complex x,y,z; x = Complex(1.0,-2.0); y = Complex(0.5,1.8); test_cmul(x,y); test_phasor(); test_polar(); } void test_cmul(Complex x, Complex y) { Complex z; z = x * y; printf("x = (%s)\n", x.format().c_str()); printf("y = (%s)\n", y.format().c_str()); printf("z = x*y = (%5.2f %5.2f)\n", real(z), imag(z)); } void test_phasor() { Complex a,b,c; a = Complex::polar(10.0,30.0); b = Complex::polar(5.0,-60.0); cout << endl; cout << "a = " << a.phasor() << endl; cout << "b = " << b.phasor() << endl; c = a + b; cout << "a+b = " << c.phasor() << endl; a = Complex::polar(20.0); b = Complex::polar(15.0,-60.0); cout << "a = " << a.phasor() << endl; cout << "b = " << b.phasor() << endl; c = a + b; cout << "a+b = " << c.phasor() << endl; } void test_polar() { Complex a,b; double r,theta; r = 4.0; printf("\n theta real imag modulus phase\n"); for (int i=0; i<13; i++) { theta = 30.0*i; if (theta>180.0) theta = theta - 360.0; a = Complex::polar(r,theta); b = sqrt(a); printf("%8.3f%8.3f%8.3f%10.3f%8.3f\n",theta,a.real(),a.imag(),b.mag(),b.angle()); } }
C:\classes\ece538\complex>ctest x = (1 - 2 j) y = (0.5 + 1.8 j) z = x*y = ( 4.10 0.80) a = 10 at 30 dg b = 5 at -60 dg a+b = 11.1803 at 3.43495 dg a = 20 b = 15 at -60 dg a+b = 30.4138 at -25.285 dg theta real imag modulus phase 0.000 4.000 0.000 2.000 0.000 30.000 3.464 2.000 2.000 15.000 60.000 2.000 3.464 2.000 30.000 90.000 0.000 4.000 2.000 45.000 120.000 -2.000 3.464 2.000 60.000 150.000 -3.464 2.000 2.000 75.000 180.000 -4.000 0.000 2.000 90.000 -150.000 -3.464 -2.000 2.000 -75.000 -120.000 -2.000 -3.464 2.000 -60.000 -90.000 0.000 -4.000 2.000 -45.000 -60.000 2.000 -3.464 2.000 -30.000 -30.000 3.464 -2.000 2.000 -15.000 0.000 4.000 0.000 2.000 0.000
Maintained by John Loomis, updated Fri Feb 09 11:51:14 2007