风花雪月 发表于 2006-10-10 00:35

C++语言的复数与矩阵运算库

总共包含三个文件:
COMPLEX.H
matrix.h
text.cpp
本程序打包下载见本贴4楼


COMPLEX.H如下:
/* -------------------------------------------------------------------- */
/* Z++ Version 1.10               complex.h       Last revised 10/10/92 */
/*                                                                      */
/* Complex number class for Turbo C++/Borland C++.                      */
/* Copyright 1992 by Carl W. Moreland                                 */
/* -------------------------------------------------------------------- */

#ifndef COMPLEXdotH
#define COMPLEXdotH

#include <math.h>
#include <iostream.h>

const unsigned char Z_RADIANS = 0;
const unsigned char Z_DEGREES = 1;
const unsigned char Z_COMMA   = 0;        // (x, y)
const unsigned char Z_LETTER= 1;        // x + iy

class complex
{
public:
double re, im;

private:
static unsigned char zArgMode;
static unsigned char zPrintMode;
static unsigned char zLetter;

public:
complex(void): re(0), im(0) {}
complex(const double real, const double imag=0): re(real), im(imag) {}
complex(const complex& z): re(z.re), im(z.im) {}

friend double    re(const complex& z) {        // real part
    return z.re;
}
friend double    im(const complex& z) {        // imaginary part
    return z.im;
}
friend doublereal(const complex& z) {        // real part
    return z.re;
}
friend doubleimag(const complex& z) {        // imaginary part
    return z.im;
}
friend double   mag(const complex& z) {        // magnitude |z|
    return sqrt(z.re*z.re + z.im*z.im);
}
friend double   arg(const complex& z);        // argument
friend double   ang(const complex& z) {        // angle
    return arg(z);
}
friend double    ph(const complex& z) {        // phase
    return arg(z);
}
friend complex conj(const complex& z) {        // complex conjugate
    return complex(z.re, -z.im);
}
friend doublenorm(const complex& z) {        // norm
    return z.re*z.re + z.im*z.im;
}

friend complex rtop(double x,   double y=0);
friend complex ptor(double mag, double angle=0);
complex& topolar(void);
complex& torect(void);

void operator = (const complex& z) {                // z1 = z2
    re = z.re;
    im = z.im;
}
complex& operator += (const complex& z) {        // z1 += z2
    re += z.re;
    im += z.im;
    return *this;
}
complex& operator -= (const complex& z) {        // z1 -= z2
    re -= z.re;
    im -= z.im;
    return *this;
}
complex& operator *= (const complex& z) {        // z1 *= z2
    *this = *this * z;
    return *this;
}
complex& operator /= (const complex& z) {        // z1 /= z2
    *this = *this / z;
    return *this;
}
complex operator + (void) const {                // +z1
    return *this;
}
complex operator - (void) const {                // -z1
    return complex(-re, -im);
}

friend complex operator + (const complex& z1, const complex& z2) {
    return complex(z1.re + z2.re, z1.im + z2.im);
}
friend complex operator + (const complex& z, const double x) {
    return complex(z.re+x, z.im);
}
friend complex operator + (const double x, const complex& z) {
    return complex(z.re+x, z.im);
}
friend complex operator - (const complex& z1, const complex& z2) {
    return complex(z1.re - z2.re, z1.im - z2.im);
}
friend complex operator - (const complex&, const double);
friend complex operator - (const double x, const complex& z) {
    return complex(x-z.re, -z.im);
}
friend complex operator * (const complex& z1, const complex& z2) {
    double re = z1.re*z2.re - z1.im*z2.im;
    double im = z1.re*z2.im + z1.im*z2.re;
    return complex(re, im);
}
friend complex operator * (const complex& z, const double x) {
    return complex(z.re*x, z.im*x);
}
friend complex operator * (const double x, const complex& z) {
    return complex(z.re*x, z.im*x);
}
friend complex operator / (const complex&, const complex&);
friend complex operator / (const complex& z, const double x) {
    return complex(z.re/x, z.im/x);
}
friend complex operator / (const double, const complex&);
friend complex operator ^ (const complex& z1, const complex& z2) {
    return pow(z1, z2);
}

friend int operator == (const complex& z1, const complex& z2) {
    return (z1.re == z2.re) && (z1.im == z2.im);
}
friend int operator != (const complex& z1, const complex& z2) {
    return (z1.re != z2.re) || (z1.im != z2.im);
}

friend double   abs(const complex& z);
friend complex sqrt(const complex& z);
friend complex pow(const complex& base, const complex& exp);
friend complex pow(const complex& base, const double   exp);
friend complex pow(const double   base, const complex& exp);

friend complex   exp(const complex& z);
friend complex   log(const complex& z);
friend complex    ln(const complex& z);
friend complex log10(const complex& z);

friend complexcos(const complex& z);
friend complexsin(const complex& z);
friend complextan(const complex& z);

friend complex asin(const complex& z);
friend complex acos(const complex& z);
friend complex atan(const complex& z);

friend complex sinh(const complex& z);
friend complex cosh(const complex& z);
friend complex tanh(const complex& z);

void SetArgMode(unsigned char mode) const {
    if(mode == Z_RADIANS || mode == Z_DEGREES)
      zArgMode = mode;
}
void SetPrintMode(unsigned char mode) const {
    if(mode == Z_COMMA || mode == Z_LETTER)
      zPrintMode = mode;
}
void SetLetter(unsigned char letter) const {
    zLetter = letter;
}

friend ostream& operator<<(ostream&, const complex&);
friend istream& operator>>(istream&, const complex&);
};

