类没有成员问题(代码在VS中可以找到,但在Ubuntu中失败)

发布于 2024-11-16 08:31:04 字数 20529 浏览 4 评论 0原文

全部 我得到了一段关于稀疏矩阵的代码,它在VISUAL STUDIO 2008中运行良好,但是当我想将其移植到ubuntu环境时,编译器报告以下错误:

../include/spmatrix.h(123):错误: 类模板“numc::CSRMatrix” 没有成员“调整大小”

../include/spmatrix.h(170):错误: 预期为“;”

../include/spmatrix.h(171):错误: 标识符“it”未定义

../include/spmatrix.h(176):错误: 预期为“;”

../include/spmatrix.h(178):错误: 标识符“it”未定义

../include/spmatrix.h(183):错误: 标识符“size”未定义

../include/spmatrix.h(185):错误: 预期为“;”

../include/spmatrix.h(185):错误: 标识符“it”未定义

。> ./include/spmatrix.h(186):错误: 预期为“;”

../include/spmatrix.h(187):错误: 标识符“cit”未定义

../include/spmatrix.h(205):错误: 预期为“;”

../include/spmatrix.h(205):错误: 标识符“it”未定义

../include/spmatrix.h(218):错误: 预期为“;”

../include/spmatrix.h(218):错误: 标识符“it”未定义

../include/spmatrix.h(222):错误: 预期为“;”

../include/spmatrix.h(223):错误: 标识符“f”未定义

../include/spmatrix.h(224):错误: 标识符“make_pair”未定义

../include/spmatrix.h(224):错误: 不允许使用类型名称

../include/spmatrix.h(224):错误: 不允许使用类型名称

../include/spmatrix.h(245):错误: 标识符“RowType”未定义

../include/spmatrix.h(246):错误: 名称后跟“::”必须是一个类 或命名空间名称

../include/spmatrix.h(246):错误: 预期为“;”

../include/spmatrix.h(246):错误: 标识符“it”未定义

../include/spmatrix.h(269):错误: 标识符“RowType”未定义

../include/spmatrix.h(270):错误: 名称后跟“::”必须是一个类 或命名空间名称

../include/spmatrix.h(270):错误: 预期为“;”

../include/spmatrix.h(271):错误: 标识符“it”未定义

../include/spmatrix.h(276):错误: 标识符“RowType”未定义

../include/spmatrix.h(276):错误: 标识符“crow”未定义

../include/spmatrix.h(277):错误: 名称后跟“::”必须是一个类 或命名空间名称

../include/spmatrix.h(277):错误: 预期为“;”

../include/spmatrix.h(279):错误: 标识符“it”未定义

../include/spmatrix.h(311):错误: 预期为“;”

../include/spmatrix.h(311):错误: 标识符“it”未定义

../include/spmatrix.h(350):错误: 预期为“;”

../include/spmatrix.h(350):错误: 标识符“it”未定义

../include/spmatrix.h(423):错误: 预期为“;”

../include/spmatrix.h(424):错误: 标识符“it”未定义

../include/spmatrix.h(484):错误: 预期为“;”

../include/spmatrix.h(485):错误: 标识符“it”未定义

../include/spmatrix.h(518):错误: 预期为“;”

../include/spmatrix.h(520):错误: 标识符“it”未定义

我尝试找出问题所在,但失败了。希望你能给我一些提示,问题出在哪里。预先感谢您的帮助!

下面是这个稀疏矩阵的代码,它只是一个头文件:

#pragma   warning(disable:   4786)

#ifndef NUMC_CSRMATRIX_H
#define NUMC_CSRMATRIX_H

#include <cmath>
#include <map>
#include <vector>
#include <limits>
#include <algorithm>

#ifndef _NUMC_BEGIN
#define _NUMC_BEGIN namespace numc {
#define _NUMC_END   }
#endif

_NUMC_BEGIN
using std::vector;
using std::map;
using std::swap;
using std::lower_bound;

template<typename R> class CSRMatrix;
template<typename R> struct RowMat;
template<typename R> void CreateCSRMatrixFromRowMap(CSRMatrix<R>&, const RowMat<R>&);
t    emplate<typename R> void CSRMatrixTranspose (const CSRMatrix<R>&, CSRMatrix<R>&);
template<typename R> bool Mul2MatricesSymmResult (const CSRMatrix<R>&, const CSRMatrix<R>&, RowMat<R>&);
template<typename R> bool Mul2MatricesSymmResult (const CSRMatrix<R>&, const CSRMatrix<R>&, CSRMatrix<R>&);
template<typename R> bool Mul2Matrices (const CSRMatrix<R>&, const CSRMatrix<R>&, RowMat<R>&);
template<typename R> bool Mul2Matrices (const CSRMatrix<R>&, const CSRMatrix<R>&, CSRMatrix<R>&);

template<typename R>
class CSRMatrix
{
public:
    enum MatType{ RealStrucSymm=1, RealSymmPosDef=2, RealSymmIndef=-2, 
        CompStrucSymm=3, CompHermPosDef=4, CompHermIndef=-4, 
        CompSymm=6, RealUnSymm=11, CompUnSymm=13};

    std::vector<R> mAv;
    std::vector<int> mAi, mAj;

    CSRMatrix():mNRow(0),mNCol(0),mMtype(RealUnSymm) {};
    CSRMatrix(const RowMat<R> &rm):mMtype(RealUnSymm)   { CreateCSRMatrixFromRowMap(*this, rm); }
    MatType mMtype;

#if ( defined(_MSC_VER)&&(_MSC_VER>1300) )
    //template<typename T> class CSRMatrix;
#define FFM <>  // FFM FRIEND_FUNCTION_MAGIC
#else
#define FFM
#endif

