diff --git a/apps/graph/cartesian_function.cpp b/apps/graph/cartesian_function.cpp index 1b86d64be..0112e2649 100644 --- a/apps/graph/cartesian_function.cpp +++ b/apps/graph/cartesian_function.cpp @@ -41,315 +41,24 @@ double CartesianFunction::sumBetweenBounds(double start, double end, Poincare::C return integral.approximateToScalar(*context); } -CartesianFunction::Point CartesianFunction::nextMinimumFrom(double start, double step, double max, Context * context) const { - return nextMinimumOfFunction(start, step, max, [](double x, Context * context, const Shared::Function * function0, const Shared::Function * function1 = nullptr) { - return function0->evaluateAtAbscissa(x, context); - }, context); +Expression::Coordinate2D CartesianFunction::nextMinimumFrom(double start, double step, double max, Context * context) const { + return expression(context)->nextMinimum(symbol(), start, step, max, *context); } -CartesianFunction::Point CartesianFunction::nextMaximumFrom(double start, double step, double max, Context * context) const { - Point minimumOfOpposite = nextMinimumOfFunction(start, step, max, [](double x, Context * context, const Shared::Function * function0, const Shared::Function * function1 = nullptr) { - return -function0->evaluateAtAbscissa(x, context); - }, context); - return {.abscissa = minimumOfOpposite.abscissa, .value = -minimumOfOpposite.value}; +Expression::Coordinate2D CartesianFunction::nextMaximumFrom(double start, double step, double max, Context * context) const { + return expression(context)->nextMaximum(symbol(), start, step, max, *context); } double CartesianFunction::nextRootFrom(double start, double step, double max, Context * context) const { - return nextIntersectionWithFunction(start, step, max, [](double x, Context * context, const Shared::Function * function0, const Shared::Function * function1 = nullptr) { - return function0->evaluateAtAbscissa(x, context); - }, context, nullptr); + return expression(context)->nextRoot(symbol(), start, step, max, *context); } -CartesianFunction::Point CartesianFunction::nextIntersectionFrom(double start, double step, double max, Poincare::Context * context, const Shared::Function * function) const { - double resultAbscissa = nextIntersectionWithFunction(start, step, max, [](double x, Context * context, const Shared::Function * function0, const Shared::Function * function1) { - return function0->evaluateAtAbscissa(x, context)-function1->evaluateAtAbscissa(x, context); - }, context, function); - CartesianFunction::Point result = {.abscissa = resultAbscissa, .value = evaluateAtAbscissa(resultAbscissa, context)}; - if (std::fabs(result.value) < step*k_precision) { - result.value = 0.0; - } - return result; -} - -CartesianFunction::Point CartesianFunction::nextMinimumOfFunction(double start, double step, double max, Evaluation evaluate, Context * context, const Shared::Function * function, bool lookForRootMinimum) const { - double bracket[3]; - Point result = {.abscissa = NAN, .value = NAN}; - double x = start; - bool endCondition = false; - do { - bracketMinimum(x, step, max, bracket, evaluate, context, function); - result = brentMinimum(bracket[0], bracket[2], evaluate, context, function); - x = bracket[1]; - endCondition = std::isnan(result.abscissa) && (step > 0.0 ? x <= max : x >= max); - if (lookForRootMinimum) { - endCondition |= std::fabs(result.value) >= k_sqrtEps && (step > 0.0 ? x <= max : x >= max); - } - } while (endCondition); - - if (std::fabs(result.abscissa) < step*k_precision) { - result.abscissa = 0; - result.value = evaluate(0, context, this, function); - } - if (std::fabs(result.value) < step*k_precision) { - result.value = 0; - } - if (lookForRootMinimum) { - result.abscissa = std::fabs(result.value) >= k_sqrtEps ? NAN : result.abscissa; - } - return result; -} - -void CartesianFunction::bracketMinimum(double start, double step, double max, double result[3], Evaluation evaluate, Context * context, const Shared::Function * function) const { - Point p[3]; - p[0] = {.abscissa = start, .value = evaluate(start, context, this, function)}; - p[1] = {.abscissa = start+step, .value = evaluate(start+step, context, this, function)}; - double x = start+2.0*step; - while (step > 0.0 ? x <= max : x >= max) { - p[2] = {.abscissa = x, .value = evaluate(x, context, this, function)}; - if (p[0].value > p[1].value && p[2].value > p[1].value) { - result[0] = p[0].abscissa; - result[1] = p[1].abscissa; - result[2] = p[2].abscissa; - return; - } - if (p[0].value > p[1].value && p[1].value == p[2].value) { - } else { - p[0] = p[1]; - p[1] = p[2]; - } - x += step; - } - result[0] = NAN; - result[1] = NAN; - result[2] = NAN; +Expression::Coordinate2D CartesianFunction::nextIntersectionFrom(double start, double step, double max, Poincare::Context * context, const Shared::Function * function) const { + return expression(context)->nextIntersection(symbol(), start, step, max, *context, function->expression(context)); } char CartesianFunction::symbol() const { return 'x'; } -CartesianFunction::Point CartesianFunction::brentMinimum(double ax, double bx, Evaluation evaluate, Context * context, const Shared::Function * function) const { - /* Bibliography: R. P. Brent, Algorithms for finding zeros and extrema of - * functions without calculating derivatives */ - if (ax > bx) { - return brentMinimum(bx, ax, evaluate, context, function); - } - double e = 0.0; - double a = ax; - double b = bx; - double x = a+k_goldenRatio*(b-a); - double v = x; - double w = x; - double fx = evaluate(x, context, this, function); - double fw = fx; - double fv = fw; - - double d = NAN; - double u, fu; - - for (int i = 0; i < 100; i++) { - double m = 0.5*(a+b); - double tol1 = k_sqrtEps*std::fabs(x)+1E-10; - double tol2 = 2.0*tol1; - if (std::fabs(x-m) <= tol2-0.5*(b-a)) { - double middleFax = evaluate((x+a)/2.0, context, this, function); - double middleFbx = evaluate((x+b)/2.0, context, this, function); - double fa = evaluate(a, context, this, function); - double fb = evaluate(b, context, this, function); - if (middleFax-fa <= k_sqrtEps && fx-middleFax <= k_sqrtEps && fx-middleFbx <= k_sqrtEps && middleFbx-fb <= k_sqrtEps) { - Point result = {.abscissa = x, .value = fx}; - return result; - } - } - double p = 0; - double q = 0; - double r = 0; - if (std::fabs(e) > tol1) { - r = (x-w)*(fx-fv); - q = (x-v)*(fx-fw); - p = (x-v)*q -(x-w)*r; - q = 2.0*(q-r); - if (q>0.0) { - p = -p; - } else { - q = -q; - } - r = e; - e = d; - } - if (std::fabs(p) < std::fabs(0.5*q*r) && p= tol1 ? d : (d>0 ? tol1 : -tol1)); - fu = evaluate(u, context, this, function); - if (fu <= fx) { - if (u 0.0 ? x <= max : x >= max)); - - double extremumMax = std::isnan(result) ? max : result; - Point resultExtremum[2] = { - nextMinimumOfFunction(start, step, extremumMax, [](double x, Context * context, const Shared::Function * function0, const Shared::Function * function1) { - if (function1) { - return function0->evaluateAtAbscissa(x, context)-function1->evaluateAtAbscissa(x, context); - } else { - return function0->evaluateAtAbscissa(x, context); - } - }, context, function, true), - nextMinimumOfFunction(start, step, extremumMax, [](double x, Context * context, const Shared::Function * function0, const Shared::Function * function1) { - if (function1) { - return function1->evaluateAtAbscissa(x, context)-function0->evaluateAtAbscissa(x, context); - } else { - return -function0->evaluateAtAbscissa(x, context); - } - }, context, function, true)}; - for (int i = 0; i < 2; i++) { - if (!std::isnan(resultExtremum[i].abscissa) && (std::isnan(result) || std::fabs(result - start) > std::fabs(resultExtremum[i].abscissa - start))) { - result = resultExtremum[i].abscissa; - } - } - if (std::fabs(result) < step*k_precision) { - result = 0; - } - return result; -} - -void CartesianFunction::bracketRoot(double start, double step, double max, double result[2], Evaluation evaluation, Context * context, const Shared::Function * function) const { - double a = start; - double b = start+step; - while (step > 0.0 ? b <= max : b >= max) { - double fa = evaluation(a, context, this, function); - double fb = evaluation(b, context, this, function); - if (fa*fb <= 0) { - result[0] = a; - result[1] = b; - return; - } - a = b; - b = b+step; - } - result[0] = NAN; - result[1] = NAN; -} - - -double CartesianFunction::brentRoot(double ax, double bx, double precision, Evaluation evaluation, Poincare::Context * context, const Shared::Function * function) const { - if (ax > bx) { - return brentRoot(bx, ax, precision, evaluation, context, function); - } - double a = ax; - double b = bx; - double c = bx; - double d = b-a; - double e = b-a; - double fa = evaluation(a, context, this, function); - double fb = evaluation(b, context, this, function); - double fc = fb; - for (int i = 0; i < 100; i++) { - if ((fb > 0.0 && fc > 0.0) || (fb < 0.0 && fc < 0.0)) { - c = a; - fc = fa; - e = b-a; - d = b-a; - } - if (std::fabs(fc) < std::fabs(fb)) { - a = b; - b = c; - c = a; - fa = fb; - fb = fc; - fc = fa; - } - double tol1 = 2.0*DBL_EPSILON*std::fabs(b)+0.5*precision; - double xm = 0.5*(c-b); - if (std::fabs(xm) <= tol1 || fb == 0.0) { - double fbcMiddle = evaluation(0.5*(b+c), context, this, function); - double isContinuous = (fb <= fbcMiddle && fbcMiddle <= fc) || (fc <= fbcMiddle && fbcMiddle <= fb); - if (isContinuous) { - return b; - } - } - if (std::fabs(e) >= tol1 && std::fabs(fa) > std::fabs(b)) { - double s = fb/fa; - double p = 2.0*xm*s; - double q = 1.0-s; - if (a != c) { - q = fa/fc; - double r = fb/fc; - p = s*(2.0*xm*q*(q-r)-(b-a)*(r-1.0)); - q = (q-1.0)*(r-1.0)*(s-1.0); - } - q = p > 0.0 ? -q : q; - p = std::fabs(p); - double min1 = 3.0*xm*q-std::fabs(tol1*q); - double min2 = std::fabs(e*q); - if (2.0*p < (min1 < min2 ? min1 : min2)) { - e = d; - d = p/q; - } else { - d = xm; - e =d; - } - } else { - d = xm; - e = d; - } - a = b; - fa = fb; - if (std::fabs(d) > tol1) { - b += d; - } else { - b += xm > 0.0 ? tol1 : tol1; - } - fb = evaluation(b, context, this, function); - } - return NAN; -} - } diff --git a/apps/graph/cartesian_function.h b/apps/graph/cartesian_function.h index 0b4bb4393..9015ad7dd 100644 --- a/apps/graph/cartesian_function.h +++ b/apps/graph/cartesian_function.h @@ -13,26 +13,12 @@ public: void setDisplayDerivative(bool display); double approximateDerivative(double x, Poincare::Context * context) const; double sumBetweenBounds(double start, double end, Poincare::Context * context) const override; - struct Point { - double abscissa; - double value; - }; - Point nextMinimumFrom(double start, double step, double max, Poincare::Context * context) const; - Point nextMaximumFrom(double start, double step, double max, Poincare::Context * context) const; + Poincare::Expression::Coordinate2D nextMinimumFrom(double start, double step, double max, Poincare::Context * context) const; + Poincare::Expression::Coordinate2D nextMaximumFrom(double start, double step, double max, Poincare::Context * context) const; double nextRootFrom(double start, double step, double max, Poincare::Context * context) const; - Point nextIntersectionFrom(double start, double step, double max, Poincare::Context * context, const Shared::Function * function) const; + Poincare::Expression::Coordinate2D nextIntersectionFrom(double start, double step, double max, Poincare::Context * context, const Shared::Function * function) const; char symbol() const override; private: - constexpr static double k_precision = 1.0E-5; - constexpr static double k_sqrtEps = 1.4901161193847656E-8; // sqrt(DBL_EPSILON) - constexpr static double k_goldenRatio = 0.381966011250105151795413165634361882279690820194237137864; // (3-sqrt(5))/2 - typedef double (*Evaluation)(double abscissa, Poincare::Context * context, const Shared::Function * function0, const Shared::Function * function1); - Point nextMinimumOfFunction(double start, double step, double max, Evaluation evaluation, Poincare::Context * context, const Shared::Function * function = nullptr, bool lookForRootMinimum = false) const; - void bracketMinimum(double start, double step, double max, double result[3], Evaluation evaluation, Poincare::Context * context, const Shared::Function * function= nullptr) const; - Point brentMinimum(double ax, double bx, Evaluation evaluation, Poincare::Context * context, const Shared::Function * function = nullptr) const; - double nextIntersectionWithFunction(double start, double step, double max, Evaluation evaluation, Poincare::Context * context, const Shared::Function * function) const; - void bracketRoot(double start, double step, double max, double result[2], Evaluation evaluation, Poincare::Context * context, const Shared::Function * function) const; - double brentRoot(double ax, double bx, double precision, Evaluation evaluation, Poincare::Context * context, const Shared::Function * function) const; bool m_displayDerivative; }; diff --git a/apps/graph/graph/calculation_graph_controller.cpp b/apps/graph/graph/calculation_graph_controller.cpp index 7c98b284d..de9ef00f1 100644 --- a/apps/graph/graph/calculation_graph_controller.cpp +++ b/apps/graph/graph/calculation_graph_controller.cpp @@ -24,7 +24,7 @@ View * CalculationGraphController::view() { void CalculationGraphController::viewWillAppear() { assert(m_function != nullptr); - CartesianFunction::Point pointOfInterest = computeNewPointOfInteresetFromAbscissa(m_graphRange->xMin(), 1); + Expression::Coordinate2D pointOfInterest = computeNewPointOfInteresetFromAbscissa(m_graphRange->xMin(), 1); if (std::isnan(pointOfInterest.abscissa)) { m_isActive = false; m_graphView->setCursorView(nullptr); @@ -67,7 +67,7 @@ void CalculationGraphController::reloadBannerView() { } bool CalculationGraphController::moveCursor(int direction) { - CartesianFunction::Point newPointOfInterest = computeNewPointOfInteresetFromAbscissa(m_cursor->x(), direction); + Expression::Coordinate2D newPointOfInterest = computeNewPointOfInteresetFromAbscissa(m_cursor->x(), direction); if (std::isnan(newPointOfInterest.abscissa)) { return false; } @@ -76,7 +76,7 @@ bool CalculationGraphController::moveCursor(int direction) { return true; } -CartesianFunction::Point CalculationGraphController::computeNewPointOfInteresetFromAbscissa(double start, int direction) { +Expression::Coordinate2D CalculationGraphController::computeNewPointOfInteresetFromAbscissa(double start, int direction) { TextFieldDelegateApp * myApp = (TextFieldDelegateApp *)app(); double step = m_graphRange->xGridUnit()/10.0; step = direction < 0 ? -step : step; diff --git a/apps/graph/graph/calculation_graph_controller.h b/apps/graph/graph/calculation_graph_controller.h index b277faffe..ffc26e45c 100644 --- a/apps/graph/graph/calculation_graph_controller.h +++ b/apps/graph/graph/calculation_graph_controller.h @@ -23,8 +23,8 @@ protected: BannerView * bannerView() override { return m_bannerView; } virtual void reloadBannerView(); bool moveCursor(int direction); - CartesianFunction::Point computeNewPointOfInteresetFromAbscissa(double start, int direction); - virtual CartesianFunction::Point computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) = 0; + Poincare::Expression::Coordinate2D computeNewPointOfInteresetFromAbscissa(double start, int direction); + virtual Poincare::Expression::Coordinate2D computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) = 0; GraphView * m_graphView; BannerView * m_bannerView; Shared::InteractiveCurveViewRange * m_graphRange; diff --git a/apps/graph/graph/extremum_graph_controller.cpp b/apps/graph/graph/extremum_graph_controller.cpp index 1273fa756..b2c855e95 100644 --- a/apps/graph/graph/extremum_graph_controller.cpp +++ b/apps/graph/graph/extremum_graph_controller.cpp @@ -15,7 +15,7 @@ const char * MinimumGraphController::title() { return I18n::translate(I18n::Message::Minimum); } -CartesianFunction::Point MinimumGraphController::computeNewPointOfInterest(double start, double step, double max, Context * context) { +Expression::Coordinate2D MinimumGraphController::computeNewPointOfInterest(double start, double step, double max, Context * context) { return m_function->nextMinimumFrom(start, step, max, context); } @@ -28,7 +28,7 @@ const char * MaximumGraphController::title() { return I18n::translate(I18n::Message::Maximum); } -CartesianFunction::Point MaximumGraphController::computeNewPointOfInterest(double start, double step, double max, Context * context) { +Expression::Coordinate2D MaximumGraphController::computeNewPointOfInterest(double start, double step, double max, Context * context) { return m_function->nextMaximumFrom(start, step, max, context); } diff --git a/apps/graph/graph/extremum_graph_controller.h b/apps/graph/graph/extremum_graph_controller.h index dc1f5bc30..3fd55107c 100644 --- a/apps/graph/graph/extremum_graph_controller.h +++ b/apps/graph/graph/extremum_graph_controller.h @@ -10,7 +10,7 @@ public: MinimumGraphController(Responder * parentResponder, GraphView * graphView, BannerView * bannerView, Shared::InteractiveCurveViewRange * curveViewRange, Shared::CurveViewCursor * cursor); const char * title() override; private: - CartesianFunction::Point computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) override; + Poincare::Expression::Coordinate2D computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) override; }; class MaximumGraphController : public CalculationGraphController { @@ -18,7 +18,7 @@ public: MaximumGraphController(Responder * parentResponder, GraphView * graphView, BannerView * bannerView, Shared::InteractiveCurveViewRange * curveViewRange, Shared::CurveViewCursor * cursor); const char * title() override; private: - CartesianFunction::Point computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) override; + Poincare::Expression::Coordinate2D computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) override; }; } diff --git a/apps/graph/graph/intersection_graph_controller.cpp b/apps/graph/graph/intersection_graph_controller.cpp index 94d5f6335..86168890d 100644 --- a/apps/graph/graph/intersection_graph_controller.cpp +++ b/apps/graph/graph/intersection_graph_controller.cpp @@ -36,12 +36,12 @@ void IntersectionGraphController::reloadBannerView() { bannerView()->setLegendAtIndex(buffer, 1); } -CartesianFunction::Point IntersectionGraphController::computeNewPointOfInterest(double start, double step, double max, Context * context) { - CartesianFunction::Point result = {.abscissa = NAN, .value = NAN}; +Expression::Coordinate2D IntersectionGraphController::computeNewPointOfInterest(double start, double step, double max, Context * context) { + Expression::Coordinate2D result = {.abscissa = NAN, .value = NAN}; for (int i = 0; i < m_functionStore->numberOfActiveFunctions(); i++) { Function * f = m_functionStore->activeFunctionAtIndex(i); if (f != m_function) { - CartesianFunction::Point intersection = m_function->nextIntersectionFrom(start, step, max, context, f); + Expression::Coordinate2D intersection = m_function->nextIntersectionFrom(start, step, max, context, f); if ((std::isnan(result.abscissa) || std::fabs(intersection.abscissa-start) < std::fabs(result.abscissa-start)) && !std::isnan(intersection.abscissa)) { m_intersectedFunction = f; result = (std::isnan(result.abscissa) || std::fabs(intersection.abscissa-start) < std::fabs(result.abscissa-start)) ? intersection : result; diff --git a/apps/graph/graph/intersection_graph_controller.h b/apps/graph/graph/intersection_graph_controller.h index 097de1377..8e7042081 100644 --- a/apps/graph/graph/intersection_graph_controller.h +++ b/apps/graph/graph/intersection_graph_controller.h @@ -11,7 +11,7 @@ public: const char * title() override; private: void reloadBannerView() override; - CartesianFunction::Point computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) override; + Poincare::Expression::Coordinate2D computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) override; Shared::Function * m_intersectedFunction; CartesianFunctionStore * m_functionStore; }; diff --git a/apps/graph/graph/root_graph_controller.cpp b/apps/graph/graph/root_graph_controller.cpp index ec1d379ff..07bb99147 100644 --- a/apps/graph/graph/root_graph_controller.cpp +++ b/apps/graph/graph/root_graph_controller.cpp @@ -15,7 +15,7 @@ const char * RootGraphController::title() { return I18n::translate(I18n::Message::Zeros); } -CartesianFunction::Point RootGraphController::computeNewPointOfInterest(double start, double step, double max, Context * context) { +Expression::Coordinate2D RootGraphController::computeNewPointOfInterest(double start, double step, double max, Context * context) { return {.abscissa = m_function->nextRootFrom(start, step, max, context), .value = 0.0}; } diff --git a/apps/graph/graph/root_graph_controller.h b/apps/graph/graph/root_graph_controller.h index 2d53898e7..4db493145 100644 --- a/apps/graph/graph/root_graph_controller.h +++ b/apps/graph/graph/root_graph_controller.h @@ -10,7 +10,7 @@ public: RootGraphController(Responder * parentResponder, GraphView * graphView, BannerView * bannerView, Shared::InteractiveCurveViewRange * curveViewRange, Shared::CurveViewCursor * cursor); const char * title() override; private: - CartesianFunction::Point computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) override; + Poincare::Expression::Coordinate2D computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) override; }; } diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 2bb8e8eeb..24e74a8c4 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -264,14 +264,14 @@ public: template T approximateWithValueForSymbol(char symbol, T x, Context & context) const; /* Expression roots/extrema solver*/ - struct Point { + struct Coordinate2D { double abscissa; double value; }; - Point nextMinimum(char symbol, double start, double step, double max, Context & context) const; - Point nextMaximum(char symbol, double start, double step, double max, Context & context) const; + Coordinate2D nextMinimum(char symbol, double start, double step, double max, Context & context) const; + Coordinate2D nextMaximum(char symbol, double start, double step, double max, Context & context) const; double nextRoot(char symbol, double start, double step, double max, Context & context) const; - Point nextIntersection(char symbol, double start, double step, double max, Context & context, const Expression * expression) const; + Coordinate2D nextIntersection(char symbol, double start, double step, double max, Context & context, const Expression * expression) const; protected: /* Constructor */ Expression() : m_parent(nullptr) {} @@ -334,9 +334,9 @@ private: constexpr static double k_sqrtEps = 1.4901161193847656E-8; // sqrt(DBL_EPSILON) constexpr static double k_goldenRatio = 0.381966011250105151795413165634361882279690820194237137864; // (3-sqrt(5))/2 typedef double (*EvaluationAtAbscissa)(char symbol, double abscissa, Context & context, const Expression * expression0, const Expression * expression1); - Point nextMinimumOfExpression(char symbol, double start, double step, double max, EvaluationAtAbscissa evaluation, Context & context, const Expression * expression = nullptr, bool lookForRootMinimum = false) const; + Coordinate2D nextMinimumOfExpression(char symbol, double start, double step, double max, EvaluationAtAbscissa evaluation, Context & context, const Expression * expression = nullptr, bool lookForRootMinimum = false) const; void bracketMinimum(char symbol, double start, double step, double max, double result[3], EvaluationAtAbscissa evaluation, Context & context, const Expression * expression = nullptr) const; - Point brentMinimum(char symbol, double ax, double bx, EvaluationAtAbscissa evaluation, Context & context, const Expression * expression = nullptr) const; + Coordinate2D brentMinimum(char symbol, double ax, double bx, EvaluationAtAbscissa evaluation, Context & context, const Expression * expression = nullptr) const; double nextIntersectionWithExpression(char symbol, double start, double step, double max, EvaluationAtAbscissa evaluation, Context & context, const Expression * expression) const; void bracketRoot(char symbol, double start, double step, double max, double result[2], EvaluationAtAbscissa evaluation, Context & context, const Expression * expression) const; double brentRoot(char symbol, double ax, double bx, double precision, EvaluationAtAbscissa evaluation, Context & context, const Expression * expression) const; diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 9f896c5ae..4b9805361 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -460,14 +460,14 @@ template T Expression::epsilon() { /* Expression roots/extrema solver*/ -Expression::Point Expression::nextMinimum(char symbol, double start, double step, double max, Context & context) const { +Expression::Coordinate2D Expression::nextMinimum(char symbol, double start, double step, double max, Context & context) const { return nextMinimumOfExpression(symbol, start, step, max, [](char symbol, double x, Context & context, const Expression * expression0, const Expression * expression1 = nullptr) { return expression0->approximateWithValueForSymbol(symbol, x, context); }, context); } -Expression::Point Expression::nextMaximum(char symbol, double start, double step, double max, Context & context) const { - Point minimumOfOpposite = nextMinimumOfExpression(symbol, start, step, max, [](char symbol, double x, Context & context, const Expression * expression0, const Expression * expression1 = nullptr) { +Expression::Coordinate2D Expression::nextMaximum(char symbol, double start, double step, double max, Context & context) const { + Coordinate2D minimumOfOpposite = nextMinimumOfExpression(symbol, start, step, max, [](char symbol, double x, Context & context, const Expression * expression0, const Expression * expression1 = nullptr) { return -expression0->approximateWithValueForSymbol(symbol, x, context); }, context); return {.abscissa = minimumOfOpposite.abscissa, .value = -minimumOfOpposite.value}; @@ -479,20 +479,20 @@ double Expression::nextRoot(char symbol, double start, double step, double max, }, context, nullptr); } -Expression::Point Expression::nextIntersection(char symbol, double start, double step, double max, Poincare::Context & context, const Expression * expression) const { +Expression::Coordinate2D Expression::nextIntersection(char symbol, double start, double step, double max, Poincare::Context & context, const Expression * expression) const { double resultAbscissa = nextIntersectionWithExpression(symbol, start, step, max, [](char symbol, double x, Context & context, const Expression * expression0, const Expression * expression1) { return expression0->approximateWithValueForSymbol(symbol, x, context)-expression1->approximateWithValueForSymbol(symbol, x, context); }, context, expression); - Expression::Point result = {.abscissa = resultAbscissa, .value = approximateWithValueForSymbol(symbol, resultAbscissa, context)}; + Expression::Coordinate2D result = {.abscissa = resultAbscissa, .value = approximateWithValueForSymbol(symbol, resultAbscissa, context)}; if (std::fabs(result.value) < step*k_solverPrecision) { result.value = 0.0; } return result; } -Expression::Point Expression::nextMinimumOfExpression(char symbol, double start, double step, double max, EvaluationAtAbscissa evaluate, Context & context, const Expression * expression, bool lookForRootMinimum) const { +Expression::Coordinate2D Expression::nextMinimumOfExpression(char symbol, double start, double step, double max, EvaluationAtAbscissa evaluate, Context & context, const Expression * expression, bool lookForRootMinimum) const { double bracket[3]; - Point result = {.abscissa = NAN, .value = NAN}; + Coordinate2D result = {.abscissa = NAN, .value = NAN}; double x = start; bool endCondition = false; do { @@ -519,7 +519,7 @@ Expression::Point Expression::nextMinimumOfExpression(char symbol, double start, } void Expression::bracketMinimum(char symbol, double start, double step, double max, double result[3], EvaluationAtAbscissa evaluate, Context & context, const Expression * expression) const { - Point p[3]; + Coordinate2D p[3]; p[0] = {.abscissa = start, .value = evaluate(symbol, start, context, this, expression)}; p[1] = {.abscissa = start+step, .value = evaluate(symbol, start+step, context, this, expression)}; double x = start+2.0*step; @@ -543,7 +543,7 @@ void Expression::bracketMinimum(char symbol, double start, double step, double m result[2] = NAN; } -Expression::Point Expression::brentMinimum(char symbol, double ax, double bx, EvaluationAtAbscissa evaluate, Context & context, const Expression * expression) const { +Expression::Coordinate2D Expression::brentMinimum(char symbol, double ax, double bx, EvaluationAtAbscissa evaluate, Context & context, const Expression * expression) const { /* Bibliography: R. P. Brent, Algorithms for finding zeros and extrema of * functions without calculating derivatives */ if (ax > bx) { @@ -572,7 +572,7 @@ Expression::Point Expression::brentMinimum(char symbol, double ax, double bx, Ev double fa = evaluate(symbol, a, context, this, expression); double fb = evaluate(symbol, b, context, this, expression); if (middleFax-fa <= k_sqrtEps && fx-middleFax <= k_sqrtEps && fx-middleFbx <= k_sqrtEps && middleFbx-fb <= k_sqrtEps) { - Point result = {.abscissa = x, .value = fx}; + Coordinate2D result = {.abscissa = x, .value = fx}; return result; } } @@ -633,7 +633,7 @@ Expression::Point Expression::brentMinimum(char symbol, double ax, double bx, Ev } } } - Point result = {.abscissa = NAN, .value = NAN}; + Coordinate2D result = {.abscissa = NAN, .value = NAN}; return result; } @@ -649,7 +649,7 @@ double Expression::nextIntersectionWithExpression(char symbol, double start, dou } while (std::isnan(result) && (step > 0.0 ? x <= max : x >= max)); double extremumMax = std::isnan(result) ? max : result; - Point resultExtremum[2] = { + Coordinate2D resultExtremum[2] = { nextMinimumOfExpression(symbol, start, step, extremumMax, [](char symbol, double x, Context & context, const Expression * expression0, const Expression * expression1) { if (expression1) { return expression0->approximateWithValueForSymbol(symbol, x, context)-expression1->approximateWithValueForSymbol(symbol, x, context);