diff --git a/apps/probability/Makefile b/apps/probability/Makefile index c6c38066a..6d5880d95 100644 --- a/apps/probability/Makefile +++ b/apps/probability/Makefile @@ -2,13 +2,14 @@ apps += Probability::App app_headers += apps/probability/app.h app_probability_test_src = $(addprefix apps/probability/,\ + law/chi_squared_law.cpp \ law/erf_inv.cpp \ + law/geometric_law.cpp \ + law/helper.cpp \ law/incomplete_beta_function.cpp \ law/law.cpp \ law/regularized_gamma.cpp \ - law/chi_squared_law.cpp \ law/student_law.cpp \ - law/helper.cpp \ ) app_probability_src = $(addprefix apps/probability/,\ @@ -69,10 +70,12 @@ $(eval $(call depends_on_image,apps/probability/law_controller.cpp,$(addprefix a focused_binomial_icon.png \ focused_chi_squared_icon.png \ focused_exponential_icon.png \ + focused_geometric_icon.png \ focused_normal_icon.png \ focused_poisson_icon.png \ focused_student_icon.png \ focused_uniform_icon.png \ + geometric_icon.png \ normal_icon.png \ poisson_icon.png \ student_icon.png \ diff --git a/apps/probability/base.de.i18n b/apps/probability/base.de.i18n index afe497e89..d24c5648f 100644 --- a/apps/probability/base.de.i18n +++ b/apps/probability/base.de.i18n @@ -2,6 +2,7 @@ ProbaApp = "Wahrsch." ProbaAppCapital = "WAHRSCHEINLICHKEIT" ChooseLaw = "Wählen Sie eine Verteilung" Binomial = "Binomial" +Geometric = "Geometrische" Uniforme = "Uniform" Normal = "Normal" Poisson = "Poisson" @@ -10,6 +11,7 @@ Student = "Student" BinomialLaw = "Binomialverteilung" UniformLaw = "Uniformverteilung" ExponentialLaw = "Exponentialverteilung" +GeometricLaw = "Geometrischeverteilung" NormalLaw = "Normalverteilung" PoissonLaw = "Poisson-Verteilung" ChiSquaredLaw = "Chi-Quadrat-Verteilung" diff --git a/apps/probability/base.en.i18n b/apps/probability/base.en.i18n index 0d4e9b7c6..6d7b8b102 100644 --- a/apps/probability/base.en.i18n +++ b/apps/probability/base.en.i18n @@ -2,6 +2,7 @@ ProbaApp = "Probability" ProbaAppCapital = "PROBABILITY" ChooseLaw = "Choose the distribution" Binomial = "Binomial" +Geometric = "Geometric" Uniforme = "Uniform" Normal = "Normal" Poisson = "Poisson" @@ -10,6 +11,7 @@ Student = "Student" BinomialLaw = "Binomial distribution" UniformLaw = "Uniform distribution" ExponentialLaw = "Exponential distribution" +GeometricLaw = "Geometric distribution" NormalLaw = "Normal distribution" PoissonLaw = "Poisson distribution" ChiSquaredLaw = "Chi-squared distribution" diff --git a/apps/probability/base.es.i18n b/apps/probability/base.es.i18n index d184b1816..14024ab7f 100644 --- a/apps/probability/base.es.i18n +++ b/apps/probability/base.es.i18n @@ -2,6 +2,7 @@ ProbaApp = "Probabilidad" ProbaAppCapital = "PROBABILIDAD" ChooseLaw = "Seleccionar la distribución" Binomial = "Binomial" +Geometric = "Geométrica" Uniforme = "Uniforme" Normal = "Normal" Poisson = "Poisson" @@ -10,6 +11,7 @@ Student = "Student" BinomialLaw = "Distribución binomial" UniformLaw = "Distribución uniforme" ExponentialLaw = "Distribución exponencial" +GeometricLaw = "Distribución geométrica" NormalLaw = "Distribución normal" PoissonLaw = "Distribución de Poisson" ChiSquaredLaw = "Distribución chi-cuadrado" diff --git a/apps/probability/base.fr.i18n b/apps/probability/base.fr.i18n index 780fd51f9..6e35adf32 100644 --- a/apps/probability/base.fr.i18n +++ b/apps/probability/base.fr.i18n @@ -2,6 +2,7 @@ ProbaApp = "Probabilités" ProbaAppCapital = "PROBABILITÉS" ChooseLaw = "Choisir le type de loi" Binomial = "Binomiale" +Geometric = "Géométrique" Uniforme = "Uniforme" Normal = "Normale" Poisson = "Poisson" @@ -10,6 +11,7 @@ Student = "Student" BinomialLaw = "Loi binomiale" UniformLaw = "Loi uniforme" ExponentialLaw = "Loi exponentielle" +GeometricLaw = "Loi géométrique" NormalLaw = "Loi normale" PoissonLaw = "Loi de Poisson" ChiSquaredLaw = "Loi du chi2" diff --git a/apps/probability/base.pt.i18n b/apps/probability/base.pt.i18n index 63484b522..f273d27e4 100644 --- a/apps/probability/base.pt.i18n +++ b/apps/probability/base.pt.i18n @@ -2,6 +2,7 @@ ProbaApp = "Probabilidade" ProbaAppCapital = "PROBABILIDADE" ChooseLaw = "Selecionar a distribuição" Binomial = "Binomial" +Geometric = "Geométrica" Uniforme = "Uniforme" Normal = "Normal" Poisson = "Poisson" @@ -10,6 +11,7 @@ Student = "Student" BinomialLaw = "Distribuição binomial" UniformLaw = "Distribuição uniforme" ExponentialLaw = "Distribuição exponencial" +GeometricLaw = "Distribuição geométrica" NormalLaw = "Distribuição normal" PoissonLaw = "Distribuição de Poisson" ChiSquaredLaw = "Distribuição qui-quadrado" diff --git a/apps/probability/images/focused_geometric_icon.png b/apps/probability/images/focused_geometric_icon.png new file mode 100644 index 000000000..e4802b8e1 Binary files /dev/null and b/apps/probability/images/focused_geometric_icon.png differ diff --git a/apps/probability/images/geometric_icon.png b/apps/probability/images/geometric_icon.png new file mode 100644 index 000000000..1233e1682 Binary files /dev/null and b/apps/probability/images/geometric_icon.png differ diff --git a/apps/probability/law/geometric_law.cpp b/apps/probability/law/geometric_law.cpp new file mode 100644 index 000000000..94b380600 --- /dev/null +++ b/apps/probability/law/geometric_law.cpp @@ -0,0 +1,47 @@ +#include "geometric_law.h" +#include +#include +#include + +namespace Probability { + +float GeometricLaw::xMin() const { + return -k_displayLeftMarginRatio * xMax(); +} + +float GeometricLaw::xMax() const { + assert(m_parameter1 != 0); + return 5/m_parameter1 * (1.0f + k_displayRightMarginRatio); +} + +float GeometricLaw::yMax() const { + int maxAbscissa = 0; + float result = evaluateAtAbscissa(maxAbscissa); + return result * (1.0f + k_displayTopMarginRatio); +} + +bool GeometricLaw::authorizedValueAtIndex(float x, int index) const { + assert(index == 0); + if (x <= 0.0f || x > 1.0f) { + return false; + } + return true; +} + +template +T GeometricLaw::templatedApproximateAtAbscissa(T x) const { + if (x < 0) { + return NAN; + } + T p = (T)m_parameter1; + if (p == (T)1.0) { + return (T)(x == 0 ? 1.0 : 0.0); + } + T lResult = x * std::log(((T)1.0) - p); + return p*std::exp(lResult); +} + +} + +template float Probability::GeometricLaw::templatedApproximateAtAbscissa(float x) const; +template double Probability::GeometricLaw::templatedApproximateAtAbscissa(double x) const; diff --git a/apps/probability/law/geometric_law.h b/apps/probability/law/geometric_law.h new file mode 100644 index 000000000..7778e3933 --- /dev/null +++ b/apps/probability/law/geometric_law.h @@ -0,0 +1,38 @@ +#ifndef PROBABILITE_GEOMETRIC_LAW_H +#define PROBABILITE_GEOMETRIC_LAW_H + +#include "one_parameter_law.h" + +namespace Probability { + +class GeometricLaw final : public OneParameterLaw { +public: + GeometricLaw() : OneParameterLaw(0.5f) {} + I18n::Message title() override { return I18n::Message::GeometricLaw; } + Type type() const override { return Type::Geometric; } + bool isContinuous() const override { return false; } + float xMin() const override; + float xMax() const override; + float yMax() const override; + I18n::Message parameterNameAtIndex(int index) override { + assert(index == 0); + return I18n::Message::P; + } + I18n::Message parameterDefinitionAtIndex(int index) override { + assert(index == 0); + return I18n::Message::SuccessProbability; + } + float evaluateAtAbscissa(float x) const override { + return templatedApproximateAtAbscissa(x); + } + bool authorizedValueAtIndex(float x, int index) const override; +private: + double evaluateAtDiscreteAbscissa(int k) const override { + return templatedApproximateAtAbscissa((double)k); + } + template T templatedApproximateAtAbscissa(T x) const; +}; + +} + +#endif diff --git a/apps/probability/law/law.h b/apps/probability/law/law.h index f29a7bb21..1ff629053 100644 --- a/apps/probability/law/law.h +++ b/apps/probability/law/law.h @@ -16,9 +16,10 @@ public: Uniform, Exponential, Normal, - Poisson, ChiSquared, - Student + Student, + Geometric, + Poisson }; virtual ~Law() = default; virtual I18n::Message title() = 0; diff --git a/apps/probability/law_controller.cpp b/apps/probability/law_controller.cpp index 01408ca2d..88a5a7c19 100644 --- a/apps/probability/law_controller.cpp +++ b/apps/probability/law_controller.cpp @@ -5,6 +5,7 @@ #include "law/binomial_law.h" #include "law/chi_squared_law.h" #include "law/exponential_law.h" +#include "law/geometric_law.h" #include "law/normal_law.h" #include "law/poisson_law.h" #include "law/student_law.h" @@ -12,6 +13,7 @@ #include "images/binomial_icon.h" #include "images/chi_squared_icon.h" #include "images/exponential_icon.h" +#include "images/geometric_icon.h" #include "images/normal_icon.h" #include "images/poisson_icon.h" #include "images/student_icon.h" @@ -19,6 +21,7 @@ #include "images/focused_binomial_icon.h" #include "images/focused_chi_squared_icon.h" #include "images/focused_exponential_icon.h" +#include "images/focused_geometric_icon.h" #include "images/focused_normal_icon.h" #include "images/focused_poisson_icon.h" #include "images/focused_student_icon.h" @@ -55,9 +58,10 @@ static I18n::Message sMessages[] = { I18n::Message::Uniforme, I18n::Message::Exponential, I18n::Message::Normal, - I18n::Message::Poisson, I18n::Message::ChiSquared, - I18n::Message::Student + I18n::Message::Student, + I18n::Message::Geometric, + I18n::Message::Poisson }; LawController::LawController(Responder * parentResponder, Law * law, ParametersController * parametersController) : @@ -122,18 +126,20 @@ void Probability::LawController::willDisplayCellForIndex(HighlightCell * cell, i ImageStore::UniformIcon, ImageStore::ExponentialIcon, ImageStore::NormalIcon, - ImageStore::PoissonIcon, ImageStore::ChiSquaredIcon, - ImageStore::StudentIcon + ImageStore::StudentIcon, + ImageStore::GeometricIcon, + ImageStore::PoissonIcon }; const Image * focusedImages[k_totalNumberOfModels] = { ImageStore::FocusedBinomialIcon, ImageStore::FocusedUniformIcon, ImageStore::FocusedExponentialIcon, ImageStore::FocusedNormalIcon, - ImageStore::FocusedPoissonIcon, ImageStore::FocusedChiSquaredIcon, - ImageStore::FocusedStudentIcon + ImageStore::FocusedStudentIcon, + ImageStore::FocusedGeometricIcon, + ImageStore::FocusedPoissonIcon }; myCell->setImage(images[index], focusedImages[index]); myCell->reloadCell(); @@ -162,14 +168,18 @@ void Probability::LawController::setLawAccordingToIndex(int index) { new(m_law) NormalLaw(); break; case 4: - new(m_law) PoissonLaw(); - break; - case 5: new(m_law) ChiSquaredLaw(); break; - case 6: + case 5: new(m_law) StudentLaw(); break; + case 6: + new(m_law) GeometricLaw(); + break; + case 7: + new(m_law) PoissonLaw(); + break; + default: return; } diff --git a/apps/probability/law_controller.h b/apps/probability/law_controller.h index 28e7ee4e1..81c58c2b4 100644 --- a/apps/probability/law_controller.h +++ b/apps/probability/law_controller.h @@ -34,7 +34,7 @@ private: SelectableTableView * m_selectableTableView; }; void setLawAccordingToIndex(int index); - constexpr static int k_totalNumberOfModels = 7; + constexpr static int k_totalNumberOfModels = 8; Cell m_cells[k_totalNumberOfModels]; SelectableTableView m_selectableTableView; ContentView m_contentView; diff --git a/apps/probability/test/laws.cpp b/apps/probability/test/laws.cpp index b1cf1e0f8..29f2b7ed3 100644 --- a/apps/probability/test/laws.cpp +++ b/apps/probability/test/laws.cpp @@ -4,6 +4,7 @@ #include #include #include "../law/chi_squared_law.h" +#include "../law/geometric_law.h" #include "../law/student_law.h" void assert_cumulative_distributive_function_direct_and_inverse_is(Probability::Law * law, double x, double result) { @@ -62,3 +63,16 @@ QUIZ_CASE(student_law) { assert_cumulative_distributive_function_direct_and_inverse_is(&law, 1.3, 0.876837383157582639370275501278229057788848876953125); assert_cumulative_distributive_function_direct_and_inverse_is(&law, 2.9874567, 0.98612148076325445433809591122553683817386627197265625); } + +QUIZ_CASE(geometric_law) { + // Geometric law with probability of success 0.5 + Probability::GeometricLaw law; + law.setParameterAtIndex(0.5, 0); + assert_cumulative_distributive_function_direct_and_inverse_is(&law, 2.0, 0.875); + assert_cumulative_distributive_function_direct_and_inverse_is(&law, 3.0, 0.9375); + + // Geometric law with probability of success 0.2 + law.setParameterAtIndex(0.2, 0); + assert_cumulative_distributive_function_direct_and_inverse_is(&law, 7.0, 0.8322278399999998299563230830244719982147216796875); + assert_cumulative_distributive_function_direct_and_inverse_is(&law, 3.0, 0.5904); +}