    friend void CreateCSRMatrixFromRowMap FFM(CSRMatrix<R>&, const RowMat<R>&);
    friend void CSRMatrixTranspose FFM(const CSRMatrix<R>&, CSRMatrix<R>&);
    friend bool Mul2MatricesSymmResult FFM(const CSRMatrix<R>&, const CSRMatrix<R>&, RowMat<R>&);
    friend bool Mul2MatricesSymmResult FFM(const CSRMatrix<R>&, const CSRMatrix<R>&, CSRMatrix<R>&);
    friend bool Mul2Matrices FFM(const CSRMatrix<R>&, const CSRMatrix<R>&, RowMat<R>&);
    friend bool Mul2Matrices FFM(const CSRMatrix<R>&, const CSRMatrix<R>&, CSRMatrix<R>&);

#undef FFM

private:
    int mNRow, mNCol;

public:
    inline int nRow() const { return mNRow; }
    inline int nCol() const { return mNCol; }
    inline int empty() const { return (0==nRow() || 0==nCol()) ;}
        inline bool onebase() const { return (!mAi.empty()) && (mAi[0]==1); }       //default: zerobase, including empty matrix!
    inline MatType mtype() const { return mMtype; }

    inline bool issymm() const
    { return (RealSymmIndef==mMtype || RealSymmPosDef==mMtype || CompSymm==mMtype); }

    inline void clear() 
    { mNRow = 0; mNCol = 0; mMtype = RealUnSymm; mAv.clear(); mAi.clear(); mAj.clear(); }

    R getElementV(int x, int y) const{
        double *p = const_cast<CSRMatrix*>(this)->getElementP(x, y);
        return (NULL==p)?0:*p;  
    }

    R* getElementP(int x, int y) {
        if (x<0||y<0)   return NULL;
        if ( issymm() && x>y) swap(x, y);
        const int off = onebase();
        std::vector<int>::const_iterator it = lower_bound(mAj.begin()+mAi[x]-off, mAj.begin()+(mAi[x+1]-off), y+off);
        if (it==mAj.begin()+(mAi[x+1]-off) || *it!=(y+off) ) return NULL;

        return &mAv.front() + ( it-mAj.begin() );
    }

    void MultiVect(R* in, R *out) const;

    bool ChangeBase(bool oneBase) {
        if( onebase() == oneBase )  return true;
        int ii;
        if (oneBase) {
            if (mAi[0] != 0){
                fprintf(stderr, "error matrix!");
                return false;
            }

            for (ii=0; ii<mAi.back(); ii++) mAj[ii]++;

            for (ii=0; ii<mNRow+1; ii++) mAi[ii]++;
        }
        else {
            if (mAi[0] != 1){
                fprintf(stderr, "error matrix!");
                return false;
            }

            for (ii=0; ii<mAi.back()-1; ii++) mAj[ii]--;

            for (ii=0; ii<mNRow+1; ii++) mAi[ii]--;
        }
        return true;
    }

    void GetSubMat(const std::vector<int> &xi, const std::vector<int> &yi, CSRMatrix& mat){
        mat.resize( yi.size() );
        for(int j=0; j<yi.size(); j++){
            for(int i=0; i<xi.size(); i++){

            }
        }

    }

    void print(FILE *f=stdout){
        fprintf(f, "The matrix:\n");
        for(int i=0; i<nRow(); i++){
            fprintf(f, "%2d#:", i);
            for(int j=0; j<nCol(); j++) {
                fprintf(f, "\t%.3e", getElementV(i, j) );
            }
            fprintf(f, "\n");
        }
    }

};

template<typename R>
struct RowMat:public vector<map<int, R> >
{
    typedef map<int, R> RowType;
    typedef vector<RowType> BaseType;
    int mNCol;

    RowMat(int nrow=0, int ncol=0):BaseType(nrow),mNCol(ncol)   { }
    ~RowMat()   { }
    RowMat(const CSRMatrix<R> &mat)
    {
        resize(mat.nCol(), mat.nRow());

        int off = mat.onebase()?1:0;
        for(unsigned int i=0; i+1<mat.mAi.size(); i++){
            for(int j=mat.mAi[i]; j<mat.mAi[i+1]; j++){
                (*this)(i, mat.mAj[j-off]-off) = mat.mAv[ j-off ];
            }
        }

    }

    virtual bool symmetric() const {return false;}
    virtual inline R operator()(int i, int j) const{
        const RowType &crow = (*this)[i];
        RowType::const_iterator it = crow.find(j);
        return ( it==crow.end() )?0:it->second;
    }

    virtual inline R& operator()(int i, int j){
        RowType &crow = (*this)[i];
        RowType::iterator it = crow.find(j);

        return ( it==crow.end() )?crow.insert( std::pair<int,R>(j, 0) ).first->second:it->second;
    }

    int clearZero() {
        int nZero;
        for (size_t i=0; i<size(); i++) {
            RowType &r = (*this)[i];
            for (RowType::const_iterator it=r.begin(); it!=r.end(); ) {
                RowType::const_iterator cit = it++;
                if(fabs(cit->second) < std::numeric_limits<R>::epsilon()){
                    r.erase(cit);
                    ++nZero;
                }
            }
        }
        return nZero;
    }

    inline void resize(int nrow, int ncol=0) { BaseType::resize(nrow); mNCol = ncol>0?ncol:mNCol; }
    inline int nRow()   const { return BaseType::size(); }
    inline int nCol()   const { return mNCol; }

    int operator+=(const RowMat<R>& r) { return add(r, 1); }

    void operator *= (const double v) {
        for(int i=0; i<nRow(); i++){
            map<int, R>& crow = (*this)[i];
            for(map<int,R>::iterator it=crow.begin(); it!=crow.end(); ++it){
                it->second *= v;
            }
        }
    }