static const complex Z0(0, 0);                // complex number 0
static const complex Z1(1, 0);                // complex number 1
static const complex Zi(0, 1);                // complex number i
static const complex Zinf(HUGE_VAL, HUGE_VAL); // complex number infinity
static const complex Complex;

/* -------------------------------------------------------------------- */
/* Here is the same class with the name capitalized. If you prefer this */
/* simply remove the comment delimiters below and comment out the 5   */
/* static globals above.                                                */
/* -------------------------------------------------------------------- */
/*
class Complex: public complex
{
public:
Complex(void): re(0), im(0) {}
Complex(const double real, const double imag=0): re(real), im(imag) {}
Complex(const complex& z): re(z.re), im(z.im) {}
};

static const Complex Z0(0, 0);                // complex number 0
static const Complex Z1(1, 0);                // complex number 1
static const Complex Zi(0, 1);                // complex number i
static const Complex Zinf(HUGE_VAL, HUGE_VAL); // complex number infinity
static const Complex complex;
*/

#endif

[ 本帖最后由 风花雪月 于 2006-10-10 00:44 编辑 ]

风花雪月 发表于 2006-10-10 00:41

matrix.h如下:
#include "afxwin.h"
#include "strstrea.h"
#include "fstream.h"
#include "iomanip.h"
#include "stdlib.h"
#include "malloc.h"
#include "math.h"

#define CDMatrix (CMatrix<double>)
#define CIMatrix (CMatrix<int>)

template<class Type>
class CMatrix :public CObject
{
        protected:               
                        Type    **f;
                        int   row;
                        int   col;
        public:
                intGetRow(){return row;}
                intGetCol(){return col;}
                void SetRow(int r){row=r;}
                void SetCol(int l){col=l;}
                Type** GetF(){return f;}               
                CMatrix();
                CMatrix(int,int);
                CMatrix(CMatrix &copy);
                ~CMatrix();
                BOOL Ones(int);
                BOOL Ones(int,int);
                BOOL Zeros(int);
                BOOL Zeros(int,int);
                CMatrix Turn();
                CMatrix Inverse();
                CMatrix Construct(CMatrix &mat,CString style);
                CMatrix GetChild(int,int,int,int);
                BOOL Diag(Type *,int);
                BOOL Malloc(int,int);
                CMatrix   operator*(CMatrix&m);
                friend CMatrixoperator*(double,CMatrix);
                friend CMatrixoperator*(CMatrix,double);
                CMatrix   operator/(Type x);
                CMatrix   operator+(CMatrix&m);
                CMatrix   operator+(Type x);
                CMatrix   operator-(CMatrix&m);
                CMatrix   operator-(Type x);
                CMatrix   operator-();
                Type* &operator[](int);
                friend istream&operator>>(istream&,CMatrix&);
                friend ostream&operator<<(ostream&,CMatrix&);
                void operator=(const CMatrix&m);
                void operator=(Type);
                Type ** MatrixAlloc(int,int);
                void    MatrixFree(Type **);
                void    Hessenberg();
                BOOL    Cholesky();
                CMatrix QREigen(double,int);// return eigenvalue in two row matrix of a real matrix                
                CMatrix Jacobi(double eps,int jt);
};

template<class Type>
Type* &CMatrix<Type>::operator[](int i)
{
        Type *tp;
        tp=(Type *)f;
        return tp;
}
template<class Type>
CMatrix<Type>::CMatrix()
{
        f=NULL;
        row=0;
        col=0;
}
template<class Type>
CMatrix<Type>::CMatrix(int m,int n)
{       
        f=MatrixAlloc(m,n);
        row=m;
        col=n;
}
template<class Type>
CMatrix<Type>::~CMatrix()
{
        if(f!=NULL) MatrixFree(f);
}

template<class Type>
BOOL CMatrix<Type>::Ones(int m)
{        
        f=MatrixAlloc(m,m);
        for(int i=0;i<m;i++)
        for(int j=0;j<m;j++)
        {
                if(i!=j)f=0;
                else f=1;
        }
        row=m;
        col=m;
        return TRUE;
}
template<class Type>
BOOL CMatrix<Type>::Ones(int m,int n)
{        
        f=MatrixAlloc(m,n);
        for(int i=0;i<m;i++)
        for(int j=0;j<n;j++)
        {
                f=1;
        }
        row=m;
        col=n;
        return TRUE;
}
template<class Type>
BOOL CMatrix<Type>::Zeros(int m)
{        
        f=MatrixAlloc(m,m);
        for(int i=0;i<m;i++)
        for(int j=0;j<m;j++)
        {
                f=0;
        }
        row=m;
        col=m;
        return TRUE;
}
template<class Type>
BOOL CMatrix<Type>::Zeros(int m,int n)
{        
        f=MatrixAlloc(m,n);
        if(f==NULL) return FALSE;
        for(int i=0;i<m;i++)
        for(int j=0;j<n;j++)
        {
                f=0;
        }
        row=m;
        col=n;
        return TRUE;
}

template<class Type>
CMatrix<Type> CMatrix<Type>::operator*(CMatrix<Type>&mat)
{
        int l,m,n;
        l=GetRow();
        m=GetCol();
        n=mat.GetCol();
        CMatrix tmp(l,n);
        for(int k=0;k<l;k++)
        for(int j=0;j<n;j++)
        {
                for(int i=0;i<m;i++)
                tmp.f+=f*mat.f;
        }       
        return tmp;
}

