/*********************************************************
** Copyright (c) 2005
** University of Washington
** Licensed under the terms set forth by University of
** Washington. If you did not sign such a license, you
** are using this software/code illegally and you do not
** have permission to use, modify, or redistribute
** this or any files in this software package.
**
** File: OdpThread.h   $Revision: 242 $
**
**********************************************************/
#ifndef ODPTHREAD_H
#define ODPTHREAD_H

#include "R.h"
#include "Rdefines.h"
#include "Rinternals.h"

#include "ProgressThread.h"
#include <assert.h>

/*
 * Class for computing the ODP algorithm using threads.
 * This class does the work of threading; all the computation
 * is done by original ODP functions in edge.c
 */
class COdpThread : public CProgressThread
{
 public:
  /*
   * Constructs a COdpThread object.
   * Arguments: (see original ODP functions in edge.c)
   *   pSumDat, sumdatlen: Pointer to and length of []
   *   [todo...]
   */

  COdpThread(SEXP arglist) {
     SEXP arg;
// arglist is a list containing: 
// B, updatefunc, finalfunc, printmsg, grp, match, dat, startTime, xx, xk, 
// mu, sigma, sigma0, muBS, sigmaBS, sigma0BS, ID, n.grp, res, vv, 
// nii, m, n, k, B, m0, lr, pvals

     assert(length(arglist)>=24);
// make debug will #define EDGE_DEBUG
#ifdef EDGE_DEBUG
#define xerr(a) cerr << #a "[0]=" << a[0] << "\n";
#define yerr(a) cerr << #a "=" << a << "\n";
     cerr << "length(arglist)" << length(arglist) << "\n";
#else
#define xerr(a)
#define yerr(a)
#endif

     arg=VECTOR_ELT(arglist,0);
     m_B=INTEGER(arg)[0];
yerr(m_B)
     arg=VECTOR_ELT(arglist,7);
     m_xxlen=length(arg);
     m_pXX=CopyVector(REAL(arg),m_xxlen);
xerr(m_pXX)
     arg=VECTOR_ELT(arglist,8);
     m_xklen=length(arg);
     m_pXK=CopyVector(REAL(arg),m_xklen);
xerr(m_pXK)
     arg=VECTOR_ELT(arglist,9);
     m_mulen=length(arg);
     m_pMu=CopyVector(REAL(arg),m_mulen);
xerr(m_pMu)
     arg=VECTOR_ELT(arglist,10);
     m_sigmalen=length(arg);
     m_pSigma=CopyVector(REAL(arg),m_sigmalen);
xerr(m_pSigma)
     arg=VECTOR_ELT(arglist,11);
     m_sigma0len=length(arg);
     m_pSigma0=CopyVector(REAL(arg),m_sigma0len);
xerr(m_pSigma0)
     arg=VECTOR_ELT(arglist,12);
     m_mubslen=length(arg);
     m_pMuBS=CopyVector(REAL(arg),m_mubslen);
xerr(m_pMuBS)
     arg=VECTOR_ELT(arglist,13);
     m_sigmabslen=length(arg);
     m_pSigmaBS=CopyVector(REAL(arg),m_sigmabslen);
xerr(m_pSigmaBS)
     arg=VECTOR_ELT(arglist,14);
     m_sigma0bslen=length(arg);
     m_pSigma0BS=CopyVector(REAL(arg),m_sigma0bslen);
xerr(m_pSigma0BS)
     arg=VECTOR_ELT(arglist,15);
     m_idlen=length(arg);
     m_pID=CopyVector(INTEGER(arg),m_idlen);
xerr(m_pID)
     arg=VECTOR_ELT(arglist,16);
     m_ngrplen=length(arg);
     m_pNGrp=CopyVector(INTEGER(arg),m_ngrplen);
xerr(m_pNGrp)
     arg=VECTOR_ELT(arglist,17);
     m_reslen=length(arg);
     m_pRes=CopyVector(REAL(arg),m_reslen);
xerr(m_pRes)
     arg=VECTOR_ELT(arglist,18);
     m_vvlen=length(arg);
     m_pVV=CopyVector(INTEGER(arg),m_vvlen);
xerr(m_pVV)
     arg=VECTOR_ELT(arglist,19);
     m_niilen=length(arg);
     m_pNii=CopyVector(INTEGER(arg),m_niilen);
xerr(m_pNii)

     arg=VECTOR_ELT(arglist,20);
     m_m=INTEGER(arg)[0];
yerr(m_m)
     arg=VECTOR_ELT(arglist,21);
     m_n=INTEGER(arg)[0];
yerr(m_n)
     arg=VECTOR_ELT(arglist,22);
     m_k=INTEGER(arg)[0];
yerr(m_k)
     arg=VECTOR_ELT(arglist,23);
     m_m0=INTEGER(arg)[0];
yerr(m_m0)

     m_observedResultSize = m_m;
     m_pObservedResult = new double[m_observedResultSize];

     m_nullResultSize = m_m0*m_B;
     m_pNullResult = new double[m_nullResultSize];

     assert(m_xxlen == m_m);
     assert(m_xklen == m_m*m_k);
    //    assert(mulen == m_m);
     assert(m_sigmalen == m_m);
     assert(m_idlen == m_n*m_k);
     assert(m_ngrplen == m_k);
     assert(m_reslen == m_m0*m_n);
     assert(m_vvlen == m_B*m_n);
  }
  virtual ~COdpThread();

  int Go(THREAD_ID_T tid);

  /* Accessors */
  int GetNullResultSize() { return m_nullResultSize; }
  double* GetNullResult() { return m_pNullResult; }
  int GetObservedResultSize() { return m_observedResultSize; }
  double* GetObservedResult() { return m_pObservedResult; }

 private:

  double* CopyVector(double* vec, int len);
  int* CopyVector(int* vec, int len);
  void DivideVector(double *pNum, double *pDenom, int len);

  private:
  double *m_pObservedResult;
  int m_observedResultSize;
  double *m_pNullResult;
  int m_nullResultSize;

  double *m_pXX; int m_xxlen;
  double *m_pXK; int m_xklen;
  double *m_pMu; int m_mulen;
  double *m_pSigma; int m_sigmalen;
  double *m_pSigma0; int m_sigma0len;
  double *m_pMuBS; int m_mubslen;
  double *m_pSigmaBS; int m_sigmabslen;
  double *m_pSigma0BS; int m_sigma0bslen;
  int *m_pID; int m_idlen;
  int *m_pNGrp; int m_ngrplen;
  double *m_pRes; int m_reslen;
  int *m_pVV; int m_vvlen;
  int *m_pNii; int m_niilen;
  long m_m;
  long m_n;
  long m_k;
  long m_B;
  long m_m0;
};

#endif