    int add(const RowMat<R>& r, R k){
        const int h = nRow();
        if( r.nRow() != h ) return -1;

        for(int i=0; i<h; i++){
            const map<int, R>& rrow = r[i];
            map<int, R>& lrow = (*this)[i];
            for(RowType::const_iterator it=rrow.begin(); it!=rrow.end(); ++it){
                int col = it->first;
                R val = it->second * k;

                map<int,R>::iterator f = lrow.find(col);
                if( f != lrow.end() )   f->second += val;
                lrow.insert( make_pair<int, R>(col, val) );
            }
        }

        return 0;
    }

};

template<typename R>
struct RowMatSym : public RowMat<R>
{
    typedef RowMat<R> Base;

    RowMatSym(int nrow=0, int ncol=0):Base(nrow, ncol)  {}
    ~RowMatSym()    { }

    RowMatSym(const RowMat<R> &rm){
        resize(rm.nCol(), rm.nRow());

        for(unsigned int i=0; i<rm.nRow(); i++){
            const RowType &crow = rm[i];
            for(RowType::const_iterator it=crow.begin(); it!=crow.end(); ++it){
                (*this)(i, it->first) = it->second;
            }
        }
    }

    RowMatSym(const CSRMatrix<R> &mat)
    {
        resize(mat.nCol(), mat.nRow());

        int off = mat.onebase()?1:0;
        for(unsigned int i=0; i+1<mat.mAi.size(); i++){
            for(int j=mat.mAi[i]; j<mat.mAi[i+1]; j++){
                const int k = mat.mAj[j-off]-off;
                (*this)(i, k) = mat.mAv[ j-off ];
            }
        }
    }

    virtual bool symmetric() const {return true;}

    inline R operator()(int i, int j) const{
        if(i>j) std::swap(i, j);
        const RowType &crow = (*this)[i];
        RowType::const_iterator it = crow.find(j);
        return ( it==crow.end() )?0:it->second;
    }

    inline R& operator()(int i, int j){
        if(i>j) std::swap(i, j);
        RowType &crow = (*this)[i];
        RowType::iterator it = crow.find(j);

        return ( it==crow.end() )?crow.insert( std::pair<int,R>(j, 0) ).first->second
            :it->second;
    }

};


//////////////////////////////////////////////////////////////////////////
/// Get SubMatrix from rowmap
//////////////////////////////////////////////////////////////////////////
template <typename R>
void GetSubRowMap(const RowMat<R>& src,
                  const std::vector<int> &xi, const std::vector<int> &yi,
                  RowMat<R>& dst)
{
    assert( xi.size()>0 && yi.size()>0 );
    assert( yi.back() < (int)src.size() );
    if( xi.empty() || yi.empty() || yi.back() >= (int)src.size() ){
        fprintf(stderr, "\nerror matrix!");
        return;
    }


    typedef std::map<int, R> row;
    dst.resize( yi.size() );

    for(unsigned int j=0; j<yi.size(); j++){
        const row &srow = src[ yi[j] ];
        row &drow = dst[j];

        const int* pxi = &xi.front();

        for(row::const_iterator it=srow.begin(); it!=srow.end(); ++it ){
            pxi = std::lower_bound(pxi, &xi.back(), it->first);

            if(*pxi != it->first){          // done
                continue;
            }

            int col = pxi - &xi.front();
            drow[col] = it->second;
        }
    }
}

//////////////////////////////////////////////////////////////////////////
/// Create CSR matrix from vector of rowmap
//////////////////////////////////////////////////////////////////////////
template <typename R>
void CreateCSRMatrixFromRowMap(CSRMatrix<R> &matC, const RowMat<R>& rowC)
{
    if(rowC.mNCol <= 0){
        fprintf(stderr, "\nnumber of column not specified in the RowMat, exit!");
        return;
    }
    matC.clear();
    matC.mNRow = rowC.nRow();
    matC.mNCol = rowC.nCol();

    matC.mAi.reserve(matC.nRow()+1);
    int i,nnz=0;
    for (i=0; i<matC.nRow(); i++) {
        nnz += rowC[i].size();
    }
    matC.mAj.reserve(nnz);
    matC.mAv.reserve(nnz);

    // copy rows into matC
    matC.mAi.push_back(0);
    for (i=0; i<matC.nRow(); i++) {
        matC.mAi.push_back(matC.mAi.back());
        for (std::map<int, R>::const_iterator it=rowC[i].begin(); it!=rowC[i].end(); it++) {
            matC.mAi.back()++;
            matC.mAj.push_back(it->first);
            matC.mAv.push_back(it->second);
        }
    }
}


//////////////////////////////////////////////////////////////////////////
/// Computes the transpose of a matrix.
template <typename R>
void CSRMatrixTranspose(const CSRMatrix<R> &matA, CSRMatrix<R> &matAT)
{
    if (matA.issymm()) {        // symmetric - just copy the matrix
        matAT = matA;
        return;
        }

    matAT.mNRow = matA.nCol();
    matAT.mNCol = matA.nRow();
    matAT.mMtype = matA.mMtype;

    // non-symmetric matrix -> need to build data structure.
    // we'll go over the columns and build the rows
    int off = matA.onebase()?1:0;
    RowMat<R> rowC(matA.nCol(), matA.nRow());
    for (int i=0; i<matA.nRow(); i++) {
        for (int j=matA.mAi[i]; j<matA.mAi[i+1]; j++) {
            rowC[matA.mAj[j-off]-off][i] = matA.mAv[j-off];
        }
    }

    CreateCSRMatrixFromRowMap(matAT, rowC);
}


