#include <config.h>
#include <distributions/DistScalar.h>
#include <sarray/SArray.h>

#include <stdexcept>
#include <cfloat>
#include <cmath>
#include <algorithm>

#include <Rmath.h>

using std::max;
using std::min;
using std::string;
using std::vector;
using std::length_error;
using std::logic_error;


DistScalar::DistScalar(string const &name, unsigned int npar, Support support, 
		       bool canbound, bool discrete)
  
  : Distribution(name, npar + 2*canbound, canbound, discrete), 
    _support(support)
{
}

double 
DistScalar::lowerSupport(unsigned long i,
			 vector<SArray const *> const &parameters) const
{
  if (i != 0) {
    throw logic_error("Invalid index in Distreal::lowerSupport");
  }

  SArray const *lb = lowerBound(parameters);
  if (lb) {
    return max(l(parameters), *lb->value());
  }
  else {
    return l(parameters);
  }
}

double
DistScalar::upperSupport(unsigned long i,
			 vector<SArray const *> const &parameters) const
{
  if (i != 0) {
    throw logic_error("Invalid index in Distreal::upperSupport");
  }

  SArray const *ub = upperBound(parameters);
  if (ub) {
    return min(u(parameters), *ub->value());
  }
  else {
    return u(parameters);
  }
}

unsigned long DistScalar::df(vector<SArray const *> const &parameters) const
{
  return 1;
}

Index const &
DistScalar::dim(vector<SArray const *> const &parameters) const
{
    static const Index ScalarIndex(1);
    return ScalarIndex;
}

double DistScalar::l(vector<SArray const *> const &parameters) const
{
  switch(_support) {
  case DIST_UNBOUNDED:
      return -DBL_MAX;
      break;
  case DIST_POSITIVE: case DIST_PROPORTION:
      return 0;
      break;
  case DIST_SPECIAL:
      //You must overload this function 
      throw logic_error("Cannot call DistScalar::l for special distribution");
  }
  return 0; //Wall
      
}

double DistScalar::u(vector<SArray const *> const &parameters) const
{
  switch(_support) {
  case DIST_UNBOUNDED: case DIST_POSITIVE:
    return DBL_MAX;
    break;
  case DIST_PROPORTION:
    return 1;
    break;
  case DIST_SPECIAL:
    //You must overload this function 
    throw logic_error("Cannot call DistScalar::u for special distribution");
  }
  return 0; //Wall
}


syntax highlighted by Code2HTML, v. 0.9.1