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