
//	Header:		Complex
//	Version:	2.00  28-Oct-1989
//	Language:	C++ 2.0;  Environ: Any;  Compilers: Zortech C++ 2.01
//	Purpose:	Provides the class "Complex" for C++ programs.  The
//			majority of the class is implemented inline for
//			efficiency.  Only the division, power, and i/o methods
//			are actual functions.
//	Written by:	Scott Robert Ladd, 705 West Virginia, Gunnison CO 81230
//			BBS (303)641-6438; FidoNet 1:104/708

#ifndef COMPLEX_HPP
#define COMPLEX_HPP

#include <math.h>
#include <stream.hpp>

class Complex {
private:
	double		re;
	double		im;
	static void	( * errorHandler) ();
protected:
public:
			Complex ( void);
			Complex ( const Complex &);
			Complex ( double &, double &);
			Complex ( double &);
	static void	setErrorHandler ( void ( * userHandler) ());
	friend double	real ( const Complex &);
	friend double	imag ( const Complex &);
	void		operator= ( const Complex &);
	void		operator= ( double &);
	Complex		operator- ();
	friend Complex 	operator+ ( const Complex &, const Complex &);
	friend Complex 	operator- ( const Complex &, const Complex &);
	friend Complex 	operator* ( const Complex &, const Complex &);
	friend Complex 	operator/ ( const Complex &, const Complex &);
	Complex 	operator+= ( const Complex &);
	Complex		operator-= ( const Complex &);
	Complex		operator*= ( const Complex &);
	Complex		operator/= ( const Complex &);
	friend int	operator== ( const Complex &, const Complex &);
	friend int	operator!= ( const Complex &, const Complex &);
	friend int	operator< ( const Complex &, const Complex &);
	friend int	operator<= ( const Complex &, const Complex &);
	friend int	operator> ( const Complex &, const Complex &);
	friend int	operator>= ( const Complex &, const Complex &);
	friend double	abs ( const Complex &);
	friend double	norm ( const Complex &);
	friend double	arg ( const Complex &);
	friend Complex	polar ( double radius, double theta = 0.0);
	friend Complex	conj ( const Complex &);
	friend Complex	cos ( const Complex &);
	friend Complex	sin ( const Complex &);
	friend Complex	tan ( const Complex &);
	friend Complex	cosh ( const Complex &);
	friend Complex	sinh ( const Complex &);
	friend Complex	tanh ( const Complex &);
	friend Complex	exp ( const Complex &);
	friend Complex	log ( const Complex &);
	friend Complex	pow ( const Complex &, const Complex &);
	friend Complex	sqrt ( const Complex &);
	friend ostream &operator<< ( ostream &, const Complex &);
	friend istream &operator>> ( istream &, Complex &);
};

inline
Complex::Complex (
) {
	re = im = 0.0;
}

inline
Complex::Complex (
	const Complex &	c
) {
	re = c.re;
	im = c.im;
}

inline
Complex::Complex (
	double &	r,
	double &	i
) {
	re = r;
	im = i;
}

inline
Complex::Complex (
	double &	r
) {
	re = r;
	im = 0.0;
}

inline
void
Complex::setErrorHandler (
	void		( * userHandler) ()
) {
	errorHandler = userHandler;
}

inline
double
real (
	const Complex &	c
) {
	return c.re;
}

inline
double
imag (
	const Complex &	c
) {
	return c.im;
}

inline
void
Complex::operator= (
	const Complex &	c
) {
	re = c.re;
	im = c.im;
}

inline
void
Complex::operator= (
	double &	r
) {
	re = r;
	im = 0.0;
}

inline
Complex
Complex::operator- (
) {
	Complex		result;
	result.re = -re;
	result.im = -im;
	return result;
}

inline
Complex
operator+ (
	const Complex &	c1,
	const Complex &	c2
) {
	Complex		result;
	result.re = c1.re + c2.re;
	result.im = c1.im + c2.im;
	return result;
}

inline
Complex
operator- (
	const Complex &	c1,
	const Complex &	c2
) {
	Complex		result;
	result.re = c1.re - c2.re;
	result.im = c1.im - c2.im;
	return result;
}

