Files
Upsilon/apps/probability/distribution/student_distribution.cpp
2019-08-20 17:16:19 +02:00

61 lines
1.8 KiB
C++

#include "student_distribution.h"
#include "incomplete_beta_function.h"
#include "helper.h"
#include <cmath>
namespace Probability {
float StudentDistribution::xMin() const {
return -xMax();
}
float StudentDistribution::xMax() const {
return 5.0f;
}
float StudentDistribution::yMax() const {
return coefficient() * (1.0f + k_displayTopMarginRatio);
}
float StudentDistribution::evaluateAtAbscissa(float x) const {
const float d = m_parameter1;
return coefficient() * std::pow(1+std::pow(x,2)/d, -(d+1)/2);
}
bool StudentDistribution::authorizedValueAtIndex(float x, int index) const {
return x >= FLT_EPSILON;
}
double StudentDistribution::cumulativeDistributiveFunctionAtAbscissa(double x) const {
if (x == 0) {
return 0.5;
}
/* TODO There are some computation errors, where the probability falsly jumps to 1.
* k = 0.001 and P(x < 42000000) (for 41000000 it is around 0.5)
* k = 0.01 and P(x < 8400000) (for 41000000 it is around 0.6) */
const float k = m_parameter1;
const double sqrtXSquaredPlusK = std::sqrt(x*x + k);
double t = (x + sqrtXSquaredPlusK) / (2.0 * sqrtXSquaredPlusK);
return IncompleteBetaFunction(k/2.0, k/2.0, t);
}
double StudentDistribution::cumulativeDistributiveInverseForProbability(double * probability) {
if (*probability == 0.5) {
return 0.0;
}
const double small = DBL_EPSILON;
const double standardBig = 10000.0;
const double big = m_parameter1 >= 1 ? standardBig : standardBig / m_parameter1;
double xmin = *probability < 0.5 ? -big : small;
double xmax = *probability < 0.5 ? -small : big;
return cumulativeDistributiveInverseForProbabilityUsingIncreasingFunctionRoot(probability, xmin, xmax);
}
float StudentDistribution::coefficient() const {
const float k = m_parameter1;
const float lnOfResult = std::lgamma((k+1)/2) - std::lgamma(k/2) - (M_PI+k)/2;
return std::exp(lnOfResult);
}
}