#ifndef __FILE_PFMOD_H_SEEN__
#define __FILE_PFMOD_H_SEEN__ 

/*-----------------------------------------------------------------------------

Copyright (C) 2014

A. Ronald Gallant
Post Office Box 659
Chapel Hill NC 27514-0659
USA   

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

-------------------------------------------------------------------------------

This is part of an implementation of the generic sequential Monte Carlo 
algorithm and the conditional sequential Monte Carlo update described 
in Andrieu, C., A. Douced, and R. Holenstein (2010), "Particle Markov Chain 
Monte Carlo Methods," Journal of the Royal Statistical Society, Series B, 
72, 269--342.

Usage is described in the header particles.h.

-----------------------------------------------------------------------------*/

#include "libscl.h"
#include "particles.h"

struct sample {
  scl::realmat X;
  scl::realmat Y;
  scl::realmat X0_Y0;
  scl::realmat Mean_X0_Y0;
  scl::realmat Var_X0_Y0;
};

class pfmod : public scl::pfmod_base {
private:
  REAL a0,a1;
  REAL b01,b02;
  REAL b11,b21,b12,b22;
  REAL r11,r21,r22,r31,r32,r33;
  INTEGER xdim, xlag;
  INTEGER ydim, ylag;
  scl::denval psave;
  scl::realmat Mean_X0_Y0;
  scl::realmat Var_X0_Y0;
public:
  pfmod() 
  : a0(0), a1(0.1), 
    b01(0), b02(0), 
    b11(0.01), b21(0.0), b12(0.0), b22(0.9), 
    r11(0.25), r21(0.0), r22(0.25), r31(0.01), r32(0.0), r33(0.5), 
    xdim(2), xlag(1), ydim(1), ylag(1), psave() 
    { scl::realmat theta = get_parms(); set_parms(theta); }
  void set_parms(const scl::realmat& theta); 
  scl::realmat get_parms();
  void q_draw_x0_y0(scl::particles* pf, INT_32BIT& seed);
  scl::denval q_prob_x0_y0(scl::particles* pf);
  scl::denval p_prob_x0_y0(scl::particles* pf);
  void q_draw_xt(scl::particles* pf, INT_32BIT& seed);
  scl::denval q_prob_xt(scl::particles* pf);
  scl::denval p_prob_xt(scl::particles* pf);
  scl::denval p_prob_yt(scl::particles* pf); 
  INTEGER get_xdim() {return xdim;}
  INTEGER get_xlag() {return xlag;}
  INTEGER get_ydim() {return ydim;}
  INTEGER get_ylag() {return ylag;}
  sample draw_sample(INTEGER T, INT_32BIT& seed);
};

#endif