//////////////////////////////////////////////////////////////////////////
// multiplication of sparse matrix
// Assuming nothing about the result (the result is not stored symmetric)
//////////////////////////////////////////////////////////////////////////
template <typename R>
bool Mul2Matrices(const CSRMatrix<R> &matA, const CSRMatrix<R> &matB,
                  RowMat<R> &rowsC)
{
    if(matA.onebase() || matB.onebase() ){
        fprintf(stderr, "\nmatrix saved in 1-based format, pleased converted it to 0-based and try again!");
        return false;
    }
    // Compatibility of dimensions
    if (matA.nCol() != matB.nRow())
        return false;

    // (m x n)*(n x k) = (m x k)
    const int m=matA.nRow();
    const int n=matA.nCol();
    const int k=matB.nCol();

    rowsC = RowMat<R>(m, k);    // clean all coefficients

    R aiv, valB;
    int colInd, colB;

    for (int i=0; i<m; ++i) {                   // creating row i of C
        std::map<int, R> &mapRow2Val = rowsC[i];
        for (int iAi = matA.mAi[i]; iAi < matA.mAi[i+1]; ++iAi) {           // travel on ai
            colInd = matA.mAj[iAi];
            aiv = matA.mAv[iAi];
            // make aiv*b_{rowInd} and insert into mapRow2Val
            for (int iB=matB.mAi[colInd]; iB<matB.mAi[colInd+1]; ++iB) {
                colB=matB.mAj[iB];
                valB=matB.mAv[iB];
                // insert valA*aiv into map
                std::map<int, R>::iterator it = mapRow2Val.find(colB);
                if (it == mapRow2Val.end()) {       // first time
                    mapRow2Val[colB] = valB*aiv;
                }
                else {
                    it->second = it->second + valB*aiv;
                }
            }
        }
    }// now column i is created

    return true;
}

template <typename R>
bool Mul2Matrices(const CSRMatrix<R> &matA, const CSRMatrix<R> &matB, CSRMatrix<R> &matC)
{
    RowMat<R> rowsC;
    if( !Mul2Matrices(matA, matB, rowsC) ) return false;

    const int k=matB.mNCol;
    rowsC.mNCol = k;
    CreateCSRMatrixFromRowMap(matC, rowsC);                     // modified by jianwei hu @ 16/09/07
    return true;
}

//////////////////////////////////////////////////////////////////////////
// multiplication of sparse matrix
// The result is symmetric
//////////////////////////////////////////////////////////////////////////
template <typename R>
bool Mul2MatricesSymmResult(const CSRMatrix<R> &matA, const CSRMatrix<R> &matB,
                            RowMat<R> &rowsC)
{
    if(matA.onebase() || matB.onebase()){
        fprintf(stderr, "\nmatrix saved in 1-based format, pleased converted it to 0-based and try again!");
        return false;
    }
    // Compatibility of dimensions
    if(matA.nCol() != matB.nRow() || matA.nRow() != matB.nCol())    return false;

    // (m x n)*(n x m) = (m x m)
    const int m=matA.nRow();
    const int n=matA.nCol();

    rowsC = RowMat<R>(m, m);    // clean all coefficients

    R aiv, valB;
    int colInd, colB;

    for(int i=0; i<m; ++i) {                    // creating row i of C
        std::map<int, R> &mapRow2Val = rowsC[i];
        for (int iAi = matA.mAi[i]; iAi < matA.mAi[i+1]; ++iAi) {           // travel on ai
            colInd = matA.mAj[iAi];
            aiv = matA.mAv[iAi];
            // make aiv*b_{colInd} and insert into mapRow2Val
            for (int iB=matB.mAi[colInd]; iB<matB.mAi[colInd+1]; ++iB) {
                colB=matB.mAj[iB];
                if (colB >= i) {
                    valB=matB.mAv[iB];
                    // insert valA*aiv into map
                    std::map<int, R>::iterator it = mapRow2Val.find(colB);
                    if (it == mapRow2Val.end()) {       // first time
                        mapRow2Val[colB] = valB*aiv;
                    }
                    else {
                        it->second = it->second + valB*aiv;
                    }
                }
            }
        }
    }// now column i is created

    return true;
}

template <typename R>
bool Mul2MatricesSymmResult(const CSRMatrix<R> &matA, const CSRMatrix<R> &matB, CSRMatrix<R> &matC)
{
    RowMat<R> rowsC;
    if( !Mul2MatricesSymmResult(matA, matB, rowsC) )    return false;

    rowsC.mNCol = matA.nCol();
    CreateCSRMatrixFromRowMap(matC, rowsC);
    matC.mMtype = CSRMatrix<R>::RealSymmIndef;
    return true;
}


template<typename R>
void DebugShowRowMatrix(const std::vector<std::map<int,R> > &rowA)
{
    printf("\n");
    for(unsigned int i=0; i<rowA.size(); i++){
        printf("\n%3d#", i);
        std::map<int,R>::const_iterator it=rowA[i].begin();
        int j=0;
        for(; it!=rowA[i].end(); ++it){
            for(int k=j; k<it->first; k++){
                printf("\t%3.2f", 0);
            }

            j=it->first+1;
            printf("\t%3.2f", it->second);
        }
    }
}

typedef CSRMatrix<float> CSRMatrixf;
typedef CSRMatrix<double> CSRMatrixd;


_NUMC_END

#endif      // NUMC_CSRMATRIX_H

all
I got a piece of code about sparse matrix, it works fine in VISUAL STUDIO 2008, but when I want to port it to ubuntu environment, the compiler report the following errors:

../include/spmatrix.h(123): error:
class template "numc::CSRMatrix"
has no member "resize"

../include/spmatrix.h(170): error:
expected a ";"

