void sortByRow(Point *a, int l, int r) { // We choose the most right element as pivot if(r <= l) return; int i = l - 1, j = r; int p = l - 1, q = r; int k; while(1) { // while(a[++i].row < a[r].row); // Swap me i++; while(utilityFunct(a[i].row, a[i].col) < utilityFunct(a[r].row, a[r].col)) { i++; } j--; // while(a[r].row < a[--j].row) while(utilityFunct(a[r].row, a[r].col) < utilityFunct(a[j].row, a[j].col)) { if(j == l) { break; } j--; } if(i >= j) break; // Out of order exch(a, i, j); // if(a[i].row == a[r].row) if(utilityFunct(a[i].row, a[i].col) == utilityFunct(a[r].row, a[r].col)) { exch(a, ++p, i); } // if(a[j].row == a[r].row) if(utilityFunct(a[j].row, a[j].col) == utilityFunct(a[r].row, a[r].col)) { exch(a, --q, j); } } exch(a, i, r); j = i - 1; i = i + 1; for(k = l; k <= p; k++) exch(a, k, j--); for(k = r - 1; k >= q; k--) exch(a, k, i++); sortByRow(a, l, j); sortByRow(a, i, r); }
/** * constructor */ SellCSigma_Matrix::SellCSigma_Matrix( MMreader mmMatrix, int C, int const sigma ) :C_(C), sigma_(sigma) ,M_(mmMatrix.getRows()), N_(mmMatrix.getCols()) ,nz_(mmMatrix.getNonZeros()), numberOfChunks_((M_-1)/C+1) ,colInd_(nullptr) ,chunkPtr_(new int[numberOfChunks_]), chunkLength_(new int[numberOfChunks_]) ,permute_(new int[M_]), antiPermute_(new int[M_]) ,val_(nullptr) { // sort input Matrix by row ID if( !mmMatrix.isRowSorted() ) sortByRow(mmMatrix); std::vector< std::tuple<int,int,double> > & mmData = mmMatrix.getMatrx(); std::vector< std::tuple<int, int> > rowLengths = getRowLengths(mmMatrix); // sort sigam chunks by row length auto begin = rowLengths.begin(); auto end = rowLengths.begin() + getSigma(); for (; end <= rowLengths.end(); begin += getSigma(), end += getSigma() ) { std::sort(begin, end, [](std::tuple<int,int> const & a, std::tuple<int,int> const & b) {return std::get<1>(a) < std::get<1>(b);} ); } begin -= getSigma(); std::sort(begin, rowLengths.end(), [](std::tuple<int,int> const & a, std::tuple<int,int> const & b) {return std::get<1>(a) < std::get<1>(b);} ); // determine chunk length and size // and set backword permutation std::vector<int> valuesPerChunk( getNumberOfChunks() ); #ifdef _OPENMP #pragma omp parallel for schedule(runtime) #endif for (int chunk=0; chunk < getNumberOfChunks(); ++chunk) { int maxRowLenghth = 0; for (int i=0, row=chunk*getChunkSize(); i<getChunkSize() && row<getRows(); ++i, ++row ) { if ( maxRowLenghth < std::get<1>(rowLengths[row]) ) maxRowLenghth = std::get<1>(rowLengths[row]); // set backword permutation antiPermute_[ std::get<0>(rowLengths[row]) ] = row; } chunkLength_[chunk] = maxRowLenghth; valuesPerChunk[chunk] = maxRowLenghth * getChunkSize(); } // calculate memory usage and allocate memmory for values and colum IDs capasety_ = std::accumulate(std::begin(valuesPerChunk), std::end(valuesPerChunk), 0 ); val_ = new double[capasety_]; colInd_ = new int [capasety_]; // calulate memory overhead overhead_ = capasety_ - getNonZeros(); // creat Sell-C-sigma data std::vector<int> chunkOffset = getOffsets(valuesPerChunk); std::vector<int> rowOffset = getOffsets(getValsPerRow(mmMatrix)); #ifdef _OPENMP #pragma omp parallel for schedule(runtime) #endif for (int chunk=0; chunk < getNumberOfChunks(); ++chunk) { chunkPtr_[chunk] = chunkOffset[chunk]; for (int j=0; j<chunkLength_[chunk]; ++j) { for (int i=0, row=chunk*getChunkSize(); i<getChunkSize(); ++i, ++row ) { int col; double val; if (row<getRows()) { // set permutation permute_[row] = std::get<0>(rowLengths[row]); // finde values and collumn index if ( j < std::get<1>(rowLengths[row]) ) { // fill with matrix values int id = rowOffset[ permute_[row] ] + j; val = std::get<2>( mmData[id] ); col = std::get<1>( mmData[id] ); } else { // fill chunk with 0 val = 0.; col = 0; } } else { // add zero rows to end of matrix fill up last chunk val = 0.; col = 0; } val_ [chunkPtr_[chunk] + i + j*getChunkSize()] = val; colInd_[chunkPtr_[chunk] + i + j*getChunkSize()] = antiPermute_[col]; } } } /* std::cout << "Sell-C-sigma constructed:" << "\nC: " << getChunkSize() << " sigma: " << getSigma() << "\n(" << getRows() << "," << getCols() << ") " << getNonZeros() << ":\n"; for (int i=0; i<valueMemoryUsage; ++i) { std::cout << getValues()[i] << " (" << getColInd()[i] << ")\n"; } std::cout << std::endl; */ }