#inlcude "cudahmm.h"

__device__ float cuda_gaussian( float *data, cuda_gm *gm, float *tbuff,
                                int size )
{
  for(int i = 0; i < size; i++)
    tbuff[i] = data[i] - gm->mean[i];
  float ts, t;
  t = 0;
  for(int i = 0; i < size; i++)
    {
      ts = 0;
      for(int j = 0; j < size; j++)
        ts = ts + tbuff[j] * gm->ichol[j * size + i];
      t = t + pow(ts, 2);
    }
  float res = exp(gm->gc - 0.5*t);
  return res;
}

int load_cuda_data( cuda_cpu_seq *cpu_data, cuda_train_set **cuda_data  )
{
  cuda_train_set *ts;
  cudaMalloc( (void**) &ts, sizeof(cuda_train_set) );
  cudaMemcpy( &(ts->size), &(cpu_data->numsamples), sizeof(int), cudaMemcpyHostToDevice );
  cudaMemcpy( &(ts->featuresize), &(cpu_data->featuresize), sizeof(int), cudaMemcpyHostToDevice );
  float **cuda_memlocs;
  cuda_memlocs = new float* [cpu_data->numsamples];
  for( int i = 0; i < cpu_data->numsamples; i++ )
    {
      float *cuda_t;
      cudaMalloc( (void**) &cuda_t, sizeof(float)*(cpu_data->seqs[i]->numsamples)*cpu_data->featuresize );
      cuda_memlocs[i] = cuda_t;
      cudaMemcpy( &cuda_t, cpu_data->seq[i]->time_series,
                  sizeof(float)*(cpu_data->seqs[i]->numsamples)*cpu_data->featuresize,
                  cudaMemcpyHostToDevice);
    }
  float **cuda_tmp;
  cudaMalloc( (void**) &cuda_tmp, sizeof( float* )*cpu_data->numsamples );
  cudaMemcpy( cuda_tmp, cuda_memlocs, sizeof( float* )*cpu_data->numsamples,
              cudaMemcpyHostToDevice );
  cudaMemcpy( cuda_tmp->seqs, cuda_tmp, sizeof( float* ) );
  delete [] cuda_memlocs;
  return 0;
}

int load_cuda_model( cuda_hmmmodel *cpu_model, cuda_hmmmodel **cuda_model )
{
  return 0;
}

int start_cuda_estep( cuda_train_set *cuda_data, cuda_hmmmodel *cuda_model )
{
  return 0;
}

int get_cuda_estep( cuda_hmmodel *cpu_model, cuda_train_set *cuda_data )
{
  return 0;
}