../include/spmatrix.h(171): error:
identifier "it" is undefined

../include/spmatrix.h(176): error:
expected a ";"

../include/spmatrix.h(178): error:
identifier "it" is undefined

../include/spmatrix.h(183): error:
identifier "size" is undefined

../include/spmatrix.h(185): error:
expected a ";"

../include/spmatrix.h(185): error:
identifier "it" is undefined

.> ./include/spmatrix.h(186): error:
expected a ";"

../include/spmatrix.h(187): error:
identifier "cit" is undefined

../include/spmatrix.h(205): error:
expected a ";"

../include/spmatrix.h(205): error:
identifier "it" is undefined

../include/spmatrix.h(218): error:
expected a ";"

../include/spmatrix.h(218): error:
identifier "it" is undefined

../include/spmatrix.h(222): error:
expected a ";"

../include/spmatrix.h(223): error:
identifier "f" is undefined

../include/spmatrix.h(224): error:
identifier "make_pair" is undefined

../include/spmatrix.h(224): error:
type name is not allowed

../include/spmatrix.h(224): error:
type name is not allowed

../include/spmatrix.h(245): error:
identifier "RowType" is undefined

../include/spmatrix.h(246): error:
name followed by "::" must be a class
or namespace name

../include/spmatrix.h(246): error:
expected a ";"

../include/spmatrix.h(246): error:
identifier "it" is undefined

../include/spmatrix.h(269): error:
identifier "RowType" is undefined

../include/spmatrix.h(270): error:
name followed by "::" must be a class
or namespace name

../include/spmatrix.h(270): error:
expected a ";"

../include/spmatrix.h(271): error:
identifier "it" is undefined

../include/spmatrix.h(276): error:
identifier "RowType" is undefined

../include/spmatrix.h(276): error:
identifier "crow" is undefined

../include/spmatrix.h(277): error:
name followed by "::" must be a class
or namespace name

../include/spmatrix.h(277): error:
expected a ";"

../include/spmatrix.h(279): error:
identifier "it" is undefined

../include/spmatrix.h(311): error:
expected a ";"

../include/spmatrix.h(311): error:
identifier "it" is undefined

../include/spmatrix.h(350): error:
expected a ";"

../include/spmatrix.h(350): error:
identifier "it" is undefined

../include/spmatrix.h(423): error:
expected a ";"

../include/spmatrix.h(424): error:
identifier "it" is undefined

../include/spmatrix.h(484): error:
expected a ";"

../include/spmatrix.h(485): error:
identifier "it" is undefined

../include/spmatrix.h(518): error:
expected a ";"

../include/spmatrix.h(520): error:
identifier "it" is undefined

I try to figure out where the problem is, but failed. Hope you can give me some hint where the problem is. Thanks in advance for your help!

Below is the code of this sparse matrix, it is just a header file:

#pragma   warning(disable:   4786)

#ifndef NUMC_CSRMATRIX_H
#define NUMC_CSRMATRIX_H

#include <cmath>
#include <map>
#include <vector>
#include <limits>
#include <algorithm>

#ifndef _NUMC_BEGIN
#define _NUMC_BEGIN namespace numc {
#define _NUMC_END   }
#endif

_NUMC_BEGIN
using std::vector;
using std::map;
using std::swap;
using std::lower_bound;

template<typename R> class CSRMatrix;
template<typename R> struct RowMat;
template<typename R> void CreateCSRMatrixFromRowMap(CSRMatrix<R>&, const RowMat<R>&);
t    emplate<typename R> void CSRMatrixTranspose (const CSRMatrix<R>&, CSRMatrix<R>&);
template<typename R> bool Mul2MatricesSymmResult (const CSRMatrix<R>&, const CSRMatrix<R>&, RowMat<R>&);
template<typename R> bool Mul2MatricesSymmResult (const CSRMatrix<R>&, const CSRMatrix<R>&, CSRMatrix<R>&);
template<typename R> bool Mul2Matrices (const CSRMatrix<R>&, const CSRMatrix<R>&, RowMat<R>&);
template<typename R> bool Mul2Matrices (const CSRMatrix<R>&, const CSRMatrix<R>&, CSRMatrix<R>&);

template<typename R>
class CSRMatrix
{
public:
    enum MatType{ RealStrucSymm=1, RealSymmPosDef=2, RealSymmIndef=-2, 
        CompStrucSymm=3, CompHermPosDef=4, CompHermIndef=-4, 
        CompSymm=6, RealUnSymm=11, CompUnSymm=13};

    std::vector<R> mAv;
    std::vector<int> mAi, mAj;

    CSRMatrix():mNRow(0),mNCol(0),mMtype(RealUnSymm) {};
    CSRMatrix(const RowMat<R> &rm):mMtype(RealUnSymm)   { CreateCSRMatrixFromRowMap(*this, rm); }
    MatType mMtype;

#if ( defined(_MSC_VER)&&(_MSC_VER>1300) )
    //template<typename T> class CSRMatrix;
#define FFM <>  // FFM FRIEND_FUNCTION_MAGIC
#else
#define FFM
#endif

    friend void CreateCSRMatrixFromRowMap FFM(CSRMatrix<R>&, const RowMat<R>&);
    friend void CSRMatrixTranspose FFM(const CSRMatrix<R>&, CSRMatrix<R>&);
    friend bool Mul2MatricesSymmResult FFM(const CSRMatrix<R>&, const CSRMatrix<R>&, RowMat<R>&);
    friend bool Mul2MatricesSymmResult FFM(const CSRMatrix<R>&, const CSRMatrix<R>&, CSRMatrix<R>&);
    friend bool Mul2Matrices FFM(const CSRMatrix<R>&, const CSRMatrix<R>&, RowMat<R>&);
    friend bool Mul2Matrices FFM(const CSRMatrix<R>&, const CSRMatrix<R>&, CSRMatrix<R>&);

#undef FFM

private:
    int mNRow, mNCol;

public:
    inline int nRow() const { return mNRow; }
    inline int nCol() const { return mNCol; }
    inline int empty() const { return (0==nRow() || 0==nCol()) ;}
        inline bool onebase() const { return (!mAi.empty()) && (mAi[0]==1); }       //default: zerobase, including empty matrix!
    inline MatType mtype() const { return mMtype; }