template<class Type>
CMatrix<Type> CMatrix<Type>::operator/(Type x)
{
        int l,n;
        l=GetRow();
        n=GetCol();
        CMatrix<Type> tmp(l,n);
        for(int j=0;j<l;j++)
        for(int i=0;i<n;i++)
                tmp.f=f/x;
        return tmp;
}

template<class Type>
CMatrix<Type> CMatrix<Type>::operator+( CMatrix<Type>&mat)
{
        int l1,m1;
        l1=GetRow();
        m1=GetCol();
        CMatrix<Type> tmp(l1,m1);
        for(int j=0;j<l1;j++)
        for(int i=0;i<m1;i++)
                tmp.f=f+mat.f;
        return tmp;
}

template<class Type>
CMatrix<Type> CMatrix<Type>::operator+(Type x)
{
        int l,m;
        l=GetRow();
        m=GetCol();
        CMatrix<Type> tmp(l,m);
        for(int j=0;j<l;j++)
        for(int i=0;i<m;i++)
                tmp.f=f+x;
        return tmp;
}

template<class Type>
CMatrix<Type> CMatrix<Type>::operator-(CMatrix<Type>&mat)
{
        int l1,m1;
        l1=GetRow();
        m1=GetCol();
        CMatrix<Type> tmp(l1,m1);
        for(int j=0;j<l1;j++)
        for(int i=0;i<m1;i++)
                tmp.f=f-mat.f;
        return tmp;
}
template<class Type>
CMatrix<Type> CMatrix<Type>::operator-()
{
        for(int i=0;i<row;i++)
        for(int j=0;j<col;j++)
                f=-f;
        return *this;
}       

template<class Type>
CMatrix<Type> CMatrix<Type>::operator-( Type x)
{
        int l,m;
        l=GetRow();
        m=GetCol();
        CMatrix<Type> temp(l,m);
        for(int j=0;j<l;j++)
        for(int i=0;i<m;i++)
                temp.f=f-x;
        return temp;
}

template<class Type>
istream &operator>>(istream &in,CMatrix<Type> &mat)
{   
        int i,j;
        for(i=0;i<mat.row;i++)
        for(j=0;j<mat.col;j++)
               in>>mat.f;
        cout<<endl;
        return in;
};

template<class Type>
ostream& operator<<(ostream& out,CMatrix<Type> &v1)
{
        if(v1.GetF()==NULL)
        {
                out<<"This Matrix cannot be output!";
                return out<<endl;
        }
        out<<setiosflags(ios::right||ios::fixed);
        out<<setprecision(5);
        out<<"["<<endl;
        int mr=v1.GetRow();
        int mc=v1.GetCol();
        for(int j=0;j<mr;j++)
        {
                for(int i=0;i<mc-1;i++)
                        out<<setw(12)<<v1.f;
                out<<setw(12)<<v1.f<<";"<<endl;
        }
        return out<<"]"<<endl;
       
}
template<class Type>
CMatrix<Type>::CMatrix(CMatrix<Type> &copy)
{
        f=NULL;
        *this=copy;
}
       
template<class Type>
void CMatrix<Type>::operator=(const CMatrix<Type> &copy)
{
       
        if(this==&copy) return;
        if(f!=NULL) MatrixFree(f);
        int m,n;
        m=copy.row;
        n=copy.col;
        f=MatrixAlloc(m,n);
        for(int i=0;i<m;i++)
        for(int j=0;j<n;j++)
                f=copy.f;
        row=m;
        col=n;
}

template<class Type>
void CMatrix<Type>::operator=(Type d)
{
       
        if(f==NULL)
        {
                cout<<"The Matrix is not be allociated"<<endl;
                return;
        }
        for(int i=0;i<row;i++)
        for(int j=0;j<col;j++)
                f=d;
}

template<class Type>
Type ** CMatrix<Type>::MatrixAlloc(int r,int c)
{
    Type *x,**y;
    int   n;
    x=(Type *)calloc(r*c,sizeof(Type));
    y=(Type **)calloc(r,sizeof(Type *));
        for(n=0;n<=r-1;++n)
        y=&x;
        return(y);
}

template<class Type>
void CMatrix<Type>::MatrixFree(Type **x)
{
   free(x);
   free(x);
}
template<class Type>
BOOL CMatrix<Type>::Malloc(int m,int n)
{
        f=MatrixAlloc(m,n);
        if(f==NULL) return FALSE;
        row=m;
        col=n;
        return TRUE;
}

       
template<class Type>
CMatrix<Type> CMatrix<Type>::Turn()
{
        CMatrix<Type> tmp(col,row);
        for(int i=0;i<row;i++)
        for(int j=0;j<col;j++)
                tmp.f=f;
        return tmp;
}

template<class Type>
BOOL CMatrix<Type>::Diag(Type *array,int m)
{
        f=MatrixAlloc(m,m);
        for(int i=0;i<m;i++)
        for(int j=0;j<m;j++)
                if(i==j) f=array;
        row=m;
        col=m;
        return TRUE;
}

template<class Type>
CMatrix<Type> CMatrix<Type>::Construct(CMatrix<Type> &mat,CString style)
{
        int i,j;
        CMatrix<Type> tmp;
        if(style=="LR"||style=="lr")
        {
                if(row!=mat.row)    return tmp;
                if(!tmp.Malloc(row,col+mat.col)) return tmp;
                for(i=0;i<tmp.row;i++)
                {
                        for(j=0;j<tmp.col;j++)
                        {
                                if(j<col) tmp.f=f;
                                else      tmp.f=mat.f;
                        }
                }
        }
        return tmp;
}

