Exemple #1
0
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;
    */
}