[comp.lang.c++] A PD complex number capability

jima@hplsla.HP.COM (Jim Adcock) (07/20/89)

/*****
  A PD complex number "work-similar" class.

  Copyright 1989 James L. Adcock. This work is placed in the public domain,
  for use without restriction, for the common good of the people.
  Please do not add usage restrictions to simple derivations of this work.

  Defined to be able to either give a double precision or single precision
  capability.

  If you have an archaic compiler you may have to remove or modify the
  const keywords in this file.
****/

#ifndef DCMPX_H
#define DCMPX_H

#define dblepreccomplex
#undef snglpreccomplex

#define USING_STREAMS
#ifdef USING_STREAMS
#ifndef STREAM_H
#define STREAM_H
#include <stream.h>
#endif
#endif

#ifndef MATH_H
#define MATH_H
#include <math.h>
#endif

#ifdef dblepreccomplex
#define complex cmpx
#define cmpx dcmpx
#define basis double
#endif

#ifdef snglpreccomplex
#define fcmpx cmpx
#define cmpx scmpx
#define basis float
#endif

#define ZERO (basis(0.0))

/*****
  In the following, features not found frequently in C++ complex number
  packages are marked "not common."  I have not included definitions
  for advanced functions since I believe these are more frequently a 
  nuisance than a help.  Define them if you like.  I have made the 
  real and imag parts "public" as distributed to make this easily possible.

  You should find this implementation generally faster than other 
  implementations.  Error trapping or recovery not attempted.

  Please let me know if you find any bugs
*****/

class cmpx
{
public:
  basis r;
  basis i;
public:
  cmpx(){} 	/*other packages may initialize to zero*/
  cmpx(basis real) {r = real; i = ZERO;}
  cmpx(basis real, basis imag) {r = real; i = imag;}
  cmpx(const cmpx& c) {r=c.r; i=c.i;}
  cmpx& operator=(const cmpx& c) {r=c.r; i=c.i; return *this;}
  cmpx& operator=(basis b) {r=b; return *this;}
  basis real() const {return r;} 				/*not common*/
  friend basis real(const cmpx& c) {return c.r;}
  friend basis imag(const cmpx& c) {return c.i;}
  basis imag() const {return i;} 				/*not common*/
  basis mag() const {return (basis)sqrt(double(r*r + i*i));} 	/*not common*/
  friend basis mag(const cmpx& c){return c.mag();}		/*not common*/
  basis abs() const {return (basis)sqrt(double(r*r + i*i));} 	/*not common*/
  friend basis abs(const cmpx& c){return c.mag();}
  basis magsq() const {return r*r + i*i;} 			/*not common*/
  basis norm() const {return r*r + i*i;} 			/*not common*/
  basis norm(const cmpx& c) {return c.r*c.r + c.i*c.i;} 
  friend basis magsq(const cmpx& c) {return c.r*c.r+c.i*c.i;}
  basis phase() const {return (basis)atan2(i,r);}		/*not common*/
  friend basis phase(const cmpx& c) {return atan2(c.i,c.r);}	/*not common*/
  basis arg() const {return (basis)atan2(i,r);}	
  friend basis arg(const cmpx& c) {return (basis)atan2(c.i,c.r);}/*not common*/
  friend cmpx conj(const cmpx& c) {return cmpx(c.r,-c.i);}

  /*caution -- the following is defined "in place"*/
  cmpx& conj() {i = -i; return *this;}				/*not common*/

