diff --git a/apps/regression/graph_options_controller.cpp b/apps/regression/graph_options_controller.cpp index c1ddf0940..71bf107c1 100644 --- a/apps/regression/graph_options_controller.cpp +++ b/apps/regression/graph_options_controller.cpp @@ -2,6 +2,7 @@ #include "app.h" #include "graph_controller.h" #include "regression_controller.h" +#include #include using namespace Shared; @@ -56,7 +57,11 @@ bool GraphOptionsController::handleEvent(Ion::Events::Event event) { } int GraphOptionsController::numberOfRows() { - return k_numberOfParameterCells + 1; + int series = m_graphController->selectedSeriesIndex(); + Poincare::Context * globContext = const_cast(static_cast(app()->container()))->globalContext(); + double * coefs = m_store->coefficientsForSeries(series, globContext); + int numberOfParameterCells = m_store->modelForSeries(series)->levelSetAvailable(coefs) ? k_numberOfParameterCells : k_numberOfParameterCells - 1; + return numberOfParameterCells + 1; } KDCoordinate GraphOptionsController::rowHeight(int j) { @@ -80,7 +85,8 @@ KDCoordinate GraphOptionsController::cumulatedHeightFromIndex(int j) { int GraphOptionsController::indexFromCumulatedHeight(KDCoordinate offsetY) { int result = 0; int j = 0; - while (result < offsetY && j < numberOfRows()) { + int numberRows = numberOfRows(); + while (result < offsetY && j < numberRows) { result += rowHeight(j++); } return (result < offsetY || offsetY == 0) ? j : j - 1; @@ -113,14 +119,14 @@ int GraphOptionsController::typeAtLocation(int i, int j) { } void GraphOptionsController::willDisplayCellForIndex(HighlightCell * cell, int index) { - if (index < k_numberOfParameterCells) { - MessageTableCellWithChevron * myCell = (MessageTableCellWithChevron *)cell; - I18n::Message titles[k_numberOfParameterCells] = {I18n::Message::XPrediction, I18n::Message::YPrediction}; - myCell->setMessage(titles[index]); - } else { - assert(index == numberOfRows() - 1); + if (index == numberOfRows() - 1) { m_changeRegressionCell.setExpressionLayout(static_cast(m_store)->modelForSeries(m_graphController->selectedSeriesIndex())->layout()); + return; } + assert(index >=0 && index < k_numberOfParameterCells); + MessageTableCellWithChevron * myCell = (MessageTableCellWithChevron *)cell; + I18n::Message titles[k_numberOfParameterCells] = {I18n::Message::XPrediction, I18n::Message::YPrediction}; + myCell->setMessage(titles[index]); } } diff --git a/apps/regression/model/cubic_model.h b/apps/regression/model/cubic_model.h index 0a41dae2f..b1dad2eb6 100644 --- a/apps/regression/model/cubic_model.h +++ b/apps/regression/model/cubic_model.h @@ -12,6 +12,7 @@ public: Poincare::ExpressionLayout * layout() override; I18n::Message formulaMessage() const override { return I18n::Message::CubicRegressionFormula; } double evaluate(double * modelCoefficients, double x) const override; + bool levelSetAvailable(double * modelCoefficients) const override { return false; } double levelSet(double * modelCoefficients, double y) const override; double partialDerivate(double * modelCoefficients, int derivateCoefficientIndex, double x) const override; int numberOfCoefficients() const override { return 4; } diff --git a/apps/regression/model/exponential_model.cpp b/apps/regression/model/exponential_model.cpp index 338d2505b..f5e78ff6c 100644 --- a/apps/regression/model/exponential_model.cpp +++ b/apps/regression/model/exponential_model.cpp @@ -32,10 +32,19 @@ double ExponentialModel::evaluate(double * modelCoefficients, double x) const { return a*exp(b*x); } +bool ExponentialModel::levelSetAvailable(double * modelCoefficients) const { + double a = modelCoefficients[0]; + double b = modelCoefficients[1]; + if (a == 0 || b == 0) { + return false; + } + return true; +} + double ExponentialModel::levelSet(double * modelCoefficients, double y) const { double a = modelCoefficients[0]; double b = modelCoefficients[1]; - if (a == 0 || b == 0 || y/a <= 0) { + if (!levelSetAvailable(modelCoefficients) || y/a <= 0) { return NAN; } return log(y/a)/b; diff --git a/apps/regression/model/exponential_model.h b/apps/regression/model/exponential_model.h index d51e00bb9..3e97f841b 100644 --- a/apps/regression/model/exponential_model.h +++ b/apps/regression/model/exponential_model.h @@ -12,6 +12,7 @@ public: Poincare::ExpressionLayout * layout() override; I18n::Message formulaMessage() const override { return I18n::Message::ExponentialRegressionFormula; } double evaluate(double * modelCoefficients, double x) const override; + bool levelSetAvailable(double * modelCoefficients) const override; double levelSet(double * modelCoefficients, double y) const override; double partialDerivate(double * modelCoefficients, int derivateCoefficientIndex, double x) const override; int numberOfCoefficients() const override { return 2; } diff --git a/apps/regression/model/linear_model.h b/apps/regression/model/linear_model.h index 0249a841d..6554e4be8 100644 --- a/apps/regression/model/linear_model.h +++ b/apps/regression/model/linear_model.h @@ -12,6 +12,7 @@ public: Poincare::ExpressionLayout * layout() override; I18n::Message formulaMessage() const override { return I18n::Message::LinearRegressionFormula; } double evaluate(double * modelCoefficients, double x) const override; + bool levelSetAvailable(double * modelCoefficients) const override { return true; } double levelSet(double * modelCoefficients, double y) const override; virtual void fit(Store * store, int series, double * modelCoefficients, Poincare::Context * context) override; double partialDerivate(double * modelCoefficients, int derivateCoefficientIndex, double x) const override; diff --git a/apps/regression/model/logarithmic_model.cpp b/apps/regression/model/logarithmic_model.cpp index dcc089a81..7329f2bfb 100644 --- a/apps/regression/model/logarithmic_model.cpp +++ b/apps/regression/model/logarithmic_model.cpp @@ -18,12 +18,17 @@ double LogarithmicModel::evaluate(double * modelCoefficients, double x) const { return a*log(x)+b; } -double LogarithmicModel::levelSet(double * modelCoefficients, double y) const { +bool LogarithmicModel::levelSetAvailable(double * modelCoefficients) const { double a = modelCoefficients[0]; - double b = modelCoefficients[1]; - if (a == 0) { + return a != 0; +} + +double LogarithmicModel::levelSet(double * modelCoefficients, double y) const { + if (!levelSetAvailable(modelCoefficients)) { return NAN; } + double a = modelCoefficients[0]; + double b = modelCoefficients[1]; return exp((y-b)/a); } diff --git a/apps/regression/model/logarithmic_model.h b/apps/regression/model/logarithmic_model.h index 7e8dc6954..6a51436d7 100644 --- a/apps/regression/model/logarithmic_model.h +++ b/apps/regression/model/logarithmic_model.h @@ -12,6 +12,7 @@ public: Poincare::ExpressionLayout * layout() override; I18n::Message formulaMessage() const override { return I18n::Message::LogarithmicRegressionFormula; } double evaluate(double * modelCoefficients, double x) const override; + bool levelSetAvailable(double * modelCoefficients) const override; double levelSet(double * modelCoefficients, double y) const override; double partialDerivate(double * modelCoefficients, int derivateCoefficientIndex, double x) const override; int numberOfCoefficients() const override { return 2; } diff --git a/apps/regression/model/logistic_model.cpp b/apps/regression/model/logistic_model.cpp index 45451621d..992850295 100644 --- a/apps/regression/model/logistic_model.cpp +++ b/apps/regression/model/logistic_model.cpp @@ -39,11 +39,21 @@ double LogisticModel::evaluate(double * modelCoefficients, double x) const { return c/(1.0+a*exp(-b*x)); } +bool LogisticModel::levelSetAvailable(double * modelCoefficients) const { + double a = modelCoefficients[0]; + double b = modelCoefficients[1]; + double c = modelCoefficients[2]; + if (a == 0 || b == 0 || c == 0) { + return false; + } + return true; +} + double LogisticModel::levelSet(double * modelCoefficients, double y) const { double a = modelCoefficients[0]; double b = modelCoefficients[1]; double c = modelCoefficients[2]; - if (a == 0 || b == 0 || c == 0 || y == 0) { + if (!levelSetAvailable(modelCoefficients) || y == 0) { return NAN; } double lnArgument = (c/y - 1)/a; diff --git a/apps/regression/model/logistic_model.h b/apps/regression/model/logistic_model.h index 6450ba116..7f5c28bb9 100644 --- a/apps/regression/model/logistic_model.h +++ b/apps/regression/model/logistic_model.h @@ -12,6 +12,7 @@ public: Poincare::ExpressionLayout * layout() override; I18n::Message formulaMessage() const override { return I18n::Message::LogisticRegressionFormula; } double evaluate(double * modelCoefficients, double x) const override; + bool levelSetAvailable(double * modelCoefficients) const override; double levelSet(double * modelCoefficients, double y) const override; double partialDerivate(double * modelCoefficients, int derivateCoefficientIndex, double x) const override; int numberOfCoefficients() const override { return 3; } diff --git a/apps/regression/model/model.h b/apps/regression/model/model.h index ee5065a19..1b48453f0 100644 --- a/apps/regression/model/model.h +++ b/apps/regression/model/model.h @@ -29,6 +29,7 @@ public: virtual Poincare::ExpressionLayout * layout() = 0; virtual I18n::Message formulaMessage() const = 0; virtual double evaluate(double * modelCoefficients, double x) const = 0; + virtual bool levelSetAvailable(double * modelCoefficients) const = 0; virtual double levelSet(double * modelCoefficients, double y) const = 0; virtual void fit(Store * store, int series, double * modelCoefficients, Poincare::Context * context); virtual int numberOfCoefficients() const = 0; diff --git a/apps/regression/model/power_model.cpp b/apps/regression/model/power_model.cpp index 8130dcbd6..cbe67c0ac 100644 --- a/apps/regression/model/power_model.cpp +++ b/apps/regression/model/power_model.cpp @@ -29,10 +29,19 @@ double PowerModel::evaluate(double * modelCoefficients, double x) const { return a*pow(x,b); } +bool PowerModel::levelSetAvailable(double * modelCoefficients) const { + double a = modelCoefficients[0]; + double b = modelCoefficients[1]; + if (a == 0 || b == 0) { + return false; + } + return true; +} + double PowerModel::levelSet(double * modelCoefficients, double y) const { double a = modelCoefficients[0]; double b = modelCoefficients[1]; - if (a == 0 || b == 0 || y/a <= 0) { + if (!levelSetAvailable(modelCoefficients) || y/a <= 0) { return NAN; } return exp(log(y/a)/b); diff --git a/apps/regression/model/power_model.h b/apps/regression/model/power_model.h index 86a3390e0..5216bd652 100644 --- a/apps/regression/model/power_model.h +++ b/apps/regression/model/power_model.h @@ -12,6 +12,7 @@ public: Poincare::ExpressionLayout * layout() override; I18n::Message formulaMessage() const override { return I18n::Message::PowerRegressionFormula; } double evaluate(double * modelCoefficients, double x) const override; + bool levelSetAvailable(double * modelCoefficients) const override; double levelSet(double * modelCoefficients, double y) const override; double partialDerivate(double * modelCoefficients, int derivateCoefficientIndex, double x) const override; int numberOfCoefficients() const override { return 2; } diff --git a/apps/regression/model/quadratic_model.h b/apps/regression/model/quadratic_model.h index 3d35b3ad3..e9189f9eb 100644 --- a/apps/regression/model/quadratic_model.h +++ b/apps/regression/model/quadratic_model.h @@ -12,6 +12,7 @@ public: Poincare::ExpressionLayout * layout() override; I18n::Message formulaMessage() const override { return I18n::Message::QuadraticRegressionFormula; } double evaluate(double * modelCoefficients, double x) const override; + bool levelSetAvailable(double * modelCoefficients) const override { return false; } double levelSet(double * modelCoefficients, double y) const override; double partialDerivate(double * modelCoefficients, int derivateCoefficientIndex, double x) const override; int numberOfCoefficients() const override { return 3; } diff --git a/apps/regression/model/quartic_model.h b/apps/regression/model/quartic_model.h index 087d3369a..3eb48ad07 100644 --- a/apps/regression/model/quartic_model.h +++ b/apps/regression/model/quartic_model.h @@ -12,6 +12,7 @@ public: Poincare::ExpressionLayout * layout() override; I18n::Message formulaMessage() const override { return I18n::Message::QuarticRegressionFormula; } double evaluate(double * modelCoefficients, double x) const override; + bool levelSetAvailable(double * modelCoefficients) const override { return false; } double levelSet(double * modelCoefficients, double y) const override; double partialDerivate(double * modelCoefficients, int derivateCoefficientIndex, double x) const override; int numberOfCoefficients() const override { return 5; } diff --git a/apps/regression/model/trigonometric_model.h b/apps/regression/model/trigonometric_model.h index a2f14e62a..abf6e0985 100644 --- a/apps/regression/model/trigonometric_model.h +++ b/apps/regression/model/trigonometric_model.h @@ -12,6 +12,7 @@ public: Poincare::ExpressionLayout * layout() override; I18n::Message formulaMessage() const override { return I18n::Message::TrigonometricRegressionFormula; } double evaluate(double * modelCoefficients, double x) const override; + bool levelSetAvailable(double * modelCoefficients) const override { return false; } double levelSet(double * modelCoefficients, double y) const override; double partialDerivate(double * modelCoefficients, int derivateCoefficientIndex, double x) const override; int numberOfCoefficients() const override { return 3; }