xue@11: /* xue@11: Harmonic sinusoidal modelling and tools xue@11: xue@11: C++ code package for harmonic sinusoidal modelling and relevant signal processing. xue@11: Centre for Digital Music, Queen Mary, University of London. xue@11: This file copyright 2011 Wen Xue. xue@11: xue@11: This program is free software; you can redistribute it and/or xue@11: modify it under the terms of the GNU General Public License as xue@11: published by the Free Software Foundation; either version 2 of the xue@11: License, or (at your option) any later version. xue@11: */ xue@1: #ifndef MatrixH xue@1: #define MatrixH xue@1: Chris@5: /** Chris@5: \file matrix.h - matrix operations. xue@1: xue@1: Matrices are accessed by double pointers as MATRIX[Y][X], where Y is the row index. xue@1: */ xue@1: xue@1: #include "xcomplex.h" xue@1: #include "arrayalloc.h" xue@1: xue@1: //--Similar balance---------------------------------------------------------- xue@1: void BalanceSim(int n, double** A); xue@1: xue@1: //--Choleski factorization--------------------------------------------------- xue@1: int Choleski(int N, double** L, double** A); xue@1: xue@1: //--matrix copy-------------------------------------------------------------- xue@1: double** Copy(int M, int N, double** Z, double** A, MList* List=0); xue@1: double** Copy(int M, int N, double** A, MList* List=0); xue@1: double** Copy(int N, double** Z, double ** A, MList* List=0); xue@1: double** Copy(int N, double ** A, MList* List=0); xue@1: cdouble** Copy(int M, int N, cdouble** Z, cdouble** A, MList* List=0); xue@1: cdouble** Copy(int M, int N, cdouble** A, MList* List=0); xue@1: cdouble** Copy(int N, cdouble** Z, cdouble** A, MList* List=0); xue@1: cdouble** Copy(int N, cdouble** A, MList* List=0); xue@1: double* Copy(int N, double* z, double* a, MList* List=0); xue@1: double* Copy(int N, double* a, MList* List=0); xue@1: cdouble* Copy(int N, cdouble* z, cdouble* a, MList* List=0); xue@1: cdouble* Copy(int N, cdouble* a, MList* List=0); xue@1: xue@1: //--matrix determinant calculation------------------------------------------- xue@1: double det(int N, double** A, int mode=0); xue@1: cdouble det(int N, cdouble** A, int mode=0); xue@1: xue@1: //--power methods for solving eigenproblems---------------------------------- xue@1: int EigPower(int N, double& l, double* x, double** A, double ep=1e-6, int maxiter=50); xue@1: int EigPowerA(int N, double& l, double* x, double** A, double ep=1e-6, int maxiter=50); xue@1: int EigPowerI(int N, double& l, double* x, double** A, double ep=1e-6, int maxiter=50); xue@1: int EigPowerS(int N, double& l, double* x, double** A, double ep=1e-6, int maxiter=50); xue@1: int EigPowerWielandt(int N, double& m, double* u, double l, double* v, double** A, double ep=1e-06, int maxiter=50); xue@1: int EigenValues(int N, double** A, cdouble* ev); xue@1: int EigSym(int N, double** A, double* d, double** Q); xue@1: xue@1: //--Gaussian elimination for solving linear systems-------------------------- xue@1: int GEB(int N, double* x, double** A, double* b); xue@1: int GESCP(int N, double* x, double** A, double*b); xue@1: void GExL(int N, double* x, double** L, double* a); xue@1: void GExLAdd(int N, double* x, double** L, double* a); xue@1: void GExL1(int N, double* x, double** L, double a); xue@1: void GExL1Add(int N, double* x, double** L, double a); xue@1: xue@1: /* xue@1: template GECP: Gaussian elimination with maximal column pivoting for solving linear system Ax=b xue@1: xue@1: In: matrix A[N][N], vector b[N] xue@1: Out: vector x[N] xue@1: xue@1: Returns 0 if successful. Contents of matrix A and vector b are destroyed on return. xue@1: */ xue@1: templateint GECP(int N, T* x, Ta** A, T *b, Ta* logdet=0) xue@1: { xue@1: if (logdet) *logdet=1E-302; int c, p, ip, *rp=new int[N]; for (int i=0; ifabs(A[rp[p]][i])) p=ip; ip++;} xue@1: if (A[rp[p]][i]==0) {delete[] rp; return 1;} xue@1: if (p!=i) {c=rp[i]; rp[i]=rp[p]; rp[p]=c;} xue@1: for (int j=i+1; j=0; i--) xue@1: { xue@1: x[i]=b[rp[i]]; for (int j=i+1; j xue@1: xue@1: In: vectors x[N], w[N] and y[N] xue@1: xue@1: Returns inner product of xw and y. xue@1: */ xue@1: templatecdouble Inner(int N, Tx* x, Tw* w, cdouble* y) xue@1: { xue@1: cdouble result=0; xue@1: for (int i=0; icdouble Inner(int N, Tx* x, Tw* w, double* y) xue@1: { xue@1: cdouble result=0; xue@1: for (int i=0; i=N. xue@1: xue@1: In: matrix A[M][N], vector y[M] xue@1: Out: vector x[N] xue@1: xue@1: Returns the log determinant of AtA. Contents of matrix A and vector y are unchanged on return. xue@1: */ xue@1: template T LSLinear(int M, int N, T* x, T** A, T* y) xue@1: { xue@1: MList* mlist=new MList; xue@1: T** AtA=MultiplyXtX(N, M, A, mlist); xue@1: T* Aty=MultiplyXty(N, M, A, y, mlist); xue@1: T result; GECP(N, x, AtA, Aty, &result); xue@1: delete mlist; xue@1: return result; xue@1: }//LSLinear xue@1: xue@1: //--2-stage Least-square solution of overdetermined linear system------------ xue@1: void LSLinear2(int M, int N, double* x, double** A, double* y); xue@1: xue@1: //--LU factorization of a non-singular matrix-------------------------------- xue@1: int LU_Direct(int mode, int N, double* diag, double** a); xue@1: int LU(int N, double** l, double** u, double** a); void LU_DiagL(int N, double** l, double* diagl, double** u, double** a); xue@1: int LU_PD(int N, double** b); xue@1: int LU_PD(int N, double** b, double* c); xue@1: double LUCP(double **a, int N, int *ind, int& parity, int mode=1); xue@1: xue@1: //--LU factorization method for solving a linear system---------------------- xue@1: void LU(int N, double* x, double** A, double* y, int* ind=0); xue@1: xue@1: //--find maximum of vector--------------------------------------------------- xue@1: int maxind(double* data, int from, int to); xue@1: xue@1: //--matrix linear combination------------------------------------------------ xue@1: /* xue@1: template MultiAdd: matrix linear combination Z=X+aY xue@1: xue@1: In: matrices X[M][N], Y[M][N], scalar a xue@1: Out: matrix Z[M][N] xue@1: xue@1: Returns pointer to Z. Z is created anew if Z=0 is specified on start. xue@1: */ xue@1: template Tz** MultiAdd(int M, int N, Tz** Z, Tx** X, Ty** Y, Ta a, MList* List=0) xue@1: { xue@1: if (!Z){Allocate2(Tz, M, N, Z); if (List) List->Add(Z, 2);} xue@1: for (int i=0; i Tz* MultiAdd(int N, Tz* z, Tx* x, Ty* y, Ta a, MList* List=0) xue@1: { xue@1: if (!z){z=new Tz[N]; if (List) List->Add(z, 1);} xue@1: for (int i=0; i Tx* MultiAdd(int N, Tx* x, Ty* y, Ta a, MList* List=0) xue@1: { xue@1: return MultiAdd(N, (Tx*)0, x, y, a, List); xue@1: }//MultiAdd xue@1: xue@1: //--matrix multiplication by constant---------------------------------------- xue@1: /* xue@1: template Multiply: matrix-constant multiplication Z=aX xue@1: xue@1: In: matrix X[M][N], scalar a xue@1: Out: matrix Z[M][N] xue@1: xue@1: Returns pointer to Z. Z is created anew if Z=0 is specified on start. xue@1: */ xue@1: template Tz** Multiply(int M, int N, Tz** Z, Tx** X, Ta a, MList* List=0) xue@1: { xue@1: if (!Z){Allocate2(Tz, M, N, Z); if (List) List->Add(Z, 2);} xue@1: for (int i=0; i Tz* Multiply(int N, Tz* z, Tx* x, Ta a, MList* List=0) xue@1: { xue@1: if (!z){z=new Tz[N]; if (List) List->Add(z, 1);} xue@1: for (int i=0; iTx* Multiply(int N, Tx* x, Ta a, MList* List=0) xue@1: { xue@1: return Multiply(N, (Tx*)0, x, a, List); xue@1: }//Multiply xue@1: xue@1: //--matrix multiplication operations----------------------------------------- xue@1: /* xue@1: macro Multiply_full: matrix-matrix multiplication z=xy and multiplication-accumulation z=z+xy. xue@1: xue@1: Each expansion of the macro defines three function templates; two are named $MULTIPLY and do matrix xue@1: multiplication only; one is named $MULTIADD and accumulates the multiplicated result on top of a xue@1: specified matrix. One of the two $MULTIPLY functions allows using a pre-allocated matrix to accept xue@1: the matrix product, while the other directly allocates a new matrix and returns the pointer. xue@1: xue@1: Functions are named after their exact functions. For example, MultiplyXYc multiplies matrix X with xue@1: the complex conjugate of matrix Y, where postfix "c" attched to Y stands for conjugate. Likewise, xue@1: the postfix "t" stands for transpose, and "h" stnads for Hermitian (conjugate transpose). xue@1: xue@1: Three dimension arguments are needed by each function template. The first and last of the three are xue@1: the number of rows and columns, respectively, of the product (output) matrix. The middle one is the xue@1: "other", common dimension of both multiplier matrices. xue@1: */ xue@1: #define Multiply_full(MULTIPLY, MULTIADD, xx, yy) \ xue@1: templateTx** MULTIPLY(int N, int M, int K, Tx** z, Tx** x, Ty** y, MList* List=0){ \ xue@1: if (!z) {Allocate2(Tx, N, K, z); if (List) List->Add(z, 2);} \ xue@1: for (int n=0; nTx** MULTIPLY(int N, int M, int K, Tx** x, Ty** y, MList* List=0){ \ xue@1: Tx** Allocate2(Tx, N, K, z); if (List) List->Add(z, 2); \ xue@1: for (int n=0; nvoid MULTIADD(int N, int M, int K, Tx** z, Tx** x, Ty** y){ \ xue@1: for (int n=0; nT** MULTIPLY(int N, T** z, T** x, T** y, MList* List=0){ \ xue@1: if (!z){Allocate2(T, N, N, z); if (List) List->Add(z, 2);} \ xue@1: if (z!=x) MULTIPLY(N, N, N, z, x, y); else{ \ xue@1: T* tmp=new T[N]; int sizeN=sizeof(T)*N; for (int i=0; iT** MULTIPLY(int N, T** x, T** y, MList* List=0){return MULTIPLY(N, N, N, x, y, List);}\ xue@1: templatevoid MULTIADD(int N, T** z, T** x, T** y){MULTIADD(N, N, N, z, x, y);} xue@1: Multiply_square(MultiplyXY, MultiAddXY) xue@1: xue@1: /* xue@1: macro Multiply_xx: matrix self multiplication z=xx and self-multiplication-accumulation z=z+xx. xue@1: xue@1: Each expansion of the macro defines three function templates; two are named $MULTIPLY and do matrix xue@1: multiplication only; one is named $MULTIADD and accumulates the multiplicated result on top of a xue@1: specified matrix. One of the two $MULTIPLY functions allows using a pre-allocated matrix to accept xue@1: the matrix product, while the other directly allocates a new matrix and returns the pointer. xue@1: */ xue@1: #define Multiply_xx(MULTIPLY, MULTIADD, xx1, xx2, zzt) \ xue@1: templateT** MULTIPLY(int M, int N, T** z, T** x, MList* List=0){ \ xue@1: if (!z){Allocate2(T, M, M, z); if (List) List->Add(z, 2);} \ xue@1: for (int m=0; mT** MULTIPLY(int M, int N, T ** x, MList* List=0){ \ xue@1: T** Allocate2(T, M, M, z); if (List) List->Add(z, 2); \ xue@1: for (int m=0; mvoid MULTIADD(int M, int N, T** z, T** x){ \ xue@1: for (int m=0; m