예제 #1
0
void SpParMat<IT,NT,DER>::DimScale(const DenseParVec<IT,NT> & v, Dim dim)
{
	switch(dim)
	{
		case Column:	// scale each "Column", using a row vector
		{
			// Diagonal processor broadcast data so that everyone gets the scaling vector 
			NT * scaler = NULL;
			int root = commGrid->GetDiagOfProcCol();
			if(v.diagonal)
			{	
				scaler = const_cast<NT*>(SpHelper::p2a(v.arr));	
			}
			else
			{	
				scaler = new NT[getlocalcols()];	
			}
			MPI_Bcast(scaler, getlocalcols(), MPIType<NT>(), root, commGrid->GetColWorld());	

			for(typename DER::SpColIter colit = spSeq->begcol(); colit != spSeq->endcol(); ++colit)	// iterate over columns
			{
				for(typename DER::SpColIter::NzIter nzit = spSeq->begnz(colit); nzit != spSeq->endnz(colit); ++nzit)
				{
					nzit.value() *=  scaler[colit.colid()];
				}
			}
			if(!v.diagonal)	delete [] scaler;
			break;
		}
		case Row:
		{
			NT * scaler = NULL;
			int root = commGrid->GetDiagOfProcRow();
			if(v.diagonal)
			{	
				scaler = const_cast<NT*>(SpHelper::p2a(v.arr));	
			}
			else
			{	
				scaler = new NT[getlocalrows()];	
			}
			MPI_Bcast(scaler, getlocalrows(), MPIType<NT>(), root, commGrid->GetRowWorld());	

			for(typename DER::SpColIter colit = spSeq->begcol(); colit != spSeq->endcol(); ++colit)
			{
				for(typename DER::SpColIter::NzIter nzit = spSeq->begnz(colit); nzit != spSeq->endnz(colit); ++nzit)
				{
					nzit.value() *= scaler[nzit.rowid()];
				}
			}
			if(!v.diagonal)	delete [] scaler;			
			break;
		}
		default:
		{
			cout << "Unknown scaling dimension, returning..." << endl;
			break;
		}
	}
}
예제 #2
0
DenseParVec<IT,NT> SpParMat<IT,NT,DER>::Reduce(Dim dim, _BinaryOperation __binary_op, NT id, _UnaryOperation __unary_op) const
{
	DenseParVec<IT,NT> parvec(commGrid, id);

	switch(dim)
	{
		case Row:	// pack along the columns, result is a "Row" vector of size n
		{
			NT * sendbuf = new NT[getlocalcols()];
			fill(sendbuf, sendbuf+getlocalcols(), id);	// fill with identity

			for(typename DER::SpColIter colit = spSeq->begcol(); colit != spSeq->endcol(); ++colit)	// iterate over columns
			{
				for(typename DER::SpColIter::NzIter nzit = spSeq->begnz(colit); nzit != spSeq->endnz(colit); ++nzit)
				{
					sendbuf[colit.colid()] = __binary_op(__unary_op(nzit.value()), sendbuf[colit.colid()]);
				}
			}
			NT * recvbuf = NULL;
			int root = commGrid->GetDiagOfProcCol();
			if(parvec.diagonal)
			{
				parvec.arr.resize(getlocalcols());
				recvbuf = &parvec.arr[0];	
			}
			(commGrid->GetColWorld()).Reduce(sendbuf, recvbuf, getlocalcols(), MPIType<NT>(), MPIOp<_BinaryOperation, NT>::op(), root);
			delete [] sendbuf;
			break;
		}
		case Column:	// pack along the rows, result is a "Column" vector of size m
		{
			NT * sendbuf = new NT[getlocalrows()];
			fill(sendbuf, sendbuf+getlocalcols(), id);	// fill with identity
			
			for(typename DER::SpColIter colit = spSeq->begcol(); colit != spSeq->endcol(); ++colit)	// iterate over columns
			{
				for(typename DER::SpColIter::NzIter nzit = spSeq->begnz(colit); nzit != spSeq->endnz(colit); ++nzit)
				{
					sendbuf[nzit.rowid()] = __binary_op(__unary_op(nzit.value()), sendbuf[nzit.rowid()]);
				}
			}
			NT * recvbuf = NULL;
			int root = commGrid->GetDiagOfProcRow();
			if(parvec.diagonal)
			{
				parvec.arr.resize(getlocalrows());
				recvbuf = &parvec.arr[0];	
			}
			(commGrid->GetRowWorld()).Reduce(sendbuf, recvbuf, getlocalrows(), MPIType<NT>(), MPIOp<_BinaryOperation, NT>::op(), root);
			delete [] sendbuf;
			break;
		}
		default:
		{
			cout << "Unknown reduction dimension, returning empty vector" << endl;
			break;
		}
	}
	return parvec;

}