void Matrix<real>::RemoveRows(int rowStart, int rowEnd) { InPlaceTransposeMatrix(m, n, data); int mBuf = m; m = n; n = mBuf; RemoveColumns(rowStart, rowEnd); InPlaceTransposeMatrix(m, n, data); mBuf = m; m = n; n = mBuf; }
Matrix<real> & Matrix<real>::InPlaceTranspose() { InPlaceTransposeMatrix(m, n, data); // swap m,n int swap = m; m = n; n = swap; return (*this); }
void Matrix<real>::AppendRows(const Matrix<real> & rows) { if (rows.Getn() != n) { printf("Error: mismatch in number of columns in AppendRows.\n"); throw 42; } InPlaceTransposeMatrix(m, n, data); int mBuf = m; m = n; n = mBuf; Matrix<real> rowsT = Transpose(rows); AppendColumns(rowsT); InPlaceTransposeMatrix(m, n, data); mBuf = m; m = n; n = mBuf; }
int MatrixPCA(ThresholdingSpecification * thresholdingSpecification, int m, int n, double * A, int * r, double * weights) { if (!A) { printf("Error: input matrix is NULL.\n"); return -1; } if (weights != NULL) { // transform row i of A by sqrt(weights[i]) for(int row=0; row<m; row++) { double rowWeight = sqrt(weights[row]); for(int column=0; column<n; column++) A[ELT(m, row, column)] *= rowWeight; } } bool transpose = false; if (m > n) { transpose = true; InPlaceTransposeMatrix(m,n,A); // swap m,n int bufferi = m; m = n; n = bufferi; } // do SVD char jobu = 'O';//overwrites A with U (left singular vectors) //char jobu = 'N'; char jobvt = 'S';//all rows returned in VT //char jobvt = 'N'; int ldA = m; int ldU = m; int lwork = 64*MAX(3*MIN( m, n)+MAX(m,n), 5*MIN(m,n)-4); double * work = (double*) malloc (sizeof(double) * lwork); if (!work) { printf("Error: failed to allocate workspace.\n"); return -2; } //printf("Workspace size is: %G Mb .\n",1.0 * lwork * sizeof(int) / 1024 / 1024); // allocate array for singular vectors double * S = (double *) malloc (sizeof(double) * MIN(m,n)); if (!S) { printf("Error: failed to allocate singular vectors.\n"); return -2; } double * dummyU = NULL; // allocate array for VT int ldVT = MIN(m,n); double * VT = (double *) malloc (sizeof(double) * ldVT * n); if (!VT) { printf("Error: failed to allocate VT.\n"); return -2; } #ifdef __APPLE__ #define DGESVD dgesvd_ #define INTEGER __CLPK_integer #else #define DGESVD dgesvd #define INTEGER int #endif INTEGER M = m; INTEGER N = n; INTEGER LDA = ldA; INTEGER LDU = ldU; INTEGER LDVT = ldVT; INTEGER LWORK = lwork; INTEGER INFO; //printf("Calling LAPACK dgesvd routine...\n");fflush(NULL); //SUBROUTINE SGESVD( JOBU, JOBVT, M, N, A, LDA, S, U, LDU, VT, LDVT, WORK, LWORK, INFO ) DGESVD (&jobu, &jobvt, &M, &N, A, &LDA, S, dummyU, &LDU, VT, &LDVT, work, &LWORK, &INFO); if (INFO != 0) { int code = INFO; printf("Error: SVD solver returned non-zero exit code: %d.\n", code); free(VT); free(S); free(work); return code; } free(work); if (transpose) { InPlaceTransposeMatrix(m,n,VT); memcpy(A, VT, sizeof(double) * m * n); // swap m and n int bufferii = m; m = n; n = bufferii; } free(VT); if (weights != NULL) { // transform row i of A by sqrt(weights[i])^{-1} for(int row=0; row<m; row++) { double rowWeight = 1.0 / sqrt(weights[row]); for(int column=0; column<n; column++) A[ELT(m, row, column)] *= rowWeight; } } //double totalEnergy = 0; //printf ("Singular values:\n");fflush(NULL); //for (int i=0; i< MIN(m,n); i++) //printf("%f ",S[i]); //printf ("\n"); // discard unneccesary modes //printf("Discarding unnecessary components...\n");fflush(NULL); if (thresholdingSpecification->tresholdingType == ThresholdingSpecification::epsilonBased) DoTresholding_Epsilon(S,MIN(m,n),r,thresholdingSpecification->epsilon); else DoTresholding_NumberOfModes(S,MIN(m,n),r,thresholdingSpecification->rDesired); // now, variable r has been set to the number of retained modes free(S); return 0; }
void MatrixSVD(int m, int n, real * mtx, real * U, real * Sigma, real * VT) { real * A = (real*) malloc (sizeof(real) * m * n); memcpy(A, mtx, sizeof(real) * m * n); // must deal with transpose since Intel MKL sometimes crashes on thin matrices bool transpose = (m > n); if (transpose) { InPlaceTransposeMatrix(m, n, A); // swap arguments int buffer = m; m = n; n = buffer; real * bufferr = U; U = VT; VT = bufferr; } // now, we always have m <= n char jobu = 'S'; //left singular vectors returned in U char jobvt = 'S'; //right singular vectors returned in VT INTEGER NB = 32; // optimal block size; could also call ilaenv int lwork = NB*MAX(3*MIN( m, n)+MAX(m,n), 5*MIN(m,n)-4); real * work = (real*) malloc (sizeof(real) * lwork); if (!work) { printf("Error: failed to allocate workspace.\n"); throw 1; } //printf("Workspace size is: %G Mb .\n",1.0 * lwork * sizeof(int) / 1024 / 1024); INTEGER M = m; INTEGER N = n; INTEGER LDA = m; INTEGER LDU = m; INTEGER LDVT = MIN(m,n); INTEGER LWORK = lwork; INTEGER INFO; //printf("Calling LAPACK dgesvd routine...\n");fflush(NULL); //SUBROUTINE SGESVD( JOBU, JOBVT, M, N, A, LDA, S, U, LDU, VT, LDVT, WORK, LWORK, INFO ) _xgesvd<sizeof(real)==sizeof(float)>::f (&jobu, &jobvt, &M, &N, A, &LDA, Sigma, U, &LDU, VT, &LDVT, work, &LWORK, &INFO); if (INFO != 0) { int code = INFO; printf("Error: SVD solver returned non-zero exit code: %d.\n", code); free(work); free(A); throw 2; } free(work); free(A); if (transpose) { InPlaceTransposeMatrix(m, MIN(m,n), U); InPlaceTransposeMatrix(MIN(m,n), n, VT); } }
real * PseudoInverseMatrix(int m, int n, real * mtx, real singularValueThreshold, int * rank_, real * output) { real * A = (real*) malloc (sizeof(real) * m * n); memcpy(A, mtx, sizeof(real) * m * n); bool transpose = (m > n); if (transpose) { // swap m,n InPlaceTransposeMatrix(m,n, A); int buffer = m; m = n; n = buffer; } // now, we always have m <= n char jobu = 'O';//overwrites A with U (left singular vectors) char jobvt = 'S';//all rows returned in VT int ldA = m; int ldU = m; INTEGER NB = 32; // optimal block size; could also call ilaenv int lwork = NB*MAX(3*MIN( m, n)+MAX(m,n), 5*MIN(m,n)-4); real * work = (real*) malloc (sizeof(real) * lwork); if (!work) { printf("Error: failed to allocate workspace.\n"); throw 1; } //printf("Workspace size is: %G Mb .\n",1.0 * lwork * sizeof(int) / 1024 / 1024); // allocate array for singular vectors real * S = (real *) malloc (sizeof(real) * MIN(m,n)); if (!S) { printf("Error: failed to allocate singular vectors.\n"); free(work); throw 2; } // allocate array for VT int ldVT = MIN(m,n); real * VT = (real *) malloc (sizeof(real) * ldVT * n); if (!VT) { printf("Error: failed to allocate VT.\n"); free(S); free(work); throw 3; } INTEGER M = m; INTEGER N = n; INTEGER LDA = ldA; INTEGER LDU = ldU; INTEGER LDVT = ldVT; INTEGER LWORK = lwork; INTEGER INFO; //printf("Calling LAPACK dgesvd routine...\n");fflush(NULL); //SUBROUTINE SGESVD( JOBU, JOBVT, M, N, A, LDA, S, U, LDU, VT, LDVT, WORK, LWORK, INFO ) _xgesvd<sizeof(real)==sizeof(float)>::f (&jobu, &jobvt, &M, &N, A, &LDA, S, NULL, &LDU, VT, &LDVT, work, &LWORK, &INFO); if (INFO != 0) { int code = INFO; printf("Error: SVD solver returned non-zero exit code: %d.\n", code); free(VT); free(S); free(work); throw 4; } free(work); //printf ("Singular values:\n");fflush(NULL); //for (int i=0; i< MIN(m,n); i++) // printf("%f ",S[i]); //printf ("\n"); // discard small singular values int rank = MIN(m,n); for(int i=0; i< MIN(m,n); i++) { if (S[i] / S[0] < singularValueThreshold) { rank = i; break; } } for(int i=0; i< rank; i++) S[i] = ((real)1.0) / S[i]; for(int i=rank; i< MIN(m,n); i++) S[i] = 0.0; real * U = A; memset(&U[ELT(m,0,rank)], 0, sizeof(real) * m * (n-rank)); InPlaceTransposeMatrix(m, m, U); real * UT = U; // UT is now m x m InPlaceTransposeMatrix(m,n,VT); real * V = VT; // V is now n x m // multiply A^{\dagger} = V * Sigma^{-1} * U^T for(int j=0; j<m; j++) // over all columns for(int i=0; i<n; i++) // over all rows V[ELT(n, i, j)] *= S[j]; real * target = output; if (target == NULL) target = (real*) malloc (sizeof(real) * n * m); // V * UT // (n x m) * (m x m) // output is n x m MultiplyMatrices(n, m, m, V, UT, target); if (transpose) InPlaceTransposeMatrix(n, m, target); free(A); free(S); free(VT); if (rank_ != NULL) *rank_ = rank; return target; }