template<class Type>       
CMatrix<Type> CMatrix<Type>::GetChild(int sr,int sc,int er,int ec)
{
        int i,j;
        CMatrix<Type> tmp(er-sr+1,ec-sc+1);
        for(i=0;i<tmp.row;i++)
        for(j=0;j<tmp.col;j++)
                tmp=f;
        return tmp;
}
template<class Type>       
CMatrix<Type> CMatrix<Type>::Inverse()
{
        Type d,p;
    int *is,*js,i,j,k,v;
    if(row!=col)
        {
                cout<<"\nrow!=column,this matrix can't be inversed";
                return *this;   
        }
    is=new int;
    js=new int;
    for(k=0;k<=row-1;k++)
        {
                d=0.0;
          for(i=k;i<=row-1;i++)
          for(j=k;j<=row-1;j++)
          {
                        p=fabs(f);
                  if(p>d)
                        {
                                d=p;
                                is=i;
                                js=j;
                        }
                }
          if(d+1.0==1.0)   //singular
          {
                        delete is,js;
                  cerr<<"\nerror*****not inv,be careful your matrix had been changed\n";
                  return *this;   
                }
          if(is!=k)
          for(j=0;j<=row-1;j++)
                {   
                        v=is;
                  p=f;
                        f=f;
                        f=p;
                }
          if(js!=k)
          for(i=0;i<=row-1;i++)
                {
                        v=js;
                  p=f;
                        f=f;
                        f=p;
                }
          f=1.0/f;
          for(j=0;j<=row-1;j++)
          if(j!=k)
             f*=f;
          for(i=0;i<=row-1;i++)
                        if(i!=k)
                for(j=0;j<=row-1;j++)
                                if(j!=k)
                           f-=f*f;
                for(i=0;i<=row-1;i++)
          if(i!=k)
                       f=-f*f;
        }
    // change row and column after inverse
        for(k=row-1;k>=0;k--)
        {
                if(js!=k)
                for(j=0;j<=row-1;j++)
                {
                        v=js;
                  p=f;
                        f=f;
                        f=p;
                }
          if(is!=k)
                       for(i=0;i<=row-1;i++)
                       {
                               v=is;
                               p=f;
                               f=f;
                               f=p;
                     }
      }
        delete is,js;
        return *this;   
}

template<class Type>       
CMatrix<Type> operator * (double num,CMatrix<Type> right)
{
    CMatrix<Type> tmp(right.row,right.col);
        int i,j;
        for(i=0;i<right.row;i++)
        for(j=0;j<right.col;j++)
               tmp.f=num*right.f;
        return tmp;
}

template<class Type>       
CMatrix<Type> operator * (CMatrix<Type> left,double num)
{   
        CMatrix<Type> tmp(left.row,left.col);
        int i,j;
        for(i=0;i<left.row;i++)
        for(j=0;j<left.col;j++)
               tmp.f=num*left.f;
        return tmp;
}
template<class Type>       
void CMatrix<Type>::Hessenberg()
{
        int i,j,k;
        double d,t;
        if(row==0)
        {
          cerr<<"\na null matrix,can't use hessenberg transformation";
          exit(1);
       }
        if(row!=col)
        {
          cerr<<"\nnot a square matrix,can't use hessenberg transformation";
          exit(1);
       }
        for(k=1;k<=row-2;k++)
        {
          d=0.0;
          for(j=k;j<=row-1;j++)
          {
               t=f;
               if(fabs(t)>fabs(d))      { d=t;i=j;}
             }
          if(fabs(d)+1.0!=1.0)
          {
               if(i!=k)
               {      for(j=k-1;j<=row-1;j++)
                        {   t=f;f=f;f=t;
                       }
                        for(j=0;j<=row-1;j++)
                        {      t=f;f=f;f=t;
                       }
                  }
               for(i=k+1;i<=row-1;i++)
               {       t=f/d;
                       f=0.0;
                       for(j=k;j<=row-1;j++)
                       {      f-=t*f;
                          }
                       for(j=0;j<=row-1;j++)
                       {      f+=t*f;
                          }
                  }
             }
        }
}

