#include <config.h>
#include <distributions/DCat.h>
#include <sarray/SArray.h>
#include <cfloat>
#include <algorithm>
#include <cmath>
#include <Rmath.h>
using std::min;
using std::max;
using std::vector;
DCat::DCat()
: DistDiscrete("dcat", 1, DIST_SPECIAL, true)
{}
DCat::~DCat()
{}
bool DCat::checkParameterDim(vector<SArray const *> const ¶meters) const
{
return parameters[0]->ndim(true) == 1 && parameters[0]->length() > 1;
}
bool DCat::checkParameterValue(vector<SArray const *> const ¶meters) const
{
double const *prob = parameters[0]->value();
long length = parameters[0]->length();
double sump = 0.0;
for (long i = 0; i < length; i++) {
if (prob[i] < 0.0 || prob[i] > 1.0) {
return false; // Invalid probability
}
sump += prob[i];
}
if (fabs(sump - 1.0) > 16*DBL_EPSILON)
return false; // Probabilities do not sum to 1
return true;
}
double DCat::l(vector<SArray const *> const ¶meters) const
{
return 1;
}
double DCat::u(vector<SArray const *> const ¶meters) const
{
return parameters[0]->length();
}
double DCat::d(double x, std::vector<SArray const *> const ¶meters,
bool give_log) const
{
double const *prob = parameters[0]->value();
long length = parameters[0]->length();
double value = 0;
long y = static_cast<long>(x);
if (y >= 1 && y <= length) {
value = prob[y-1];
}
if (give_log) {
return value == 0 ? -DBL_MAX : log(value);
}
else {
return value;
}
}
double DCat::p(double x, std::vector<SArray const *> const ¶meters,
bool lower, bool give_log) const
{
double const *prob = parameters[0]->value();
double sump = 0;
if (x > parameters[0]->length()) {
sump = 1;
}
else {
for (long i = 1; i <= x; ++i) {
sump += prob[i-1];
}
}
if (!lower) {
sump = max(1 - sump, 0.0);
}
if (give_log) {
return sump == 0 ? -DBL_MAX : log(sump);
}
else {
return sump;
}
}
double DCat::q(double p, std::vector<SArray const *> const ¶meters,
bool lower, bool log_p) const
{
if (log_p)
p = exp(p);
if (!lower)
p = 1 - p;
long length = parameters[0]->length();
double const *prob = parameters[0]->value();
double sump = 0;
for (long i = 1; i < length; ++i) {
sump += prob[i-1];
if (sump > p + 16*DBL_EPSILON)
return i;
}
return length;
}
double DCat::r(std::vector<SArray const *> const ¶meters) const
{
return q(runif(0,1), parameters, true, false);
}
double
DCat::mean(std::vector<SArray const *> const ¶meters) const
{
long length = parameters[0]->length();
double const *prob = parameters[0]->value();
double mean = 0;
for (long i = 0; i < length; ++i) {
mean += i * prob[i];
}
return mean + 1;
}
double
DCat::var(std::vector<SArray const *> const ¶meters) const
{
long length = parameters[0]->length();
double const *prob = parameters[0]->value();
double mean = 0;
for (long i = 0; i < length; ++i) {
mean += i * prob[i];
}
double var = 0;
for (long i = 0; i < length; ++i) {
var += (i - mean) * (i - mean) * prob[i];
}
return var;
}
syntax highlighted by Code2HTML, v. 0.9.1