
// author: N. Matloff

// Rth replacements for R order(), rank()

#include <thrust/device_vector.h>
#include <thrust/sequence.h>
#include <thrust/sort.h>

#include <Rcpp.h>

typedef thrust::device_vector<int> intvec;
typedef thrust::device_vector<double> doublevec;
typedef intvec::iterator intveciter;
typedef doublevec::iterator doubleveciter;

// returns order(x) in out, unless *rnk=TRUE, in which case 
// rank(x) is returned
//
// x is overwritten
RcppExport SEXP rthorder(SEXP x, SEXP rnk) 
{  
   Rcpp::NumericVector rx = Rcpp::NumericVector(x);
   int n = rx.size();
   bool rank = Rcpp::as<bool>(rnk);
   doublevec dx(rx.begin(),rx.end());
   intvec seq(n);
   thrust::sequence(seq.begin(),seq.end());
   thrust::sort_by_key(dx.begin(),dx.end(),seq.begin());
   if (!rank) thrust::copy(seq.begin(),seq.end(),rx.begin());
   else {
      thrust::counting_iterator<int> seqa(0);
      thrust::counting_iterator<int> seqb =  seqa + n;
      intvec locout(n);
      thrust::scatter(seqa,seqb,seq.begin(),locout.begin()); 
      thrust::copy(locout.begin(),locout.end(),rx.begin());
   }
   return rx;
}



