#ifndef __FILE_LIBSMM_BASE_H_SEEN__
#define __FILE_LIBSMM_BASE_H_SEEN__ 

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

Copyright (C) 2004, 2005, 2006, 2007.

A. Ronald Gallant

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.

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

#include "libscl.h" 

namespace libsmm {

/* Now in libscl

struct den_val {
  bool    positive;
  REAL    log_den;
          den_val() : positive(false), log_den(-REAL_MAX) { }  
          den_val(bool p, REAL l) : positive(p), log_den(l) { }  
  den_val operator+=(den_val f) 
  { 
    positive = positive && f.positive; 
    if (positive) log_den += f.log_den; 
    else  log_den = -REAL_MAX;
    return *this;
  }
};

*/

class usrmod_base {
public:
  virtual INTEGER len_rho() = 0;
  virtual INTEGER len_stats() = 0;
  virtual bool gen_sim(scl::realmat& sim, scl::realmat& stats) = 0; 
    //Same seed every call
  virtual void get_rho(scl::realmat& rho) = 0;
  virtual void set_rho(const scl::realmat& rho) = 0;
  virtual bool support(const scl::realmat& rho) = 0;
  virtual scl::den_val prior(const scl::realmat& rho, 
    const scl::realmat& stats) = 0;
  virtual void write_usrvar(const char* filename) { return; }
  virtual ~usrmod_base() {}
  virtual bool gen_bootstrap(std::vector<scl::realmat>& bs)  
    //New seed each call
    {scl::error("Error, libsmm, usrmod::bootstrap not coded");
    return false;}
  virtual void set_data(const scl::realmat& dat) 
    {scl::error("Error, libsmm, usrmod::set_data not coded");}
  virtual scl::den_val likelihood(scl::realmat& predicted, 
    scl::realmat& residuals)
    {scl::error("Error, libsmm, usrmod::likelihood not coded");
    return scl::den_val(false,-REAL_MAX);}
};
  
struct prop_group {
  REAL    freq;        // Relative probability of choosing this group
  scl::intvec  gvec;   // Contains indexes of group memebers 
  scl::realmat ginc;   // Increment of group, (fractional) power of two.
  scl::realmat mean;   // Mean vector of group, not used by r.w. props.
  scl::realmat Vmat;   // Variance matrix of group
  prop_group() : freq(1), gvec(), mean(), Vmat() { }
  prop_group(REAL f, const scl::intvec& gv, const scl::realmat& gi,
    const scl::realmat& u, const scl::realmat& V)
    : freq(f), gvec(gv), ginc(gi), mean(u), Vmat(V) { }
};

typedef std::vector<prop_group> prop_def;

class proposal_base {
public:
  virtual scl::den_val operator()(const scl::realmat& th_old, 
    const scl::realmat& th_new)=0;
  virtual void draw(INT_32BIT& seed, const scl::realmat& th_old,
    scl::realmat& th_new)=0;
  virtual INTEGER len_rho()=0;
  virtual bool transition_is_symmetric() { return false; }
  virtual ~proposal_base() {};
};

class objfun_base {
private:
  void required() const 
    { scl::error("Error, objfun_base, derived class must overide"); }
public:
  virtual void set_data(const scl::realmat& boot_dat) {required();}
  virtual REAL operator()(const scl::realmat& rho, 
    const scl::realmat& sim, const scl::realmat& stats) const 
    { required(); return 0; }
  virtual bool write_diagnostics(const char* filename) const {return true;}
  virtual objfun_base* new_objfun() { required(); return 0; } 
  virtual void delete_objfun(objfun_base*) { required(); }
  virtual ~objfun_base() {};
};

class cachemgr_base {
public:
  virtual scl::den_val operator()(const scl::realmat& rho, 
    scl::realmat& stats) = 0; 
  virtual INTEGER len_rho() = 0;
  virtual INTEGER len_stats() = 0;
  virtual ~cachemgr_base() {};
};

class asymptotics_base {
public:
  virtual bool set_asymptotics(const scl::realmat& sim) = 0;
  virtual void get_asymptotics(scl::realmat& rho_hat, 
    scl::realmat& V_hat, INTEGER& n) = 0;
  virtual void get_asymptotics(scl::realmat& rho_mean, 
    scl::realmat& rho_mode, REAL& post_high, scl::realmat& I, 
    scl::realmat& invJ, scl::realmat& foc_hat, INTEGER& reps) = 0;
  virtual ~asymptotics_base() {};
};

class mcmc_base {
public:
  virtual scl::realmat draw(INT_32BIT& seed, scl::realmat& rho_start,
    scl::realmat& rho_sim, scl::realmat& stats_sim, 
    scl::realmat& pi_sim) = 0;
  virtual void set_simulation_size(INTEGER n) = 0;
  virtual void set_stride(INTEGER k) = 0;
  virtual void set_draw_from_posterior(bool from_posterior) = 0;
  virtual void set_temp(REAL temperature) = 0;
  virtual REAL get_temp() = 0;
  virtual scl::realmat get_mode() = 0;    // Returns mode of posterior
  virtual REAL get_high() = 0;    // Returns posterior at mode
  virtual ~mcmc_base() {};
};

}

#endif
