void PageRankSerial::calculatePageRank (
    const CSRMatrix& matrix,
    RVec& input,
    const ConvergenceCriterion& criterion)
{
    assert( matrix.numColumns() == input.size() );
    R old_norm = 1e5, new_norm;
    double toldiff = 1e5;
    std::shared_ptr< RVec >
        input_buf( new RVec( input ) ), output_buf( new RVec( input.size() ) ), temp;
    unsigned int i = 0;
    while( ++i < criterion.max_iterations ) {
        matrix.multiply( *(input_buf), *(output_buf) ) ;
        // Utils::normalize( *(output_buf) );
        new_norm = sqrt( Utils::sumOfSquares( *(output_buf) ));
        toldiff = std::abs( new_norm - old_norm );
        std::cout << "DEBUG: iterations = " << i <<
            " toldiff = " << toldiff << "\n";
        std::swap( input_buf, output_buf );
        old_norm = new_norm;
        if( toldiff <= criterion.tolerance ) break;
    };
    input = *(input_buf);
    if( i == criterion.max_iterations )
        std::cout << "DEBUG: Terminated because of maxiterations with " <<
            " tolerancediff = " << toldiff << " and max_iterations = "
            << criterion.max_iterations << "\n";
    else
        std::cout << "DEBUG: Finished and converged on pagerank vector"
            " in " << i << " iterations with ||Ax - x||_2 = " << toldiff << "\n";


}
R Utils::normOfDiff(
    const RVec& v1,
    const RVec& v2 )
{
    ASSERT_EQUALS( v1.size(), v2.size() );
    R norm_diff = 0;
    for( N i = 0; i < v1.size(); ++i )
    {
        R diff = v1[i] - v2[i];
        norm_diff += diff * diff;
    }
    return sqrt( norm_diff );
}
R Utils::sumOfSquares( const RVec& input )
{
    R squared_norm = 0;
    for(N i= 0; i < input.size(); ++i)
        squared_norm += input[i]* input[i];
    return squared_norm;
}
void PageRankPthread::calculatePageRank (
    const CSRMatrix::CPtr& matrix,
    RVec& input,
    N num_threads,
    const ConvergenceCriterion& criterion)
{
    assert( matrix->numColumns() == input.size() );
    toldiff = 1e5;
    RVec *input_buf =  new RVec( input );
    RVec *output_buf =  new RVec( input.size() );
    const CSRMatrix* matrix_ptr = matrix.get();

    pthread_t threads[num_threads];
    ::num_threads = num_threads;
    tol_threads.resize( num_threads );
    std::vector< ThreadStruct > tstruct;
    pthread_barrier_init( &barr, NULL, num_threads );
    N start = 0, rows = matrix->numRows();
    N chunk = rows/num_threads + 1;
    for( N i = 0; i < num_threads; ++i )
    {
        N end = std::min( start + chunk, rows );
        tstruct.push_back( ThreadStruct( i, start, end,
                                         CSRMatrixPthread( matrix_ptr, start, end ),
                                         criterion, input_buf, output_buf) );
        start = end ;
    }

    for( N i = 0; i < num_threads; ++i )
        pthread_create( &threads[i], NULL, pageRankIteration, &tstruct[i] );

    for( N i = 0; i < num_threads; ++i )
        pthread_join( threads[i], NULL);
    input = *(output);

    if( iters == criterion.max_iterations )
        std::cout << "DEBUG: Terminated because of maxiterations with " <<
                  " tolerancediff = " << toldiff << " and max_iterations = "
                  << criterion.max_iterations << "\n";
    else
        std::cout << "DEBUG: Finished and converged on pagerank vector"
                  " in " << iters << " iterations with ||Ax - x||_2 = " << toldiff << "\n";


}
CSRMatrix::CPtr CSRMatrix::create(
    N num_cols,
    const RVec& values,
    const NVec& cols,
    const NVec& row_ptrs )
{
     assert( values.size() == cols.size() );
     N size = values.size();
     NVecPtr row_ptr( new NVec( row_ptrs ) );
     std::shared_ptr< std::vector< CSRMatrixEntry > > entries(
             new std::vector< CSRMatrixEntry >( size ));
     for( N i = 0; i < size; ++i  )
     {
          entries->at(i).value = values[i];
          entries->at(i).column_idx = cols[i];
     }

     return CPtr( new CSRMatrix( row_ptrs.size() -1, num_cols, entries, row_ptr) );
}
void Utils::writePageRank( std::ostream& oss, const RVec& page_rank_weight )
{
    N num_nodes = page_rank_weight.size();
    std::vector< std::pair< N, N > > page_rank( num_nodes );
    N i;
    for( i =0; i < num_nodes; ++i )
    {
        oss << i << " " << std::fixed <<
            std::setprecision( 12 ) << page_rank_weight[i] << "\n";
    }

}
void Utils::normalize( RVec& vec ) {
    R norm_2 = sqrt(sumOfSquares( vec ));
    for(unsigned int i= 0; i < vec.size(); ++i)
        vec[i] /= norm_2;
}
void FFTWInterface::get_momentum_for_fftw(RVec &p, const double xl)
{
  get_momentum_for_fftw((double *) p, p.size(), xl);
}