类没有成员问题(代码在VS中可以找到,但在Ubuntu中失败)
全部 我得到了一段关于稀疏矩阵的代码,它在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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
第 123 行:CSRMatrix::resize 方法未定义,并且由于 CSRMatrix 没有基类,因此它不是继承的。
第 171 行:使用 typedef 的嵌套类型(如 RowType::const_iterator)是 Visual Studio 扩展,它可能无法在其他编译器中工作。您应该用其他 typedef 替换这些和类似的用法,如下所示:
更新:需要 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:
UPDATE: The typename keyword is required (just learned it!)