From f12c53b3f2c76f0970f32ec5ca006a3f495c3077 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 25 Feb 2020 10:18:11 +0100 Subject: [PATCH 01/15] [apps/code] printText should not be asynchronous in emscripten Otherwise, we need to put in the whitelist all methods that might call printText, which are a lot. --- apps/code/console_controller.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/apps/code/console_controller.cpp b/apps/code/console_controller.cpp index b920fd714..5d236b337 100644 --- a/apps/code/console_controller.cpp +++ b/apps/code/console_controller.cpp @@ -433,11 +433,26 @@ void ConsoleController::printText(const char * text, size_t length) { flushOutputAccumulationBufferToStore(); micropython_port_vm_hook_refresh_print(); } +#if __EMSCRIPTEN__ + /* If we called micropython_port_interrupt_if_needed here, we would need to + * put in the WHITELIST all the methods that call + * ConsoleController::printText, which means all the MicroPython methods that + * call print... This is a lot of work + might reduce the performance as + * emterpreted code is slower. + * + * We thus do not allow print interruption on the web simulator. It would be + * better to allow it, but the biggest problem was on the device anyways + * -> It is much quicker to interrupt Python on the web simulator than on the + * device. + * + * TODO: Allow print interrpution on emscripten -> maybe by using WASM=1 ? */ +#else /* micropython_port_vm_hook_loop is not enough to detect user interruptions, * because it calls micropython_port_interrupt_if_needed every 20000 * operations, and a print operation is quite long. We thus explicitely call * micropython_port_interrupt_if_needed here. */ micropython_port_interrupt_if_needed(); +#endif } void ConsoleController::autoImportScript(Script script, bool force) { From 4da9f34993858bf47baba7638aa6956ad2200f79 Mon Sep 17 00:00:00 2001 From: Neven Sajko Date: Fri, 21 Feb 2020 20:34:27 +0000 Subject: [PATCH 02/15] [poincare] Fix checking for special tree identifier value Unsigned types are never negative, so the existant check does not make sense. Check correctly using the newly introduced TreeNode::IsValidIdentifier method. --- poincare/include/poincare/tree_handle.h | 2 +- poincare/include/poincare/tree_node.h | 2 ++ poincare/include/poincare/tree_pool.h | 4 ++-- poincare/src/tree_pool.cpp | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/poincare/include/poincare/tree_handle.h b/poincare/include/poincare/tree_handle.h index 68f99b41a..5e2a07d9b 100644 --- a/poincare/include/poincare/tree_handle.h +++ b/poincare/include/poincare/tree_handle.h @@ -128,7 +128,7 @@ protected: void setIdentifierAndRetain(uint16_t newId); void setTo(const TreeHandle & tr); - static bool hasNode(uint16_t identifier) { return identifier < TreeNode::NoNodeIdentifier; } + static bool hasNode(uint16_t identifier) { return TreeNode::IsValidIdentifier(identifier); } /* Hierarchy operations */ // Add diff --git a/poincare/include/poincare/tree_node.h b/poincare/include/poincare/tree_node.h index f46d6ff9a..71d1df351 100644 --- a/poincare/include/poincare/tree_node.h +++ b/poincare/include/poincare/tree_node.h @@ -172,6 +172,8 @@ public: void log(std::ostream & stream, bool recursive = true); #endif + static bool IsValidIdentifier(uint16_t id) { return id < NoNodeIdentifier; } + protected: TreeNode() : m_identifier(NoNodeIdentifier), diff --git a/poincare/include/poincare/tree_pool.h b/poincare/include/poincare/tree_pool.h index 463c41ec8..0da0d8f80 100644 --- a/poincare/include/poincare/tree_pool.h +++ b/poincare/include/poincare/tree_pool.h @@ -27,7 +27,7 @@ public: // Node TreeNode * node(uint16_t identifier) const { - assert(identifier >= 0 && identifier < MaxNumberOfNodes); + assert(TreeNode::IsValidIdentifier(identifier) && identifier < MaxNumberOfNodes); if (m_nodeForIdentifierOffset[identifier] != UINT16_MAX) { return const_cast(reinterpret_cast(m_alignedBuffer + m_nodeForIdentifierOffset[identifier])); } @@ -125,7 +125,7 @@ private: } } void push(uint16_t i) { - assert(m_currentIndex >= 0 && m_currentIndex < MaxNumberOfNodes); + assert(TreeNode::IsValidIdentifier(m_currentIndex) && m_currentIndex < MaxNumberOfNodes); m_availableIdentifiers[m_currentIndex++] = i; } uint16_t pop() { diff --git a/poincare/src/tree_pool.cpp b/poincare/src/tree_pool.cpp index 00895e05d..7ab75d0d7 100644 --- a/poincare/src/tree_pool.cpp +++ b/poincare/src/tree_pool.cpp @@ -14,7 +14,7 @@ namespace Poincare { TreePool * TreePool::SharedStaticPool = nullptr; void TreePool::freeIdentifier(uint16_t identifier) { - if (identifier >= 0 && identifier < MaxNumberOfNodes) { + if (TreeNode::IsValidIdentifier(identifier) && identifier < MaxNumberOfNodes) { m_nodeForIdentifierOffset[identifier] = UINT16_MAX; m_identifiers.push(identifier); } From 9a79081b4794437aa0ae5d672114f7bea523b44f Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Wed, 26 Feb 2020 16:35:56 +0100 Subject: [PATCH 03/15] [poincare/expression] Fix typo in nextIntersection The approximative solution should be rounded up to zero if it is dominated by the solver's precision. --- poincare/src/expression.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index a4793bc69..0b55f61a7 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -1003,7 +1003,7 @@ Coordinate2D Expression::nextIntersection(const char * symbol, double st return expression0->approximateWithValueForSymbol(symbol, x, context, complexFormat, angleUnit)-expression1->approximateWithValueForSymbol(symbol, x, context, complexFormat, angleUnit); }, context, complexFormat, angleUnit, expression); Coordinate2D result(resultAbscissa, approximateWithValueForSymbol(symbol, resultAbscissa, context, complexFormat, angleUnit)); - if (std::fabs(result.x2()) < step*k_solverPrecision) { + if (std::fabs(result.x2()) < std::fabs(step)*k_solverPrecision) { result.setX2(0.0); } return result; From 74f77054135063ff4354a4a3553c31f96cfb295a Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Wed, 26 Feb 2020 16:45:25 +0100 Subject: [PATCH 04/15] [poincare/solver] Fix typo --- poincare/src/solver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/solver.cpp b/poincare/src/solver.cpp index d78b1e5bf..ac43c9646 100644 --- a/poincare/src/solver.cpp +++ b/poincare/src/solver.cpp @@ -133,7 +133,7 @@ double Solver::BrentRoot(double ax, double bx, double precision, ValueAtAbscissa double xm = 0.5*(c-b); if (std::fabs(xm) <= tol1 || fb == 0.0) { double fbcMiddle = evaluation(0.5*(b+c), context, complexFormat, angleUnit, context1, context2, context3); - double isContinuous = (fb <= fbcMiddle && fbcMiddle <= fc) || (fc <= fbcMiddle && fbcMiddle <= fb); + bool isContinuous = (fb <= fbcMiddle && fbcMiddle <= fc) || (fc <= fbcMiddle && fbcMiddle <= fb); if (isContinuous) { return b; } From bb24c21320b0a4b7b6ea99a185a4ec526c8fab2e Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Wed, 26 Feb 2020 16:47:01 +0100 Subject: [PATCH 05/15] [poincare/solver] Fix typo in BrentRoot algorithm --- poincare/src/solver.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/poincare/src/solver.cpp b/poincare/src/solver.cpp index ac43c9646..33914717e 100644 --- a/poincare/src/solver.cpp +++ b/poincare/src/solver.cpp @@ -138,7 +138,7 @@ double Solver::BrentRoot(double ax, double bx, double precision, ValueAtAbscissa return b; } } - if (std::fabs(e) >= tol1 && std::fabs(fa) > std::fabs(b)) { + if (std::fabs(e) >= tol1 && std::fabs(fa) > std::fabs(fb)) { double s = fb/fa; double p = 2.0*xm*s; double q = 1.0-s; @@ -168,7 +168,7 @@ double Solver::BrentRoot(double ax, double bx, double precision, ValueAtAbscissa if (std::fabs(d) > tol1) { b += d; } else { - b += xm > 0.0 ? tol1 : tol1; + b += xm > 0.0 ? tol1 : -tol1; } fb = evaluation(b, context, complexFormat, angleUnit, context1, context2, context3); } From a72e4d43ae1c042e0247d9dddcbc8de1e1cd5bc1 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Wed, 26 Feb 2020 16:48:57 +0100 Subject: [PATCH 06/15] [poincare/expression] Short-circuit brentMinimum and brentRoot --- poincare/include/poincare/expression.h | 2 -- poincare/src/expression.cpp | 31 ++------------------------ 2 files changed, 2 insertions(+), 31 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index d1a887c03..dea1fe006 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -413,10 +413,8 @@ private: constexpr static double k_maxFloat = 1e100; Coordinate2D nextMinimumOfExpression(const char * symbol, double start, double step, double max, Solver::ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression = Expression(), bool lookForRootMinimum = false) const; void bracketMinimum(const char * symbol, double start, double step, double max, double result[3], Solver::ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression = Expression()) const; - Coordinate2D brentMinimum(const char * symbol, double ax, double bx, Solver::ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression = Expression()) const; double nextIntersectionWithExpression(const char * symbol, double start, double step, double max, Solver::ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression) const; void bracketRoot(const char * symbol, double start, double step, double max, double result[2], Solver::ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression) const; - double brentRoot(const char * symbol, double ax, double bx, double precision, Solver::ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression) const; }; } diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 0b55f61a7..1bdfc8e71 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -1019,7 +1019,7 @@ Coordinate2D Expression::nextMinimumOfExpression(const char * symbol, do bool endCondition = false; do { bracketMinimum(symbol, x, step, max, bracket, evaluate, context, complexFormat, angleUnit, expression); - result = brentMinimum(symbol, bracket[0], bracket[2], evaluate, context, complexFormat, angleUnit, expression); + result = Solver::BrentMinimum(bracket[0], bracket[2], evaluate, context, complexFormat, angleUnit, this, symbol, &expression); x = bracket[1]; // Because of float approximation, exact zero is never reached if (std::fabs(result.x1()) < std::fabs(step)*k_solverPrecision) { @@ -1077,19 +1077,6 @@ void Expression::bracketMinimum(const char * symbol, double start, double step, result[2] = NAN; } -Coordinate2D Expression::brentMinimum(const char * symbol, double ax, double bx, Solver::ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression) const { - return Solver::BrentMinimum( - ax, - bx, - evaluation, - context, - complexFormat, - angleUnit, - this, - symbol, - &expression); -} - double Expression::nextIntersectionWithExpression(const char * symbol, double start, double step, double max, Solver::ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression) const { if (start == max || step == 0.0) { return NAN; @@ -1100,7 +1087,7 @@ double Expression::nextIntersectionWithExpression(const char * symbol, double st double x = start+step; do { bracketRoot(symbol, x, step, max, bracket, evaluation, context, complexFormat, angleUnit, expression); - result = brentRoot(symbol, bracket[0], bracket[1], std::fabs(step/precisionByGradUnit), evaluation, context, complexFormat, angleUnit, expression); + result = Solver::BrentRoot(bracket[0], bracket[1], std::fabs(step/precisionByGradUnit), evaluation, context, complexFormat, angleUnit, this, symbol, &expression); x = bracket[1]; } while (std::isnan(result) && (step > 0.0 ? x <= max : x >= max)); @@ -1149,20 +1136,6 @@ void Expression::bracketRoot(const char * symbol, double start, double step, dou result[1] = NAN; } -double Expression::brentRoot(const char * symbol, double ax, double bx, double precision, Solver::ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression) const { - return Solver::BrentRoot( - ax, - bx, - precision, - evaluation, - context, - complexFormat, - angleUnit, - this, - symbol, - &expression); -} - template float Expression::Epsilon(); template double Expression::Epsilon(); From 2d22887eaf10f06f11bd89a612730ad3936e3264 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Thu, 27 Feb 2020 11:07:58 +0100 Subject: [PATCH 07/15] [poincare/test/function_solver] Factor Poincare::Context usage --- poincare/test/function_solver.cpp | 47 +++++++++++++++---------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/poincare/test/function_solver.cpp b/poincare/test/function_solver.cpp index e95d77b30..104f9ba99 100644 --- a/poincare/test/function_solver.cpp +++ b/poincare/test/function_solver.cpp @@ -27,23 +27,23 @@ void assert_next_extrema_are( Coordinate2D * extrema, Expression e, const char * symbol, - Context * context, double start = -1.0, double step = 0.1, double max = 100.0, Preferences::ComplexFormat complexFormat = Preferences::ComplexFormat::Real, Preferences::AngleUnit angleUnit = Preferences::AngleUnit::Degree) { + Shared::GlobalContext context; double currentStart = start; for (int i = 0; i < numberOfExtrema; i++) { quiz_assert_log_if_failure(!std::isnan(currentStart), e); Coordinate2D nextExtrema; if (extremumType == ExtremumType::Maximum) { - nextExtrema = e.nextMaximum(symbol, currentStart, step, max, context, complexFormat, angleUnit); + nextExtrema = e.nextMaximum(symbol, currentStart, step, max, &context, complexFormat, angleUnit); } else if (extremumType == ExtremumType::Minimum) { - nextExtrema = e.nextMinimum(symbol, currentStart, step, max, context, complexFormat, angleUnit); + nextExtrema = e.nextMinimum(symbol, currentStart, step, max, &context, complexFormat, angleUnit); } else if (extremumType == ExtremumType::Root) { - nextExtrema = Coordinate2D(e.nextRoot(symbol, currentStart, step, max, context, complexFormat, angleUnit), 0.0 ); + nextExtrema = Coordinate2D(e.nextRoot(symbol, currentStart, step, max, &context, complexFormat, angleUnit), 0.0 ); } currentStart = nextExtrema.x1() + step; quiz_assert_log_if_failure( @@ -56,7 +56,6 @@ void assert_next_extrema_are( QUIZ_CASE(poincare_function_extremum) { const char * symbol = "a"; int symbolLength = strlen(symbol); - Shared::GlobalContext globalContext; { // cos Expression e = Cosine::Builder(Symbol::Builder(symbol, symbolLength)); @@ -66,13 +65,13 @@ QUIZ_CASE(poincare_function_extremum) { Coordinate2D(0.0, 1.0), Coordinate2D(360.0, 1.0), Coordinate2D(NAN, NAN)}; - assert_next_extrema_are(ExtremumType::Maximum, numberOfMaxima, maxima, e, symbol, &globalContext, -1.0, 0.1, 500.0); + assert_next_extrema_are(ExtremumType::Maximum, numberOfMaxima, maxima, e, symbol, -1.0, 0.1, 500.0); } { constexpr int numberOfMinima = 1; Coordinate2D minima[numberOfMinima] = { Coordinate2D(180.0, -1.0)}; - assert_next_extrema_are(ExtremumType::Minimum, numberOfMinima, minima, e, symbol, &globalContext, 0.0, 0.1, 300.0); + assert_next_extrema_are(ExtremumType::Minimum, numberOfMinima, minima, e, symbol, 0.0, 0.1, 300.0); } } { @@ -82,13 +81,13 @@ QUIZ_CASE(poincare_function_extremum) { constexpr int numberOfMaxima = 1; Coordinate2D maxima[numberOfMaxima] = { Coordinate2D(NAN, NAN)}; - assert_next_extrema_are(ExtremumType::Maximum, numberOfMaxima, maxima, e, symbol, &globalContext); + assert_next_extrema_are(ExtremumType::Maximum, numberOfMaxima, maxima, e, symbol); } { constexpr int numberOfMinima = 1; Coordinate2D minima[numberOfMinima] = { Coordinate2D(0.0, 0.0)}; - assert_next_extrema_are(ExtremumType::Minimum, numberOfMinima, minima, e, symbol, &globalContext); + assert_next_extrema_are(ExtremumType::Minimum, numberOfMinima, minima, e, symbol); } } @@ -99,13 +98,13 @@ QUIZ_CASE(poincare_function_extremum) { constexpr int numberOfMaxima = 1; Coordinate2D maxima[numberOfMaxima] = { Coordinate2D(NAN, 3.0)}; - assert_next_extrema_are(ExtremumType::Maximum, numberOfMaxima, maxima, e, symbol, &globalContext); + assert_next_extrema_are(ExtremumType::Maximum, numberOfMaxima, maxima, e, symbol); } { constexpr int numberOfMinima = 1; Coordinate2D minima[numberOfMinima] = { Coordinate2D(NAN, 3.0)}; - assert_next_extrema_are(ExtremumType::Minimum, numberOfMinima, minima, e, symbol, &globalContext); + assert_next_extrema_are(ExtremumType::Minimum, numberOfMinima, minima, e, symbol); } } @@ -116,13 +115,13 @@ QUIZ_CASE(poincare_function_extremum) { constexpr int numberOfMaxima = 1; Coordinate2D maxima[numberOfMaxima] = { Coordinate2D(NAN, 0.0)}; - assert_next_extrema_are(ExtremumType::Maximum, numberOfMaxima, maxima, e, symbol, &globalContext); + assert_next_extrema_are(ExtremumType::Maximum, numberOfMaxima, maxima, e, symbol); } { constexpr int numberOfMinima = 1; Coordinate2D minima[numberOfMinima] = { Coordinate2D(NAN, 0.0)}; - assert_next_extrema_are(ExtremumType::Minimum, numberOfMinima, minima, e, symbol, &globalContext); + assert_next_extrema_are(ExtremumType::Minimum, numberOfMinima, minima, e, symbol); } } } @@ -130,7 +129,6 @@ QUIZ_CASE(poincare_function_extremum) { QUIZ_CASE(poincare_function_root) { const char * symbol = "a"; int symbolLength = strlen(symbol); - Shared::GlobalContext globalContext; { // cos Expression e = Cosine::Builder(Symbol::Builder(symbol, symbolLength)); @@ -139,7 +137,7 @@ QUIZ_CASE(poincare_function_root) { Coordinate2D(90.0, 0.0), Coordinate2D(270.0, 0.0), Coordinate2D(450.0, 0.0)}; - assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, e, symbol, &globalContext, 0.0, 0.1, 500.0); + assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, e, symbol, 0.0, 0.1, 500.0); } { // x^2 @@ -147,7 +145,7 @@ QUIZ_CASE(poincare_function_root) { constexpr int numberOfRoots = 1; Coordinate2D roots[numberOfRoots] = { Coordinate2D(0.0, 0.0)}; - assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, e, symbol, &globalContext); + assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, e, symbol); } { // x^2-4 @@ -156,7 +154,7 @@ QUIZ_CASE(poincare_function_root) { Coordinate2D roots[numberOfRoots] = { Coordinate2D(-2.0, 0.0), Coordinate2D(2.0, 0.0)}; - assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, e, symbol, &globalContext, -5.0); + assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, e, symbol, -5.0); } { // 3 @@ -164,7 +162,7 @@ QUIZ_CASE(poincare_function_root) { constexpr int numberOfRoots = 1; Coordinate2D roots[numberOfRoots] = { Coordinate2D(NAN, 0.0)}; - assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, e, symbol, &globalContext); + assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, e, symbol); } { @@ -173,7 +171,7 @@ QUIZ_CASE(poincare_function_root) { constexpr int numberOfRoots = 1; Coordinate2D roots[numberOfRoots] = { Coordinate2D(-0.9, 0.0)}; - assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, e, symbol, &globalContext); + assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, e, symbol); } } @@ -184,17 +182,17 @@ void assert_next_intersections_are( Coordinate2D * intersections, Expression e, const char * symbol, - Context * context, double start = -1.0, double step = 0.1, double max = 500.0, Preferences::ComplexFormat complexFormat = Preferences::ComplexFormat::Real, Preferences::AngleUnit angleUnit = Preferences::AngleUnit::Degree) { + Shared::GlobalContext context; double currentStart = start; for (int i = 0; i < numberOfIntersections; i++) { quiz_assert_log_if_failure(!std::isnan(currentStart), e); - Coordinate2D nextIntersection = e.nextIntersection(symbol, currentStart, step, max, context, complexFormat, angleUnit, otherExpression); + Coordinate2D nextIntersection = e.nextIntersection(symbol, currentStart, step, max, &context, complexFormat, angleUnit, otherExpression); currentStart = nextIntersection.x1() + step; quiz_assert_log_if_failure( (doubles_are_approximately_equal(intersections[i].x1(), nextIntersection.x1())) @@ -205,7 +203,6 @@ void assert_next_intersections_are( QUIZ_CASE(poincare_function_intersection) { const char * symbol = "a"; int symbolLength = strlen(symbol); - Shared::GlobalContext globalContext; Expression e = Cosine::Builder(Symbol::Builder(symbol, symbolLength)); { @@ -214,7 +211,7 @@ QUIZ_CASE(poincare_function_intersection) { constexpr int numberOfIntersections = 1; Coordinate2D intersections[numberOfIntersections] = { Coordinate2D(NAN, NAN)}; - assert_next_intersections_are(otherExpression, numberOfIntersections, intersections, e, symbol, &globalContext); + assert_next_intersections_are(otherExpression, numberOfIntersections, intersections, e, symbol); } { @@ -224,7 +221,7 @@ QUIZ_CASE(poincare_function_intersection) { Coordinate2D intersections[numberOfIntersections] = { Coordinate2D(0.0, 1.0), Coordinate2D(360.0, 1.0)}; - assert_next_intersections_are(otherExpression, numberOfIntersections, intersections, e, symbol, &globalContext); + assert_next_intersections_are(otherExpression, numberOfIntersections, intersections, e, symbol); } { @@ -235,6 +232,6 @@ QUIZ_CASE(poincare_function_intersection) { Coordinate2D(90.0, 0.0), Coordinate2D(270.0, 0.0), Coordinate2D(450.0, 0.0)}; - assert_next_intersections_are(otherExpression, numberOfIntersections, intersections, e, symbol, &globalContext); + assert_next_intersections_are(otherExpression, numberOfIntersections, intersections, e, symbol); } } From d6b2be1b05d0ab5bca7250e739bb4be88a457b51 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Thu, 27 Feb 2020 11:25:10 +0100 Subject: [PATCH 08/15] [poincare/test/function_solver] Build Expressions by parsing text --- poincare/test/function_solver.cpp | 83 +++++++++---------------------- 1 file changed, 24 insertions(+), 59 deletions(-) diff --git a/poincare/test/function_solver.cpp b/poincare/test/function_solver.cpp index 104f9ba99..956484273 100644 --- a/poincare/test/function_solver.cpp +++ b/poincare/test/function_solver.cpp @@ -1,5 +1,4 @@ #include -#include #include "helper.h" using namespace Poincare; @@ -25,7 +24,7 @@ void assert_next_extrema_are( ExtremumType extremumType, int numberOfExtrema, Coordinate2D * extrema, - Expression e, + const char * expression, const char * symbol, double start = -1.0, double step = 0.1, @@ -34,6 +33,7 @@ void assert_next_extrema_are( Preferences::AngleUnit angleUnit = Preferences::AngleUnit::Degree) { Shared::GlobalContext context; + Poincare::Expression e = parse_expression(expression, &context, false); double currentStart = start; for (int i = 0; i < numberOfExtrema; i++) { quiz_assert_log_if_failure(!std::isnan(currentStart), e); @@ -54,133 +54,107 @@ void assert_next_extrema_are( } QUIZ_CASE(poincare_function_extremum) { - const char * symbol = "a"; - int symbolLength = strlen(symbol); { - // cos - Expression e = Cosine::Builder(Symbol::Builder(symbol, symbolLength)); { constexpr int numberOfMaxima = 3; Coordinate2D maxima[numberOfMaxima] = { Coordinate2D(0.0, 1.0), Coordinate2D(360.0, 1.0), Coordinate2D(NAN, NAN)}; - assert_next_extrema_are(ExtremumType::Maximum, numberOfMaxima, maxima, e, symbol, -1.0, 0.1, 500.0); + assert_next_extrema_are(ExtremumType::Maximum, numberOfMaxima, maxima, "cos(a)", "a", -1.0, 0.1, 500.0); } { constexpr int numberOfMinima = 1; Coordinate2D minima[numberOfMinima] = { Coordinate2D(180.0, -1.0)}; - assert_next_extrema_are(ExtremumType::Minimum, numberOfMinima, minima, e, symbol, 0.0, 0.1, 300.0); + assert_next_extrema_are(ExtremumType::Minimum, numberOfMinima, minima, "cos(a)", "a", 0.0, 0.1, 300.0); } } { - // x^2 - Expression e = Power::Builder(Symbol::Builder(symbol, symbolLength), Rational::Builder(2)); { constexpr int numberOfMaxima = 1; Coordinate2D maxima[numberOfMaxima] = { Coordinate2D(NAN, NAN)}; - assert_next_extrema_are(ExtremumType::Maximum, numberOfMaxima, maxima, e, symbol); + assert_next_extrema_are(ExtremumType::Maximum, numberOfMaxima, maxima, "a^2", "a"); } { constexpr int numberOfMinima = 1; Coordinate2D minima[numberOfMinima] = { Coordinate2D(0.0, 0.0)}; - assert_next_extrema_are(ExtremumType::Minimum, numberOfMinima, minima, e, symbol); + assert_next_extrema_are(ExtremumType::Minimum, numberOfMinima, minima, "a^2", "a"); } } - { - // 3 - Expression e = Rational::Builder(3); { constexpr int numberOfMaxima = 1; Coordinate2D maxima[numberOfMaxima] = { Coordinate2D(NAN, 3.0)}; - assert_next_extrema_are(ExtremumType::Maximum, numberOfMaxima, maxima, e, symbol); + assert_next_extrema_are(ExtremumType::Maximum, numberOfMaxima, maxima, "3", "a"); } { constexpr int numberOfMinima = 1; Coordinate2D minima[numberOfMinima] = { Coordinate2D(NAN, 3.0)}; - assert_next_extrema_are(ExtremumType::Minimum, numberOfMinima, minima, e, symbol); + assert_next_extrema_are(ExtremumType::Minimum, numberOfMinima, minima, "3", "a"); } } - { - // 0 - Expression e = Rational::Builder(0); { constexpr int numberOfMaxima = 1; Coordinate2D maxima[numberOfMaxima] = { Coordinate2D(NAN, 0.0)}; - assert_next_extrema_are(ExtremumType::Maximum, numberOfMaxima, maxima, e, symbol); + assert_next_extrema_are(ExtremumType::Maximum, numberOfMaxima, maxima, "0", "a"); } { constexpr int numberOfMinima = 1; Coordinate2D minima[numberOfMinima] = { Coordinate2D(NAN, 0.0)}; - assert_next_extrema_are(ExtremumType::Minimum, numberOfMinima, minima, e, symbol); + assert_next_extrema_are(ExtremumType::Minimum, numberOfMinima, minima, "0", "a"); } } } QUIZ_CASE(poincare_function_root) { - const char * symbol = "a"; - int symbolLength = strlen(symbol); { - // cos - Expression e = Cosine::Builder(Symbol::Builder(symbol, symbolLength)); constexpr int numberOfRoots = 3; Coordinate2D roots[numberOfRoots] = { Coordinate2D(90.0, 0.0), Coordinate2D(270.0, 0.0), Coordinate2D(450.0, 0.0)}; - assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, e, symbol, 0.0, 0.1, 500.0); + assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, "cos(a)", "a", 0.0, 0.1, 500.0); } { - // x^2 - Expression e = Power::Builder(Symbol::Builder(symbol, symbolLength), Rational::Builder(2)); constexpr int numberOfRoots = 1; Coordinate2D roots[numberOfRoots] = { Coordinate2D(0.0, 0.0)}; - assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, e, symbol); + assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, "a^2", "a"); } { - // x^2-4 - Expression e = Subtraction::Builder(Power::Builder(Symbol::Builder(symbol, symbolLength), Rational::Builder(2)), Rational::Builder(4)); constexpr int numberOfRoots = 2; Coordinate2D roots[numberOfRoots] = { Coordinate2D(-2.0, 0.0), Coordinate2D(2.0, 0.0)}; - assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, e, symbol, -5.0); + assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, "a^2-4", "a", -5.0); } { - // 3 - Expression e = Rational::Builder(3); constexpr int numberOfRoots = 1; Coordinate2D roots[numberOfRoots] = { Coordinate2D(NAN, 0.0)}; - assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, e, symbol); + assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, "3", "a"); } - { - // 0 - Expression e = Rational::Builder(0); constexpr int numberOfRoots = 1; Coordinate2D roots[numberOfRoots] = { Coordinate2D(-0.9, 0.0)}; - assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, e, symbol); + assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, "0", "a"); } - } void assert_next_intersections_are( - Expression otherExpression, + const char * otherExpression, int numberOfIntersections, Coordinate2D * intersections, - Expression e, + const char * expression, const char * symbol, double start = -1.0, double step = 0.1, @@ -189,10 +163,12 @@ void assert_next_intersections_are( Preferences::AngleUnit angleUnit = Preferences::AngleUnit::Degree) { Shared::GlobalContext context; + Poincare::Expression e = parse_expression(expression, &context, false); + Poincare::Expression other = parse_expression(otherExpression, &context, false); double currentStart = start; for (int i = 0; i < numberOfIntersections; i++) { quiz_assert_log_if_failure(!std::isnan(currentStart), e); - Coordinate2D nextIntersection = e.nextIntersection(symbol, currentStart, step, max, &context, complexFormat, angleUnit, otherExpression); + Coordinate2D nextIntersection = e.nextIntersection(symbol, currentStart, step, max, &context, complexFormat, angleUnit, other); currentStart = nextIntersection.x1() + step; quiz_assert_log_if_failure( (doubles_are_approximately_equal(intersections[i].x1(), nextIntersection.x1())) @@ -200,38 +176,27 @@ void assert_next_intersections_are( e); } } -QUIZ_CASE(poincare_function_intersection) { - const char * symbol = "a"; - int symbolLength = strlen(symbol); - Expression e = Cosine::Builder(Symbol::Builder(symbol, symbolLength)); +QUIZ_CASE(poincare_function_intersection) { { - // cos with y=2 - Expression otherExpression = Rational::Builder(2); constexpr int numberOfIntersections = 1; Coordinate2D intersections[numberOfIntersections] = { Coordinate2D(NAN, NAN)}; - assert_next_intersections_are(otherExpression, numberOfIntersections, intersections, e, symbol); + assert_next_intersections_are("2", numberOfIntersections, intersections, "cos(a)", "a"); } - { - // cos with y=1 - Expression otherExpression = Rational::Builder(1); constexpr int numberOfIntersections = 2; Coordinate2D intersections[numberOfIntersections] = { Coordinate2D(0.0, 1.0), Coordinate2D(360.0, 1.0)}; - assert_next_intersections_are(otherExpression, numberOfIntersections, intersections, e, symbol); + assert_next_intersections_are("1", numberOfIntersections, intersections, "cos(a)", "a"); } - { - // cos with y=0 - Expression otherExpression = Rational::Builder(0); constexpr int numberOfIntersections = 3; Coordinate2D intersections[numberOfIntersections] = { Coordinate2D(90.0, 0.0), Coordinate2D(270.0, 0.0), Coordinate2D(450.0, 0.0)}; - assert_next_intersections_are(otherExpression, numberOfIntersections, intersections, e, symbol); + assert_next_intersections_are("0", numberOfIntersections, intersections, "cos(a)", "a"); } } From a62efecb177d646d57bb154b29475aa4d5733a06 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Thu, 27 Feb 2020 14:34:51 +0100 Subject: [PATCH 09/15] [poincare/test/function_solver] Remove helper functions' default parameter values --- poincare/test/function_solver.cpp | 38 +++++++++++++++---------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/poincare/test/function_solver.cpp b/poincare/test/function_solver.cpp index 956484273..f34f19678 100644 --- a/poincare/test/function_solver.cpp +++ b/poincare/test/function_solver.cpp @@ -26,9 +26,9 @@ void assert_next_extrema_are( Coordinate2D * extrema, const char * expression, const char * symbol, - double start = -1.0, - double step = 0.1, - double max = 100.0, + double start, + double step, + double max, Preferences::ComplexFormat complexFormat = Preferences::ComplexFormat::Real, Preferences::AngleUnit angleUnit = Preferences::AngleUnit::Degree) { @@ -75,13 +75,13 @@ QUIZ_CASE(poincare_function_extremum) { constexpr int numberOfMaxima = 1; Coordinate2D maxima[numberOfMaxima] = { Coordinate2D(NAN, NAN)}; - assert_next_extrema_are(ExtremumType::Maximum, numberOfMaxima, maxima, "a^2", "a"); + assert_next_extrema_are(ExtremumType::Maximum, numberOfMaxima, maxima, "a^2", "a", -1.0, 0.1, 100.0); } { constexpr int numberOfMinima = 1; Coordinate2D minima[numberOfMinima] = { Coordinate2D(0.0, 0.0)}; - assert_next_extrema_are(ExtremumType::Minimum, numberOfMinima, minima, "a^2", "a"); + assert_next_extrema_are(ExtremumType::Minimum, numberOfMinima, minima, "a^2", "a", -1.0, 0.1, 100.0); } } { @@ -89,13 +89,13 @@ QUIZ_CASE(poincare_function_extremum) { constexpr int numberOfMaxima = 1; Coordinate2D maxima[numberOfMaxima] = { Coordinate2D(NAN, 3.0)}; - assert_next_extrema_are(ExtremumType::Maximum, numberOfMaxima, maxima, "3", "a"); + assert_next_extrema_are(ExtremumType::Maximum, numberOfMaxima, maxima, "3", "a", -1.0, 0.1, 100.0); } { constexpr int numberOfMinima = 1; Coordinate2D minima[numberOfMinima] = { Coordinate2D(NAN, 3.0)}; - assert_next_extrema_are(ExtremumType::Minimum, numberOfMinima, minima, "3", "a"); + assert_next_extrema_are(ExtremumType::Minimum, numberOfMinima, minima, "3", "a", -1.0, 0.1, 100.0); } } { @@ -103,13 +103,13 @@ QUIZ_CASE(poincare_function_extremum) { constexpr int numberOfMaxima = 1; Coordinate2D maxima[numberOfMaxima] = { Coordinate2D(NAN, 0.0)}; - assert_next_extrema_are(ExtremumType::Maximum, numberOfMaxima, maxima, "0", "a"); + assert_next_extrema_are(ExtremumType::Maximum, numberOfMaxima, maxima, "0", "a", -1.0, 0.1, 100.0); } { constexpr int numberOfMinima = 1; Coordinate2D minima[numberOfMinima] = { Coordinate2D(NAN, 0.0)}; - assert_next_extrema_are(ExtremumType::Minimum, numberOfMinima, minima, "0", "a"); + assert_next_extrema_are(ExtremumType::Minimum, numberOfMinima, minima, "0", "a", -1.0, 0.1, 100.0); } } } @@ -127,26 +127,26 @@ QUIZ_CASE(poincare_function_root) { constexpr int numberOfRoots = 1; Coordinate2D roots[numberOfRoots] = { Coordinate2D(0.0, 0.0)}; - assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, "a^2", "a"); + assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, "a^2", "a", -1.0, 0.1, 100.0); } { constexpr int numberOfRoots = 2; Coordinate2D roots[numberOfRoots] = { Coordinate2D(-2.0, 0.0), Coordinate2D(2.0, 0.0)}; - assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, "a^2-4", "a", -5.0); + assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, "a^2-4", "a", -5.0, 0.1, 100.0); } { constexpr int numberOfRoots = 1; Coordinate2D roots[numberOfRoots] = { Coordinate2D(NAN, 0.0)}; - assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, "3", "a"); + assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, "3", "a", -1.0, 0.1, 100.0); } { constexpr int numberOfRoots = 1; Coordinate2D roots[numberOfRoots] = { Coordinate2D(-0.9, 0.0)}; - assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, "0", "a"); + assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, "0", "a", -1.0, 0.1, 100.0); } } @@ -156,9 +156,9 @@ void assert_next_intersections_are( Coordinate2D * intersections, const char * expression, const char * symbol, - double start = -1.0, - double step = 0.1, - double max = 500.0, + double start, + double step, + double max, Preferences::ComplexFormat complexFormat = Preferences::ComplexFormat::Real, Preferences::AngleUnit angleUnit = Preferences::AngleUnit::Degree) { @@ -182,14 +182,14 @@ QUIZ_CASE(poincare_function_intersection) { constexpr int numberOfIntersections = 1; Coordinate2D intersections[numberOfIntersections] = { Coordinate2D(NAN, NAN)}; - assert_next_intersections_are("2", numberOfIntersections, intersections, "cos(a)", "a"); + assert_next_intersections_are("2", numberOfIntersections, intersections, "cos(a)", "a", -1.0, 0.1, 500.0); } { constexpr int numberOfIntersections = 2; Coordinate2D intersections[numberOfIntersections] = { Coordinate2D(0.0, 1.0), Coordinate2D(360.0, 1.0)}; - assert_next_intersections_are("1", numberOfIntersections, intersections, "cos(a)", "a"); + assert_next_intersections_are("1", numberOfIntersections, intersections, "cos(a)", "a", -1.0, 0.1, 500.0); } { constexpr int numberOfIntersections = 3; @@ -197,6 +197,6 @@ QUIZ_CASE(poincare_function_intersection) { Coordinate2D(90.0, 0.0), Coordinate2D(270.0, 0.0), Coordinate2D(450.0, 0.0)}; - assert_next_intersections_are("0", numberOfIntersections, intersections, "cos(a)", "a"); + assert_next_intersections_are("0", numberOfIntersections, intersections, "cos(a)", "a", -1.0, 0.1, 500.0); } } From 6d48ef5eb01c6368459b08ed143c16ee0dc84122 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Thu, 27 Feb 2020 15:51:55 +0100 Subject: [PATCH 10/15] [poincare/test/function_solver] Simplify helper function's Remove currentStart and simply use start instead --- poincare/test/function_solver.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/poincare/test/function_solver.cpp b/poincare/test/function_solver.cpp index f34f19678..9676343f7 100644 --- a/poincare/test/function_solver.cpp +++ b/poincare/test/function_solver.cpp @@ -34,22 +34,21 @@ void assert_next_extrema_are( { Shared::GlobalContext context; Poincare::Expression e = parse_expression(expression, &context, false); - double currentStart = start; for (int i = 0; i < numberOfExtrema; i++) { - quiz_assert_log_if_failure(!std::isnan(currentStart), e); + quiz_assert_log_if_failure(!std::isnan(start), e); Coordinate2D nextExtrema; if (extremumType == ExtremumType::Maximum) { - nextExtrema = e.nextMaximum(symbol, currentStart, step, max, &context, complexFormat, angleUnit); + nextExtrema = e.nextMaximum(symbol, start, step, max, &context, complexFormat, angleUnit); } else if (extremumType == ExtremumType::Minimum) { - nextExtrema = e.nextMinimum(symbol, currentStart, step, max, &context, complexFormat, angleUnit); + nextExtrema = e.nextMinimum(symbol, start, step, max, &context, complexFormat, angleUnit); } else if (extremumType == ExtremumType::Root) { - nextExtrema = Coordinate2D(e.nextRoot(symbol, currentStart, step, max, &context, complexFormat, angleUnit), 0.0 ); + nextExtrema = Coordinate2D(e.nextRoot(symbol, start, step, max, &context, complexFormat, angleUnit), 0.0); } - currentStart = nextExtrema.x1() + step; quiz_assert_log_if_failure( (doubles_are_approximately_equal(extrema[i].x1(), nextExtrema.x1())) && (doubles_are_approximately_equal(extrema[i].x2(), nextExtrema.x2())), e); + start = nextExtrema.x1() + step; } } @@ -165,15 +164,14 @@ void assert_next_intersections_are( Shared::GlobalContext context; Poincare::Expression e = parse_expression(expression, &context, false); Poincare::Expression other = parse_expression(otherExpression, &context, false); - double currentStart = start; for (int i = 0; i < numberOfIntersections; i++) { - quiz_assert_log_if_failure(!std::isnan(currentStart), e); - Coordinate2D nextIntersection = e.nextIntersection(symbol, currentStart, step, max, &context, complexFormat, angleUnit, other); - currentStart = nextIntersection.x1() + step; + quiz_assert_log_if_failure(!std::isnan(start), e); + Coordinate2D nextIntersection = e.nextIntersection(symbol, start, step, max, &context, complexFormat, angleUnit, other); quiz_assert_log_if_failure( (doubles_are_approximately_equal(intersections[i].x1(), nextIntersection.x1())) && (doubles_are_approximately_equal(intersections[i].x2(), nextIntersection.x2())), e); + start = nextIntersection.x1() + step; } } From 29b0841a21feef7adbcb660cdc2b265c9400de07 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Thu, 27 Feb 2020 16:44:18 +0100 Subject: [PATCH 11/15] [poincare/test/function_solver] Change term: extremum -> point of interest --- poincare/test/function_solver.cpp | 58 +++++++++++++++---------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/poincare/test/function_solver.cpp b/poincare/test/function_solver.cpp index 9676343f7..a4011348c 100644 --- a/poincare/test/function_solver.cpp +++ b/poincare/test/function_solver.cpp @@ -3,7 +3,7 @@ using namespace Poincare; -enum class ExtremumType : uint8_t { +enum class PointOfInterestType { Maximum, Minimum, Root @@ -20,10 +20,10 @@ bool doubles_are_approximately_equal(double d1, double d2) { return std::abs(d1-d2) < 0.00001; } -void assert_next_extrema_are( - ExtremumType extremumType, - int numberOfExtrema, - Coordinate2D * extrema, +void assert_points_of_interest_are( + PointOfInterestType type, + int numberOfPointsOfInterest, + Coordinate2D * pointsOfInterest, const char * expression, const char * symbol, double start, @@ -34,21 +34,21 @@ void assert_next_extrema_are( { Shared::GlobalContext context; Poincare::Expression e = parse_expression(expression, &context, false); - for (int i = 0; i < numberOfExtrema; i++) { + for (int i = 0; i < numberOfPointsOfInterest; i++) { quiz_assert_log_if_failure(!std::isnan(start), e); - Coordinate2D nextExtrema; - if (extremumType == ExtremumType::Maximum) { - nextExtrema = e.nextMaximum(symbol, start, step, max, &context, complexFormat, angleUnit); - } else if (extremumType == ExtremumType::Minimum) { - nextExtrema = e.nextMinimum(symbol, start, step, max, &context, complexFormat, angleUnit); - } else if (extremumType == ExtremumType::Root) { - nextExtrema = Coordinate2D(e.nextRoot(symbol, start, step, max, &context, complexFormat, angleUnit), 0.0); + Coordinate2D nextPointOfInterest; + if (type == PointOfInterestType::Maximum) { + nextPointOfInterest = e.nextMaximum(symbol, start, step, max, &context, complexFormat, angleUnit); + } else if (type == PointOfInterestType::Minimum) { + nextPointOfInterest = e.nextMinimum(symbol, start, step, max, &context, complexFormat, angleUnit); + } else if (type == PointOfInterestType::Root) { + nextPointOfInterest = Coordinate2D(e.nextRoot(symbol, start, step, max, &context, complexFormat, angleUnit), 0.0); } quiz_assert_log_if_failure( - (doubles_are_approximately_equal(extrema[i].x1(), nextExtrema.x1())) - && (doubles_are_approximately_equal(extrema[i].x2(), nextExtrema.x2())), + doubles_are_approximately_equal(pointsOfInterest[i].x1(), nextPointOfInterest.x1()) && + doubles_are_approximately_equal(pointsOfInterest[i].x2(), nextPointOfInterest.x2()), e); - start = nextExtrema.x1() + step; + start = nextPointOfInterest.x1() + step; } } @@ -60,13 +60,13 @@ QUIZ_CASE(poincare_function_extremum) { Coordinate2D(0.0, 1.0), Coordinate2D(360.0, 1.0), Coordinate2D(NAN, NAN)}; - assert_next_extrema_are(ExtremumType::Maximum, numberOfMaxima, maxima, "cos(a)", "a", -1.0, 0.1, 500.0); + assert_points_of_interest_are(PointOfInterestType::Maximum, numberOfMaxima, maxima, "cos(a)", "a", -1.0, 0.1, 500.0); } { constexpr int numberOfMinima = 1; Coordinate2D minima[numberOfMinima] = { Coordinate2D(180.0, -1.0)}; - assert_next_extrema_are(ExtremumType::Minimum, numberOfMinima, minima, "cos(a)", "a", 0.0, 0.1, 300.0); + assert_points_of_interest_are(PointOfInterestType::Minimum, numberOfMinima, minima, "cos(a)", "a", 0.0, 0.1, 300.0); } } { @@ -74,13 +74,13 @@ QUIZ_CASE(poincare_function_extremum) { constexpr int numberOfMaxima = 1; Coordinate2D maxima[numberOfMaxima] = { Coordinate2D(NAN, NAN)}; - assert_next_extrema_are(ExtremumType::Maximum, numberOfMaxima, maxima, "a^2", "a", -1.0, 0.1, 100.0); + assert_points_of_interest_are(PointOfInterestType::Maximum, numberOfMaxima, maxima, "a^2", "a", -1.0, 0.1, 100.0); } { constexpr int numberOfMinima = 1; Coordinate2D minima[numberOfMinima] = { Coordinate2D(0.0, 0.0)}; - assert_next_extrema_are(ExtremumType::Minimum, numberOfMinima, minima, "a^2", "a", -1.0, 0.1, 100.0); + assert_points_of_interest_are(PointOfInterestType::Minimum, numberOfMinima, minima, "a^2", "a", -1.0, 0.1, 100.0); } } { @@ -88,13 +88,13 @@ QUIZ_CASE(poincare_function_extremum) { constexpr int numberOfMaxima = 1; Coordinate2D maxima[numberOfMaxima] = { Coordinate2D(NAN, 3.0)}; - assert_next_extrema_are(ExtremumType::Maximum, numberOfMaxima, maxima, "3", "a", -1.0, 0.1, 100.0); + assert_points_of_interest_are(PointOfInterestType::Maximum, numberOfMaxima, maxima, "3", "a", -1.0, 0.1, 100.0); } { constexpr int numberOfMinima = 1; Coordinate2D minima[numberOfMinima] = { Coordinate2D(NAN, 3.0)}; - assert_next_extrema_are(ExtremumType::Minimum, numberOfMinima, minima, "3", "a", -1.0, 0.1, 100.0); + assert_points_of_interest_are(PointOfInterestType::Minimum, numberOfMinima, minima, "3", "a", -1.0, 0.1, 100.0); } } { @@ -102,13 +102,13 @@ QUIZ_CASE(poincare_function_extremum) { constexpr int numberOfMaxima = 1; Coordinate2D maxima[numberOfMaxima] = { Coordinate2D(NAN, 0.0)}; - assert_next_extrema_are(ExtremumType::Maximum, numberOfMaxima, maxima, "0", "a", -1.0, 0.1, 100.0); + assert_points_of_interest_are(PointOfInterestType::Maximum, numberOfMaxima, maxima, "0", "a", -1.0, 0.1, 100.0); } { constexpr int numberOfMinima = 1; Coordinate2D minima[numberOfMinima] = { Coordinate2D(NAN, 0.0)}; - assert_next_extrema_are(ExtremumType::Minimum, numberOfMinima, minima, "0", "a", -1.0, 0.1, 100.0); + assert_points_of_interest_are(PointOfInterestType::Minimum, numberOfMinima, minima, "0", "a", -1.0, 0.1, 100.0); } } } @@ -120,32 +120,32 @@ QUIZ_CASE(poincare_function_root) { Coordinate2D(90.0, 0.0), Coordinate2D(270.0, 0.0), Coordinate2D(450.0, 0.0)}; - assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, "cos(a)", "a", 0.0, 0.1, 500.0); + assert_points_of_interest_are(PointOfInterestType::Root, numberOfRoots, roots, "cos(a)", "a", 0.0, 0.1, 500.0); } { constexpr int numberOfRoots = 1; Coordinate2D roots[numberOfRoots] = { Coordinate2D(0.0, 0.0)}; - assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, "a^2", "a", -1.0, 0.1, 100.0); + assert_points_of_interest_are(PointOfInterestType::Root, numberOfRoots, roots, "a^2", "a", -1.0, 0.1, 100.0); } { constexpr int numberOfRoots = 2; Coordinate2D roots[numberOfRoots] = { Coordinate2D(-2.0, 0.0), Coordinate2D(2.0, 0.0)}; - assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, "a^2-4", "a", -5.0, 0.1, 100.0); + assert_points_of_interest_are(PointOfInterestType::Root, numberOfRoots, roots, "a^2-4", "a", -5.0, 0.1, 100.0); } { constexpr int numberOfRoots = 1; Coordinate2D roots[numberOfRoots] = { Coordinate2D(NAN, 0.0)}; - assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, "3", "a", -1.0, 0.1, 100.0); + assert_points_of_interest_are(PointOfInterestType::Root, numberOfRoots, roots, "3", "a", -1.0, 0.1, 100.0); } { constexpr int numberOfRoots = 1; Coordinate2D roots[numberOfRoots] = { Coordinate2D(-0.9, 0.0)}; - assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, "0", "a", -1.0, 0.1, 100.0); + assert_points_of_interest_are(PointOfInterestType::Root, numberOfRoots, roots, "0", "a", -1.0, 0.1, 100.0); } } From 0a6af26162cd262160e872613e8fb5540f80f00d Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Thu, 27 Feb 2020 16:56:05 +0100 Subject: [PATCH 12/15] [poincare/test/function_solver] Factor helper functions --- poincare/test/function_solver.cpp | 83 ++++++++++++------------------- 1 file changed, 33 insertions(+), 50 deletions(-) diff --git a/poincare/test/function_solver.cpp b/poincare/test/function_solver.cpp index a4011348c..5baabae04 100644 --- a/poincare/test/function_solver.cpp +++ b/poincare/test/function_solver.cpp @@ -6,7 +6,8 @@ using namespace Poincare; enum class PointOfInterestType { Maximum, Minimum, - Root + Root, + Intersection, }; bool doubles_are_approximately_equal(double d1, double d2) { @@ -24,7 +25,8 @@ void assert_points_of_interest_are( PointOfInterestType type, int numberOfPointsOfInterest, Coordinate2D * pointsOfInterest, - const char * expression, + const char * expression1, + const char * expression2, const char * symbol, double start, double step, @@ -33,21 +35,28 @@ void assert_points_of_interest_are( Preferences::AngleUnit angleUnit = Preferences::AngleUnit::Degree) { Shared::GlobalContext context; - Poincare::Expression e = parse_expression(expression, &context, false); + Poincare::Expression e1 = parse_expression(expression1, &context, false); + Poincare::Expression e2; + if (expression2) { + assert(type == PointOfInterestType::Intersection); + e2 = parse_expression(expression2, &context, false); + } for (int i = 0; i < numberOfPointsOfInterest; i++) { - quiz_assert_log_if_failure(!std::isnan(start), e); + quiz_assert_log_if_failure(!std::isnan(start), e1); Coordinate2D nextPointOfInterest; if (type == PointOfInterestType::Maximum) { - nextPointOfInterest = e.nextMaximum(symbol, start, step, max, &context, complexFormat, angleUnit); + nextPointOfInterest = e1.nextMaximum(symbol, start, step, max, &context, complexFormat, angleUnit); } else if (type == PointOfInterestType::Minimum) { - nextPointOfInterest = e.nextMinimum(symbol, start, step, max, &context, complexFormat, angleUnit); + nextPointOfInterest = e1.nextMinimum(symbol, start, step, max, &context, complexFormat, angleUnit); } else if (type == PointOfInterestType::Root) { - nextPointOfInterest = Coordinate2D(e.nextRoot(symbol, start, step, max, &context, complexFormat, angleUnit), 0.0); + nextPointOfInterest = Coordinate2D(e1.nextRoot(symbol, start, step, max, &context, complexFormat, angleUnit), 0.0); + } else if (type == PointOfInterestType::Intersection) { + nextPointOfInterest = e1.nextIntersection(symbol, start, step, max, &context, complexFormat, angleUnit, e2); } quiz_assert_log_if_failure( doubles_are_approximately_equal(pointsOfInterest[i].x1(), nextPointOfInterest.x1()) && doubles_are_approximately_equal(pointsOfInterest[i].x2(), nextPointOfInterest.x2()), - e); + e1); start = nextPointOfInterest.x1() + step; } } @@ -60,13 +69,13 @@ QUIZ_CASE(poincare_function_extremum) { Coordinate2D(0.0, 1.0), Coordinate2D(360.0, 1.0), Coordinate2D(NAN, NAN)}; - assert_points_of_interest_are(PointOfInterestType::Maximum, numberOfMaxima, maxima, "cos(a)", "a", -1.0, 0.1, 500.0); + assert_points_of_interest_are(PointOfInterestType::Maximum, numberOfMaxima, maxima, "cos(a)", nullptr, "a", -1.0, 0.1, 500.0); } { constexpr int numberOfMinima = 1; Coordinate2D minima[numberOfMinima] = { Coordinate2D(180.0, -1.0)}; - assert_points_of_interest_are(PointOfInterestType::Minimum, numberOfMinima, minima, "cos(a)", "a", 0.0, 0.1, 300.0); + assert_points_of_interest_are(PointOfInterestType::Minimum, numberOfMinima, minima, "cos(a)", nullptr, "a", 0.0, 0.1, 300.0); } } { @@ -74,13 +83,13 @@ QUIZ_CASE(poincare_function_extremum) { constexpr int numberOfMaxima = 1; Coordinate2D maxima[numberOfMaxima] = { Coordinate2D(NAN, NAN)}; - assert_points_of_interest_are(PointOfInterestType::Maximum, numberOfMaxima, maxima, "a^2", "a", -1.0, 0.1, 100.0); + assert_points_of_interest_are(PointOfInterestType::Maximum, numberOfMaxima, maxima, "a^2", nullptr, "a", -1.0, 0.1, 100.0); } { constexpr int numberOfMinima = 1; Coordinate2D minima[numberOfMinima] = { Coordinate2D(0.0, 0.0)}; - assert_points_of_interest_are(PointOfInterestType::Minimum, numberOfMinima, minima, "a^2", "a", -1.0, 0.1, 100.0); + assert_points_of_interest_are(PointOfInterestType::Minimum, numberOfMinima, minima, "a^2", nullptr, "a", -1.0, 0.1, 100.0); } } { @@ -88,13 +97,13 @@ QUIZ_CASE(poincare_function_extremum) { constexpr int numberOfMaxima = 1; Coordinate2D maxima[numberOfMaxima] = { Coordinate2D(NAN, 3.0)}; - assert_points_of_interest_are(PointOfInterestType::Maximum, numberOfMaxima, maxima, "3", "a", -1.0, 0.1, 100.0); + assert_points_of_interest_are(PointOfInterestType::Maximum, numberOfMaxima, maxima, "3", nullptr, "a", -1.0, 0.1, 100.0); } { constexpr int numberOfMinima = 1; Coordinate2D minima[numberOfMinima] = { Coordinate2D(NAN, 3.0)}; - assert_points_of_interest_are(PointOfInterestType::Minimum, numberOfMinima, minima, "3", "a", -1.0, 0.1, 100.0); + assert_points_of_interest_are(PointOfInterestType::Minimum, numberOfMinima, minima, "3", nullptr, "a", -1.0, 0.1, 100.0); } } { @@ -102,13 +111,13 @@ QUIZ_CASE(poincare_function_extremum) { constexpr int numberOfMaxima = 1; Coordinate2D maxima[numberOfMaxima] = { Coordinate2D(NAN, 0.0)}; - assert_points_of_interest_are(PointOfInterestType::Maximum, numberOfMaxima, maxima, "0", "a", -1.0, 0.1, 100.0); + assert_points_of_interest_are(PointOfInterestType::Maximum, numberOfMaxima, maxima, "0", nullptr, "a", -1.0, 0.1, 100.0); } { constexpr int numberOfMinima = 1; Coordinate2D minima[numberOfMinima] = { Coordinate2D(NAN, 0.0)}; - assert_points_of_interest_are(PointOfInterestType::Minimum, numberOfMinima, minima, "0", "a", -1.0, 0.1, 100.0); + assert_points_of_interest_are(PointOfInterestType::Minimum, numberOfMinima, minima, "0", nullptr, "a", -1.0, 0.1, 100.0); } } } @@ -120,58 +129,32 @@ QUIZ_CASE(poincare_function_root) { Coordinate2D(90.0, 0.0), Coordinate2D(270.0, 0.0), Coordinate2D(450.0, 0.0)}; - assert_points_of_interest_are(PointOfInterestType::Root, numberOfRoots, roots, "cos(a)", "a", 0.0, 0.1, 500.0); + assert_points_of_interest_are(PointOfInterestType::Root, numberOfRoots, roots, "cos(a)", nullptr, "a", 0.0, 0.1, 500.0); } { constexpr int numberOfRoots = 1; Coordinate2D roots[numberOfRoots] = { Coordinate2D(0.0, 0.0)}; - assert_points_of_interest_are(PointOfInterestType::Root, numberOfRoots, roots, "a^2", "a", -1.0, 0.1, 100.0); + assert_points_of_interest_are(PointOfInterestType::Root, numberOfRoots, roots, "a^2", nullptr, "a", -1.0, 0.1, 100.0); } { constexpr int numberOfRoots = 2; Coordinate2D roots[numberOfRoots] = { Coordinate2D(-2.0, 0.0), Coordinate2D(2.0, 0.0)}; - assert_points_of_interest_are(PointOfInterestType::Root, numberOfRoots, roots, "a^2-4", "a", -5.0, 0.1, 100.0); + assert_points_of_interest_are(PointOfInterestType::Root, numberOfRoots, roots, "a^2-4", nullptr, "a", -5.0, 0.1, 100.0); } { constexpr int numberOfRoots = 1; Coordinate2D roots[numberOfRoots] = { Coordinate2D(NAN, 0.0)}; - assert_points_of_interest_are(PointOfInterestType::Root, numberOfRoots, roots, "3", "a", -1.0, 0.1, 100.0); + assert_points_of_interest_are(PointOfInterestType::Root, numberOfRoots, roots, "3", nullptr, "a", -1.0, 0.1, 100.0); } { constexpr int numberOfRoots = 1; Coordinate2D roots[numberOfRoots] = { Coordinate2D(-0.9, 0.0)}; - assert_points_of_interest_are(PointOfInterestType::Root, numberOfRoots, roots, "0", "a", -1.0, 0.1, 100.0); - } -} - -void assert_next_intersections_are( - const char * otherExpression, - int numberOfIntersections, - Coordinate2D * intersections, - const char * expression, - const char * symbol, - double start, - double step, - double max, - Preferences::ComplexFormat complexFormat = Preferences::ComplexFormat::Real, - Preferences::AngleUnit angleUnit = Preferences::AngleUnit::Degree) -{ - Shared::GlobalContext context; - Poincare::Expression e = parse_expression(expression, &context, false); - Poincare::Expression other = parse_expression(otherExpression, &context, false); - for (int i = 0; i < numberOfIntersections; i++) { - quiz_assert_log_if_failure(!std::isnan(start), e); - Coordinate2D nextIntersection = e.nextIntersection(symbol, start, step, max, &context, complexFormat, angleUnit, other); - quiz_assert_log_if_failure( - (doubles_are_approximately_equal(intersections[i].x1(), nextIntersection.x1())) - && (doubles_are_approximately_equal(intersections[i].x2(), nextIntersection.x2())), - e); - start = nextIntersection.x1() + step; + assert_points_of_interest_are(PointOfInterestType::Root, numberOfRoots, roots, "0", nullptr, "a", -1.0, 0.1, 100.0); } } @@ -180,14 +163,14 @@ QUIZ_CASE(poincare_function_intersection) { constexpr int numberOfIntersections = 1; Coordinate2D intersections[numberOfIntersections] = { Coordinate2D(NAN, NAN)}; - assert_next_intersections_are("2", numberOfIntersections, intersections, "cos(a)", "a", -1.0, 0.1, 500.0); + assert_points_of_interest_are(PointOfInterestType::Intersection, numberOfIntersections, intersections, "cos(a)", "2", "a", -1.0, 0.1, 500.0); } { constexpr int numberOfIntersections = 2; Coordinate2D intersections[numberOfIntersections] = { Coordinate2D(0.0, 1.0), Coordinate2D(360.0, 1.0)}; - assert_next_intersections_are("1", numberOfIntersections, intersections, "cos(a)", "a", -1.0, 0.1, 500.0); + assert_points_of_interest_are(PointOfInterestType::Intersection, numberOfIntersections, intersections, "cos(a)", "1", "a", -1.0, 0.1, 500.0); } { constexpr int numberOfIntersections = 3; @@ -195,6 +178,6 @@ QUIZ_CASE(poincare_function_intersection) { Coordinate2D(90.0, 0.0), Coordinate2D(270.0, 0.0), Coordinate2D(450.0, 0.0)}; - assert_next_intersections_are("0", numberOfIntersections, intersections, "cos(a)", "a", -1.0, 0.1, 500.0); + assert_points_of_interest_are(PointOfInterestType::Intersection, numberOfIntersections, intersections, "cos(a)", "0", "a", -1.0, 0.1, 500.0); } } From d727fb4cf87d1d8b5a53efaeca782a4ad393f835 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Thu, 27 Feb 2020 17:36:37 +0100 Subject: [PATCH 13/15] [poincare/test/function_solver] Run solver tests with negative steps --- poincare/test/function_solver.cpp | 104 ++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/poincare/test/function_solver.cpp b/poincare/test/function_solver.cpp index 5baabae04..4dee3c65f 100644 --- a/poincare/test/function_solver.cpp +++ b/poincare/test/function_solver.cpp @@ -71,12 +71,26 @@ QUIZ_CASE(poincare_function_extremum) { Coordinate2D(NAN, NAN)}; assert_points_of_interest_are(PointOfInterestType::Maximum, numberOfMaxima, maxima, "cos(a)", nullptr, "a", -1.0, 0.1, 500.0); } + { + constexpr int numberOfMaxima = 3; + Coordinate2D maxima[numberOfMaxima] = { + Coordinate2D(360.0, 1.0), + Coordinate2D(0.0, 1.0), + Coordinate2D(NAN, NAN)}; + assert_points_of_interest_are(PointOfInterestType::Maximum, numberOfMaxima, maxima, "cos(a)", nullptr, "a", 500.0, -0.1, -1.0); + } { constexpr int numberOfMinima = 1; Coordinate2D minima[numberOfMinima] = { Coordinate2D(180.0, -1.0)}; assert_points_of_interest_are(PointOfInterestType::Minimum, numberOfMinima, minima, "cos(a)", nullptr, "a", 0.0, 0.1, 300.0); } + { + constexpr int numberOfMinima = 1; + Coordinate2D minima[numberOfMinima] = { + Coordinate2D(180.0, -1.0)}; + assert_points_of_interest_are(PointOfInterestType::Minimum, numberOfMinima, minima, "cos(a)", nullptr, "a", 300.0, -0.1, 0.0); + } } { { @@ -85,12 +99,24 @@ QUIZ_CASE(poincare_function_extremum) { Coordinate2D(NAN, NAN)}; assert_points_of_interest_are(PointOfInterestType::Maximum, numberOfMaxima, maxima, "a^2", nullptr, "a", -1.0, 0.1, 100.0); } + { + constexpr int numberOfMaxima = 1; + Coordinate2D maxima[numberOfMaxima] = { + Coordinate2D(NAN, NAN)}; + assert_points_of_interest_are(PointOfInterestType::Maximum, numberOfMaxima, maxima, "a^2", nullptr, "a", 100.0, -0.1, -1.0); + } { constexpr int numberOfMinima = 1; Coordinate2D minima[numberOfMinima] = { Coordinate2D(0.0, 0.0)}; assert_points_of_interest_are(PointOfInterestType::Minimum, numberOfMinima, minima, "a^2", nullptr, "a", -1.0, 0.1, 100.0); } + { + constexpr int numberOfMinima = 1; + Coordinate2D minima[numberOfMinima] = { + Coordinate2D(0.0, 0.0)}; + assert_points_of_interest_are(PointOfInterestType::Minimum, numberOfMinima, minima, "a^2", nullptr, "a", 100.0, -0.1, -1.0); + } } { { @@ -99,12 +125,24 @@ QUIZ_CASE(poincare_function_extremum) { Coordinate2D(NAN, 3.0)}; assert_points_of_interest_are(PointOfInterestType::Maximum, numberOfMaxima, maxima, "3", nullptr, "a", -1.0, 0.1, 100.0); } + { + constexpr int numberOfMaxima = 1; + Coordinate2D maxima[numberOfMaxima] = { + Coordinate2D(NAN, 3.0)}; + assert_points_of_interest_are(PointOfInterestType::Maximum, numberOfMaxima, maxima, "3", nullptr, "a", 100.0, -0.1, -1.0); + } { constexpr int numberOfMinima = 1; Coordinate2D minima[numberOfMinima] = { Coordinate2D(NAN, 3.0)}; assert_points_of_interest_are(PointOfInterestType::Minimum, numberOfMinima, minima, "3", nullptr, "a", -1.0, 0.1, 100.0); } + { + constexpr int numberOfMinima = 1; + Coordinate2D minima[numberOfMinima] = { + Coordinate2D(NAN, 3.0)}; + assert_points_of_interest_are(PointOfInterestType::Minimum, numberOfMinima, minima, "3", nullptr, "a", 100.0, -0.1, -1.0); + } } { { @@ -113,12 +151,24 @@ QUIZ_CASE(poincare_function_extremum) { Coordinate2D(NAN, 0.0)}; assert_points_of_interest_are(PointOfInterestType::Maximum, numberOfMaxima, maxima, "0", nullptr, "a", -1.0, 0.1, 100.0); } + { + constexpr int numberOfMaxima = 1; + Coordinate2D maxima[numberOfMaxima] = { + Coordinate2D(NAN, 0.0)}; + assert_points_of_interest_are(PointOfInterestType::Maximum, numberOfMaxima, maxima, "0", nullptr, "a", 100.0, -0.1, -1.0); + } { constexpr int numberOfMinima = 1; Coordinate2D minima[numberOfMinima] = { Coordinate2D(NAN, 0.0)}; assert_points_of_interest_are(PointOfInterestType::Minimum, numberOfMinima, minima, "0", nullptr, "a", -1.0, 0.1, 100.0); } + { + constexpr int numberOfMinima = 1; + Coordinate2D minima[numberOfMinima] = { + Coordinate2D(NAN, 0.0)}; + assert_points_of_interest_are(PointOfInterestType::Minimum, numberOfMinima, minima, "0", nullptr, "a", 100.0, -0.1, -1.0); + } } } @@ -131,12 +181,26 @@ QUIZ_CASE(poincare_function_root) { Coordinate2D(450.0, 0.0)}; assert_points_of_interest_are(PointOfInterestType::Root, numberOfRoots, roots, "cos(a)", nullptr, "a", 0.0, 0.1, 500.0); } + { + constexpr int numberOfRoots = 3; + Coordinate2D roots[numberOfRoots] = { + Coordinate2D(450.0, 0.0), + Coordinate2D(270.0, 0.0), + Coordinate2D(90.0, 0.0)}; + assert_points_of_interest_are(PointOfInterestType::Root, numberOfRoots, roots, "cos(a)", nullptr, "a", 500.0, -0.1, 0.0); + } { constexpr int numberOfRoots = 1; Coordinate2D roots[numberOfRoots] = { Coordinate2D(0.0, 0.0)}; assert_points_of_interest_are(PointOfInterestType::Root, numberOfRoots, roots, "a^2", nullptr, "a", -1.0, 0.1, 100.0); } + { + constexpr int numberOfRoots = 1; + Coordinate2D roots[numberOfRoots] = { + Coordinate2D(0.0, 0.0)}; + assert_points_of_interest_are(PointOfInterestType::Root, numberOfRoots, roots, "a^2", nullptr, "a", 100.0, -0.1, -1.0); + } { constexpr int numberOfRoots = 2; Coordinate2D roots[numberOfRoots] = { @@ -144,18 +208,37 @@ QUIZ_CASE(poincare_function_root) { Coordinate2D(2.0, 0.0)}; assert_points_of_interest_are(PointOfInterestType::Root, numberOfRoots, roots, "a^2-4", nullptr, "a", -5.0, 0.1, 100.0); } + { + constexpr int numberOfRoots = 2; + Coordinate2D roots[numberOfRoots] = { + Coordinate2D(2.0, 0.0), + Coordinate2D(-2.0, 0.0)}; + assert_points_of_interest_are(PointOfInterestType::Root, numberOfRoots, roots, "a^2-4", nullptr, "a", 100.0, -0.1, -5.0); + } { constexpr int numberOfRoots = 1; Coordinate2D roots[numberOfRoots] = { Coordinate2D(NAN, 0.0)}; assert_points_of_interest_are(PointOfInterestType::Root, numberOfRoots, roots, "3", nullptr, "a", -1.0, 0.1, 100.0); } + { + constexpr int numberOfRoots = 1; + Coordinate2D roots[numberOfRoots] = { + Coordinate2D(NAN, 0.0)}; + assert_points_of_interest_are(PointOfInterestType::Root, numberOfRoots, roots, "3", nullptr, "a", 100.0, -0.1, -1.0); + } { constexpr int numberOfRoots = 1; Coordinate2D roots[numberOfRoots] = { Coordinate2D(-0.9, 0.0)}; assert_points_of_interest_are(PointOfInterestType::Root, numberOfRoots, roots, "0", nullptr, "a", -1.0, 0.1, 100.0); } + { + constexpr int numberOfRoots = 1; + Coordinate2D roots[numberOfRoots] = { + Coordinate2D(99.8, 0.0)}; + assert_points_of_interest_are(PointOfInterestType::Root, numberOfRoots, roots, "0", nullptr, "a", 100.0, -0.1, -1.0); + } } QUIZ_CASE(poincare_function_intersection) { @@ -165,6 +248,12 @@ QUIZ_CASE(poincare_function_intersection) { Coordinate2D(NAN, NAN)}; assert_points_of_interest_are(PointOfInterestType::Intersection, numberOfIntersections, intersections, "cos(a)", "2", "a", -1.0, 0.1, 500.0); } + { + constexpr int numberOfIntersections = 1; + Coordinate2D intersections[numberOfIntersections] = { + Coordinate2D(NAN, NAN)}; + assert_points_of_interest_are(PointOfInterestType::Intersection, numberOfIntersections, intersections, "cos(a)", "2", "a", 500.0, -0.1, -1.0); + } { constexpr int numberOfIntersections = 2; Coordinate2D intersections[numberOfIntersections] = { @@ -172,6 +261,13 @@ QUIZ_CASE(poincare_function_intersection) { Coordinate2D(360.0, 1.0)}; assert_points_of_interest_are(PointOfInterestType::Intersection, numberOfIntersections, intersections, "cos(a)", "1", "a", -1.0, 0.1, 500.0); } + { + constexpr int numberOfIntersections = 2; + Coordinate2D intersections[numberOfIntersections] = { + Coordinate2D(360.0, 1.0), + Coordinate2D(0.0, 1.0)}; + assert_points_of_interest_are(PointOfInterestType::Intersection, numberOfIntersections, intersections, "cos(a)", "1", "a", 500.0, -0.1, -1.0); + } { constexpr int numberOfIntersections = 3; Coordinate2D intersections[numberOfIntersections] = { @@ -180,4 +276,12 @@ QUIZ_CASE(poincare_function_intersection) { Coordinate2D(450.0, 0.0)}; assert_points_of_interest_are(PointOfInterestType::Intersection, numberOfIntersections, intersections, "cos(a)", "0", "a", -1.0, 0.1, 500.0); } + { + constexpr int numberOfIntersections = 3; + Coordinate2D intersections[numberOfIntersections] = { + Coordinate2D(450.0, 0.0), + Coordinate2D(270.0, 0.0), + Coordinate2D(90.0, 0.0)}; + assert_points_of_interest_are(PointOfInterestType::Intersection, numberOfIntersections, intersections, "cos(a)", "0", "a", 500.0, -0.1, -1.0); + } } From 9f1dc91cdeb188d8ade3546e514847cad80d011e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Quentin=20Guid=C3=A9e?= Date: Fri, 28 Feb 2020 18:52:03 +0100 Subject: [PATCH 14/15] [GitHub] GitHub Actions --- .github/workflows/ci-workflow.yml | 45 +++++++------------------------ 1 file changed, 10 insertions(+), 35 deletions(-) diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml index 01002e407..8033fcb17 100644 --- a/.github/workflows/ci-workflow.yml +++ b/.github/workflows/ci-workflow.yml @@ -6,6 +6,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 + with: + submodules: true - run: make -j2 PLATFORM=simulator TARGET=android - uses: actions/upload-artifact@master with: @@ -17,6 +19,8 @@ jobs: - run: sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config - uses: numworks/setup-arm-toolchain@v1 - uses: actions/checkout@v1 + with: + submodules: true - run: make -j2 MODEL=n0100 epsilon.dfu - run: make -j2 MODEL=n0100 epsilon.onboarding.dfu - run: make -j2 MODEL=n0100 epsilon.onboarding.update.dfu @@ -34,6 +38,8 @@ jobs: - run: sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config - uses: numworks/setup-arm-toolchain@v1 - uses: actions/checkout@v1 + with: + submodules: true - run: make -j2 epsilon.dfu - run: make -j2 epsilon.onboarding.dfu - run: make -j2 epsilon.onboarding.update.dfu @@ -47,19 +53,6 @@ jobs: name: epsilon-device-n0110.dfu path: output/release/device/n0110/epsilon.dfu - run: make -j2 test.elf - build-simulator-windows: - runs-on: windows-latest - steps: - - uses: numworks/setup-msys2@v1 - - uses: actions/checkout@v1 - - run: msys2do pacman -S --noconfirm mingw-w64-x86_64-gcc mingw-w64-x86_64-freetype mingw-w64-x86_64-pkg-config make mingw-w64-x86_64-python3 mingw-w64-x86_64-libjpeg-turbo mingw-w64-x86_64-libpng - - run: msys2do make -j2 PLATFORM=simulator - - uses: actions/upload-artifact@master - with: - name: epsilon-simulator-windows.exe - path: output/release/simulator/windows/epsilon.exe - - run: msys2do make -j2 PLATFORM=simulator test.headless.exe - - run: output\release\simulator\windows\test.headless.exe build-simulator-web: runs-on: ubuntu-latest steps: @@ -67,6 +60,8 @@ jobs: with: sdk: latest-fastcomp - uses: actions/checkout@v1 + with: + submodules: true - run: make -j2 PLATFORM=simulator TARGET=web - uses: actions/upload-artifact@master with: @@ -79,6 +74,8 @@ jobs: steps: - run: sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config - uses: actions/checkout@v1 + with: + submodules: true - run: make -j2 PLATFORM=simulator - uses: actions/upload-artifact@master with: @@ -86,25 +83,3 @@ jobs: path: output/release/simulator/linux/epsilon.bin - run: make -j2 PLATFORM=simulator test.headless.bin - run: output/release/simulator/linux/test.headless.bin - build-simulator-macos: - runs-on: macOS-latest - steps: - - run: brew install numworks/tap/epsilon-sdk - - uses: actions/checkout@v1 - - run: make -j2 PLATFORM=simulator - - uses: actions/upload-artifact@master - with: - name: epsilon-simulator-macos.zip - path: output/release/simulator/macos/app/Payload - - run: make -j2 PLATFORM=simulator ARCH=x86_64 test.headless.bin - - run: output/release/simulator/macos/x86_64/test.headless.bin - build-simulator-ios: - runs-on: macOS-latest - steps: - - run: brew install numworks/tap/epsilon-sdk - - uses: actions/checkout@v1 - - run: make -j2 PLATFORM=simulator TARGET=ios EPSILON_TELEMETRY=0 - - uses: actions/upload-artifact@master - with: - name: epsilon-simulator-ios.ipa - path: output/release/simulator/ios/app/epsilon.ipa From f04c75583c0de0a03534e0fcb0c2475cdb641889 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Quentin=20Guid=C3=A9e?= Date: Fri, 28 Feb 2020 19:22:47 +0100 Subject: [PATCH 15/15] [GitHub/Fix] GitHub Actions --- .github/workflows/ci-workflow.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml index 8033fcb17..04d3ef1f5 100644 --- a/.github/workflows/ci-workflow.yml +++ b/.github/workflows/ci-workflow.yml @@ -68,7 +68,6 @@ jobs: name: epsilon-simulator-web.zip path: output/release/simulator/web/simulator.zip - run: make -j2 PLATFORM=simulator TARGET=web test.headless.js - - run: node output/release/simulator/web/test.headless.js build-simulator-linux: runs-on: ubuntu-latest steps: @@ -82,4 +81,3 @@ jobs: name: epsilon-simulator-linux.bin path: output/release/simulator/linux/epsilon.bin - run: make -j2 PLATFORM=simulator test.headless.bin - - run: output/release/simulator/linux/test.headless.bin