    inline bool issymm() const
    { return (RealSymmIndef==mMtype || RealSymmPosDef==mMtype || CompSymm==mMtype); }

    inline void clear() 
    { mNRow = 0; mNCol = 0; mMtype = RealUnSymm; mAv.clear(); mAi.clear(); mAj.clear(); }

    R getElementV(int x, int y) const{
        double *p = const_cast<CSRMatrix*>(this)->getElementP(x, y);
        return (NULL==p)?0:*p;  
    }

    R* getElementP(int x, int y) {
        if (x<0||y<0)   return NULL;
        if ( issymm() && x>y) swap(x, y);
        const int off = onebase();
        std::vector<int>::const_iterator it = lower_bound(mAj.begin()+mAi[x]-off, mAj.begin()+(mAi[x+1]-off), y+off);
        if (it==mAj.begin()+(mAi[x+1]-off) || *it!=(y+off) ) return NULL;

        return &mAv.front() + ( it-mAj.begin() );
    }

    void MultiVect(R* in, R *out) const;

    bool ChangeBase(bool oneBase) {
        if( onebase() == oneBase )  return true;
        int ii;
        if (oneBase) {
            if (mAi[0] != 0){
                fprintf(stderr, "error matrix!");
                return false;
            }

            for (ii=0; ii<mAi.back(); ii++) mAj[ii]++;

            for (ii=0; ii<mNRow+1; ii++) mAi[ii]++;
        }
        else {
            if (mAi[0] != 1){
                fprintf(stderr, "error matrix!");
                return false;
            }

            for (ii=0; ii<mAi.back()-1; ii++) mAj[ii]--;

            for (ii=0; ii<mNRow+1; ii++) mAi[ii]--;
        }
        return true;
    }

    void GetSubMat(const std::vector<int> &xi, const std::vector<int> &yi, CSRMatrix& mat){
        mat.resize( yi.size() );
        for(int j=0; j<yi.size(); j++){
            for(int i=0; i<xi.size(); i++){

            }
        }

    }

    void print(FILE *f=stdout){
        fprintf(f, "The matrix:\n");
        for(int i=0; i<nRow(); i++){
            fprintf(f, "%2d#:", i);
            for(int j=0; j<nCol(); j++) {
                fprintf(f, "\t%.3e", getElementV(i, j) );
            }
            fprintf(f, "\n");
        }
    }

};

template<typename R>
struct RowMat:public vector<map<int, R> >
{
    typedef map<int, R> RowType;
    typedef vector<RowType> BaseType;
    int mNCol;

    RowMat(int nrow=0, int ncol=0):BaseType(nrow),mNCol(ncol)   { }
    ~RowMat()   { }
    RowMat(const CSRMatrix<R> &mat)
    {
        resize(mat.nCol(), mat.nRow());

        int off = mat.onebase()?1:0;
        for(unsigned int i=0; i+1<mat.mAi.size(); i++){
            for(int j=mat.mAi[i]; j<mat.mAi[i+1]; j++){
                (*this)(i, mat.mAj[j-off]-off) = mat.mAv[ j-off ];
            }
        }

    }

    virtual bool symmetric() const {return false;}
    virtual inline R operator()(int i, int j) const{
        const RowType &crow = (*this)[i];
        RowType::const_iterator it = crow.find(j);
        return ( it==crow.end() )?0:it->second;
    }

    virtual inline R& operator()(int i, int j){
        RowType &crow = (*this)[i];
        RowType::iterator it = crow.find(j);

        return ( it==crow.end() )?crow.insert( std::pair<int,R>(j, 0) ).first->second:it->second;
    }

    int clearZero() {
        int nZero;
        for (size_t i=0; i<size(); i++) {
            RowType &r = (*this)[i];
            for (RowType::const_iterator it=r.begin(); it!=r.end(); ) {
                RowType::const_iterator cit = it++;
                if(fabs(cit->second) < std::numeric_limits<R>::epsilon()){
                    r.erase(cit);
                    ++nZero;
                }
            }
        }
        return nZero;
    }

    inline void resize(int nrow, int ncol=0) { BaseType::resize(nrow); mNCol = ncol>0?ncol:mNCol; }
    inline int nRow()   const { return BaseType::size(); }
    inline int nCol()   const { return mNCol; }

    int operator+=(const RowMat<R>& r) { return add(r, 1); }

    void operator *= (const double v) {
        for(int i=0; i<nRow(); i++){
            map<int, R>& crow = (*this)[i];
            for(map<int,R>::iterator it=crow.begin(); it!=crow.end(); ++it){
                it->second *= v;
            }
        }
    }

    int add(const RowMat<R>& r, R k){
        const int h = nRow();
        if( r.nRow() != h ) return -1;

        for(int i=0; i<h; i++){
            const map<int, R>& rrow = r[i];
            map<int, R>& lrow = (*this)[i];
            for(RowType::const_iterator it=rrow.begin(); it!=rrow.end(); ++it){
                int col = it->first;
                R val = it->second * k;

                map<int,R>::iterator f = lrow.find(col);
                if( f != lrow.end() )   f->second += val;
                lrow.insert( make_pair<int, R>(col, val) );
            }
        }

        return 0;
    }

};

