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; } } }
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; }