Mercurial > hg > x
diff Matrix.h @ 1:6422640a802f
first upload
author | Wen X <xue.wen@elec.qmul.ac.uk> |
---|---|
date | Tue, 05 Oct 2010 10:45:57 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Matrix.h Tue Oct 05 10:45:57 2010 +0100 @@ -0,0 +1,407 @@ +#ifndef MatrixH +#define MatrixH + +/* + Matrix.cpp - matrix operations. + + Matrices are accessed by double pointers as MATRIX[Y][X], where Y is the row index. +*/ + +#include "xcomplex.h" +#include "arrayalloc.h" + +//--Similar balance---------------------------------------------------------- +void BalanceSim(int n, double** A); + +//--Choleski factorization--------------------------------------------------- +int Choleski(int N, double** L, double** A); + +//--matrix copy-------------------------------------------------------------- +double** Copy(int M, int N, double** Z, double** A, MList* List=0); + double** Copy(int M, int N, double** A, MList* List=0); + double** Copy(int N, double** Z, double ** A, MList* List=0); + double** Copy(int N, double ** A, MList* List=0); +cdouble** Copy(int M, int N, cdouble** Z, cdouble** A, MList* List=0); + cdouble** Copy(int M, int N, cdouble** A, MList* List=0); + cdouble** Copy(int N, cdouble** Z, cdouble** A, MList* List=0); + cdouble** Copy(int N, cdouble** A, MList* List=0); +double* Copy(int N, double* z, double* a, MList* List=0); + double* Copy(int N, double* a, MList* List=0); +cdouble* Copy(int N, cdouble* z, cdouble* a, MList* List=0); + cdouble* Copy(int N, cdouble* a, MList* List=0); + +//--matrix determinant calculation------------------------------------------- +double det(int N, double** A, int mode=0); +cdouble det(int N, cdouble** A, int mode=0); + +//--power methods for solving eigenproblems---------------------------------- +int EigPower(int N, double& l, double* x, double** A, double ep=1e-6, int maxiter=50); +int EigPowerA(int N, double& l, double* x, double** A, double ep=1e-6, int maxiter=50); +int EigPowerI(int N, double& l, double* x, double** A, double ep=1e-6, int maxiter=50); +int EigPowerS(int N, double& l, double* x, double** A, double ep=1e-6, int maxiter=50); +int EigPowerWielandt(int N, double& m, double* u, double l, double* v, double** A, double ep=1e-06, int maxiter=50); +int EigenValues(int N, double** A, cdouble* ev); +int EigSym(int N, double** A, double* d, double** Q); + +//--Gaussian elimination for solving linear systems-------------------------- +int GEB(int N, double* x, double** A, double* b); +int GESCP(int N, double* x, double** A, double*b); +void GExL(int N, double* x, double** L, double* a); +void GExLAdd(int N, double* x, double** L, double* a); +void GExL1(int N, double* x, double** L, double a); +void GExL1Add(int N, double* x, double** L, double a); + +/* + template GECP: Gaussian elimination with maximal column pivoting for solving linear system Ax=b + + In: matrix A[N][N], vector b[N] + Out: vector x[N] + + Returns 0 if successful. Contents of matrix A and vector b are destroyed on return. +*/ +template<class T, class Ta>int GECP(int N, T* x, Ta** A, T *b, Ta* logdet=0) +{ + if (logdet) *logdet=1E-302; int c, p, ip, *rp=new int[N]; for (int i=0; i<N; i++) rp[i]=i; + Ta m; + //Gaussian eliminating + for (int i=0; i<N-1; i++) + { + p=i, ip=i+1; + while (ip<N){if (fabs(A[rp[ip]][i])>fabs(A[rp[p]][i])) p=ip; ip++;} + if (A[rp[p]][i]==0) {delete[] rp; return 1;} + if (p!=i) {c=rp[i]; rp[i]=rp[p]; rp[p]=c;} + for (int j=i+1; j<N; j++) + { + m=A[rp[j]][i]/A[rp[i]][i]; + A[rp[j]][i]=0; + for (int k=i+1; k<N; k++) A[rp[j]][k]-=m*A[rp[i]][k]; + b[rp[j]]-=m*b[rp[i]]; + } + } + if (A[rp[N-1]][N-1]==0) {delete[] rp; return 1;} + //backward substitution + x[N-1]=b[rp[N-1]]/A[rp[N-1]][N-1]; + for (int i=N-2; i>=0; i--) + { + x[i]=b[rp[i]]; for (int j=i+1; j<N; j++) x[i]-=A[rp[i]][j]*x[j]; x[i]/=A[rp[i]][i]; + } + if (logdet){*logdet=log(fabs(A[rp[0]][0])); for (int n=1; n<N; n++) *logdet+=log(fabs(A[rp[n]][n]));} + delete[] rp; + return 0; +}//GECP + +//--inverse lower and upper triangular matrices------------------------------ +double GILT(int N, double** A); +double GIUT(int N, double** A); + +//--inverse matrix calculation with gaussian elimination--------------------- +double GICP(int N, double** X, double** A); +double GICP(int N, double** A); +cdouble GICP(int N, cdouble** A); +double GISCP(int N, double** X, double** A); +double GISCP(int N, double** A); + +//--Gaussian-Seidel method for solving linear systems------------------------ +int GSI(int N, double* x0, double** A, double* b, double ep=1e-4, int maxiter=50); + +//Reduction to upper Heissenberg matrix by elimination with pivoting +void Hessenb(int n, double** A); + +//--Householder algorithm converting a matrix tridiagonal-------------------- +void HouseHolder(int N, double** A); +void HouseHolder(int N, double** T, double** Q, double** A); +void HouseHolder(int n, double **A, double* d, double* sd); + +//--inner product------------------------------------------------------------ +double Inner(int N, double* x, double* y); +cdouble Inner(int N, double* x, cdouble* y); +cdouble Inner(int N, cdouble* x, cdouble* y); +cdouble Inner(int N, cfloat* x, cdouble* y); +cfloat Inner(int N, cfloat* x, cfloat* y); +double Inner(int M, int N, double** X, double** Y); + +/* + template Inner: Inner product <xw, y> + + In: vectors x[N], w[N] and y[N] + + Returns inner product of xw and y. +*/ +template<class Tx, class Tw>cdouble Inner(int N, Tx* x, Tw* w, cdouble* y) +{ + cdouble result=0; + for (int i=0; i<N; i++) result+=(x[i]*w[i])**y[i]; + return result; +}//Inner +template<class Tx, class Tw>cdouble Inner(int N, Tx* x, Tw* w, double* y) +{ + cdouble result=0; + for (int i=0; i<N; i++) result+=x[i]*w[i]*y[i]; + return result; +}//Inner + +//--Jacobi iterative method for solving linear systems----------------------- +int JI(int N, double* x, double** A, double* b, double ep=1e-4, int maxiter=50); + +//--LDL factorization of a symmetric matrix---------------------------------- +int LDL(int N, double** L, double* d, double** A); + +//--LQ factorization by Gram-Schmidt----------------------------------------- +void LQ_GS(int M, int N, double** A, double** L, double** Q); + +//--1-stage Least-square solution of overdetermined linear system------------ +/* + template LSLinera: direct LS solution of A[M][N]x[N]=y[M], M>=N. + + In: matrix A[M][N], vector y[M] + Out: vector x[N] + + Returns the log determinant of AtA. Contents of matrix A and vector y are unchanged on return. +*/ +template <class T> T LSLinear(int M, int N, T* x, T** A, T* y) +{ + MList* mlist=new MList; + T** AtA=MultiplyXtX(N, M, A, mlist); + T* Aty=MultiplyXty(N, M, A, y, mlist); + T result; GECP(N, x, AtA, Aty, &result); + delete mlist; + return result; +}//LSLinear + +//--2-stage Least-square solution of overdetermined linear system------------ +void LSLinear2(int M, int N, double* x, double** A, double* y); + +//--LU factorization of a non-singular matrix-------------------------------- +int LU_Direct(int mode, int N, double* diag, double** a); +int LU(int N, double** l, double** u, double** a); void LU_DiagL(int N, double** l, double* diagl, double** u, double** a); +int LU_PD(int N, double** b); +int LU_PD(int N, double** b, double* c); +double LUCP(double **a, int N, int *ind, int& parity, int mode=1); + +//--LU factorization method for solving a linear system---------------------- +void LU(int N, double* x, double** A, double* y, int* ind=0); + +//--find maximum of vector--------------------------------------------------- +int maxind(double* data, int from, int to); + +//--matrix linear combination------------------------------------------------ +/* + template MultiAdd: matrix linear combination Z=X+aY + + In: matrices X[M][N], Y[M][N], scalar a + Out: matrix Z[M][N] + + Returns pointer to Z. Z is created anew if Z=0 is specified on start. +*/ +template<class Tz, class Tx, class Ty, class Ta> Tz** MultiAdd(int M, int N, Tz** Z, Tx** X, Ty** Y, Ta a, MList* List=0) +{ + if (!Z){Allocate2(Tz, M, N, Z); if (List) List->Add(Z, 2);} + for (int i=0; i<M; i++) for (int j=0; j<N; j++) Z[i][j]=X[i][j]+a*Y[i][j]; + return Z; +}//MultiAdd + +/* + template MultiAdd: vector linear combination z=x+ay + + In: vectors x[N], y[N], scalar a + Out: vector z[N] + + Returns pointer to z. z is created anew if z=0 is specified on start. +*/ +template<class Tz, class Tx, class Ty, class Ta> Tz* MultiAdd(int N, Tz* z, Tx* x, Ty* y, Ta a, MList* List=0) +{ + if (!z){z=new Tz[N]; if (List) List->Add(z, 1);} + for (int i=0; i<N; i++) z[i]=x[i]+Ty(a)*y[i]; + return z; +}//MultiAdd +template<class Tx, class Ty, class Ta> Tx* MultiAdd(int N, Tx* x, Ty* y, Ta a, MList* List=0) +{ + return MultiAdd(N, (Tx*)0, x, y, a, List); +}//MultiAdd + +//--matrix multiplication by constant---------------------------------------- +/* + template Multiply: matrix-constant multiplication Z=aX + + In: matrix X[M][N], scalar a + Out: matrix Z[M][N] + + Returns pointer to Z. Z is created anew if Z=0 is specified on start. +*/ +template<class Tz, class Tx, class Ta> Tz** Multiply(int M, int N, Tz** Z, Tx** X, Ta a, MList* List=0) +{ + if (!Z){Allocate2(Tz, M, N, Z); if (List) List->Add(Z, 2);} + for (int i=0; i<M; i++) for (int j=0; j<N; j++) Z[i][j]=a*X[i][j]; + return Z; +}//Multiply + +/* + template Multiply: vector-constant multiplication z=ax + + In: matrix x[N], scalar a + Out: matrix z[N] + + Returns pointer to z. z is created anew if z=0 is specified on start. +*/ +template<class Tz, class Tx, class Ta> Tz* Multiply(int N, Tz* z, Tx* x, Ta a, MList* List=0) +{ + if (!z){z=new Tz[N]; if (List) List->Add(z, 1);} + for (int i=0; i<N; i++) z[i]=x[i]*a; + return z; +}//Multiply +template<class Tx, class Ta>Tx* Multiply(int N, Tx* x, Ta a, MList* List=0) +{ + return Multiply(N, (Tx*)0, x, a, List); +}//Multiply + +//--matrix multiplication operations----------------------------------------- +/* + macro Multiply_full: matrix-matrix multiplication z=xy and multiplication-accumulation z=z+xy. + + Each expansion of the macro defines three function templates; two are named $MULTIPLY and do matrix + multiplication only; one is named $MULTIADD and accumulates the multiplicated result on top of a + specified matrix. One of the two $MULTIPLY functions allows using a pre-allocated matrix to accept + the matrix product, while the other directly allocates a new matrix and returns the pointer. + + Functions are named after their exact functions. For example, MultiplyXYc multiplies matrix X with + the complex conjugate of matrix Y, where postfix "c" attched to Y stands for conjugate. Likewise, + the postfix "t" stands for transpose, and "h" stnads for Hermitian (conjugate transpose). + + Three dimension arguments are needed by each function template. The first and last of the three are + the number of rows and columns, respectively, of the product (output) matrix. The middle one is the + "other", common dimension of both multiplier matrices. +*/ +#define Multiply_full(MULTIPLY, MULTIADD, xx, yy) \ + template<class Tx, class Ty>Tx** MULTIPLY(int N, int M, int K, Tx** z, Tx** x, Ty** y, MList* List=0){ \ + if (!z) {Allocate2(Tx, N, K, z); if (List) List->Add(z, 2);} \ + for (int n=0; n<N; n++) for (int k=0; k<K; k++){ \ + Tx zz=0; for (int m=0; m<M; m++) zz+=xx*yy; z[n][k]=zz;} return z;} \ + template<class Tx, class Ty>Tx** MULTIPLY(int N, int M, int K, Tx** x, Ty** y, MList* List=0){ \ + Tx** Allocate2(Tx, N, K, z); if (List) List->Add(z, 2); \ + for (int n=0; n<N; n++) for (int k=0; k<K; k++){ \ + Tx zz=0; for (int m=0; m<M; m++) zz+=xx*yy; z[n][k]=zz;} return z;} \ + template<class Tx, class Ty>void MULTIADD(int N, int M, int K, Tx** z, Tx** x, Ty** y){ \ + for (int n=0; n<N; n++) for (int k=0; k<K; k++){ \ + Tx zz=0; for (int m=0; m<M; m++) zz+=xx*yy; z[n][k]+=zz;}} +Multiply_full(MultiplyXY, MultiAddXY, x[n][m], y[m][k]) //z[N][K]=x[N][M]y[M][K], identical z and x or y not allowed +Multiply_full(MultiplyXYc, MultiAddXYc, x[n][m], *y[m][k]) //z[N][K]=x[N][M](y*)[M][K], identical z and x or y not allowed +Multiply_full(MultiplyXYt, MultiAddXYt, x[n][m], y[k][m]) //z[N][K]=x[N][M]Yt[M][K], identical z and x or y not allowed +Multiply_full(MultiplyXYh, MultiAddXYh, x[n][m], *y[k][m]) //z[N][K]=x[N][M](Yt*)[M][K], identical z and x or y not allowed + +/* + macro Multiply_square: square matrix multiplication z=xy and multiplication-accumulation z=z+xy. + Identical z and x allowed for multiplication but not for multiplication-accumulation. + + Each expansion of the macro defines three function templates; two are named $MULTIPLY and do matrix + multiplication only; one is named $MULTIADD and accumulates the multiplicated result on top of a + specified matrix. One of the two $MULTIPLY functions allows using a pre-allocated matrix to accept + the matrix product, while the other directly allocates a new matrix and returns the pointer. +*/ +#define Multiply_square(MULTIPLY, MULTIADD) \ + template<class T>T** MULTIPLY(int N, T** z, T** x, T** y, MList* List=0){ \ + if (!z){Allocate2(T, N, N, z); if (List) List->Add(z, 2);} \ + if (z!=x) MULTIPLY(N, N, N, z, x, y); else{ \ + T* tmp=new T[N]; int sizeN=sizeof(T)*N; for (int i=0; i<N; i++){ \ + MULTIPLY(1, N, N, &tmp, &x[i], y); memcpy(z[i], tmp, sizeN);} delete[] tmp;} \ + return z;} \ + template<class T>T** MULTIPLY(int N, T** x, T** y, MList* List=0){return MULTIPLY(N, N, N, x, y, List);}\ + template<class T>void MULTIADD(int N, T** z, T** x, T** y){MULTIADD(N, N, N, z, x, y);} +Multiply_square(MultiplyXY, MultiAddXY) + +/* + macro Multiply_xx: matrix self multiplication z=xx and self-multiplication-accumulation z=z+xx. + + Each expansion of the macro defines three function templates; two are named $MULTIPLY and do matrix + multiplication only; one is named $MULTIADD and accumulates the multiplicated result on top of a + specified matrix. One of the two $MULTIPLY functions allows using a pre-allocated matrix to accept + the matrix product, while the other directly allocates a new matrix and returns the pointer. +*/ +#define Multiply_xx(MULTIPLY, MULTIADD, xx1, xx2, zzt) \ + template<class T>T** MULTIPLY(int M, int N, T** z, T** x, MList* List=0){ \ + if (!z){Allocate2(T, M, M, z); if (List) List->Add(z, 2);} \ + for (int m=0; m<M; m++) for (int k=0; k<=m; k++){ \ + T zz=0; for (int n=0; n<N; n++) zz+=xx1*xx2; z[m][k]=zz; if (m!=k) z[k][m]=zzt;} \ + return z;} \ + template<class T>T** MULTIPLY(int M, int N, T ** x, MList* List=0){ \ + T** Allocate2(T, M, M, z); if (List) List->Add(z, 2); \ + for (int m=0; m<M; m++) for (int k=0; k<=m; k++){ \ + T zz=0; for (int n=0; n<N; n++) zz+=xx1*xx2; z[m][k]=zz; if (m!=k) z[k][m]=zzt;} \ + return z;} \ + template<class T>void MULTIADD(int M, int N, T** z, T** x){ \ + for (int m=0; m<M; m++) for (int k=0; k<=m; k++){ \ + T zz=0; for (int n=0; n<N; n++) zz+=xx1*xx2; z[m][k]+=zz; if (m!=k) z[k][m]+=zzt;}} +Multiply_xx(MultiplyXtX, MultiAddXtX, x[n][m], x[n][k], zz) //z[M][M]=xt[M][N]x[N][M], identical z and x NOT ALLOWED. +Multiply_xx(MultiplyXXt, MultiAddXXt, x[m][n], x[k][n], zz) //z[M][M]=X[M][N]xt[N][M], identical z and x NOT ALLOWED. +Multiply_xx(MultiplyXhX, MultiAddXhX, *x[n][m], x[n][k], *zz) //z[M][M]=(xt*)[M][N]x[N][M], identical z and x NOT ALLOWED. +Multiply_xx(MultiplyXXh, MultiAddXXh, x[m][n], *x[k][n], *zz) //z[M][M]=x[M][N](xt*)[N][M], identical z and x NOT ALLOWED. +Multiply_xx(MultiplyXcXt, MultiAddXcXt, *x[m][n], x[k][n], *zz) //z[M][M]=(x*)[M][N]xt[N][M], identical z and x NOT ALLOWED. + +//matrix-vector multiplication routines +double* MultiplyXy(int M, int N, double* z, double** x, double* y, MList* List=0); +double* MultiplyXy(int M, int N, double** x, double* y, MList* List=0); +cdouble* MultiplyXy(int M, int N, cdouble* z, cdouble** x, cdouble* y, MList* List=0); +cdouble* MultiplyXy(int M, int N, cdouble** x, cdouble* y, MList* List=0); +cdouble* MultiplyXy(int M, int N, cdouble* z, double** x, cdouble* y, MList* List=0); +cdouble* MultiplyXy(int M, int N, double** x, cdouble* y, MList* List=0); +double* MultiplyxY(int M, int N, double* zt, double* xt, double** y, MList* List=0); +double* MultiplyxY(int M, int N, double* xt, double** y, MList* List=0); +cdouble* MultiplyxY(int M, int N, cdouble* zt, cdouble* xt, cdouble** y, MList* List=0); +cdouble* MultiplyxY(int M, int N, cdouble* xt, cdouble** y, MList* List=0); +double* MultiplyXty(int M, int N, double* z, double** x, double* y, MList* List=0); +double* MultiplyXty(int M, int N, double** x, double* y, MList* List=0); +cdouble* MultiplyXty(int M, int N, cdouble* z, cdouble** x, cdouble* y, MList* List=0); +cdouble* MultiplyXty(int M, int N, cdouble** x, cdouble* y, MList* List=0); +cdouble* MultiplyXhy(int M, int N, cdouble* z, cdouble** x, cdouble* y, MList* List=0); +cdouble* MultiplyXhy(int M, int N, cdouble** x, cdouble* y, MList* List=0); +cdouble* MultiplyXcy(int M, int N, cdouble* z, cdouble** x, cfloat* y, MList* List=0); +cdouble* MultiplyXcy(int M, int N, cdouble** x, cfloat* y, MList* List=0); +cdouble* MultiplyXcy(int M, int N, cdouble* z, cdouble** x, cdouble* y, MList* List=0); +cdouble* MultiplyXcy(int M, int N, cdouble** x, cdouble* y, MList* List=0); +double* MultiplyxYt(int M, int N, double* zt, double* xt, double** y, MList* MList=0); +double* MultiplyxYt(int M, int N, double* xt, double** y, MList* MList=0); + +//--matrix norms------------------------------------------------------------- +double Norm1(int N, double** A); + +//--QR factorization--------------------------------------------------------- +void QR_GS(int M, int N, double** A, double** Q, double** R); +void QR_householder(int M, int N, double** A, double** Q, double** R); + +//--QR factorization of a tridiagonal matrix--------------------------------- +int QL(int N, double* d, double* sd, double** z); +int QR(int N, double **A, cdouble* ev); + +//--QU factorization of a matrix--------------------------------------------- +void QU(int N, double** Q, double** A); + +//--Extract the real part---------------------------------------------------- +double** Real(int M, int N, double** z, cdouble** x, MList* List); +double** Real(int M, int N, cdouble** x, MList* List); + +//--Finding roots of real polynomials---------------------------------------- +int Roots(int N, double* p, double* rr, double* ri); + +//--Sor iterative method for solving linear systems-------------------------- +int SorI(int N, double* x0, double** a, double* b, double w=1, double ep=1e-4, int maxiter=50); + +//--Submatrix---------------------------------------------------------------- +void SetSubMatrix(double** z, double** x, int Y1, int Y, int X1, int X); +void SetSubMatrix(cdouble** z, cdouble** x, int Y1, int Y, int X1, int X); +cdouble** SubMatrix(cdouble** z, cdouble** x, int Y1, int Y, int X1, int X, MList* List=0); +cdouble** SubMatrix(cdouble** x, int Y1, int Y, int X1, int X, MList* List=0); +cdouble* SubVector(cdouble* z, cdouble* x, int X1, int X, MList* List=0); +cdouble* SubVector(cdouble* x, int X1, int X, MList* List=0); + +//--matrix transpose operation----------------------------------------------- +void transpose(int N, double** a); +void transpose(int N, cdouble** a); +double** transpose(int N, int M, double** ta, double** a, MList* List=0); //z[NM]=a[MN]' +double** transpose(int N, int M, double** a, MList* List=0); + +//--rotation matrix converting between vectors------------------------------- +double** Unitary(int N, double** P, double* x, double* y, MList* List=0); +double** Unitary(int N, double* x, double* y, MList* List=0); +cdouble** Unitary(int N, cdouble** P, cdouble* x, cdouble* y, MList* List=0); +cdouble** Unitary(int N, cdouble* x, cdouble* y, MList* List=0); + +#endif