template<class Type>       
BOOL CMatrix<Type>::Cholesky()
{
        int i,j,k;
        double d;
        if(row!=col)
        {        cerr<<"\nnot a squre matrix, can't use Cholesky disintegration";
                return FALSE;
        }
        if((f+1.0==1.0)||(f<0.0))
        {        cerr<<"\nnot a Zhengdin matrix, can't use Cholesky disintegration";
                return FALSE;
        }
        f=sqrt(f);
        d=f;
        for(i=1;i<=row-1;i++)
        {        f/=f;
        }
        for(j=1;j<=row-1;j++)
        {        for(k=0;k<=j-1;k++)
                {   f-=f*f;
                }
      if((f+1.0==1.0)||(f<0.0))
                {   cerr<<"\nnot a zhendin matrix, can't use Cholesky disintegration";
                  return FALSE;
                }
                f=sqrt(f);
                d*=f;
          for(i=j+1;i<=row-1;i++)
                {        for(k=0;k<=j-1;k++)
                f-=f*f;
                  f/=f;
                }
        }
        for(i=0;i<=row-2;i++)
                for(j=i+1;j<=row-1;j++)
                        f=0.0;
    return TRUE;
}
template<class Type>       
CMatrix<Type> CMatrix<Type>::Jacobi(double eps,int jt)
{
                CMatrix<Type> v;
                v.Zeros(row,col);
                if(row!=col) return v;
                int i,j,p,q,l,n;
                n=row;
                for(i=0;i<=n-1;i++)    // check the matrix's symmetrition
                        for(j=0;j<=n-1;j++)
                                if((f-f)>0.001)
                                        return v;
                double fm,cn,sn,omega,x,y,d;
                l=1;
                for (i=0; i<=n-1; i++)
                {
                        v=1.0;
                        for (j=0; j<=n-1; j++)
                        if (i!=j) v=0.0;
                }
    while (1==1)//????????????????????????????????????
      { fm=0.0;
      for (i=0; i<=n-1; i++)
      for (j=0; j<=n-1; j++)
          { d=fabs(f);
            if ((i!=j)&&(d>fm))
            { fm=d; p=i; q=j;}
          }
      if (fm<eps)return v;
      if (l>jt)return v;
      l=l+1;
      x=-f; y=(f-f)/2.0;
      omega=x/sqrt(x*x+y*y);
      if (y<0.0) omega=-omega;
      sn=1.0+sqrt(1.0-omega*omega);
      sn=omega/sqrt(2.0*sn);
      cn=sqrt(1.0-sn*sn);
      fm=f;
      f=fm*cn*cn+f*sn*sn+f*omega;
      f=fm*sn*sn+f*cn*cn-f*omega;
      f=0.0; f=0.0;
      for (j=0; j<=n-1; j++)
      if ((j!=p)&&(j!=q))
      {
            fm=f;
            f=fm*cn+f*sn;
            f=-fm*sn+f*cn;
          }
      for (i=0; i<=n-1; i++)
          if ((i!=p)&&(i!=q))
          {
            fm=f;
            f=fm*cn+f*sn;
            f=-fm*sn+f*cn;
            }
      for (i=0; i<=n-1; i++)
          {
            fm=v;
            v=fm*cn+v*sn;
            v=-fm*sn+v*cn;
          }
      }
    return v;
}




template<class Type>
CMatrix<double> CMatrix<Type>::QREigen(double eps,int jt)
{            // return eigenvalue in two row matrix of a real matrix
        int m,it,i,j,k,l,ii,jj,kk,ll;
    CMatrix<double> uv;
        uv.Zeros(row,2);
        if(row!=col) return uv;
        int n=row;
    double b,c,w,g,xy,p,q,r,x,s,e,ff,z,y;
    double *u,*v,*a;
    u=(double*)calloc(n,sizeof(double));
    v=(double*)calloc(n,sizeof(double));
    a=(double*)calloc(n*n,sizeof(double));
    this->Hessenberg();
        for(i=0;i<n;i++)
                for(j=0;j<n;j++)
                        a=f;
        it=0; m=n;
    while (m!=0)
      { l=m-1;
      while ((l>0)&&(fabs(a)>eps*
              (fabs(a[(l-1)*n+l-1])+fabs(a)))) l=l-1;
      ii=(m-1)*n+m-1; jj=(m-1)*n+m-2;
      kk=(m-2)*n+m-1; ll=(m-2)*n+m-2;
      if (l==m-1)
          { u=a[(m-1)*n+m-1]; v=0.0;
            m=m-1; it=0;
          }
      else if (l==m-2)
          { b=-(a+a);
            c=a*a-a*a;
            w=b*b-4.0*c;
            y=sqrt(fabs(w));
            if (w>0.0)
            { xy=1.0;
                if (b<0.0) xy=-1.0;
                u=(-b-xy*y)/2.0;
                u=c/u;
                v=0.0; v=0.0;
            }
            else
            { u=-b/2.0; u=u;
                v=y/2.0; v=-v;
            }
            m=m-2; it=0;
          }
      else
          { if (it>=jt)
            { cout<<"fail\n";
                return uv;
            }
            it=it+1;
            for (j=l+2; j<=m-1; j++)
            a=0.0;
            for (j=l+3; j<=m-1; j++)
            a=0.0;
            for (k=l; k<=m-2; k++)
            { if (k!=l)
                  { p=a; q=a[(k+1)*n+k-1];
                  r=0.0;
                  if (k!=m-2) r=a[(k+2)*n+k-1];
                  }
                else
                  { x=a+a;
                  y=a*a-a*a;
                  ii=l*n+l; jj=l*n+l+1;
                  kk=(l+1)*n+l; ll=(l+1)*n+l+1;
                  p=a*(a-x)+a*a+y;
                  q=a*(a+a-x);
                  r=a*a[(l+2)*n+l+1];
                  }
                if ((fabs(p)+fabs(q)+fabs(r))!=0.0)
                  { xy=1.0;
                  if (p<0.0) xy=-1.0;
                  s=xy*sqrt(p*p+q*q+r*r);
                  if (k!=l) a=-s;
                  e=-q/s; ff=-r/s; x=-p/s;
                  y=-x-ff*r/(p+s);
                  g=e*r/(p+s);
                  z=-x-e*q/(p+s);
                  for (j=k; j<=m-1; j++)
                      { ii=k*n+j; jj=(k+1)*n+j;
                        p=x*a+e*a;
                        q=e*a+y*a;
                        r=ff*a+g*a;
                        if (k!=m-2)
                        { kk=(k+2)*n+j;
                            p=p+ff*a;
                            q=q+g*a;
                            r=r+z*a; a=r;
                        }
                        a=q; a=p;
                      }
                  j=k+3;
                  if (j>=m-1) j=m-1;
                  for (i=l; i<=j; i++)
                      { ii=i*n+k; jj=i*n+k+1;
                        p=x*a+e*a;
                        q=e*a+y*a;
                        r=ff*a+g*a;
                        if (k!=m-2)
                        { kk=i*n+k+2;
                            p=p+ff*a;
                            q=q+g*a;
                            r=r+z*a; a=r;
                        }
                        a=q; a=p;
                      }
                  }
            }
          }
      }

    for(i=0;i<n;i++)
                uv=u;
        for(i=0;i<n;i++)
                uv=v;
        return uv;
}

