diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 9db2b6c43..e3dfcf3f7 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -440,10 +440,9 @@ Expression Multiplication::shallowBeautify(ExpressionNode::ReductionContext redu * - Repeat those steps until no more simplification is possible. */ Multiplication unitsAccu = Multiplication::Builder(); - /* If exponents are not integers, FromBaseUnits will return the closest - * representation of units with base units and integer exponents. - * It cause no problem because once the best derived units are found, - * units is divided then multiplied by them. */ + /* If exponents are not integers, FromBaseUnits will return a null + * vector, preventing any attempt at simplification. This protects us + * against undue "simplifications" such as _C^1.3 -> _C*_A^0.3*_s^0.3 */ UnitNode::Vector unitsExponents = UnitNode::Vector::FromBaseUnits(units); size_t unitsSupportSize = unitsExponents.supportSize(); UnitNode::Vector bestRemainderExponents; diff --git a/poincare/src/unit.cpp b/poincare/src/unit.cpp index 9bb2370d0..901085695 100644 --- a/poincare/src/unit.cpp +++ b/poincare/src/unit.cpp @@ -128,6 +128,12 @@ UnitNode::Vector UnitNode::Vector::FromBaseUnits(const Expression base assert(exp.type() == ExpressionNode::Type::Rational); // Using the closest integer to the exponent. float exponentFloat = static_cast(exp).node()->templatedApproximate(); + if (exponentFloat != std::round(exponentFloat)) { + /* If non-integer exponents are found, we round a null vector so that + * Multiplication::shallowBeautify will not attempt to find derived + * units. */ + return vector; + } /* We limit to INT_MAX / 3 because an exponent might get bigger with * simplification. As a worst case scenario, (_s²_m²_kg/_A²)^n should be * simplified to (_s^5_S)^n. If 2*n is under INT_MAX, 5*n might not. */ diff --git a/poincare/test/simplification.cpp b/poincare/test/simplification.cpp index b8bc06276..8ccc7718b 100644 --- a/poincare/test/simplification.cpp +++ b/poincare/test/simplification.cpp @@ -361,6 +361,13 @@ QUIZ_CASE(poincare_simplification_units) { assert_parsed_expression_simplify_to("1/(-3_°C)", Undefined::Name()); assert_parsed_expression_simplify_to("-1×100×_°C→_K", Undefined::Name()); + /* Rational exponents */ + assert_parsed_expression_simplify_to("√(_m)", "1×_m^\u00121/2\u0013"); + assert_parsed_expression_simplify_to("√(_N)", "1×_kg^\u00121/2\u0013×_m^\u00121/2\u0013×_s^\u0012-1\u0013"); + assert_parsed_expression_simplify_to("√(_N)", "1.5527410012845×_lb^\u00121/2\u0013×_yd^\u00121/2\u0013×_s^\u0012-1\u0013", User, Radian, Imperial); + assert_parsed_expression_simplify_to("_C^0.3", "1×_A^\u00123/10\u0013×_s^\u00123/10\u0013"); + assert_parsed_expression_simplify_to("_kat_kg^-2.8", "1×_mol×_kg^\u0012-14/5\u0013×_s^\u0012-1\u0013"); + /* Unit sum/subtract */ assert_parsed_expression_simplify_to("_m+_m", "2×_m"); assert_parsed_expression_simplify_to("_m-_m", "0×_m"); @@ -528,6 +535,7 @@ QUIZ_CASE(poincare_simplification_units) { assert_parsed_expression_simplify_to("-2×_A", "-2×_A"); assert_parsed_expression_simplify_to("cos(1_s/1_s)", "cos(1)"); assert_parsed_expression_simplify_to("1_m+π_m+√(2)_m-cos(15)_m", "6.3154941288217×_m"); + assert_parsed_expression_simplify_to("√(16×_m^2)", "4×_m"); } QUIZ_CASE(poincare_simplification_power) {