Files
Upsilon/apps/probability/distribution/fisher_distribution.cpp
Arthur Camouseigt 018dd91ca1 [Probability] Changed distribution parameter's type to double
Plots are still rendered in float but computations are now in double

Change-Id: I7e0a38effb780861b1443ee92a097cd319de3bc8
2020-11-04 14:45:35 +01:00

87 lines
2.6 KiB
C++

#include "fisher_distribution.h"
#include <poincare/beta_function.h>
#include <poincare/regularized_incomplete_beta_function.h>
#include <cmath>
#include <float.h>
#include <algorithm>
namespace Probability {
float FisherDistribution::xMin() const {
return -k_displayLeftMarginRatio * xMax();
}
float FisherDistribution::xMax() const {
return 5.0f; // The mode is always < 1
}
float FisherDistribution::yMax() const {
const float m = mode();
float max = std::isnan(m) ? k_defaultMax : evaluateAtAbscissa(m);
max = std::isnan(max) ? k_defaultMax : max;
return max * (1.0f + k_displayTopMarginRatio);
}
I18n::Message FisherDistribution::parameterNameAtIndex(int index) {
if (index == 0) {
return I18n::Message::D1;
}
assert(index == 1);
return I18n::Message::D2;
}
I18n::Message FisherDistribution::parameterDefinitionAtIndex(int index) {
if (index == 0) {
return I18n::Message::D1FisherDefinition;
}
assert(index == 1);
return I18n::Message::D2FisherDefinition;
}
float FisherDistribution::evaluateAtAbscissa(float x) const {
if (x < 0.0f) {
return NAN;
}
const float d1 = m_parameter1;
const float d2 = m_parameter2;
const float f = d1*x/(d1*x+d2);
const float numerator = std::pow(f, d1/2.0f) * std::pow(1.0f - f, d2/2.0f);
const float denominator = x * Poincare::BetaFunction(d1/2.0f, d2/2.0f);
return numerator / denominator;
}
bool FisherDistribution::authorizedValueAtIndex(float x, int index) const {
assert(index == 0 || index == 1);
return x > FLT_MIN && x <= k_maxParameter;
}
void FisherDistribution::setParameterAtIndex(float f, int index) {
TwoParameterDistribution::setParameterAtIndex(f, index);
}
double FisherDistribution::cumulativeDistributiveFunctionAtAbscissa(double x) const {
return Poincare::RegularizedIncompleteBetaFunction(m_parameter1/2.0, m_parameter2/2.0, m_parameter1*x/(m_parameter1*x+m_parameter2));
}
double FisherDistribution::cumulativeDistributiveInverseForProbability(double * probability) {
/* We have to compute the values of the interval in which to look for x.
* We cannot put xMin because xMin is < 0 for display purposes, and negative
* values are not accepted.
* The maximum of the interval: we want */
if (*probability < DBL_EPSILON) {
return 0.0;
}
return cumulativeDistributiveInverseForProbabilityUsingIncreasingFunctionRoot(probability, DBL_EPSILON, std::max<double>(xMax(), 100.0)); // Ad-hoc value;
}
float FisherDistribution::mode() const {
const float d1 = m_parameter1;
if (d1 > 2.0f) {
const float d2 = m_parameter2;
return (d1 - 2.0f)/d1 * d2/(d2 + 2.0f);
}
return NAN;
}
}