template<typename R>
struct RowMatSym : public RowMat<R>
{
    typedef RowMat<R> Base;

    RowMatSym(int nrow=0, int ncol=0):Base(nrow, ncol)  {}
    ~RowMatSym()    { }

    RowMatSym(const RowMat<R> &rm){
        resize(rm.nCol(), rm.nRow());

        for(unsigned int i=0; i<rm.nRow(); i++){
            const RowType &crow = rm[i];
            for(RowType::const_iterator it=crow.begin(); it!=crow.end(); ++it){
                (*this)(i, it->first) = it->second;
            }
        }
    }

    RowMatSym(const CSRMatrix<R> &mat)
    {
        resize(mat.nCol(), mat.nRow());

        int off = mat.onebase()?1:0;
        for(unsigned int i=0; i+1<mat.mAi.size(); i++){
            for(int j=mat.mAi[i]; j<mat.mAi[i+1]; j++){
                const int k = mat.mAj[j-off]-off;
                (*this)(i, k) = mat.mAv[ j-off ];
            }
        }
    }

    virtual bool symmetric() const {return true;}

    inline R operator()(int i, int j) const{
        if(i>j) std::swap(i, j);
        const RowType &crow = (*this)[i];
        RowType::const_iterator it = crow.find(j);
        return ( it==crow.end() )?0:it->second;
    }

    inline R& operator()(int i, int j){
        if(i>j) std::swap(i, j);
        RowType &crow = (*this)[i];
        RowType::iterator it = crow.find(j);

        return ( it==crow.end() )?crow.insert( std::pair<int,R>(j, 0) ).first->second
            :it->second;
    }

};


//////////////////////////////////////////////////////////////////////////
/// Get SubMatrix from rowmap
//////////////////////////////////////////////////////////////////////////
template <typename R>
void GetSubRowMap(const RowMat<R>& src,
                  const std::vector<int> &xi, const std::vector<int> &yi,
                  RowMat<R>& dst)
{
    assert( xi.size()>0 && yi.size()>0 );
    assert( yi.back() < (int)src.size() );
    if( xi.empty() || yi.empty() || yi.back() >= (int)src.size() ){
        fprintf(stderr, "\nerror matrix!");
        return;
    }


    typedef std::map<int, R> row;
    dst.resize( yi.size() );

    for(unsigned int j=0; j<yi.size(); j++){
        const row &srow = src[ yi[j] ];
        row &drow = dst[j];

        const int* pxi = &xi.front();

        for(row::const_iterator it=srow.begin(); it!=srow.end(); ++it ){
            pxi = std::lower_bound(pxi, &xi.back(), it->first);

            if(*pxi != it->first){          // done
                continue;
            }

            int col = pxi - &xi.front();
            drow[col] = it->second;
        }
    }
}

//////////////////////////////////////////////////////////////////////////
/// Create CSR matrix from vector of rowmap
//////////////////////////////////////////////////////////////////////////
template <typename R>
void CreateCSRMatrixFromRowMap(CSRMatrix<R> &matC, const RowMat<R>& rowC)
{
    if(rowC.mNCol <= 0){
        fprintf(stderr, "\nnumber of column not specified in the RowMat, exit!");
        return;
    }
    matC.clear();
    matC.mNRow = rowC.nRow();
    matC.mNCol = rowC.nCol();

    matC.mAi.reserve(matC.nRow()+1);
    int i,nnz=0;
    for (i=0; i<matC.nRow(); i++) {
        nnz += rowC[i].size();
    }
    matC.mAj.reserve(nnz);
    matC.mAv.reserve(nnz);

    // copy rows into matC
    matC.mAi.push_back(0);
    for (i=0; i<matC.nRow(); i++) {
        matC.mAi.push_back(matC.mAi.back());
        for (std::map<int, R>::const_iterator it=rowC[i].begin(); it!=rowC[i].end(); it++) {
            matC.mAi.back()++;
            matC.mAj.push_back(it->first);
            matC.mAv.push_back(it->second);
        }
    }
}


//////////////////////////////////////////////////////////////////////////
/// Computes the transpose of a matrix.
template <typename R>
void CSRMatrixTranspose(const CSRMatrix<R> &matA, CSRMatrix<R> &matAT)
{
    if (matA.issymm()) {        // symmetric - just copy the matrix
        matAT = matA;
        return;
        }

    matAT.mNRow = matA.nCol();
    matAT.mNCol = matA.nRow();
    matAT.mMtype = matA.mMtype;

    // non-symmetric matrix -> need to build data structure.
    // we'll go over the columns and build the rows
    int off = matA.onebase()?1:0;
    RowMat<R> rowC(matA.nCol(), matA.nRow());
    for (int i=0; i<matA.nRow(); i++) {
        for (int j=matA.mAi[i]; j<matA.mAi[i+1]; j++) {
            rowC[matA.mAj[j-off]-off][i] = matA.mAv[j-off];
        }
    }

    CreateCSRMatrixFromRowMap(matAT, rowC);
}


