[poincare] Factorize reduce and removeUnit methods

This commit is contained in:
Hugo Saint-Vignes
2020-12-22 15:29:30 +01:00
committed by EmilieNumworks
parent 7146eff7ee
commit e09bd0a18c
8 changed files with 22 additions and 19 deletions

View File

@@ -28,8 +28,7 @@ void UnitListController::setExpression(Poincare::Expression e) {
Expression copy = m_expression.clone();
Expression units;
// Reduce to be able to recognize units
PoincareHelpers::Reduce(&copy, App::app()->localContext(), ExpressionNode::ReductionTarget::User);
copy = copy.removeUnit(&units);
PoincareHelpers::ReduceAndRemoveUnit(&copy, App::app()->localContext(), ExpressionNode::ReductionTarget::User, &units);
double value = Shared::PoincareHelpers::ApproximateToScalar<double>(copy, App::app()->localContext());
ExpressionNode::ReductionContext reductionContext(
App::app()->localContext(),

View File

@@ -255,8 +255,7 @@ Calculation::AdditionalInformationType Calculation::additionalInformationType(Co
}
if (o.hasUnit()) {
Expression unit;
PoincareHelpers::Reduce(&o, App::app()->localContext(), ExpressionNode::ReductionTarget::User, ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithDefinitionsOrUndefined, ExpressionNode::UnitConversion::None);
o = o.removeUnit(&unit);
PoincareHelpers::ReduceAndRemoveUnit(&o, App::app()->localContext(), ExpressionNode::ReductionTarget::User, &unit, ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithDefinitionsOrUndefined, ExpressionNode::UnitConversion::None);
double value = PoincareHelpers::ApproximateToScalar<double>(o, App::app()->localContext());
return (Unit::ShouldDisplayAdditionalOutputs(value, unit, GlobalPreferences::sharedGlobalPreferences()->unitFormat())) ? AdditionalInformationType::Unit : AdditionalInformationType::None;
}

View File

@@ -77,6 +77,11 @@ inline void Reduce(Poincare::Expression * e, Poincare::Context * context, Poinca
*e = e->reduce(Poincare::ExpressionNode::ReductionContext(context, complexFormat, preferences->angleUnit(), GlobalPreferences::sharedGlobalPreferences()->unitFormat(), target, symbolicComputation, unitConversion));
}
inline void ReduceAndRemoveUnit(Poincare::Expression * e, Poincare::Context * context, Poincare::ExpressionNode::ReductionTarget target, Poincare::Expression * unit, Poincare::ExpressionNode::SymbolicComputation symbolicComputation = Poincare::ExpressionNode::SymbolicComputation::ReplaceAllDefinedSymbolsWithDefinition, Poincare::ExpressionNode::UnitConversion unitConversion = Poincare::ExpressionNode::UnitConversion::Default) {
PoincareHelpers::Reduce(e, context, target, symbolicComputation, unitConversion);
*e = e->removeUnit(unit);
}
inline void ParseAndSimplifyAndApproximate(const char * text, Poincare::Expression * simplifiedExpression, Poincare::Expression * approximateExpression, Poincare::Context * context, Poincare::ExpressionNode::SymbolicComputation symbolicComputation = Poincare::ExpressionNode::SymbolicComputation::ReplaceAllDefinedSymbolsWithDefinition) {
Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences();
Poincare::Preferences::ComplexFormat complexFormat = Poincare::Expression::UpdatedComplexFormatWithTextInput(preferences->complexFormat(), text);

View File

@@ -248,6 +248,7 @@ public:
static void ParseAndSimplifyAndApproximate(const char * text, Expression * simplifiedExpression, Expression * approximateExpression, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, Preferences::UnitFormat unitFormat, ExpressionNode::SymbolicComputation symbolicComputation = ExpressionNode::SymbolicComputation::ReplaceAllDefinedSymbolsWithDefinition, ExpressionNode::UnitConversion unitConversion = ExpressionNode::UnitConversion::Default);
void simplifyAndApproximate(Expression * simplifiedExpression, Expression * approximateExpression, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, Preferences::UnitFormat unitFormat, ExpressionNode::SymbolicComputation symbolicComputation = ExpressionNode::SymbolicComputation::ReplaceAllDefinedSymbolsWithDefinition, ExpressionNode::UnitConversion unitConversion = ExpressionNode::UnitConversion::Default);
Expression reduce(ExpressionNode::ReductionContext context);
Expression reduceAndRemoveUnit(ExpressionNode::ReductionContext context, Expression * Unit);
Expression mapOnMatrixFirstChild(ExpressionNode::ReductionContext reductionContext);
/* 'ExpressionWithoutSymbols' returns an uninitialized expression if it is

View File

@@ -827,6 +827,12 @@ Expression Expression::angleUnitToRadian(Preferences::AngleUnit angleUnit) {
return *this;
}
Expression Expression::reduceAndRemoveUnit(ExpressionNode::ReductionContext reductionContext, Expression * Unit) {
/* RemoveUnit has to be called on reduced expression. reduce method is called
* instead of deepReduce to catch interrupted simplification. */
return reduce(reductionContext).removeUnit(Unit);
}
Expression Expression::reduce(ExpressionNode::ReductionContext reductionContext) {
sSimplificationHasBeenInterrupted = false;
Expression result = deepReduce(reductionContext);

View File

@@ -425,8 +425,7 @@ Expression Multiplication::shallowBeautify(ExpressionNode::ReductionContext * re
Expression units;
/* removeUnit has to be called on reduced expression but we want to modify
* the least the expression so we use the uninvasive reduction context. */
self = self.reduce(ExpressionNode::ReductionContext::NonInvasiveReductionContext(*reductionContext));
self = self.removeUnit(&units);
self = self.reduceAndRemoveUnit(ExpressionNode::ReductionContext::NonInvasiveReductionContext(*reductionContext), &units);
if (self.isUndefined() || units.isUninitialized()) {
// TODO: handle error "Invalid unit"
@@ -500,11 +499,9 @@ Expression Multiplication::shallowBeautify(ExpressionNode::ReductionContext * re
}
// Apply simplifications
if (unitsAccu.numberOfChildren() > 0) {
// Divide by derived units
units = Division::Builder(units, unitsAccu.clone()).reduce(*reductionContext);
Expression newUnits;
// Separate units and generated values
units = units.removeUnit(&newUnits);
// Divide by derived units, separate units and generated values
units = Division::Builder(units, unitsAccu.clone()).reduceAndRemoveUnit(*reductionContext, &newUnits);
// Assemble final value
Multiplication m = Multiplication::Builder(units);
self.replaceWithInPlace(m);

View File

@@ -77,7 +77,7 @@ Expression UnitConvert::shallowBeautify(ExpressionNode::ReductionContext * reduc
reductionContext->target(),
ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithUndefined);
Expression unit;
Expression childWithoutUnit = childAtIndex(1).clone().reduce(reductionContextWithUnits).removeUnit(&unit);
Expression childWithoutUnit = childAtIndex(1).clone().reduceAndRemoveUnit(reductionContextWithUnits, &unit);
if (childWithoutUnit.isUndefined() || unit.isUninitialized()) {
// There is no unit on the right
return replaceWithUndefinedInPlace();
@@ -104,9 +104,8 @@ Expression UnitConvert::shallowBeautify(ExpressionNode::ReductionContext * reduc
// Divide the left member by the new unit
Expression division = Division::Builder(childAtIndex(0), unit.clone());
division = division.reduce(*reductionContext);
Expression divisionUnit;
division = division.removeUnit(&divisionUnit);
division = division.reduceAndRemoveUnit(*reductionContext, &divisionUnit);
if (!divisionUnit.isUninitialized()) {
// The left and right members are not homogeneous
return replaceWithUndefinedInPlace();

View File

@@ -401,13 +401,11 @@ void assert_reduced_expression_unit_is(const char * expression, const char * uni
Shared::GlobalContext globalContext;
ExpressionNode::ReductionContext redContext(&globalContext, Real, Degree, Metric, SystemForApproximation);
Expression e = parse_expression(expression, &globalContext, false);
e = e.reduce(redContext);
Expression u1;
e = e.removeUnit(&u1);
e = e.reduceAndRemoveUnit(redContext, &u1);
Expression e2 = parse_expression(unit, &globalContext, false);
Expression u2;
e2 = e2.reduce(redContext);
e2.removeUnit(&u2);
e2.reduceAndRemoveUnit(redContext, &u2);
quiz_assert_print_if_failure(u1.isUninitialized() == u2.isUninitialized() && (u1.isUninitialized() || u1.isIdenticalTo(u2)), expression);
}
@@ -425,9 +423,8 @@ void assert_additional_results_compute_to(const char * expression, const char *
assert(length <= maxNumberOfResults);
Expression additional[maxNumberOfResults];
ExpressionNode::ReductionContext reductionContext = ExpressionNode::ReductionContext(&globalContext, Cartesian, Degree, unitFormat, User, ReplaceAllSymbolsWithUndefined, DefaultUnitConversion);
Expression e = parse_expression(expression, &globalContext, false).reduce(reductionContext);
Expression units;
e = e.removeUnit(&units);
Expression e = parse_expression(expression, &globalContext, false).reduceAndRemoveUnit(reductionContext, &units);
double value = e.approximateToScalar<double>(&globalContext, Cartesian, Degree);
if (!Unit::ShouldDisplayAdditionalOutputs(value, units, unitFormat)) {