void CLinkMatrix::completePivotInformation() { // We need to convert the pivot vector into a swap vector. mPivotInverse.resize(mRowPivots.size()); size_t * pCurrentIndex = mPivotInverse.array(); size_t * pEnd = pCurrentIndex + mRowPivots.size(); for (size_t i = 0; pCurrentIndex != pEnd; ++pCurrentIndex, ++i) { *pCurrentIndex = i; } CVector< size_t > CurrentColumn(mPivotInverse); size_t * pCurrentColumn = CurrentColumn.array(); mSwapVector.resize(mRowPivots.size()); C_INT * pJPVT = mSwapVector.array(); pCurrentIndex = mPivotInverse.array(); const size_t * pPivot = mRowPivots.array(); for (; pCurrentIndex != pEnd; ++pPivot, ++pJPVT, ++pCurrentIndex, ++pCurrentColumn) { // Swap Index size_t * pToIndex = & mPivotInverse[*pPivot]; size_t * pFromIndex = & mPivotInverse[*pCurrentColumn]; // Swap Column size_t * pToColumn = & CurrentColumn[*pToIndex]; size_t * pFromColumn = pCurrentColumn; // Swap *pJPVT = *pToIndex + 1; size_t tmp = *pFromIndex; *pFromIndex = *pToIndex; *pToIndex = tmp; tmp = *pFromColumn; *pFromColumn = *pToColumn; *pToColumn = tmp; } }
bool CLinkMatrix::build(const CMatrix< C_FLOAT64 > & matrix) { bool success = true; CMatrix< C_FLOAT64 > M(matrix); C_INT NumCols = (C_INT) M.numCols(); C_INT NumRows = (C_INT) M.numRows(); C_INT LDA = std::max<C_INT>(1, NumCols); CVector< C_INT > JPVT(NumRows); JPVT = 0; C_INT32 Dim = std::min(NumCols, NumRows); if (Dim == 0) { C_INT32 i; mRowPivots.resize(NumRows); for (i = 0; i < NumRows; i++) mRowPivots[i] = i; resize(NumRows, 0); return success; } CVector< C_FLOAT64 > TAU(Dim); CVector< C_FLOAT64 > WORK(1); C_INT LWORK = -1; C_INT INFO; // QR factorization of the stoichiometry matrix /* * -- LAPACK routine (version 3.0) -- * Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., * Courant Institute, Argonne National Lab, and Rice University * June 30, 1999 * * Purpose * ======= * * DGEQP3 computes a QR factorization with column pivoting of a * matrix A: A*P = Q*R using Level 3 BLAS. * * Arguments * ========= * * M (input) INTEGER * The number of rows of the matrix A. M >= 0. * * N (input) INTEGER * The number of columns of the matrix A. N >= 0. * * A (input/output) DOUBLE PRECISION array, dimension (LDA,N) * On entry, the M-by-N matrix A. * On exit, the upper triangle of the array contains the * min(M,N)-by-N upper trapezoidal matrix R; the elements below * the diagonal, together with the array TAU, represent the * orthogonal matrix Q as a product of min(M,N) elementary * reflectors. * * LDA (input) INTEGER * The leading dimension of the array A. LDA >= max(1,M). * * JPVT (input/output) INTEGER array, dimension (N) * On entry, if JPVT(J).ne.0, the J-th column of A is permuted * to the front of A*P (a leading column); if JPVT(J)=0, * the J-th column of A is a free column. * On exit, if JPVT(J)=K, then the J-th column of A*P was the * the K-th column of A. * * TAU (output) DOUBLE PRECISION array, dimension (min(M,N)) * The scalar factors of the elementary reflectors. * * WORK (workspace/output) DOUBLE PRECISION array, dimension (LWORK) * On exit, if INFO=0, WORK(1) returns the optimal LWORK. * * LWORK (input) INTEGER * The dimension of the array WORK. LWORK >= 3*N+1. * For optimal performance LWORK >= 2*N+(N+1)*NB, where NB * is the optimal blocksize. * * If LWORK = -1, then a workspace query is assumed; the routine * only calculates the optimal size of the WORK array, returns * this value as the first entry of the WORK array, and no error * message related to LWORK is issued by XERBLA. * * INFO (output) INTEGER * = 0: successful exit. * < 0: if INFO = -i, the i-th argument had an illegal value. * * Further Details * =============== * * The matrix Q is represented as a product of elementary reflectors * * Q = H(1) H(2) . . . H(k), where k = min(m,n). * * Each H(i) has the form * * H(i) = I - tau * v * v' * * where tau is a real/complex scalar, and v is a real/complex vector * with v(1:i-1) = 0 and v(i) = 1; v(i+1:m) is stored on exit in * A(i+1:m,i), and tau in TAU(i). * * Based on contributions by * G. Quintana-Orti, Depto. de Informatica, Universidad Jaime I, Spain * X. Sun, Computer Science Dept., Duke University, USA * */ dgeqp3_(&NumCols, &NumRows, M.array(), &LDA, JPVT.array(), TAU.array(), WORK.array(), &LWORK, &INFO); if (INFO < 0) fatalError(); LWORK = (C_INT) WORK[0]; WORK.resize(LWORK); dgeqp3_(&NumCols, &NumRows, M.array(), &LDA, JPVT.array(), TAU.array(), WORK.array(), &LWORK, &INFO); if (INFO < 0) fatalError(); C_INT32 i; mRowPivots.resize(NumRows); for (i = 0; i < NumRows; i++) mRowPivots[i] = JPVT[i] - 1; C_INT independent = 0; while (independent < Dim && fabs(M(independent, independent)) > 100.0 * std::numeric_limits< C_FLOAT64 >::epsilon()) independent++; mIndependent = independent; // Resize mL resize(NumRows - independent, independent); if (NumRows == independent || independent == 0) { return success; } /* to take care of differences between fortran's and c's memory access, we need to take the transpose, i.e.,the upper triangular */ char cL = 'U'; char cU = 'N'; /* values in the diagonal of R */ // Calculate Row Echelon form of R. // First invert R_1,1 /* int dtrtri_(char *uplo, * char *diag, * integer *n, * doublereal * A, * integer *lda, * integer *info); * -- LAPACK routine (version 3.0) -- * Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., * Courant Institute, Argonne National Lab, and Rice University * March 31, 1993 * * Purpose * ======= * * DTRTRI computes the inverse of a real upper or lower triangular * matrix A. * * This is the Level 3 BLAS version of the algorithm. * * Arguments * ========= * * uplo (input) CHARACTER*1 * = 'U': A is upper triangular; * = 'L': A is lower triangular. * * diag (input) CHARACTER*1 * = 'N': A is non-unit triangular; * = 'U': A is unit triangular. * * n (input) INTEGER * The order of the matrix A. n >= 0. * * A (input/output) DOUBLE PRECISION array, dimension (lda,n) * On entry, the triangular matrix A. If uplo = 'U', the * leading n-by-n upper triangular part of the array A contains * the upper triangular matrix, and the strictly lower * triangular part of A is not referenced. If uplo = 'L', the * leading n-by-n lower triangular part of the array A contains * the lower triangular matrix, and the strictly upper * triangular part of A is not referenced. If diag = 'U', the * diagonal elements of A are also not referenced and are * assumed to be 1. * On exit, the (triangular) inverse of the original matrix, in * the same storage format. * * lda (input) INTEGER * The leading dimension of the array A. lda >= max(1,n). * * info (output) INTEGER * = 0: successful exit * < 0: if info = -i, the i-th argument had an illegal value * > 0: if info = i, A(i,i) is exactly zero. The triangular * matrix is singular and its inverse can not be computed. */ dtrtri_(&cL, &cU, &independent, M.array(), &LDA, &INFO); if (INFO < 0) fatalError(); C_INT32 j, k; // Compute Link_0 = inverse(R_1,1) * R_1,2 // :TODO: Use dgemm C_FLOAT64 * pTmp1 = array(); C_FLOAT64 * pTmp2; C_FLOAT64 * pTmp3; for (j = 0; j < NumRows - independent; j++) for (i = 0; i < independent; i++, pTmp1++) { pTmp2 = &M(j + independent, i); pTmp3 = &M(i, i); // assert(&mL(j, i) == pTmp3); *pTmp1 = 0.0; for (k = i; k < independent; k++, pTmp2++, pTmp3 += NumCols) { // assert(&M(j + independent, k) == pTmp2); // assert(&M(k, i) == pTmp3); *pTmp1 += *pTmp3 * *pTmp2; } if (fabs(*pTmp1) < 100.0 * std::numeric_limits< C_FLOAT64 >::epsilon()) *pTmp1 = 0.0; } // We need to convert the pivot vector into a swap vector. mPivotInverse.resize(mRowPivots.size()); size_t * pCurrentIndex = mPivotInverse.array(); size_t * pEnd = pCurrentIndex + mRowPivots.size(); for (size_t i = 0; pCurrentIndex != pEnd; ++pCurrentIndex, ++i) { *pCurrentIndex = i; } CVector< size_t > CurrentColumn(mPivotInverse); size_t * pCurrentColumn = CurrentColumn.array(); mSwapVector.resize(mRowPivots.size()); C_INT * pJPVT = mSwapVector.array(); pCurrentIndex = mPivotInverse.array(); const size_t * pPivot = mRowPivots.array(); for (; pCurrentIndex != pEnd; ++pPivot, ++pJPVT, ++pCurrentIndex, ++pCurrentColumn) { // Swap Index size_t * pToIndex = & mPivotInverse[*pPivot]; size_t * pFromIndex = & mPivotInverse[*pCurrentColumn]; // Swap Column size_t * pToColumn = & CurrentColumn[*pToIndex]; size_t * pFromColumn = pCurrentColumn; // Swap *pJPVT = *pToIndex + 1; size_t tmp = *pFromIndex; *pFromIndex = *pToIndex; *pToIndex = tmp; tmp = *pFromColumn; *pFromColumn = *pToColumn; *pToColumn = tmp; } return success; }
QString toSQLParse::indentStatement(statement &stat, int level/*SQLITEMAN, toSyntaxAnalyzer &syntax*/) { QString ret; switch (stat.Type) { default: { QMessageBox::warning(QApplication::activeWindow(), "Sqliteman", "toSQLparse: Internal error in toSQLParse, should never get here"); } case statement::Block: { ret = IndentComment(level, 0, stat.Comment, false); int exc = 0; for (std::list<toSQLParse::statement>::iterator i = stat.subTokens().begin(); i != stat.subTokens().end(); i++) { int add = 0; std::list<toSQLParse::statement>::iterator j = i; j++; if (i != stat.subTokens().begin() && j != stat.subTokens().end()) add = Settings.IndentLevel; else exc = 0; QString t; if ((*i).subTokens().begin() != (*i).subTokens(). end()) t = (*(*i).subTokens().begin()).String.toUpper(); if (t == ("BEGIN") || t == ("WHEN") || t == ("ELSE") || t == ("ELSIF")) add = 0; if ((*i).Type == statement::List) ret += indentString(level + add + exc); ret += indentStatement(*i, level + add + exc/*SQLITEMAN , syntax*/); if ((*i).Type == statement::List) { int i; for (i = ret.length() - 1;i >= 0 && ret[i].isSpace();i--) ; ret = ret.mid(0, std::max(i + 1, 0)); ret += ("\n"); ret += indentString(level + exc); } if (t == ("EXCEPTION")) exc = Settings.IndentLevel * 2; } if (Settings.EndBlockNewline && level != 0) ret += ("\n"); } break; case statement::List: case statement::Statement: int maxlev = 0; int maxlevorig = 0; bool useMaxLev = false; bool any = true; int current; bool first; bool noKeyBreak = false; bool lineList = false; QString comment; if (stat.Type == statement::Statement) { ret = IndentComment(level, 0, stat.Comment, false); useMaxLev = true; first = true; current = 0; } else { for (std::list<toSQLParse::statement>::iterator i = stat.subTokens().begin(); i != stat.subTokens().end();) { if ((*i).Type != statement::Keyword) noKeyBreak = true; else useMaxLev = true; break; } current = level; first = true; } if (useMaxLev) { int count = 0; for (std::list<toSQLParse::statement>::iterator i = stat.subTokens().begin(); i != stat.subTokens().end(); i++) { if (any) { QString upp = (*i).String.toUpper(); if ((*i).Type == statement::Keyword && upp != ("LOOP") && upp != ("DO") && upp != ("THEN") && upp != ("AS") && upp != ("IS")) { if (int((*i).String.length()) + 1 > maxlev) maxlev = (*i).String.length() + 1; count++; any = false; } else if (i == stat.subTokens().begin()) { noKeyBreak = true; break; } } else if ((*i).Type == statement::Token) any = true; if ((*i).Type == statement::List) count++; } if (count <= 1 && maxlev > 0) maxlev--; maxlevorig = maxlev; any = true; } for (std::list<toSQLParse::statement>::iterator i = stat.subTokens().begin(); i != stat.subTokens().end(); i++) { comment = AddComment(comment, (*i).Comment); QString upp = (*i).String.toUpper(); #ifdef TOPARSE_DEBUG printf("%s\n", (const char*)(*i).String.toUtf8()); #endif if ((*i).Type == statement::List) { if (Settings.OperatorSpace) { ret += (" "); current++; } QString t = indentStatement(*i, current/*SQLITEMAN, syntax*/); if (t.indexOf(("\n")) >= 0) current = CurrentColumn(t); else current += CurrentColumn(t); ret += t; any = true; } else if ((*i).String == (",")) { if (Settings.CommaBefore) { ret += IndentComment(Settings.CommentColumn, current, comment, true); comment = QString::null; ret += indentString(level + maxlev - (Settings.OperatorSpace ? 2 : 1)); ret += (","); } else { ret += (","); ret += IndentComment(Settings.CommentColumn, current + 1, comment, true); comment = QString::null; ret += indentString(level + maxlev); } current = level + maxlev; any = false; lineList = true; } else if ((*i).Type == statement::Keyword && (upp == ("LOOP") || upp == ("DO") || upp == ("THEN") || upp == ("AS") || upp == ("IS"))) { if (!Settings.BlockOpenLine) { if (ret.length() > 0) { if (toIsIdent(ret.at(ret.length() - 1)) || ret.at(ret.length() - 1) == QUOTE_CHARACTER /*SQLITEMAN syntax.quoteCharacter()*/ || ret.at(ret.length() - 1) == '\'' || Settings.OperatorSpace) { ret += (" "); current++; } } ret += Settings.KeywordUpper ? (*i).String.toUpper() : (*i).String; current += (*i).String.length(); } else { ret += IndentComment(Settings.CommentColumn, current, comment, true); comment = QString::null; ret += indentString(level); ret += Settings.KeywordUpper ? (*i).String.toUpper() : (*i).String; current = level + (*i).String.length(); } any = false; } else if (any && (*i).Type == statement::Keyword && !noKeyBreak) { if (first) first = false; else { ret += IndentComment(Settings.CommentColumn, current, comment, true); current = 0; comment = QString::null; } if (current == 0) { ret += indentString(level); current = level; } else while (current < level) { ret += (" "); current++; } maxlev = maxlevorig; QString word = Settings.KeywordUpper ? (*i).String.toUpper() : (*i).String; if (ret.length()) { ret += QString("%1").arg(word, Settings.RightSeparator ? maxlev - 1 : 1 - maxlev); current = level + std::max(int(word.length()), maxlev - 1); } else { ret += word; current = level + word.length(); } any = false; lineList = false; } else { QString t = (*i).String; bool add = false; if ((*i).Type == statement::Keyword) { if (!lineList && !any && (*i).Type == statement::Keyword && !noKeyBreak && upp == ("BY")) add = true; } else { any = true; } if (isKeyword(upp) /*SQLITEMAN syntax.reservedWord(upp)*/ && Settings.KeywordUpper) t = upp; int extra; if (first) { first = false; any = false; extra = 0; } else { if (ret.length() > 0 && !ret.at(ret.length() - 1).isSpace() && (Settings.OperatorSpace || ((toIsIdent(t[0]) || t[0] == QUOTE_CHARACTER /*SQLITEMAN syntax.quoteCharacter()*/ || t[0] == '\'') && (toIsIdent(ret.at(ret.length() - 1)) || ret.at(ret.length() - 1) == QUOTE_CHARACTER /*SQLITEMAN syntax.quoteCharacter()*/ || ret.at(ret.length() - 1) == '\'') ) ) ) { if (t != (";") && t != (".") && ret.at(ret.length() - 1) != '.' && current != 0) { current++; ret += (" "); } } else if (ret.length() > 2 && ret.at(ret.length() - 2) == '*' && ret.at(ret.length() - 1) == '/') { current++; ret += (" "); } extra = maxlev; } if (current < level + maxlev) { if (current == 0) ret += indentString(level + maxlev); else while (current < level + maxlev) { ret += (" "); current++; } current = level + maxlev; } ret += t; current += t.length(); if (t.startsWith(("<<"))) { ret += ("\n"); current = 0; } if (add ) maxlev += t.length() + 1; } } if (stat.Type == statement::Statement) { ret += IndentComment(Settings.CommentColumn, current, comment, true); comment = QString::null; if (Settings.EndBlockNewline && level == 0 && stat.subTokens().begin() != stat.subTokens().end() && (*stat.subTokens().rbegin()).String == (";")) ret += ("\n"); } else if (!comment.isEmpty()) { ret += IndentComment(Settings.CommentColumn, current, comment, true); comment = QString::null; ret += indentString(level - (Settings.OperatorSpace ? 2 : 1)); } break; } return ret; }