//////////////////////////////////////////////////////////////////////////
// multiplication of sparse matrix
// Assuming nothing about the result (the result is not stored symmetric)
//////////////////////////////////////////////////////////////////////////
template <typename R>
bool Mul2Matrices(const CSRMatrix<R> &matA, const CSRMatrix<R> &matB,
                  RowMat<R> &rowsC)
{
    if(matA.onebase() || matB.onebase() ){
        fprintf(stderr, "\nmatrix saved in 1-based format, pleased converted it to 0-based and try again!");
        return false;
    }
    // Compatibility of dimensions
    if (matA.nCol() != matB.nRow())
        return false;

    // (m x n)*(n x k) = (m x k)
    const int m=matA.nRow();
    const int n=matA.nCol();
    const int k=matB.nCol();

    rowsC = RowMat<R>(m, k);    // clean all coefficients

    R aiv, valB;
    int colInd, colB;

    for (int i=0; i<m; ++i) {                   // creating row i of C
        std::map<int, R> &mapRow2Val = rowsC[i];
        for (int iAi = matA.mAi[i]; iAi < matA.mAi[i+1]; ++iAi) {           // travel on ai
            colInd = matA.mAj[iAi];
            aiv = matA.mAv[iAi];
            // make aiv*b_{rowInd} and insert into mapRow2Val
            for (int iB=matB.mAi[colInd]; iB<matB.mAi[colInd+1]; ++iB) {
                colB=matB.mAj[iB];
                valB=matB.mAv[iB];
                // insert valA*aiv into map
                std::map<int, R>::iterator it = mapRow2Val.find(colB);
                if (it == mapRow2Val.end()) {       // first time
                    mapRow2Val[colB] = valB*aiv;
                }
                else {
                    it->second = it->second + valB*aiv;
                }
            }
        }
    }// now column i is created

    return true;
}

template <typename R>
bool Mul2Matrices(const CSRMatrix<R> &matA, const CSRMatrix<R> &matB, CSRMatrix<R> &matC)
{
    RowMat<R> rowsC;
    if( !Mul2Matrices(matA, matB, rowsC) ) return false;

    const int k=matB.mNCol;
    rowsC.mNCol = k;
    CreateCSRMatrixFromRowMap(matC, rowsC);                     // modified by jianwei hu @ 16/09/07
    return true;
}

//////////////////////////////////////////////////////////////////////////
// multiplication of sparse matrix
// The result is symmetric
//////////////////////////////////////////////////////////////////////////
template <typename R>
bool Mul2MatricesSymmResult(const CSRMatrix<R> &matA, const CSRMatrix<R> &matB,
                            RowMat<R> &rowsC)
{
    if(matA.onebase() || matB.onebase()){
        fprintf(stderr, "\nmatrix saved in 1-based format, pleased converted it to 0-based and try again!");
        return false;
    }
    // Compatibility of dimensions
    if(matA.nCol() != matB.nRow() || matA.nRow() != matB.nCol())    return false;

    // (m x n)*(n x m) = (m x m)
    const int m=matA.nRow();
    const int n=matA.nCol();

    rowsC = RowMat<R>(m, m);    // clean all coefficients

    R aiv, valB;
    int colInd, colB;

    for(int i=0; i<m; ++i) {                    // creating row i of C
        std::map<int, R> &mapRow2Val = rowsC[i];
        for (int iAi = matA.mAi[i]; iAi < matA.mAi[i+1]; ++iAi) {           // travel on ai
            colInd = matA.mAj[iAi];
            aiv = matA.mAv[iAi];
            // make aiv*b_{colInd} and insert into mapRow2Val
            for (int iB=matB.mAi[colInd]; iB<matB.mAi[colInd+1]; ++iB) {
                colB=matB.mAj[iB];
                if (colB >= i) {
                    valB=matB.mAv[iB];
                    // insert valA*aiv into map
                    std::map<int, R>::iterator it = mapRow2Val.find(colB);
                    if (it == mapRow2Val.end()) {       // first time
                        mapRow2Val[colB] = valB*aiv;
                    }
                    else {
                        it->second = it->second + valB*aiv;
                    }
                }
            }
        }
    }// now column i is created

    return true;
}

template <typename R>
bool Mul2MatricesSymmResult(const CSRMatrix<R> &matA, const CSRMatrix<R> &matB, CSRMatrix<R> &matC)
{
    RowMat<R> rowsC;
    if( !Mul2MatricesSymmResult(matA, matB, rowsC) )    return false;

    rowsC.mNCol = matA.nCol();
    CreateCSRMatrixFromRowMap(matC, rowsC);
    matC.mMtype = CSRMatrix<R>::RealSymmIndef;
    return true;
}


template<typename R>
void DebugShowRowMatrix(const std::vector<std::map<int,R> > &rowA)
{
    printf("\n");
    for(unsigned int i=0; i<rowA.size(); i++){
        printf("\n%3d#", i);
        std::map<int,R>::const_iterator it=rowA[i].begin();
        int j=0;
        for(; it!=rowA[i].end(); ++it){
            for(int k=j; k<it->first; k++){
                printf("\t%3.2f", 0);
            }

            j=it->first+1;
            printf("\t%3.2f", it->second);
        }
    }
}

typedef CSRMatrix<float> CSRMatrixf;
typedef CSRMatrix<double> CSRMatrixd;


_NUMC_END

#endif      // NUMC_CSRMATRIX_H

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

仙气飘飘 2024-11-23 08:31:08

第 123 行:CSRMatrix::resize 方法未定义,并且由于 CSRMatrix 没有基类,因此它不是继承的。

第 171 行:使用 typedef 的嵌套类型(如 RowType::const_iterator)是 Visual Studio 扩展,它可能无法在其他编译器中工作。您应该用其他 typedef 替换这些和类似的用法,如下所示:

typedef typename map<int,R>::const_iterator RowTypeConstIterator;

更新:需要 typename 关键字(刚刚学会了!)

Line 123: the CSRMatrix::resize method is undefined, and since CSRMatrix has no base class, it's not inherited.

Line 171: Using a typedef's nested type, like RowType::const_iterator, is a Visual Studio extension, it may not work in other compilers. You should replace these and similar usages with other typedefs, like so:

typedef typename map<int,R>::const_iterator RowTypeConstIterator;

UPDATE: The typename keyword is required (just learned it!)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文