风花雪月 发表于 2006-10-10 00:42

text.cpp如下:
#include "matrix.h"
#include <math.h>
#include <fstream.h>
#include <malloc.h>

const unsigned char Z_RADIANS = 0;
const unsigned char Z_DEGREES = 1;
const unsigned char Z_COMMA   = 0;        // (x, y)
const unsigned char Z_LETTER= 1;        // x + iy
const double M_PI= 1.1415926;       
class complex
{
public:
double re, im;

private:
static unsigned char zArgMode;
static unsigned char zPrintMode;
static unsigned char zLetter;

public:
complex(void): re(0), im(0) {}
complex(const double real, const double imag=0): re(real), im(imag) {}
complex(const complex& z): re(z.re), im(z.im) {}

friend double    re(const complex& z) {        // real part
    return z.re;
}
friend double    im(const complex& z) {        // imaginary part
    return z.im;
}
friend doublereal(const complex& z) {        // real part
    return z.re;
}
friend doubleimag(const complex& z) {        // imaginary part
    return z.im;
}
friend double   mag(const complex& z) {        // magnitude |z|
    return sqrt(z.re*z.re + z.im*z.im);
}
friend double   arg(const complex& z);        // argument
friend double   ang(const complex& z) {        // angle
    return arg(z);
}
friend double    ph(const complex& z) {        // phase
    return arg(z);
}
friend complex conj(const complex& z) {        // complex conjugate
    return complex(z.re, -z.im);
}
friend doublenorm(const complex& z) {        // norm
    return z.re*z.re + z.im*z.im;
}

friend complex rtop(double x,   double y=0);
friend complex ptor(double mag, double angle=0);
complex& topolar(void);
complex& torect(void);

void operator = (const complex& z) {                // z1 = z2
    re = z.re;
    im = z.im;
}
complex& operator += (const complex& z) {        // z1 += z2
    re += z.re;
    im += z.im;
    return *this;
}
complex& operator -= (const complex& z) {        // z1 -= z2
    re -= z.re;
    im -= z.im;
    return *this;
}
complex& operator *= (const complex& z) {        // z1 *= z2
    *this = *this * z;
    return *this;
}
complex& operator /= (const complex& z) {        // z1 /= z2
    *this = *this / z;
    return *this;
}
complex operator + (void) const {                // +z1
    return *this;
}
complex operator - (void) const {                // -z1
    return complex(-re, -im);
}

friend complex operator + (const complex& z1, const complex& z2) {
    return complex(z1.re + z2.re, z1.im + z2.im);
}
friend complex operator + (const complex& z, const double x) {
    return complex(z.re+x, z.im);
}
friend complex operator + (const double x, const complex& z) {
    return complex(z.re+x, z.im);
}
friend complex operator - (const complex& z1, const complex& z2) {
    return complex(z1.re - z2.re, z1.im - z2.im);
}
friend complex operator - (const complex&, const double);
friend complex operator - (const double x, const complex& z) {
    return complex(x-z.re, -z.im);
}
friend complex operator * (const complex& z1, const complex& z2) {
    double re = z1.re*z2.re - z1.im*z2.im;
    double im = z1.re*z2.im + z1.im*z2.re;
    return complex(re, im);
}
friend complex operator * (const complex& z, const double x) {
    return complex(z.re*x, z.im*x);
}
friend complex operator * (const double x, const complex& z) {
    return complex(z.re*x, z.im*x);
}
friend complex operator / (const complex&, const complex&);
friend complex operator / (const complex& z, const double x) {
    return complex(z.re/x, z.im/x);
}
friend complex operator / (const double, const complex&);
friend complex operator ^ (const complex& z1, const complex& z2) {
    return pow(z1, z2);
}

friend int operator == (const complex& z1, const complex& z2) {
    return (z1.re == z2.re) && (z1.im == z2.im);
}
friend int operator != (const complex& z1, const complex& z2) {
    return (z1.re != z2.re) || (z1.im != z2.im);
}

friend double   abs(const complex& z);
friend complex sqrt(const complex& z);
friend complex pow(const complex& base, const complex& exp);
friend complex pow(const complex& base, const double   exp);
friend complex pow(const double   base, const complex& exp);

friend complex   exp(const complex& z);
friend complex   log(const complex& z);
friend complex    ln(const complex& z);
friend complex log10(const complex& z);

friend complexcos(const complex& z);
friend complexsin(const complex& z);
friend complextan(const complex& z);

friend complex asin(const complex& z);
friend complex acos(const complex& z);
friend complex atan(const complex& z);

friend complex sinh(const complex& z);
friend complex cosh(const complex& z);
friend complex tanh(const complex& z);

void SetArgMode(unsigned char mode) const {
    if(mode == Z_RADIANS || mode == Z_DEGREES)
      zArgMode = mode;
}
void SetPrintMode(unsigned char mode) const {
    if(mode == Z_COMMA || mode == Z_LETTER)
      zPrintMode = mode;
}
void SetLetter(unsigned char letter) const {
    zLetter = letter;
}

friend ostream& operator<<(ostream&, const complex&);
friend istream& operator>>(istream&, const complex&);
};

