Complex numbers

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()); 
	}
}


Results

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