
// Utilities and system includes
#include <shrUtils.h>
#include "cutil_inline.h"
#include <algorithm>

// includes, project
#include "MyReduction.hpp"

extern "C"
bool isPow2(unsigned int x)
{
    return ((x&(x-1))==0);
}

unsigned int nextPow2( unsigned int x ) {
    --x;
    x |= x >> 1;
    x |= x >> 2;
    x |= x >> 4;
    x |= x >> 8;
    x |= x >> 16;
    return ++x;
}

#define LOCMIN(x,y) ((x < y) ? x : y)

////////////////////////////////////////////////////////////////////////////////
// Compute the number of threads and blocks to use for the given reduction kernel
// For the kernels >= 3, we set threads / block to the minimum of maxThreads and
// n/2. For kernels < 3, we set to the minimum of maxThreads and n.  For kernel 
// 6, we observe the maximum specified number of blocks, because each thread in 
// that kernel can process a variable number of elements.
////////////////////////////////////////////////////////////////////////////////
void getNumBlocksAndThreads(int n, int maxBlocks, int maxThreads, int &blocks, int &threads)
{
  threads = (n < maxThreads*2) ? nextPow2((n + 1)/ 2) : maxThreads;
  blocks = (n + (threads * 2 - 1)) / (threads * 2);
  blocks = LOCMIN(maxBlocks, blocks);
}

// Instanciation

////////////////////////////////////////////////////////////////////////////////
// Instanciation explicite pour les types <int>, <float> et <double> de :
//   reduceGPU, reduceCPU, sumCPU
////////////////////////////////////////////////////////////////////////////////

template int reduceGPU<int>(int *d_idata, int  n,
                int  maxThreads,
                int  maxBlocks, 
                int  cpuFinalThreshold);

template float reduceGPU<float>(float *d_idata, int  n,
                int  maxThreads,
                int  maxBlocks, 
                int  cpuFinalThreshold);

template double reduceGPU<double>(double *d_idata, int  n,
                int  maxThreads,
                int  maxBlocks, 
                int  cpuFinalThreshold);
		

template int reduceCPU<int>(int *data, int size);

template float reduceCPU<float>(float *data, int size);

template double reduceCPU<double>(double *data, int size);

template int sumCPU<int>(int *data, int size);

template float sumCPU<float>(float *data, int size);

template double sumCPU<double>(double *data, int size);