static const complex Z0(0, 0);                // complex number 0
static const complex Z1(1, 0);                // complex number 1
static const complex Zi(0, 1);                // complex number i
static const complex Zinf(HUGE_VAL, HUGE_VAL); // complex number infinity
static const complex Complex;
///////////////////////////////////////////////
/////////////////////////////////////////////////
///////////////////////////////////////////////
unsigned char complex::zArgMode   = Z_RADIANS;
unsigned char complex::zPrintMode = Z_COMMA;
unsigned char complex::zLetter    = 'i';

/* -------------------------------------------------------------------- */

double arg(const complex& z)                // argument (angle)
{
if(z.re == 0 && z.im == 0)                // this is actually a domain error
    return 0;
if(complex::zArgMode == Z_RADIANS)
    return atan2(z.im, z.re);
return atan2(z.im, z.re)/M_PI*180;
}

complex ptor(double mag, double angle)// polar-to-rectangular
{
if(complex::zArgMode == Z_RADIANS)
    return complex(mag*cos(angle), mag*sin(angle));
return complex(mag*cos(angle/180*M_PI), mag*sin(angle/180*M_PI));
}

complex rtop(double x, double y)        // rectangular-to-polar
{
if(x == 0 && y == 0)                        // this is actually a domain error
    return Z0;
if(complex::zArgMode == Z_RADIANS)
    return complex(sqrt(x*x + y*y), atan2(y, x));
return complex(sqrt(x*x + y*y), atan2(y, x)*180/M_PI);
}

complex& complex::topolar(void)
{
double re_tmp = re;

if(re != 0 || im != 0)                // z = (0,0) is a domain error
{
    re = sqrt(re*re + im*im);
    im = atan2(im, re_tmp);
}

if(complex::zArgMode == Z_DEGREES)
    im *= (180/M_PI);

return *this;
}

complex& complex::torect(void)
{
double re_tmp = re;

re = re_tmp*cos(im);
im = re_tmp*sin(im);

return *this;
}

/* ----- Operators ---------------------------------------------------- */

complex operator/(const complex& z1, const complex& z2)
{
if(z2 == Z0)
    return complex(Zinf);                // z2 = Z0 is an error!

double denom = z2.re*z2.re + z2.im*z2.im;
double re = (z1.re*z2.re + z1.im*z2.im)/denom;
double im = (z2.re*z1.im - z2.im*z1.re)/denom;
return complex(re, im);
}

complex operator/(const double x, const complex& z)
{
if(z == Z0)
    return complex(Zinf);                // z = Z0 is an error!

double denom = z.re*z.re + z.im*z.im;
return complex(x*z.re/denom, -z.im*x/denom);
}

/* ----- Math functions ----------------------------------------------- */

double abs(const complex& z)
{
return sqrt(z.re*z.re + z.im*z.im);
}

complex sqrt(const complex& z)
{
return ptor(sqrt(abs(z)), arg(z)/2);
}

complex pow(const complex& base, const double exponent)
{
if(base != Z0 && exponent == 0.0)
    return complex(1,0);

if (base == Z0 && exponent > 0)
    return Z0;

// base == Z0 && exponent == 0 is undefined!

return ptor(pow(abs(base), exponent), exponent*arg(base));
}

complex pow(const double base, const complex& exponent)
{
if(base != 0.0 && exponent == Z0)
    return complex(1,0);

if (base == 0 && re(exponent) > 0)
    return complex(0,0);

// base == 0 && re(exponent) == 0 is undefined!

if(base > 0.0)
    return exp(exponent * log(fabs(base)));

return exp(exponent * complex(log(fabs(base)), M_PI));
}

complex pow(const complex& base, const complex& exponent)
{
if(base != Z0 && exponent == Z0)
    return complex(1,0);

if(base == Z0 && re(exponent) > 0)
    return complex(0,0);

// base == Z0 && re(exponent) == 0 is undefined!

return exp(exponent * log(base));
}

/* ----- Trig functions ----------------------------------------------- */

complex exp(const complex& z)
{
double mag = exp(z.re);
return complex(mag*cos(z.im), mag*sin(z.im));
}

complex log(const complex& z)
{
return complex(log(mag(z)), atan2(z.im, z.re));
}
/*
complex log10(const complex& z)
{
return log(z) * M_LOG10E;
}
*/
complex sin(const complex& z)
{
return (exp(Zi*z) - exp(-Zi*z))/(2*Zi);
}

complex cos(const complex& z)
{
return (exp(Zi*z) + exp(-Zi*z))/2;
}

complex tan(const complex& z)
{
return sin(z)/cos(z);
}

complex asin(const complex& z)
{
return -Zi*log(Zi*z+sqrt(1-z*z));
}

complex acos(const complex& z)
{
return -Zi*log(z+Zi*sqrt(1-z*z));
}

complex atan(const complex& z)
{
return -0.5*Zi * log((1+Zi*z)/(1-Zi*z));
}

complex sinh(const complex& z)
{
return (exp(z) - exp(-z))/2;
}

complex cosh(const complex& z)
{
return (exp(z) + exp(-z))/2;
}

complex tanh(const complex& z)
{
return sinh(z)/cosh(z);
}

