diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index b31f894f1..a15acd8c4 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -506,50 +506,49 @@ Expression Multiplication::shallowBeautify(ExpressionNode::ReductionContext redu units = unitsUnits; } - if (result.isUninitialized()) { - result = units; + double value = 1.0; + if (!result.isUninitialized()) { + value = result.approximateToScalar(reductionContext.context(), reductionContext.complexFormat(), reductionContext.angleUnit()); + } + if (std::isnan(value)) { + // If the value is undefined, return "undef" without any unit + result = Undefined::Builder(); } else { - double value = result.approximateToScalar(reductionContext.context(), reductionContext.complexFormat(), reductionContext.angleUnit()); - if (std::isnan(value)) { - // If the value is undefined, return "undef" without any unit - result = Undefined::Builder(); + Expression resultWithoutUnit; + if (std::isinf(value)) { + resultWithoutUnit = Infinity::Builder(value < 0.0); } else { - Expression resultWithoutUnit; - if (std::isinf(value)) { - resultWithoutUnit = Infinity::Builder(value < 0.0); - } else { - // Find the right unit prefix when the value ≠ 0 - if (value != 0.0) { - // Identify the first Unit factor and its exponent - Expression firstFactor = units; - int exponent = 1; - if (firstFactor.type() == ExpressionNode::Type::Multiplication) { - firstFactor = firstFactor.childAtIndex(0); - } - if (firstFactor.type() == ExpressionNode::Type::Power) { - Expression exp = firstFactor.childAtIndex(1); - firstFactor = firstFactor.childAtIndex(0); - assert(exp.type() == ExpressionNode::Type::Rational && static_cast(exp).isInteger()); - Integer expInt = static_cast(exp).signedIntegerNumerator(); - if (expInt.isLowerThan(Integer(Integer::k_maxExtractableInteger))) { - exponent = expInt.extractedInt(); - } else { - // The exponent is too large to be extracted, so do not try to use it. - exponent = 0; - } - } - assert(firstFactor.type() == ExpressionNode::Type::Unit); - // Choose its multiple and update value accordingly - if (exponent != 0) { - static_cast(firstFactor).chooseBestMultipleForValue(value, exponent, reductionContext); + // Find the right unit prefix when the value ≠ 0 + if (value != 0.0 && value != 1.0) { + // Identify the first Unit factor and its exponent + Expression firstFactor = units; + int exponent = 1; + if (firstFactor.type() == ExpressionNode::Type::Multiplication) { + firstFactor = firstFactor.childAtIndex(0); + } + if (firstFactor.type() == ExpressionNode::Type::Power) { + Expression exp = firstFactor.childAtIndex(1); + firstFactor = firstFactor.childAtIndex(0); + assert(exp.type() == ExpressionNode::Type::Rational && static_cast(exp).isInteger()); + Integer expInt = static_cast(exp).signedIntegerNumerator(); + if (expInt.isLowerThan(Integer(Integer::k_maxExtractableInteger))) { + exponent = expInt.extractedInt(); + } else { + // The exponent is too large to be extracted, so do not try to use it. + exponent = 0; } } - resultWithoutUnit = Float::Builder(value); + assert(firstFactor.type() == ExpressionNode::Type::Unit); + // Choose its multiple and update value accordingly + if (exponent != 0) { + static_cast(firstFactor).chooseBestMultipleForValue(value, exponent, reductionContext); + } } - // Build final Expression - result = Multiplication::Builder(resultWithoutUnit, units); - static_cast(result).mergeMultiplicationChildrenInPlace(); + resultWithoutUnit = Float::Builder(value); } + // Build final Expression + result = Multiplication::Builder(resultWithoutUnit, units); + static_cast(result).mergeMultiplicationChildrenInPlace(); } } diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 5191ddc42..fead4207b 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -904,6 +905,14 @@ Expression Power::shallowBeautify(ExpressionNode::ReductionContext reductionCont return result; } + // Step 4: Force Float(1) in front of an orphan Power of Unit + if (parent().isUninitialized() && childAtIndex(0).type() == ExpressionNode::Type::Unit) { + Multiplication m = Multiplication::Builder(Float::Builder(1.0)); + replaceWithInPlace(m); + m.addChildAtIndexInPlace(*this, 1, 1); + return std::move(m); + } + return *this; } diff --git a/poincare/src/unit.cpp b/poincare/src/unit.cpp index 31ad8994f..2c64f11f0 100644 --- a/poincare/src/unit.cpp +++ b/poincare/src/unit.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -250,6 +251,13 @@ Expression Unit::shallowReduce(ExpressionNode::ReductionContext reductionContext Expression Unit::shallowBeautify(ExpressionNode::ReductionContext reductionContext) { Expression ancestor = parent(); + // Force Float(1) in front of an orphan Unit + if (ancestor.isUninitialized()) { + Multiplication m = Multiplication::Builder(Float::Builder(1.0)); + replaceWithInPlace(m); + m.addChildAtIndexInPlace(*this, 1, 1); + return std::move(m); + } // Check that the exponent, if any, of a Unit is an integer if (!ancestor.isUninitialized() && ancestor.type() == ExpressionNode::Type::Power) { Expression exponent = ancestor.childAtIndex(1); diff --git a/poincare/test/simplification.cpp b/poincare/test/simplification.cpp index 80eb16db1..0428f49df 100644 --- a/poincare/test/simplification.cpp +++ b/poincare/test/simplification.cpp @@ -196,47 +196,43 @@ QUIZ_CASE(poincare_simplification_multiplication) { QUIZ_CASE(poincare_simplification_units) { /* SI base units */ - assert_parsed_expression_simplify_to("_s", "_s"); - assert_parsed_expression_simplify_to("_m", "_m"); - assert_parsed_expression_simplify_to("_kg", "_kg"); - assert_parsed_expression_simplify_to("_A", "_A"); - assert_parsed_expression_simplify_to("_K", "_K"); - assert_parsed_expression_simplify_to("_mol", "_mol"); - assert_parsed_expression_simplify_to("_cd", "_cd"); + assert_parsed_expression_simplify_to("_s", "1×_s"); + assert_parsed_expression_simplify_to("_m", "1×_m"); + assert_parsed_expression_simplify_to("_kg", "1×_kg"); + assert_parsed_expression_simplify_to("_A", "1×_A"); + assert_parsed_expression_simplify_to("_K", "1×_K"); + assert_parsed_expression_simplify_to("_mol", "1×_mol"); + assert_parsed_expression_simplify_to("_cd", "1×_cd"); /* Inverses of SI base units */ - assert_parsed_expression_simplify_to("_s^-1", "_s^\u0012-1\u0013"); - assert_parsed_expression_simplify_to("_m^-1", "_m^\u0012-1\u0013"); - assert_parsed_expression_simplify_to("_kg^-1", "_kg^\u0012-1\u0013"); - assert_parsed_expression_simplify_to("_A^-1", "_A^\u0012-1\u0013"); - assert_parsed_expression_simplify_to("_K^-1", "_K^\u0012-1\u0013"); - assert_parsed_expression_simplify_to("_mol^-1", "_mol^\u0012-1\u0013"); - assert_parsed_expression_simplify_to("_cd^-1", "_cd^\u0012-1\u0013"); + assert_parsed_expression_simplify_to("_s^-1", "1×_s^\u0012-1\u0013"); + assert_parsed_expression_simplify_to("_m^-1", "1×_m^\u0012-1\u0013"); + assert_parsed_expression_simplify_to("_kg^-1", "1×_kg^\u0012-1\u0013"); + assert_parsed_expression_simplify_to("_A^-1", "1×_A^\u0012-1\u0013"); + assert_parsed_expression_simplify_to("_K^-1", "1×_K^\u0012-1\u0013"); + assert_parsed_expression_simplify_to("_mol^-1", "1×_mol^\u0012-1\u0013"); + assert_parsed_expression_simplify_to("_cd^-1", "1×_cd^\u0012-1\u0013"); /* SI derived units with special names and symbols */ - assert_parsed_expression_simplify_to("_kg×_m×_s^(-2)", "_N"); - assert_parsed_expression_simplify_to("_kg×_m^(-1)×_s^(-2)", "_Pa"); - assert_parsed_expression_simplify_to("_kg×_m^2×_s^(-2)", "_J"); - assert_parsed_expression_simplify_to("_kg×_m^2×_s^(-3)", "_W"); - assert_parsed_expression_simplify_to("_A×_s", "_C"); - assert_parsed_expression_simplify_to("_kg×_m^2×_s^(-3)×_A^(-1)", "_V"); - assert_parsed_expression_simplify_to("_m^(-2)×_kg^(-1)×_s^4×_A^2", "_F"); - assert_parsed_expression_simplify_to("_kg×_m^2×_s^(-3)×_A^(-2)", "_Ω"); + assert_parsed_expression_simplify_to("_kg×_m×_s^(-2)", "1×_N"); + assert_parsed_expression_simplify_to("_kg×_m^(-1)×_s^(-2)", "1×_Pa"); + assert_parsed_expression_simplify_to("_kg×_m^2×_s^(-2)", "1×_J"); + assert_parsed_expression_simplify_to("_kg×_m^2×_s^(-3)", "1×_W"); + assert_parsed_expression_simplify_to("_A×_s", "1×_C"); + assert_parsed_expression_simplify_to("_kg×_m^2×_s^(-3)×_A^(-1)", "1×_V"); + assert_parsed_expression_simplify_to("_m^(-2)×_kg^(-1)×_s^4×_A^2", "1×_F"); + assert_parsed_expression_simplify_to("_kg×_m^2×_s^(-3)×_A^(-2)", "1×_Ω"); // FIXME _S should not be simplified to _Ω^(-1) // A possible solution: a unit with exponent +1 is simpler than a unit with exponent -1. // The same should probably go for Hz. - // assert_parsed_expression_simplify_to("_kg^(-1)×_m^(-2)×_s^3×_A^2", "_S"); - assert_parsed_expression_simplify_to("_kg×_m^2×_s^(-2)×_A^(-1)", "_Wb"); - assert_parsed_expression_simplify_to("_kg×_s^(-2)×_A^(-1)", "_T"); - assert_parsed_expression_simplify_to("_kg×_m^2×_s^(-2)×_A^(-2)", "_H"); - assert_parsed_expression_simplify_to("_mol×_s^-1", "_kat"); + // assert_parsed_expression_simplify_to("_kg^(-1)×_m^(-2)×_s^3×_A^2", "1×_S"); + assert_parsed_expression_simplify_to("_kg×_m^2×_s^(-2)×_A^(-1)", "1×_Wb"); + assert_parsed_expression_simplify_to("_kg×_s^(-2)×_A^(-1)", "1×_T"); + assert_parsed_expression_simplify_to("_kg×_m^2×_s^(-2)×_A^(-2)", "1×_H"); + assert_parsed_expression_simplify_to("_mol×_s^-1", "1×_kat"); /* Test simplification of all possible (prefixed) unit symbols. * Some symbols are however excluded: - * - Observe that _ms is simplified to 1×_ms but _s stays the same. Indeed - * a constant 1 is generally introduced if not already there, except when - * a unit is the standard unit with the standard prefix in a dimension. - * Thus the latter case is not tested. * - At present, some units will not appear as simplification output: * t, Hz, S, ha, L. These exceptions are tested below. */ for (const Unit::Dimension * dim = Unit::DimensionTable; dim < Unit::DimensionTableUpperBound; dim++) { @@ -246,16 +242,12 @@ QUIZ_CASE(poincare_simplification_units) { } static constexpr size_t bufferSize = 12; char buffer[bufferSize] = "1×"; - if (rep != dim->stdRepresentative()) { - Unit::Builder(dim, rep, &Unit::EmptyPrefix).serialize(buffer+strlen("1×"), bufferSize-strlen("1×"), Preferences::PrintFloatMode::Decimal, Preferences::VeryShortNumberOfSignificantDigits); - assert_parsed_expression_simplify_to(buffer, buffer); - } + Unit::Builder(dim, rep, &Unit::EmptyPrefix).serialize(buffer+strlen("1×"), bufferSize-strlen("1×"), Preferences::PrintFloatMode::Decimal, Preferences::VeryShortNumberOfSignificantDigits); + assert_parsed_expression_simplify_to(buffer, buffer); if (rep->isPrefixable()) { for (const Unit::Prefix * pre = rep->outputPrefixes(); pre < rep->outputPrefixesUpperBound(); pre++) { - if (rep != dim->stdRepresentative() || pre->exponent() != dim->stdRepresentativePrefix()->exponent()) { - Unit::Builder(dim, rep, pre).serialize(buffer+strlen("1×"), bufferSize-strlen("1×"), Preferences::PrintFloatMode::Decimal, Preferences::VeryShortNumberOfSignificantDigits); - assert_parsed_expression_simplify_to(buffer, buffer); - } + Unit::Builder(dim, rep, pre).serialize(buffer+strlen("1×"), bufferSize-strlen("1×"), Preferences::PrintFloatMode::Decimal, Preferences::VeryShortNumberOfSignificantDigits); + assert_parsed_expression_simplify_to(buffer, buffer); } } } @@ -263,51 +255,51 @@ QUIZ_CASE(poincare_simplification_units) { /* Units that do not appear as output yet */ assert_parsed_expression_simplify_to("_t", "1×_Mg"); - assert_parsed_expression_simplify_to("_Hz", "_s^\u0012-1\u0013"); - assert_parsed_expression_simplify_to("_S", "_Ω^\u0012-1\u0013"); + assert_parsed_expression_simplify_to("_Hz", "1×_s^\u0012-1\u0013"); + assert_parsed_expression_simplify_to("_S", "1×_Ω^\u0012-1\u0013"); assert_parsed_expression_simplify_to("_L", "0.001×_m^3"); assert_parsed_expression_simplify_to("_ha", "0.01×_km^2"); /* Usual physical quantities */ - assert_parsed_expression_simplify_to("_A×_s×_m^(-3)", "_C×_m^\u0012-3\u0013"); // Charge density - assert_parsed_expression_simplify_to("_kg×_m×_s^(-3)×_K^(-1)", "_N×_K^\u0012-1\u0013×_s^\u0012-1\u0013"); // Thermal conductivity _W×_m^-1×_K^-1 - assert_parsed_expression_simplify_to("_K×_kg^(-1)×_m^(-2)×_s^3", "_W^\u0012-1\u0013×_K"); // Thermal resistance - assert_parsed_expression_simplify_to("_kg×_m×_s^(-3)×_A^(-1)", "_V×_m^\u0012-1\u0013"); // Electrical field - assert_parsed_expression_simplify_to("_kg×_m^2×_s^(-1)", "_J×_s"); // Action - assert_parsed_expression_simplify_to("_kg×_m^2×_s^(-2)×_K^(-1)", "_J×_K^\u0012-1\u0013"); // Entropy | Heat capacity - assert_parsed_expression_simplify_to("_m^2×_s^(-2)×_K^(-1)", "_K^\u0012-1\u0013×_m^2×_s^\u0012-2\u0013"); // Specific heat capacity _J×_K^-1×_kg^-1 - assert_parsed_expression_simplify_to("_kg×_m^2×_s^(-2)×_K^(-1)×_mol^(-1)", "_J×_mol^\u0012-1\u0013×_K^\u0012-1\u0013"); // Molar heat capacity - assert_parsed_expression_simplify_to("_kg×_m^(-1)×_s^(-2)×_K^(-1)", "_Pa×_K^\u0012-1\u0013"); // Volumetric heat capacity _J×_K^-1×_m^-3 - assert_parsed_expression_simplify_to("_kg×_s^(-3)×_K^(-1)", "_K^\u0012-1\u0013×_kg×_s^\u0012-3\u0013"); // Heat transfer coefficient _W×_m^-2×_K^-1 - assert_parsed_expression_simplify_to("_kg×_m^2×_s^(-3)×_K^(-1)", "_W×_K^\u0012-1\u0013"); // Thermal conductivity - assert_parsed_expression_simplify_to("_kg^(-1)×_m^(-3)×_s^3×_A^2", "_Ω^\u0012-1\u0013×_m^\u0012-1\u0013"); // Electrical conductivity _S×_m^-1 - assert_parsed_expression_simplify_to("_kg×_s^(-2)", "_kg×_s^\u0012-2\u0013"); // Stiffness _N×_m^-1 - assert_parsed_expression_simplify_to("_kg×_m^(-1)×_s^(-3)", "_Pa×_s^\u0012-1\u0013"); // Power density _W×_m^-3 - assert_parsed_expression_simplify_to("_kg×_m^3×_s^(-3)×_A^(-1)", "_V×_m"); // Electric flux - assert_parsed_expression_simplify_to("_K×_kg^(-1)×_s^(3)", "_K×_kg^\u0012-1\u0013×_s^3"); // Superficial thermal resistance _m^2×_K×_W^-1 - assert_parsed_expression_simplify_to("_kg^(-1)×_m^(-2)×_s^2", "_J^\u0012-1\u0013"); // Thermodynamic beta - assert_parsed_expression_simplify_to("_kg×_m^(-1)×_s^(-1)", "_Pa×_s"); // Dynamic viscosity - assert_parsed_expression_simplify_to("_m^2×_s^(-2)", "_m^2×_s^\u0012-2\u0013"); // Gray/Sievert _J×_kg^\u0012-1\u0013 - assert_parsed_expression_simplify_to("_m^2×_kg×_s^(-1)", "_J×_s"); // Angular momentum _N×_m×_s - assert_parsed_expression_simplify_to("_m^(-1)×_kg×_s^(-2)", "_Pa"); // Energy density _J×_m^-3 - assert_parsed_expression_simplify_to("_m×_kg×_s^(-3)", "_N×_s^\u0012-1\u0013"); // Spectral power _W×_m^-1 - assert_parsed_expression_simplify_to("_m×_kg^(-1)×_s^2", "_Pa^\u0012-1\u0013"); // Compressibility - assert_parsed_expression_simplify_to("_kg^(-1)×_s^3×_A^2×_mol^(-1)", "_Ω^\u0012-1\u0013×_mol^\u0012-1\u0013×_m^2"); // Molar conductivity _S×_m^2×_mol^-1 - assert_parsed_expression_simplify_to("_m^(-2)×_s×_A", "_C×_m^\u0012-2\u0013"); // Polarization density - assert_parsed_expression_simplify_to("_kg^(-1)×_s×_A", "_C×_kg^\u0012-1\u0013"); // Exposure - assert_parsed_expression_simplify_to("_kg×_m^3×_s^(-3)×_A^(-2)", "_Ω×_m"); // Electrical resistivity - assert_parsed_expression_simplify_to("_m^(-1)×_s×_A", "_C×_m^\u0012-1\u0013"); // Dipole moment - assert_parsed_expression_simplify_to("_kg^(-1)×_s^2×_A", "_T^\u0012-1\u0013"); // Electron mobility _m^2×_V^-1×_s^-1 - assert_parsed_expression_simplify_to("_m^(-2)×_kg^(-1)×_s^2×_A^2", "_H^\u0012-1\u0013"); // Magnetic reluctance - assert_parsed_expression_simplify_to("_m×_kg×_s^(-2)×_A^(-1)", "_N×_A^\u0012-1\u0013"); // Magnetic vector potential _Wb×_m^-1 and Magnetic rigidity _T×_m - assert_parsed_expression_simplify_to("_m^3×_kg×_s^(-2)×_A^(-1)", "_Wb×_m"); // Magnetic moment - assert_parsed_expression_simplify_to("_m^(-1)×_kg^(-1)×_s^2×_A^2", "_N^\u0012-1\u0013×_A^2"); // Magnetic susceptibility _H^-1×_m + assert_parsed_expression_simplify_to("_A×_s×_m^(-3)", "1×_C×_m^\u0012-3\u0013"); // Charge density + assert_parsed_expression_simplify_to("_kg×_m×_s^(-3)×_K^(-1)", "1×_N×_K^\u0012-1\u0013×_s^\u0012-1\u0013"); // Thermal conductivity _W×_m^-1×_K^-1 + assert_parsed_expression_simplify_to("_K×_kg^(-1)×_m^(-2)×_s^3", "1×_W^\u0012-1\u0013×_K"); // Thermal resistance + assert_parsed_expression_simplify_to("_kg×_m×_s^(-3)×_A^(-1)", "1×_V×_m^\u0012-1\u0013"); // Electrical field + assert_parsed_expression_simplify_to("_kg×_m^2×_s^(-1)", "1×_J×_s"); // Action + assert_parsed_expression_simplify_to("_kg×_m^2×_s^(-2)×_K^(-1)", "1×_J×_K^\u0012-1\u0013"); // Entropy | Heat capacity + assert_parsed_expression_simplify_to("_m^2×_s^(-2)×_K^(-1)", "1×_K^\u0012-1\u0013×_m^2×_s^\u0012-2\u0013"); // Specific heat capacity _J×_K^-1×_kg^-1 + assert_parsed_expression_simplify_to("_kg×_m^2×_s^(-2)×_K^(-1)×_mol^(-1)", "1×_J×_mol^\u0012-1\u0013×_K^\u0012-1\u0013"); // Molar heat capacity + assert_parsed_expression_simplify_to("_kg×_m^(-1)×_s^(-2)×_K^(-1)", "1×_Pa×_K^\u0012-1\u0013"); // Volumetric heat capacity _J×_K^-1×_m^-3 + assert_parsed_expression_simplify_to("_kg×_s^(-3)×_K^(-1)", "1×_K^\u0012-1\u0013×_kg×_s^\u0012-3\u0013"); // Heat transfer coefficient _W×_m^-2×_K^-1 + assert_parsed_expression_simplify_to("_kg×_m^2×_s^(-3)×_K^(-1)", "1×_W×_K^\u0012-1\u0013"); // Thermal conductivity + assert_parsed_expression_simplify_to("_kg^(-1)×_m^(-3)×_s^3×_A^2", "1×_Ω^\u0012-1\u0013×_m^\u0012-1\u0013"); // Electrical conductivity _S×_m^-1 + assert_parsed_expression_simplify_to("_kg×_s^(-2)", "1×_kg×_s^\u0012-2\u0013"); // Stiffness _N×_m^-1 + assert_parsed_expression_simplify_to("_kg×_m^(-1)×_s^(-3)", "1×_Pa×_s^\u0012-1\u0013"); // Power density _W×_m^-3 + assert_parsed_expression_simplify_to("_kg×_m^3×_s^(-3)×_A^(-1)", "1×_V×_m"); // Electric flux + assert_parsed_expression_simplify_to("_K×_kg^(-1)×_s^(3)", "1×_K×_kg^\u0012-1\u0013×_s^3"); // Superficial thermal resistance _m^2×_K×_W^-1 + assert_parsed_expression_simplify_to("_kg^(-1)×_m^(-2)×_s^2", "1×_J^\u0012-1\u0013"); // Thermodynamic beta + assert_parsed_expression_simplify_to("_kg×_m^(-1)×_s^(-1)", "1×_Pa×_s"); // Dynamic viscosity + assert_parsed_expression_simplify_to("_m^2×_s^(-2)", "1×_m^2×_s^\u0012-2\u0013"); // Gray/Sievert _J×_kg^\u0012-1\u0013 + assert_parsed_expression_simplify_to("_m^2×_kg×_s^(-1)", "1×_J×_s"); // Angular momentum _N×_m×_s + assert_parsed_expression_simplify_to("_m^(-1)×_kg×_s^(-2)", "1×_Pa"); // Energy density _J×_m^-3 + assert_parsed_expression_simplify_to("_m×_kg×_s^(-3)", "1×_N×_s^\u0012-1\u0013"); // Spectral power _W×_m^-1 + assert_parsed_expression_simplify_to("_m×_kg^(-1)×_s^2", "1×_Pa^\u0012-1\u0013"); // Compressibility + assert_parsed_expression_simplify_to("_kg^(-1)×_s^3×_A^2×_mol^(-1)", "1×_Ω^\u0012-1\u0013×_mol^\u0012-1\u0013×_m^2"); // Molar conductivity _S×_m^2×_mol^-1 + assert_parsed_expression_simplify_to("_m^(-2)×_s×_A", "1×_C×_m^\u0012-2\u0013"); // Polarization density + assert_parsed_expression_simplify_to("_kg^(-1)×_s×_A", "1×_C×_kg^\u0012-1\u0013"); // Exposure + assert_parsed_expression_simplify_to("_kg×_m^3×_s^(-3)×_A^(-2)", "1×_Ω×_m"); // Electrical resistivity + assert_parsed_expression_simplify_to("_m^(-1)×_s×_A", "1×_C×_m^\u0012-1\u0013"); // Dipole moment + assert_parsed_expression_simplify_to("_kg^(-1)×_s^2×_A", "1×_T^\u0012-1\u0013"); // Electron mobility _m^2×_V^-1×_s^-1 + assert_parsed_expression_simplify_to("_m^(-2)×_kg^(-1)×_s^2×_A^2", "1×_H^\u0012-1\u0013"); // Magnetic reluctance + assert_parsed_expression_simplify_to("_m×_kg×_s^(-2)×_A^(-1)", "1×_N×_A^\u0012-1\u0013"); // Magnetic vector potential _Wb×_m^-1 and Magnetic rigidity _T×_m + assert_parsed_expression_simplify_to("_m^3×_kg×_s^(-2)×_A^(-1)", "1×_Wb×_m"); // Magnetic moment + assert_parsed_expression_simplify_to("_m^(-1)×_kg^(-1)×_s^2×_A^2", "1×_N^\u0012-1\u0013×_A^2"); // Magnetic susceptibility _H^-1×_m // Physical constants - assert_parsed_expression_simplify_to("_kg^(-1)×_m^3×_s^(-2)", "_kg^\u0012-1\u0013×_m^3×_s^\u0012-2\u0013"); // Gravitational constant G _N×_m^2×_kg^-2 - assert_parsed_expression_simplify_to("_kg×_m×_s^(-2)×_A^(-2)", "_N×_A^\u0012-2\u0013"); // Vacuum electric permittivity µ0 _H×_m^-1 - assert_parsed_expression_simplify_to("_A^2×_s^4×_kg^(-1)×_m^(-3)", "_F×_m^\u0012-1\u0013"); // Vacuum magnetic permeability 𝝴0 - assert_parsed_expression_simplify_to("_kg×_s^(-3)×_K^(-4)", "_K^\u0012-4\u0013×_kg×_s^\u0012-3\u0013"); // Stefan–Boltzmann constant _W×_m^-2×_K^-4 + assert_parsed_expression_simplify_to("_kg^(-1)×_m^3×_s^(-2)", "1×_kg^\u0012-1\u0013×_m^3×_s^\u0012-2\u0013"); // Gravitational constant G _N×_m^2×_kg^-2 + assert_parsed_expression_simplify_to("_kg×_m×_s^(-2)×_A^(-2)", "1×_N×_A^\u0012-2\u0013"); // Vacuum electric permittivity µ0 _H×_m^-1 + assert_parsed_expression_simplify_to("_A^2×_s^4×_kg^(-1)×_m^(-3)", "1×_F×_m^\u0012-1\u0013"); // Vacuum magnetic permeability 𝝴0 + assert_parsed_expression_simplify_to("_kg×_s^(-3)×_K^(-4)", "1×_K^\u0012-4\u0013×_kg×_s^\u0012-3\u0013"); // Stefan–Boltzmann constant _W×_m^-2×_K^-4 /* Keep units for 0, infinity float results, Remove unit for undefined * expression */