From a8a5ecfd4e62aaa3e06c7bdca45e8da6d2902c7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 26 Aug 2019 16:04:08 +0200 Subject: [PATCH] [apps/proba] Factorize code --- .../probability/distribution/distribution.cpp | 27 +++++-------------- poincare/include/poincare/solver.h | 2 +- poincare/src/binomial_distribution.cpp | 4 +-- poincare/src/solver.cpp | 17 +++++++----- 4 files changed, 19 insertions(+), 31 deletions(-) diff --git a/apps/probability/distribution/distribution.cpp b/apps/probability/distribution/distribution.cpp index f31ec66e4..08c99e410 100644 --- a/apps/probability/distribution/distribution.cpp +++ b/apps/probability/distribution/distribution.cpp @@ -58,27 +58,12 @@ double Distribution::cumulativeDistributiveInverseForProbability(double * probab if (*probability <= 0.0) { return 0.0; } - double p = 0.0; - int k = 0; - double delta = 0.0; - do { - delta = std::fabs(*probability-p); - p += evaluateAtDiscreteAbscissa(k++); - if (p >= k_maxProbability && std::fabs(*probability-1.0) <= delta) { - *probability = 1.0; - return k-1.0; - } - } while (std::fabs(*probability-p) <= delta && k < k_maxNumberOfOperations && p < 1.0); - p -= evaluateAtDiscreteAbscissa(--k); - if (k == k_maxNumberOfOperations) { - *probability = 1.0; - return INFINITY; - } - *probability = p; - if (std::isnan(*probability)) { - return NAN; - } - return k-1.0; + return Poincare::Solver::CumulativeDistributiveInverseForNDefinedFunction(probability, + [](double k, Poincare::Context * context, Poincare::Preferences::ComplexFormat complexFormat, Poincare::Preferences::AngleUnit angleUnit, const void * context1, const void * context2, const void * context3) { + const Distribution * distribution = reinterpret_cast(context1); + return distribution->evaluateAtDiscreteAbscissa(k); + }, nullptr, Poincare::Preferences::ComplexFormat::Real, Poincare::Preferences::AngleUnit::Degree, this); + // Context, complex format and angle unit are dummy values } double Distribution::rightIntegralInverseForProbability(double * probability) { diff --git a/poincare/include/poincare/solver.h b/poincare/include/poincare/solver.h index 414a6ea9b..639ef3a0d 100644 --- a/poincare/include/poincare/solver.h +++ b/poincare/include/poincare/solver.h @@ -20,7 +20,7 @@ public: // Proba // Cumulative distributive inverse for function defined on N (positive integers) - template static T CumulativeDistributiveInverseForNDefinedFunction(T probability, ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const void * context1 = nullptr, const void * context2 = nullptr, const void * context3 = nullptr); + template static T CumulativeDistributiveInverseForNDefinedFunction(T * probability, ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const void * context1 = nullptr, const void * context2 = nullptr, const void * context3 = nullptr); // Cumulative distributive function for function defined on N (positive integers) template static T CumulativeDistributiveFunctionForNDefinedFunction(T x, ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const void * context1 = nullptr, const void * context2 = nullptr, const void * context3 = nullptr); diff --git a/poincare/src/binomial_distribution.cpp b/poincare/src/binomial_distribution.cpp index e65ee4878..67099c834 100644 --- a/poincare/src/binomial_distribution.cpp +++ b/poincare/src/binomial_distribution.cpp @@ -81,9 +81,9 @@ T BinomialDistribution::CumulativeDistributiveInverseForProbability(T probabilit if (std::abs(probability - (T)1.0) < precision) { return n; } - + T proba = probability; return Solver::CumulativeDistributiveInverseForNDefinedFunction( - probability, + &proba, [](double x, Context * context, Poincare::Preferences::ComplexFormat complexFormat, Poincare::Preferences::AngleUnit angleUnit, const void * n, const void * p, const void * isDouble) { if (*(bool *)isDouble) { return (double)BinomialDistribution::EvaluateAtAbscissa(x, *(reinterpret_cast(n)), *(reinterpret_cast(p))); diff --git a/poincare/src/solver.cpp b/poincare/src/solver.cpp index d9dd78f7c..fdffd3376 100644 --- a/poincare/src/solver.cpp +++ b/poincare/src/solver.cpp @@ -206,23 +206,26 @@ Coordinate2D Solver::IncreasingFunctionRoot(double ax, double bx, double precisi } template -T Solver::CumulativeDistributiveInverseForNDefinedFunction(T probability, ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const void * context1, const void * context2, const void * context3) { +T Solver::CumulativeDistributiveInverseForNDefinedFunction(T * probability, ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const void * context1, const void * context2, const void * context3) { T precision = sizeof(T) == sizeof(double) ? DBL_EPSILON : FLT_EPSILON; - assert(probability <= (((T)1.0) - precision) && probability > precision); + assert(*probability <= (((T)1.0) - precision) && *probability > precision); T p = 0.0; int k = 0; T delta = 0.0; do { - delta = std::fabs(probability-p); + delta = std::fabs(*probability-p); p += evaluation(k++, context, complexFormat, angleUnit, context1, context2, context3); - if (p >= k_maxProbability && std::fabs(probability-1.0) <= delta) { + if (p >= k_maxProbability && std::fabs(*probability-1.0) <= delta) { + *probability = (T)1.0; return (T)(k-1); } - } while (std::fabs(probability-p) <= delta && k < k_maxNumberOfOperations && p < 1.0); + } while (std::fabs(*probability-p) <= delta && k < k_maxNumberOfOperations && p < 1.0); p -= evaluation(--k, context, complexFormat, angleUnit, context1, context2, context3); if (k == k_maxNumberOfOperations) { + *probability = (T)1.0; return INFINITY; } + *probability = p; if (std::isnan(p)) { return NAN; } @@ -247,8 +250,8 @@ T Solver::CumulativeDistributiveFunctionForNDefinedFunction(T x, ValueAtAbscissa return result; } -template float Solver::CumulativeDistributiveInverseForNDefinedFunction(float, ValueAtAbscissa, Context *, Preferences::ComplexFormat, Preferences::AngleUnit, const void *, const void *, const void *); -template double Solver::CumulativeDistributiveInverseForNDefinedFunction(double, ValueAtAbscissa, Context *, Preferences::ComplexFormat, Preferences::AngleUnit, const void *, const void *, const void *); +template float Solver::CumulativeDistributiveInverseForNDefinedFunction(float *, ValueAtAbscissa, Context *, Preferences::ComplexFormat, Preferences::AngleUnit, const void *, const void *, const void *); +template double Solver::CumulativeDistributiveInverseForNDefinedFunction(double *, ValueAtAbscissa, Context *, Preferences::ComplexFormat, Preferences::AngleUnit, const void *, const void *, const void *); template float Solver::CumulativeDistributiveFunctionForNDefinedFunction(float, ValueAtAbscissa, Context *, Preferences::ComplexFormat, Preferences::AngleUnit, const void *, const void *, const void *); template double Solver::CumulativeDistributiveFunctionForNDefinedFunction(double, ValueAtAbscissa, Context *, Preferences::ComplexFormat, Preferences::AngleUnit, const void *, const void *, const void *);