/* ----- Stream I/O --------------------------------------------------- */

ostream& operator<<(ostream& s, const complex& z)
{
char sign[] = "   ";

if(complex::zPrintMode == Z_COMMA)
    return s << "(" << z.re << ", " << z.im << ")";

if(z.im == 0 || z.im/fabs(z.im) == 1)
    sign = '+';
else
    sign = '-';
return s << z.re << sign << complex::zLetter << fabs(z.im);

}

istream& operator>>(istream& s, const complex& z)
{
char ch;

s >> ch;
if(ch == '(')
{
    s >> z.re >> ch;
    if(ch == ',')
      s >> z.im >> ch;
    if(ch != ')')
      s.clear(ios::badbit | s.rdstate());
}
else
{
    s.putback(ch);
    s >> z.re;
}

return s;
}
///////////////////////////////////////
////////////////////fft
void Fft(complex CA[],int n,int k,complex CB[],int l,int il)
{
    int it,m,is,i,j,nv,l0;
    double p,q,s,vr,vi,poddr,poddi;
        double *pr,*pi,*fr,*fi;
        pr=(double*)malloc(n*sizeof(double));
    pi=(double*)malloc(n*sizeof(double));
        fr=(double*)malloc(n*sizeof(double));
        fi=(double*)malloc(n*sizeof(double));
        for(i=0;i<n;i++)
        {
                pr=CA.re;
                pi=CA.im;
        }
    for (it=0; it<=n-1; it++)
      { m=it; is=0;
      for (i=0; i<=k-1; i++)
          { j=m/2; is=2*is+(m-2*j); m=j;}
      fr=pr; fi=pi;
      }
    pr=1.0; pi=0.0;
    p=6.283185306/(1.0*n);
    pr=cos(p); pi=-sin(p);
    if (l!=0) pi=-pi;
    for (i=2; i<=n-1; i++)
      { p=pr*pr; q=pi*pi;
      s=(pr+pi)*(pr+pi);
      pr=p-q; pi=s-p-q;
      }
    for (it=0; it<=n-2; it=it+2)
      { vr=fr; vi=fi;
      fr=vr+fr; fi=vi+fi;
      fr=vr-fr; fi=vi-fi;
      }
    m=n/2; nv=2;
    for (l0=k-2; l0>=0; l0--)
      { m=m/2; nv=2*nv;
      for (it=0; it<=(m-1)*nv; it=it+nv)
          for (j=0; j<=(nv/2)-1; j++)
            { p=pr*fr;
            q=pi*fi;
            s=pr+pi;
            s=s*(fr+fi);
            poddr=p-q; poddi=s-p-q;
            fr=fr-poddr;
            fi=fi-poddi;
            fr=fr+poddr;
            fi=fi+poddi;
            }
      }
    if (l!=0)
      for (i=0; i<=n-1; i++)
      { fr=fr/(1.0*n);
          fi=fi/(1.0*n);
      }
    if (il!=0)
      for (i=0; i<=n-1; i++)
      { pr=sqrt(fr*fr+fi*fi);
          if (fabs(fr)<0.000001*fabs(fi))
            { if ((fi*fr)>0) pi=90.0;
            else pi=-90.0;
            }
          else
            pi=atan(fi/fr)*360.0/6.283185306;
      }
        for(i=0;i<n;i++)
        {
                CA.re=pr;
                CA.im=pi;
        }
   
          for(i=0;i<n;i++)
          {
                  CB.re=fr;
                  CB.im=fi;
          }
    return;
}
/////////////////////////////////////
voidmain()
{
    complex a,b;
        a.re=2;
        a.im=3;
        b=a;
        b=exp(a);
        cout<<b;
        int n=64,i,j;
        double deltaT=0.1,R;
        ifstream ifile("d:\\work\\tj.fft");
        ofstream ofile("d:\\work\\tj.out");
        /*for(i=0;i<n;i++)
       ofile<<exp(-i*deltaT)<<endl;
       
        complex q;
        double L;
        int j;
        for(L=0;L<n;L++)
        {
                ifile.seekg(ios::beg);
                q=0;
                for(j=0;j<n;j++)
                {
                        ifile>>R;
                        q+=R*exp(-2*M_PI*L*Zi*L*j/n);
                }
                q*=deltaT;
                ofile<<q<<endl;
        }
        CMatrix<int> A;
        A.Ones(3);
        cout<<A;
    CMatrix<complex> B;
        B.Ones(3);
        cout<<B;
*/
        complex CA;
        complex p,f;
    for(i=0;i<64;i++)
        {
                ifile>>p;
        }
        Fft(p,64,6,f,1,1);
        for(i=0;i<=15;i++)
        {
                for(j=0;j<=3;j++)
                        ofile<<f<<"    ";
                ofile<<endl;
        }
        ofile<<endl<<endl<<endl;

for(i=0;i<=15;i++)
        {
                for(j=0;j<=3;j++)
                        ofile<<p<<"    ";
                ofile<<endl;
        }



        return ;
};

天堂泪 发表于 2007-9-20 19:36

:lol

assist 发表于 2007-9-21 09:39

有人测试过了吗?

风花雪月 发表于 2007-10-11 09:23

原帖由 assist 于 2007-9-21 09:39 发表 http://www.chinavib.com/forum/images/common/back.gif
有人测试过了吗?

有人测试过,不过会不会因为转贴造成错误,暂时没办法判断
页: [1]
查看完整版本: C++语言的复数与矩阵运算库