  friend ostream& operator<<(ostream& s, const cmpx& c);
  friend istream& operator>>(istream& s, cmpx& c);
  friend cmpx polar(basis m, basis p) {return cmpx(m*cos(p), m*sin(p));}
  friend cmpx polar(basis m) {return cmpx(m);}
  cmpx operator+(const cmpx& c) const {return cmpx(r+c.r, i+c.i);}
  cmpx operator+(basis b) const {return cmpx(r+b, i);}
  friend cmpx operator+(basis b, const cmpx& c) {return cmpx(b+c.r, c.i);}
  cmpx operator-(const cmpx& c) const {return cmpx(r-c.r, i-c.i);}
  friend cmpx operator-(basis b, const cmpx& c) {return cmpx(b-c.r, c.i);}
  cmpx operator-(basis b) const {return cmpx(r-b, i);}
  cmpx operator*(const cmpx& c) const {return cmpx(r*c.r-i*c.i, r*c.i+i*c.r);}
  cmpx operator*(basis b) const {return cmpx(r*b, i*b);}
  friend cmpx operator*(basis b, const cmpx& c) {return cmpx(b*c.r, b*c.i);}
  friend cmpx operator/(const cmpx& a, const cmpx& b) {basis d=b.r*b.r+b.i*b.i; 
    return cmpx((a.r*b.r+a.i*b.i)/d,(a.i*b.r-a.r*b.i)/d);}
  cmpx operator/(basis b) const {return cmpx(r/b, i/b);}
  cmpx operator+() const {return *this;}
  cmpx operator-() const {return cmpx(-r,-i);}
  cmpx& operator+=(const cmpx& c) {r += c.r; i += c.i; return *this;}
  cmpx& operator+=(basis b) {r += b; return *this;}
  cmpx& operator-=(const cmpx& c) {r -= c.r; i -= c.i; return *this;}
  cmpx& operator-=(basis b) {r -= b; return *this;}
  cmpx& operator*=(const cmpx& c)
  {basis re=r; r = re*c.r-i*c.i; i = re*c.i+i*c.r; return *this;}
  cmpx& operator*=(basis b) {r *= b; i *= b; return *this;}
  cmpx& operator/=(const cmpx& c) {basis re; basis d=c.r*c.r+c.i*c.i; 
    re = (r*c.r+i*c.i)/d; i = (i*c.r-r*c.i)/d; r = re; return *this;}
  cmpx& operator/=(basis b) {r/=b; i/=b; return *this;}
  int operator!() const {return (r == ZERO) && (i == ZERO);}	/*not common*/
  friend int operator&&(const cmpx& a, const cmpx& b)		/*not common*/
  {return ((a.r!=ZERO) || (a.i!=ZERO)) && ((b.r!=ZERO) || (b.i!=ZERO));}
  friend int operator||(const cmpx& a, const cmpx& b)		/*not common*/
  { return (a.r!=ZERO) || (a.i!=ZERO) || (b.r!=ZERO) || (b.i!=ZERO);}
};

#endif

/***************************/

/*the following two should be in a .c file*/

#define USING_STREAMS
#ifdef USING_STREAMS

/*older C++ compilers may require strings instead of chars below*/

ostream& operator<<(ostream& s, const cmpx& c)
{ return s << '(' << c.r << '+' << c.i << ')';}

istream& operator>>(istream& s, cmpx& c)
{ s >> c.r >> c.i; return s;}
#endif

/***************************/

/*a little test program follows*/

main()
{
  complex a, b;

  while(1)
  {
    cout << "\n?  ?  ?  ?\n";
    cin >> a >> b;
    cout << "\na = " << a ;
    cout << "\nb = " << b ;
    cout << "\na+b = " << a+b;
    cout << "\na-b = " << a-b;
    cout << "\na*b = " << a*b;
    cout << "\na/b = " << a/b;
    cout << "\na.mag() = " << a.mag();
    cout << "\na.magsq() = " << a.magsq();
    cout << "\na.phase() = " << a.phase();
    cout << "\na.real() = " << a.real();
    cout << "\na.imag() = " << a.imag();
    cout << "\n!a =  " << (!a);
    cout << "\na&&b =  " << (a&&b);
    cout << "\na||b =  " << (a||b);
    cout << "\n\n";
  }
}

bright@Data-IO.COM (Walter Bright) (07/22/89)

In article <6590209@hplsla.HP.COM> jima@hplsla.HP.COM (Jim Adcock) writes:
<  Copyright 1989 James L. Adcock. This work is placed in the public domain,
<  for use without restriction, for the common good of the people.

'Copyright' and 'public domain' are as mutually exclusive as black and
white. I suggest you change the statement to one of:

  Copyright (C) 1989 James L. Adcock. This work is
  for use without restriction, for the common good of the people.

or:

  Written by James L. Adcock. This work is placed in the public domain,
  for use without restriction, for the common good of the people.

jima@hplsla.HP.COM (Jim Adcock) (07/25/89)

> 'Copyright' and 'public domain' are as mutually exclusive as black and
> white. I suggest you change the statement to one of:

I haven't been able to get my hands on the local copyright text to verify
this, but the below statement was my intent.  Consider it so modified.

  Copyright (C) 1989 James L. Adcock. This work is
  for use without restriction, for the common good of the people.
  Please do not add copyright notices to simple derivations of this work.


I continue to ask that people using it not add their copyright notices to
trivial derivations of the work, since this confuses the ownership issue,
making the software unuseable by anyone.  I personally consider the practice
of adding a copyright notice to a trivially modified piece of software an 
act of plagiarism.  Likewise, I would consider adding a copyleft  
to this software offensive.  If people send me reliable bug information, I
will try to post "fixed" versions.