
// author: N. Matloff

// Rth implementation of Kendall's tau

// assumes continuous variables, no ties of any kind

extern "C" void rthkendall(double *x, int *nx, double *tau);

#include <thrust/device_vector.h>

typedef thrust::device_vector<int> intvec;
typedef thrust::device_vector<double> doubvec;

struct calcgti {
   doubvec dxy;
   int n;
   double *wdxy;
   calcgti(doubvec _dxy,int _n) :
      dxy(_dxy),
      n(_n)
      {  wdxy = thrust::raw_pointer_cast(&dxy[0]);  }
   __device__
   int operator()(int i)
   {  double xi = wdxy[i], yi = wdxy[i+n];
      int j,count=0;
      for (j = i+1; j < n; j++)
         count += ( (xi - wdxy[j]) * (yi - wdxy[j+n]) > 0);
      return count;
   }
};

void rthkendall(double *xy, int *nxy, double *tau)
{  int i,n = *nxy, n2 = 2*n;
   thrust::counting_iterator<int> seqa(0);
   thrust::counting_iterator<int> seqb =  seqa + n - 1;
   doubvec dxy(xy,xy+n2);
   intvec tmp(n-1);
   thrust::transform(seqa,seqb,tmp.begin(),calcgti(dxy,n));
   int totcount = thrust::reduce(tmp.begin(),tmp.end());
   double npairs = n * (n-1) / 2;
   *tau = (totcount - (npairs-totcount)) / npairs;
}

// #include <stdio.h>
// int main(int argc, char **argv)
// {
//    double xy[12] = {3,5.01,12,6,5,15,7,8,4.01,10,4,16};
//    int nxy = 6;
//    double tau;
//    rthkendall(xy,&nxy,&tau);
//    printf("%f\n",tau);  // should be 0.46667
// }

