| |
| |
| extern "C" { |
| #include "slu_ddefs.h" |
| #include "slu_util.h" |
| } |
| |
| #include <algorithm> |
| |
| #include "tlin/tlin_cblas_wrap.h" |
| |
| #include "tlin/tlin_superlu_wrap.h" |
| |
| |
| |
| |
| |
| struct tlin::SuperMatrix : public ::SuperMatrix { |
| }; |
| struct tlin::superlu_options_t : public ::superlu_options_t { |
| }; |
| |
| |
| |
| namespace |
| { |
| static const tlin::spmat::HashMap::size_t neg = -1; |
| |
| bool initialized = false; |
| static tlin::superlu_options_t defaultOpt; |
| |
| struct DefaultOptsInitializer { |
| DefaultOptsInitializer() |
| { |
| set_default_options(&defaultOpt); |
| defaultOpt.PrintStat = NO; |
| } |
| } _instance; |
| |
| inline bool rowLess(const tlin::spmat::HashMap::BucketNode *a, const tlin::spmat::HashMap::BucketNode *b) |
| { |
| return a->m_key.first < b->m_key.first; |
| } |
| } |
| |
| |
| |
| |
| |
| void tlin::allocS(SuperMatrix *&A, int rows, int cols, int nnz) |
| { |
| A = (SuperMatrix *)SUPERLU_MALLOC(sizeof(SuperMatrix)); |
| double *values = doubleMalloc(nnz); |
| int *rowind = intMalloc(nnz); |
| int *colptr = intMalloc(cols + 1); |
| |
| dCreate_CompCol_Matrix(A, rows, cols, nnz, values, rowind, colptr, SLU_NC, SLU_D, SLU_GE); |
| } |
| |
| |
| |
| void tlin::allocD(SuperMatrix *&A, int rows, int cols) |
| { |
| A = (SuperMatrix *)SUPERLU_MALLOC(sizeof(SuperMatrix)); |
| |
| double *values = doubleMalloc(rows * cols * sizeof(double)); |
| dCreate_Dense_Matrix(A, rows, cols, values, rows, SLU_DN, SLU_D, SLU_GE); |
| } |
| |
| |
| |
| void tlin::allocS(SuperMatrix *&A, int rows, int cols, int nnz, int *colptr, int *rowind, double *values) |
| { |
| A = (SuperMatrix *)SUPERLU_MALLOC(sizeof(SuperMatrix)); |
| dCreate_CompCol_Matrix(A, rows, cols, nnz, values, rowind, colptr, SLU_NC, SLU_D, SLU_GE); |
| } |
| |
| |
| |
| void tlin::allocD(SuperMatrix *&A, int rows, int cols, int lda, double *values) |
| { |
| A = (SuperMatrix *)SUPERLU_MALLOC(sizeof(SuperMatrix)); |
| dCreate_Dense_Matrix(A, rows, cols, values, lda, SLU_DN, SLU_D, SLU_GE); |
| } |
| |
| |
| |
| void tlin::freeS(SuperMatrix *m) |
| { |
| if (!m) |
| return; |
| Destroy_CompCol_Matrix(m); |
| SUPERLU_FREE(m); |
| } |
| |
| |
| |
| void tlin::freeD(SuperMatrix *m) |
| { |
| if (!m) |
| return; |
| Destroy_Dense_Matrix(m); |
| SUPERLU_FREE(m); |
| } |
| |
| |
| |
| void tlin::createS(SuperMatrix &A, int rows, int cols, int nnz) |
| { |
| double *values = doubleMalloc(nnz); |
| int *rowind = intMalloc(nnz); |
| int *colptr = intMalloc(cols + 1); |
| |
| dCreate_CompCol_Matrix(&A, rows, cols, nnz, values, rowind, colptr, SLU_NC, SLU_D, SLU_GE); |
| } |
| |
| |
| |
| void tlin::createD(SuperMatrix &A, int rows, int cols) |
| { |
| double *values = doubleMalloc(rows * cols * sizeof(double)); |
| dCreate_Dense_Matrix(&A, rows, cols, values, rows, SLU_DN, SLU_D, SLU_GE); |
| } |
| |
| |
| |
| void tlin::createS(SuperMatrix &A, int rows, int cols, int nnz, int *colptr, int *rowind, double *values) |
| { |
| dCreate_CompCol_Matrix(&A, rows, cols, nnz, values, rowind, colptr, SLU_NC, SLU_D, SLU_GE); |
| } |
| |
| |
| |
| void tlin::createD(SuperMatrix &A, int rows, int cols, int lda, double *values) |
| { |
| dCreate_Dense_Matrix(&A, rows, cols, values, lda, SLU_DN, SLU_D, SLU_GE); |
| } |
| |
| |
| |
| void tlin::destroyS(SuperMatrix &A, bool destroyData) |
| { |
| if (destroyData) |
| Destroy_CompCol_Matrix(&A); |
| else |
| SUPERLU_FREE(A.Store); |
| } |
| |
| |
| |
| void tlin::destroyD(SuperMatrix &A, bool destroyData) |
| { |
| if (destroyData) |
| Destroy_Dense_Matrix(&A); |
| else |
| SUPERLU_FREE(A.Store); |
| } |
| |
| |
| |
| void tlin::freeF(SuperFactors *F) |
| { |
| if (!F) |
| return; |
| Destroy_SuperNode_Matrix(F->L); |
| Destroy_CompCol_Matrix(F->U); |
| SUPERLU_FREE(F->L); |
| SUPERLU_FREE(F->U); |
| SUPERLU_FREE(F->perm_r); |
| SUPERLU_FREE(F->perm_c); |
| SUPERLU_FREE(F); |
| } |
| |
| |
| |
| void tlin::readDN(SuperMatrix *A, int &lda, double *&values) |
| { |
| assert(A->Stype == SLU_DN); |
| DNformat *storage = (DNformat *)A->Store; |
| |
| lda = storage->lda; |
| values = (double *)storage->nzval; |
| } |
| |
| |
| |
| void tlin::readNC(SuperMatrix *A, int &nnz, int *&colptr, int *&rowind, double *&values) |
| { |
| assert(A->Stype == SLU_NC); |
| NCformat *storage = (NCformat *)A->Store; |
| |
| nnz = storage->nnz; |
| values = (double *)storage->nzval; |
| rowind = (int *)storage->rowind; |
| colptr = (int *)storage->colptr; |
| } |
| |
| |
| |
| void tlin::traduceD(const mat &m, SuperMatrix *&A) |
| { |
| int rows = m.rows(), cols = m.cols(); |
| |
| if (!A) |
| allocD(A, rows, cols); |
| |
| int lda; |
| double *Avalues = 0; |
| readDN(A, lda, Avalues); |
| |
| assert(A->nrow == rows && A->ncol == cols && lda == rows); |
| |
| memcpy(Avalues, m.values(), rows * cols * sizeof(double)); |
| } |
| |
| |
| |
| void tlin::traduceS(spmat &m, SuperMatrix *&A) |
| { |
| int rows = m.rows(), cols = m.cols(), nnz = (int)m.entries().size(); |
| spmat::HashMap &entries = m.entries(); |
| |
| |
| double *values; |
| int *rowind, *colptr; |
| |
| if (!A) |
| allocS(A, rows, cols, nnz); |
| |
| |
| int Annz; |
| readNC(A, Annz, colptr, rowind, values); |
| assert(A->nrow == rows && A->ncol == cols && Annz == nnz); |
| |
| |
| if (entries.hashFunctor().m_cols != cols) |
| entries.hashFunctor().m_cols = cols; |
| entries.rehash(cols); |
| |
| |
| const std::vector<spmat::HashMap::size_t> &buckets = m.entries().buckets(); |
| const tcg::list<spmat::HashMap::BucketNode> &nodes = m.entries().items(); |
| |
| std::vector<const spmat::HashMap::BucketNode *> colEntries; |
| std::vector<const spmat::HashMap::BucketNode *>::size_type j, size; |
| |
| double *currVal = values; |
| int *currRowind = rowind; |
| |
| for (int i = 0; i < cols; ++i) { |
| colptr[i] = (int)(currVal - values); |
| spmat::HashMap::size_t nodeIdx = buckets[i]; |
| |
| |
| colEntries.clear(); |
| while (nodeIdx != neg) { |
| const spmat::HashMap::BucketNode &node = nodes[nodeIdx]; |
| colEntries.push_back(&node); |
| nodeIdx = nodes[nodeIdx].m_next; |
| } |
| |
| |
| std::sort(colEntries.begin(), colEntries.end(), rowLess); |
| |
| |
| size = colEntries.size(); |
| for (j = 0; j < size; ++j) { |
| const spmat::HashMap::BucketNode &node = *colEntries[j]; |
| |
| *currRowind = node.m_key.first; |
| *currVal = node.m_val; |
| |
| ++currVal, ++currRowind; |
| } |
| } |
| |
| colptr[cols] = nnz; |
| } |
| |
| |
| |
| void tlin::traduceD(const tlin::sparse_matrix<double> &m, SuperMatrix *&A) |
| { |
| int rows = m.rows(), cols = m.cols(); |
| const spmat::HashMap &entries = m.entries(); |
| |
| |
| double *values; |
| |
| if (!A) |
| allocD(A, rows, cols); |
| |
| |
| int lda; |
| readDN(A, lda, values); |
| assert(A->nrow == rows && A->ncol == cols && lda == rows); |
| |
| |
| spmat::HashMap::const_iterator it; |
| for (it = entries.begin(); it != entries.end(); ++it) |
| values[it->m_key.second * rows + it->m_key.first] = it->m_val; |
| } |
| |
| |
| |
| void tlin::factorize(SuperMatrix *A, SuperFactors *&F, superlu_options_t *opt) |
| { |
| assert(A->nrow == A->ncol); |
| int n = A->nrow; |
| |
| if (!F) |
| F = (SuperFactors *)SUPERLU_MALLOC(sizeof(SuperFactors)); |
| |
| if (!opt) |
| opt = &defaultOpt; |
| |
| F->perm_c = intMalloc(n); |
| |
| get_perm_c(3, A, F->perm_c); |
| |
| SuperMatrix AC; |
| int *etree = intMalloc(n); |
| |
| sp_preorder(opt, A, F->perm_c, etree, &AC); |
| |
| F->L = (SuperMatrix *)SUPERLU_MALLOC(sizeof(SuperMatrix)); |
| F->U = (SuperMatrix *)SUPERLU_MALLOC(sizeof(SuperMatrix)); |
| F->perm_r = intMalloc(n); |
| |
| SuperLUStat_t stat; |
| StatInit(&stat); |
| |
| int result; |
| dgstrf(opt, &AC, sp_ienv(1), sp_ienv(2), etree, NULL, 0, F->perm_c, F->perm_r, F->L, F->U, &stat, &result); |
| |
| StatFree(&stat); |
| |
| Destroy_CompCol_Permuted(&AC); |
| SUPERLU_FREE(etree); |
| |
| if (result != 0) |
| freeF(F), F = 0; |
| } |
| |
| |
| |
| void tlin::solve(SuperFactors *F, SuperMatrix *BX, superlu_options_t *opt) |
| { |
| assert(F); |
| |
| if (!opt) |
| opt = &defaultOpt; |
| |
| SuperLUStat_t stat; |
| StatInit(&stat); |
| |
| int result; |
| dgstrs(NOTRANS, F->L, F->U, F->perm_c, F->perm_r, BX, &stat, &result); |
| |
| StatFree(&stat); |
| } |
| |
| |
| |
| void tlin::solve(SuperFactors *F, SuperMatrix *B, SuperMatrix *&X, superlu_options_t *opt) |
| { |
| if (!X) |
| allocD(X, B->nrow, B->ncol); |
| |
| double *Bvalues = 0, *Xvalues = 0; |
| int lda; |
| readDN(B, lda, Bvalues); |
| readDN(X, lda, Xvalues); |
| memcpy(Xvalues, Bvalues, B->nrow * B->ncol * sizeof(double)); |
| |
| solve(F, X, opt); |
| } |
| |
| |
| |
| void tlin::solve(SuperMatrix *A, SuperMatrix *BX, superlu_options_t *opt) |
| { |
| assert(A->nrow == A->ncol); |
| int n = A->nrow; |
| |
| if (!opt) |
| opt = &defaultOpt; |
| |
| SuperMatrix L, U; |
| int *perm_c, *perm_r; |
| |
| perm_c = intMalloc(n); |
| perm_r = intMalloc(n); |
| |
| SuperLUStat_t stat; |
| StatInit(&stat); |
| |
| int result; |
| dgssv(opt, A, perm_c, perm_r, &L, &U, BX, &stat, &result); |
| |
| Destroy_SuperNode_Matrix(&L); |
| Destroy_CompCol_Matrix(&U); |
| SUPERLU_FREE(perm_r); |
| SUPERLU_FREE(perm_c); |
| StatFree(&stat); |
| } |
| |
| |
| |
| void tlin::solve(SuperMatrix *A, SuperMatrix *B, SuperMatrix *&X, superlu_options_t *opt) |
| { |
| if (!X) |
| allocD(X, B->nrow, B->ncol); |
| |
| double *Bvalues = 0, *Xvalues = 0; |
| int lda; |
| readDN(B, lda, Bvalues); |
| readDN(X, lda, Xvalues); |
| memcpy(Xvalues, Bvalues, B->nrow * B->ncol * sizeof(double)); |
| |
| solve(A, X, opt); |
| } |
| |
| |
| |
| void tlin::solve(SuperFactors *F, double *bx, superlu_options_t *opt) |
| { |
| SuperMatrix BX; |
| int rows = F->L->nrow; |
| |
| createD(BX, rows, 1, rows, bx); |
| tlin::solve(F, &BX, opt); |
| SUPERLU_FREE(BX.Store); |
| } |
| |
| |
| |
| void tlin::solve(SuperFactors *F, double *b, double *&x, superlu_options_t *opt) |
| { |
| SuperMatrix B, X; |
| int rows = F->L->nrow; |
| |
| if (!x) |
| x = (double *)malloc(rows * sizeof(double)); |
| |
| createD(B, rows, 1, rows, b); |
| createD(X, rows, 1, rows, x); |
| |
| SuperMatrix *Xptr = &X; |
| tlin::solve(F, &B, Xptr, opt); |
| |
| SUPERLU_FREE(B.Store); |
| SUPERLU_FREE(X.Store); |
| } |
| |
| |
| |
| void tlin::solve(SuperMatrix *A, double *bx, superlu_options_t *opt) |
| { |
| SuperMatrix BX; |
| int rows = A->nrow; |
| |
| createD(BX, rows, 1, rows, bx); |
| tlin::solve(A, &BX, opt); |
| SUPERLU_FREE(BX.Store); |
| } |
| |
| |
| |
| void tlin::solve(SuperMatrix *A, double *b, double *&x, superlu_options_t *opt) |
| { |
| SuperMatrix B, X; |
| int rows = A->nrow; |
| |
| if (!x) |
| x = (double *)malloc(rows * sizeof(double)); |
| |
| createD(B, rows, 1, rows, b); |
| createD(X, rows, 1, rows, x); |
| |
| SuperMatrix *Xptr = &X; |
| tlin::solve(A, &B, Xptr, opt); |
| SUPERLU_FREE(B.Store); |
| SUPERLU_FREE(X.Store); |
| } |
| |
| |
| |
| |
| |
| void tlin::multiplyS(const SuperMatrix *A, const double *x, double *&y) |
| { |
| |
| |
| |
| |
| |
| if (!y) { |
| y = (double *)malloc(A->nrow * sizeof(double)); |
| memset(y, 0, A->nrow * sizeof(double)); |
| } |
| |
| SuperMatrix *_A = const_cast<SuperMatrix *>(A); |
| double *_x = const_cast<double *>(x); |
| |
| sp_dgemv("N", 1.0, _A, _x, 1, 1.0, y, 1); |
| } |
| |
| |
| |
| void tlin::multiplyD(const SuperMatrix *A, const double *x, double *&y) |
| { |
| int lda; |
| double *values; |
| tlin::readDN(const_cast<SuperMatrix *>(A), lda, values); |
| |
| tlin::multiply(A->nrow, A->ncol, values, x, y); |
| } |
| |