[poincare] Multiplication::shallowBeautify: Keep the unit when the value

is 0 or undefined, add tests
This commit is contained in:
Émilie Feral
2020-02-03 17:07:57 +01:00
committed by Léa Saviot
parent 879843ce2b
commit ee1224dd95
2 changed files with 43 additions and 25 deletions

View File

@@ -510,36 +510,44 @@ Expression Multiplication::shallowBeautify(ExpressionNode::ReductionContext redu
result = units;
} else {
double value = result.approximateToScalar<double>(reductionContext.context(), reductionContext.complexFormat(), reductionContext.angleUnit());
if (std::isinf(value)) {
result = Infinity::Builder(false); //FIXME sign?
} else if (std::isnan(value)) {
if (std::isnan(value)) {
// If the value is undefined, return "undef" without any unit
result = Undefined::Builder();
} else {
// 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<Rational &>(exp).isInteger());
Integer expInt = static_cast<Rational &>(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;
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<Rational &>(exp).isInteger());
Integer expInt = static_cast<Rational &>(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<Unit&>(firstFactor).chooseBestMultipleForValue(value, exponent, reductionContext);
}
}
}
assert(firstFactor.type() == ExpressionNode::Type::Unit);
// Choose its multiple and update value accordingly
if (exponent != 0) {
static_cast<Unit&>(firstFactor).chooseBestMultipleForValue(value, exponent, reductionContext);
resultWithoutUnit = Float<double>::Builder(value);
}
// Build final Expression
result = Multiplication::Builder(Float<double>::Builder(value), units);
result = Multiplication::Builder(resultWithoutUnit, units);
static_cast<Multiplication &>(result).mergeMultiplicationChildrenInPlace();
}
}

View File

@@ -309,6 +309,16 @@ QUIZ_CASE(poincare_simplification_units) {
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"); // StefanBoltzmann constant _W×_m^-2×_K^-4
/* Keep units for 0, infinity float results, Remove unit for undefined
* expression */
//assert_parsed_expression_simplify_to("0_s", "0_s");
assert_parsed_expression_simplify_to("inf×_s", "inf×_s");
//assert_parsed_expression_simplify_to("-inf×_s", "-inf×_s");
//assert_parsed_expression_simplify_to("2_s+3_s-5_s", "0_s");
assert_parsed_expression_simplify_to("normcdf(0,20,3)×_s", "0×_s");
//assert_parsed_expression_simplify_to("log(0)×_s", "-inf×_s");
assert_parsed_expression_simplify_to("log(undef)*_s", "undef");
/* Units with invalid exponent */
assert_parsed_expression_simplify_to("_s^(1/2)", "undef");