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

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

using std::vector;
using std::fabs;
using std::runtime_error;
using std::logic_error;

static inline double SUM(vector<SArray const *> const &par)
{
    return *par[0]->value() + *par[1]->value();
}

DSum::DSum()
  : Distribution("dsum", 2, false, true)
{
}

DSum::~DSum()
{}

bool DSum::checkParameterValue(vector<SArray const *> const &par) const
{
  return true;
}

bool DSum::checkParameterDim(vector<SArray const *> const &par) const
{
    for (unsigned int i = 0; i < 2; ++i) {
	if (par[i]->length() != 1 || !par[i]->isDiscreteValued())
	    return false;
    }
    
    return true;
}

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

double DSum::logLikelihood(SArray const &x, 
			   vector<SArray const *> const &par) const
{
    if (fabs(*x.value() - SUM(par)) > 16*DBL_EPSILON) {
	// If this happens by accident, you have no chance of getting it right
	throw runtime_error("Inconsistent arguments for dsum");
    }
    
    return 0;
}

void
DSum::randomSample(SArray &x, vector<SArray const *> const &par) const
{
    // The random sample from DSum is not random at all, but
    // deterministic.
  
    x.setValue(SUM(par), 0);
}

unsigned long DSum::df(std::vector<SArray const *> const &par) const
{
    return 0;
}

double 
DSum::lowerSupport(unsigned long i,
		   std::vector<SArray const *> const &par) const
{
    if (i != 0)
	throw logic_error("Invalid index in DSum::lowerSupport");
    
    return SUM(par);
}


double 
DSum::upperSupport(unsigned long i,
		   std::vector<SArray const *> const &par) const
{
    if (i != 0)
	throw logic_error("Invalid index in DSum::upperSupport");
    
    return SUM(par);
}


syntax highlighted by Code2HTML, v. 0.9.1