Blame view

emulateur/epsilon-nofrendo/apps/probability/law/binomial_law.cpp 3.72 KB
6663b6c9   adorian   projet complet av...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
  #include "binomial_law.h"
  #include <assert.h>
  #include <cmath>
  
  namespace Probability {
  
  BinomialLaw::BinomialLaw() :
    TwoParameterLaw(20.0, 0.5)
  {
  }
  
  I18n::Message BinomialLaw::title() {
    return I18n::Message::BinomialLaw;
  }
  
  Law::Type BinomialLaw::type() const {
    return Type::Binomial;
  }
  
  bool BinomialLaw::isContinuous() const {
    return false;
  }
  
  I18n::Message BinomialLaw::parameterNameAtIndex(int index) {
    assert(index >= 0 && index < 2);
    if (index == 0) {
      return I18n::Message::N;
    } else {
      return I18n::Message::P;
    }
  }
  
  I18n::Message BinomialLaw::parameterDefinitionAtIndex(int index) {
    assert(index >= 0 && index < 2);
    if (index == 0) {
      return I18n::Message::RepetitionNumber;
    } else {
      return I18n::Message::SuccessProbability;
    }
  }
  
  float BinomialLaw::xMin() {
    float min = 0.0f;
    float max = m_parameter1 > 0.0f ? m_parameter1 : 1.0f;
    return min - k_displayLeftMarginRatio * (max - min);
  }
  
  float BinomialLaw::xMax() {
    float min = 0.0f;
    float max = m_parameter1;
    if (max <= min) {
      max = min + 1.0f;
    }
    return max + k_displayRightMarginRatio*(max - min);
  }
  
  float BinomialLaw::yMin() {
    return -k_displayBottomMarginRatio*yMax();
  }
  
  float BinomialLaw::yMax() {
    int maxAbscissa = m_parameter2 < 1.0f ? (m_parameter1+1)*m_parameter2 : m_parameter1;
    float result = evaluateAtAbscissa(maxAbscissa);
    if (result <= 0.0f || std::isnan(result)) {
      result = 1.0f;
    }
    return result*(1.0f+ k_displayTopMarginRatio);
  }
  
  
  bool BinomialLaw::authorizedValueAtIndex(float x, int index) const {
    if (index == 0) {
      /* As the cumulative probability are computed by looping over all discrete
       * abscissa within the interesting range, the complexity of the cumulative
       * probability is linear with the size of the range. Here we cap the maximal
       * size of the range to 10000. If one day we want to increase or get rid of
       *  this cap, we should implement the explicite formula of the cumulative
       *  probability (which depends on an incomplete beta function) to make the
       *  comlexity O(1). */
      if (x != (int)x || x < 0.0f || x > 99999.0f) {
        return false;
      }
      return true;
    }
    if (x < 0.0f || x > 1.0f) {
      return false;
    }
    return true;
  }
  
  double BinomialLaw::cumulativeDistributiveInverseForProbability(double * probability) {
    if (m_parameter1 == 0.0 && (m_parameter2 == 0.0 || m_parameter2 == 1.0)) {
      return NAN;
    }
    if (*probability >= 1.0) {
      return m_parameter1;
    }
    return Law::cumulativeDistributiveInverseForProbability(probability);
  }
  
  double BinomialLaw::rightIntegralInverseForProbability(double * probability) {
    if (m_parameter1 == 0.0 && (m_parameter2 == 0.0 || m_parameter2 == 1.0)) {
      return NAN;
    }
    if (*probability <= 0.0) {
      return m_parameter1;
    }
    return Law::rightIntegralInverseForProbability(probability);
  }
  
  template<typename T>
  T BinomialLaw::templatedApproximateAtAbscissa(T x) const {
    if (m_parameter1 == 0) {
      if (m_parameter2 == 0 || m_parameter2 == 1) {
        return NAN;
      }
      if (floor(x) == 0) {
        return 1;
      }
      return 0;
    }
    if (m_parameter2 == 1) {
      if (floor(x) == m_parameter1) {
        return 1;
      }
      return 0;
    }
    if (m_parameter2 == 0) {
      if (floor(x) == 0) {
        return 1;
      }
      return 0;
    }
    if (x > m_parameter1) {
      return 0;
    }
    T lResult = std::lgamma((T)(m_parameter1+1.0)) - std::lgamma(std::floor(x)+(T)1.0) - std::lgamma((T)m_parameter1 - std::floor(x)+(T)1.0)+
      std::floor(x)*std::log((T)m_parameter2) + ((T)m_parameter1-std::floor(x))*std::log((T)(1.0-m_parameter2));
    return std::exp(lResult);
  }
  
  }
  
  template float Probability::BinomialLaw::templatedApproximateAtAbscissa(float x) const;
  template double Probability::BinomialLaw::templatedApproximateAtAbscissa(double x) const;