#include "exo03func.hpp"
#include "InitArray.hpp"

void InitData(int argc, char** argv,
              char *&typeChoice,ReduceType &datatype,
              int &size, int &maxThreads,
	      int &maxBlocks, int &cpuFinalThreshold
	     ){
  cutGetCmdLineArgumentstr( argc, (const char**) argv, "type", &typeChoice);

  if (0 == typeChoice){
    typeChoice = (char*)malloc(4 * sizeof(char));
    strcpy(typeChoice, "int");
  }

  if (!strcasecmp(typeChoice, "float"))
    datatype = REDUCE_FLOAT;
  else if (!strcasecmp(typeChoice, "double"))
    datatype = REDUCE_DOUBLE;
  else
    datatype = REDUCE_INT;  //default
	     
  cutGetCmdLineArgumenti( argc, (const char**) argv, "n", &size);
  cutGetCmdLineArgumenti( argc, (const char**) argv, "threads", &maxThreads);
  cutGetCmdLineArgumenti( argc, (const char**) argv, "maxblocks", &maxBlocks);
  cutGetCmdLineArgumenti( argc, (const char**) argv, "cputhresh", &cpuFinalThreshold);
}

void InitDevice(int argc, char** argv, ReduceType datatype){
  cudaDeviceProp deviceProp;
  deviceProp.major = 1;
  deviceProp.minor = 0;
  int minimumComputeVersion = 10;

  if (datatype == REDUCE_DOUBLE){
    deviceProp.minor = 3;
    minimumComputeVersion = 13;
  }

  int dev;

  if( cutCheckCmdLineFlag(argc, (const char**)argv, "device") ){
    cutilDeviceInit(argc, argv);
    cutilSafeCallNoSync(cudaGetDevice(&dev));
  }else
     cutilSafeCallNoSync(cudaChooseDevice(&dev, &deviceProp));
    
  cutilSafeCallNoSync(cudaGetDeviceProperties(&deviceProp, dev));

  if((deviceProp.major * 10 + deviceProp.minor) >= minimumComputeVersion){
    shrLog("Using Device %d: %s\n\n", dev, deviceProp.name);
    cutilSafeCallNoSync(cudaSetDevice(dev));
  }else{
    shrLog("Error: the selected device does not support compute capability %d.%d.\n\n",
           minimumComputeVersion / 10, minimumComputeVersion % 10);
    shrLog("FAILED");
    cudaThreadExit();
    cutilExit(argc, argv);
  }   
}

////////////////////////////////////////////////////////////////////////////////
// Instanciation explicite de runExo03
////////////////////////////////////////////////////////////////////////////////

template void
runExo03<int>( ReduceType datatype,
              int size, int maxThreads,
	      int maxBlocks, int cpuFinalThreshold);
	      
template void
runExo03<float>( ReduceType datatype,
              int size, int maxThreads,
	      int maxBlocks, int cpuFinalThreshold);
	      
template void
runExo03<double>( ReduceType datatype,
              int size, int maxThreads,
	      int maxBlocks, int cpuFinalThreshold);