inline
Complex
operator* (
	const Complex &	c1,
	const Complex &	c2
) {
	Complex		result;
	result.re = c1.re * c2.re - c1.im * c2.im;
	result.im = c1.re * c2.im + c1.im * c2.re;
	return result;
}

inline
Complex
Complex::operator+= (
	const Complex &	c
) {
	re += c.re;
	im += c.im;
	return *this;
}

inline
Complex
Complex::operator-= (
	const Complex &	c
) {
	re -= c.re;
	im -= c.im;
	return *this;
}

inline
Complex
Complex::operator*= (
	const Complex &	c
) {
	double		oldReal;
	oldReal = re;
	re = re * c.re - im * c.im;
	im = oldReal * c.im + im * c.re;
	return *this;
}

inline
int
operator== (
	const Complex &	c1,
	const Complex & c2
) {
	return ( c1.re == c2.re) && ( c1.im == c2.im);
}

inline
int
operator!= (
	const Complex &	c1,
	const Complex & c2
) {
	return ( c1.re != c2.re) || ( c1.im != c2.im);
}

inline
int
operator< (
	const Complex &	c1,
	const Complex & c2
) {
	return abs ( c1) < abs ( c2);
}

inline
int
operator<= (
	const Complex & c1,
	const Complex & c2
) {
	return abs ( c1) <= abs ( c2);
}

inline
int
operator> (
	const Complex &	c1,
	const Complex &	c2
) {
	return abs ( c1) > abs ( c2);
}

inline
int
operator>= (
	const Complex &	c1,
	const Complex &	c2
) {
	return abs ( c1) >= abs ( c2);
}

inline
double
abs (
	const Complex &	c
) {
	double		result;
	result = sqrt ( c.re * c.re + c.im * c.im);
	return result;
}

inline
double
norm (
	const Complex &	c
) {
	double		result;
	result = c.re * c.re + c.im * c.im;
	return result;
}

inline
double
arg (
	const Complex &	c
) {
	double		result;
	result = atan2 ( c.im, c.re);
	return result;
}

inline
Complex
polar (
	double		radius,
	double		theta
) {
	Complex		result;
	result.re = radius * cos ( theta);
	result.im = radius * sin ( theta);
	return result;
}

inline
Complex
conj (
	const Complex &	c
) {
	Complex		result;
	result.re = c.re;
	result.im = -c.im;
	return result;
}

inline
Complex
cos (
	const Complex &	c
) {
	Complex		result;
	result.re = cos ( c.re) * cosh ( c.im);
	result.im = cos ( c.re) * sinh ( c.im);
	return result;
}

inline
Complex
sin (
	const Complex &	c
) {
	Complex		result;
	result.re = sin ( c.re) * cosh ( c.im);
	result.im = cos ( c.re) * sinh ( c.im);
	return result;
}

inline
Complex
tan (
	const Complex &	c
) {
	Complex		result;
	result = sin ( c) / cos ( c);
	return result;
}

inline
Complex
cosh (
	const Complex &	c
) {
	Complex		result;
	result.re = cos ( c.im) * cosh ( c.re);
	result.im = sin ( c.im) * sinh ( c.re);
	return result;
}

inline
Complex
sinh (
	const Complex & 	c
) {
	Complex		result;
	result.re = cos ( c.im) * sinh ( c.re);
	result.im = sin ( c.im) * cosh ( c.re);
	return result;
}

inline
Complex
tanh (
	const Complex &	c
) {
	Complex		result;
	result = sinh ( c) / cosh ( c);
	return result;
}

inline
Complex
exp (
	const Complex &	c
) {
	Complex		result;
	double		x = exp ( c.re);
	result.re = x * cos ( c.im);
	result.im = x * sin ( c.im);
	return result;
}

inline
Complex
log (
	const Complex &	c
) {
	Complex		result;
	double		hypot = abs ( c);
	if ( hypot > 0.0) {
		result.re = log ( hypot);
		result.im = atan2 ( c.im, c.re);
	} else
		Complex::errorHandler ();
	return result;
}

#endif 	// COMPLEX_HPP


