// cMCMCquantreg.cc is a function that draws from the posterior
// distribution of a linear regression model with errors having tauth quantile equal to zero.
//
// The initial version of this file was generated by the
// auto.Scythe.call() function in the MCMCpack R package
// written by:
//
// Andrew D. Martin
// Dept. of Political Science
// Washington University in St. Louis
// admartin@wustl.edu
//
// Kevin M. Quinn
// Dept. of Government
// Harvard University
// kevin_quinn@harvard.edu
//
// This software is distributed under the terms of the GNU GENERAL
// PUBLIC LICENSE Version 2, June 1991.  See the package LICENSE
// file for more information.
//
// Copyright (C) 2009 Andrew D. Martin and Kevin M. Quinn
//
// This file was initially generated on Wed Apr  1 11:39:12 2009
//
// The function was rewritten by:
//
// Craig Reed
// Department of Mathematical Sciences
// Brunel University
// craig.reed@brunel.ac.uk
//
// CR 9/4/09 [Rewritten function using templates]
//
// CR 7/12/09 [Placed MCMCmedreg within MCMCquantreg]

#ifndef CMCMCQUANTREG_CC
#define CMCMCQUANTREG_CC

#include "MCMCrng.h"
#include "MCMCfcds.h"
#include "matrix.h"
#include "distributions.h"
#include "stat.h"
#include "la.h"
#include "ide.h"
#include "smath.h"
#include "rng.h"

#include <R.h>           // needed to use Rprintf()
#include <R_ext/Utils.h> // needed to allow user interrupts

using namespace std;
using namespace scythe;

/* MCMCquantreg implementation.  Takes Matrix<> reference which it
 * fills with the posterior.
 */
template <typename RNGTYPE>
void MCMCquantreg_impl (rng<RNGTYPE>& stream, double tau, Matrix<>& Y,
    const Matrix<>& X, Matrix<>& beta, const Matrix<>& b0,
    const Matrix<>& B0,
    unsigned int burnin, unsigned int mcmc, unsigned int thin,
    unsigned int verbose,
    Matrix<>& result)
{
   // define constants
   const unsigned int tot_iter = burnin + mcmc; //total iterations
   const unsigned int nstore = mcmc / thin; // number of draws to store
   const unsigned int k = X.cols ();

   // storage matrices
   Matrix<> betamatrix (k, nstore);

   // Gibbs sampler
   unsigned int count = 0;
   for (unsigned int iter = 0; iter < tot_iter; ++iter) {
     Matrix<> e = gaxpy(X, (-1*beta), Y);
     Matrix<> abse = fabs(e);
     Matrix<> weights = ALaplaceIGaussregress_weights_draw (abse, stream);
     beta = ALaplaceNormregress_beta_draw (tau, X, Y, weights, b0, B0, stream);

     // store draws in storage matrix
     if (iter >= burnin && (iter % thin == 0)) {
       betamatrix(_, count) = beta;
       ++count;
     }

     // print output to stdout
     if(verbose > 0 && iter % verbose == 0) {
       Rprintf("\n\nMCMCquantreg iteration %i of %i \n",
         (iter+1), tot_iter);
       Rprintf("beta = \n");
       for (unsigned int j=0; j<k; ++j)
         Rprintf("%10.5f\n", beta(j));
     }

     R_CheckUserInterrupt(); // allow user interrupts

   } // end MCMC loop

   result = t(betamatrix);
 } // end MCMCquantreg_impl

extern "C" {
   void cMCMCquantreg(double *sampledata, const int *samplerow,
		    const int *samplecol, const double *tau, const double *Ydata, const int *Yrow,
		    const int *Ycol, const double *Xdata, const int *Xrow,
		    const int *Xcol, const int *burnin, const int *mcmc,
		    const int *thin, const int *uselecuyer, const int *seedarray,
		    const int *lecuyerstream, const int *verbose,
		    const double *betastartdata, const int *betastartrow,
		    const int *betastartcol, const double *b0data,
		    const int *b0row, const int *b0col,
		    const double *B0data, const int *B0row,
		    const int *B0col)
   {
     // pull together Matrix objects
     Matrix<> Y(*Yrow, *Ycol, Ydata);
     Matrix<> X(*Xrow, *Xcol, Xdata);
     Matrix<> betastart(*betastartrow, *betastartcol, betastartdata);
     Matrix<> b0(*b0row, *b0col, b0data);
     Matrix<> B0(*B0row, *B0col, B0data);

     Matrix<> storagematrix;
     MCMCPACK_PASSRNG2MODEL(MCMCquantreg_impl, *tau, Y, X, betastart, b0, B0,
                            *burnin, *mcmc, *thin, *verbose,
                            storagematrix);

     const unsigned int size = *samplerow * *samplecol;
     for (unsigned int i = 0; i < size; ++i)
       sampledata[i] = storagematrix(i);
   }
}

#endif
