void Permutation::invert(Permutation& result) const {
     // Rem: this is coherent with the convention 
     // size()==0 <=> this is the identity permutation
     result.allocate(size()) ;
     for(index_t i=0; i<size(); i++) {
         result[(*this)[i]] = i ;
     }
 }
 static void compute_permutation(const SparseMatrix& A, Permutation& permutation) {
     permutation.allocate(A.n()) ;
     bool RCMK = false ;
     if(RCMK) {
         SparseMatrixPatternCRS A_pattern ;
         ::OGF::convert_matrix(A, A_pattern) ;
         A_pattern.compute_RCMK_ordering(permutation) ;
         if(true) {
             std::cerr << "Bandwidth before permutation: " << A_pattern.bandwidth() << std::endl ;
             SparseMatrixCRS<double> A_crs ;
             ::OGF::convert_matrix(A, A_crs, true, permutation) ;            
             std::cerr << "Bandwidth after permutation: " << A_crs.bandwidth() << std::endl ;
         }
     } else {
         permutation.load_identity() ;
     }
 }
    void SparseMatrixPatternCRS::compute_RCMK_ordering(Permutation& result) {
        gx_assert(m() == n()) ;
        
        if(symmetric_storage) {
  	    std::cerr << "RCMK: Expanding symmetric storage" << std::endl ;
            SparseMatrixPatternCRS temp ;
            expand_symmetric_pattern(temp) ;
            temp.compute_RCMK_ordering(result) ;
            return ;
        }

        index_t cur_id = n()-1 ;
        result.allocate(n()) ;
        result.set_all(NO_INDEX) ;
        Permutation dist ;
        dist.allocate(n()) ;

        // Note: the graph of the matrix may
        // have multiple connected component,
        // therefore we need this outer loop.
        for(index_t x=0; x<n(); x++) {
            if(result[x] != NO_INDEX) { continue ; }

            std::deque<index_t> Q ;

            signed_index_t r ;
            while((r = find_furthest_node(x, dist)) != -1) {  x = r ;  }

            index_t seed = x ;

            Q.push_back(seed) ;
            result[seed] = cur_id-- ;

            while(!Q.empty()) {
                index_t cur = Q.front() ;
                Q.pop_front() ;
                
                std::vector<index_t> neighbors ;
                for(index_t jj=rowptr[cur]; jj < rowptr[cur+1]; jj++) {
                    index_t j = colind[jj] ;
                    if(result[j] == NO_INDEX) {
                        neighbors.push_back(j) ;
                    }
                }
                
                std::sort(neighbors.begin(), neighbors.end(), CompareDegree(this)) ;
                for(index_t k=0; k<neighbors.size(); k++) {
                    index_t nn = neighbors[k] ;
                    result[nn] = cur_id-- ; 
                    Q.push_back(nn) ;
                }
            }
        }

        // sanity check
        for(index_t i=0; i<n(); i++) {
	   if(result[i] == NO_INDEX) {
	      result[i] = cur_id-- ;
	   }
	}
    }