[poincare] Fix childNeedsUserParentheses with Conjugate expressions

This commit is contained in:
Émilie Feral
2019-08-16 16:04:26 +02:00
parent 64ddd6b622
commit fbbc11cf33
10 changed files with 48 additions and 24 deletions

View File

@@ -26,7 +26,6 @@ public:
Type type() const override { return Type::Addition; }
int polynomialDegree(Context * context, const char * symbolName) const override;
int getPolynomialCoefficients(Context * context, const char * symbolName, Expression coefficients[]) const override;
bool childNeedsUserParentheses(const Expression & child) const override;
// Evaluation
template<typename T> static Complex<T> compute(const std::complex<T> c, const std::complex<T> d, Preferences::ComplexFormat complexFormat) { return Complex<T>::Builder(c+d); }

View File

@@ -20,6 +20,9 @@ public:
}
void eraseNumberOfChildren() override { m_numberOfChildren = 0; }
// Properties
bool childNeedsUserParentheses(const Expression & child) const override;
// Comparison
typedef int (*ExpressionOrder)(const ExpressionNode * e1, const ExpressionNode * e2, bool canBeInterrupted);

View File

@@ -29,17 +29,6 @@ int AdditionNode::getPolynomialCoefficients(Context * context, const char * symb
}
// Layout
bool AdditionNode::childNeedsUserParentheses(const Expression & child) const {
if (((child.isNumber() && static_cast<const Number &>(child).sign() == Sign::Negative)
|| child.type() == Type::Opposite)
&& child.node() != childAtIndex(0)) {
return true;
}
if (child.type() == Type::Conjugate) {
return childNeedsUserParentheses(child.childAtIndex(0));
}
return false;
}
Layout AdditionNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const {
return LayoutHelper::Infix(Addition(this), floatDisplayMode, numberOfSignificantDigits, "+");

View File

@@ -23,7 +23,9 @@ bool FactorialNode::childNeedsUserParentheses(const Expression & child) const {
if (child.isNumber() && static_cast<const Number &>(child).sign() == Sign::Negative) {
return true;
}
if (child.type() == Type::Conjugate) {
return childNeedsUserParentheses(child.childAtIndex(0));
}
Type types[] = {Type::Subtraction, Type::Opposite, Type::Multiplication, Type::Addition};
return child.isOfType(types, 4);
}

View File

@@ -51,17 +51,9 @@ int MultiplicationNode::getPolynomialCoefficients(Context * context, const char
}
bool MultiplicationNode::childNeedsUserParentheses(const Expression & child) const {
if ((child.isNumber() && static_cast<const Number &>(child).sign() == Sign::Negative)
|| child.type() == ExpressionNode::Type::Opposite)
{
if (child.node() == childAtIndex(0)) {
return false;
}
if (NAryExpressionNode::childNeedsUserParentheses(child)) {
return true;
}
if (child.type() == Type::Conjugate) {
return childNeedsUserParentheses(child.childAtIndex(0));
}
Type types[] = {Type::Subtraction, Type::Addition};
return child.isOfType(types, 2);
}

View File

@@ -1,4 +1,5 @@
#include <poincare/n_ary_expression.h>
#include <poincare/number.h>
extern "C" {
#include <assert.h>
#include <stdlib.h>
@@ -6,6 +7,22 @@ extern "C" {
namespace Poincare {
bool NAryExpressionNode::childNeedsUserParentheses(const Expression & child) const {
/* Expressions like "-2" require parentheses in Addition/Multiplication except
* when they are the first operand. */
if (((child.isNumber() && static_cast<const Number &>(child).sign() == Sign::Negative)
|| child.type() == Type::Opposite)
/* We use "hasAncestor" instead of "==" because child might not be the
* direct child of the addition/multiplication [e.g. +(conj(-2), 3)] */
&& !child.node()->hasAncestor(childAtIndex(0), true)) {
return true;
}
if (child.type() == Type::Conjugate) {
return childNeedsUserParentheses(child.childAtIndex(0));
}
return false;
}
void NAryExpressionNode::sortChildrenInPlace(ExpressionOrder order, Context * context, bool canSwapMatrices, bool canBeInterrupted) {
Expression reference(this);
for (int i = reference.numberOfChildren()-1; i > 0; i--) {

View File

@@ -37,6 +37,9 @@ bool OppositeNode::childNeedsUserParentheses(const Expression & child) const {
if (child.isNumber() && static_cast<const Number &>(child).sign() == Sign::Negative) {
return true;
}
if (child.type() == Type::Conjugate) {
return childNeedsUserParentheses(child.childAtIndex(0));
}
Type types[] = {Type::Addition, Type::Subtraction, Type::Opposite};
return child.isOfType(types, 3);
}

View File

@@ -100,7 +100,9 @@ bool PowerNode::isReal(Context * context) const {
}
bool PowerNode::childNeedsUserParentheses(const Expression & child) const {
if (child.node() == childAtIndex(0)) {
/* We use "hasAncestor" instead of "==" because child might not be the direct
* child of thepower [e.g. ^(conj(+(A,B), C)] */
if (child.node()->hasAncestor(childAtIndex(0), true)) {
/* ^(-2.3, 4) --> (-2.3)^{4}
* ^(2/3, 4) --> (2/3)^{4}
*/
@@ -108,6 +110,9 @@ bool PowerNode::childNeedsUserParentheses(const Expression & child) const {
|| (child.type() == Type::Rational && !static_cast<const Rational &>(child).isInteger())) {
return true;
}
if (child.type() == Type::Conjugate) {
return childNeedsUserParentheses(child.childAtIndex(0));
}
// ^(2+3,4) --> (2+3)^{4}
Type types[] = {Type::Power, Type::Subtraction, Type::Opposite, Type::Multiplication, Type::Division, Type::Addition};
return child.isOfType(types, 6);

View File

@@ -24,7 +24,10 @@ int SubtractionNode::polynomialDegree(Context * context, const char * symbolName
// Private
bool SubtractionNode::childNeedsUserParentheses(const Expression & child) const {
if (child.node() == childAtIndex(0)) {
/* First operand of a subtraction never requires parentheses.
* We use "hasAncestor" instead of "==" because child might not be the direct
* child of the subtraction [e.g. 'conj(-2) - 3' ] */
if (child.node()->hasAncestor(childAtIndex(0), true)) {
return false;
}
if (child.isNumber() && static_cast<const Number &>(child).sign() == Sign::Negative) {

View File

@@ -437,4 +437,15 @@ QUIZ_CASE(poincare_parsing_adding_missing_parentheses) {
assert_parsed_expression_with_user_parentheses_is("--2", Opposite::Builder(Parenthesis::Builder(Opposite::Builder(Rational::Builder(2)))));
assert_parsed_expression_with_user_parentheses_is("\u00122/3\u0013^2", Power::Builder(Parenthesis::Builder(Division::Builder(Rational::Builder(2), Rational::Builder(3))), Rational::Builder(2)));
assert_parsed_expression_with_user_parentheses_is("log(1+-2)", CommonLogarithm::Builder(Addition::Builder(Rational::Builder(1),Parenthesis::Builder(Opposite::Builder(Rational::Builder(2))))));
// Conjugate expressions
assert_parsed_expression_with_user_parentheses_is("conj(-3)+2", Addition::Builder(Conjugate::Builder(Opposite::Builder(Rational::Builder(3))), Rational::Builder(2)));
assert_parsed_expression_with_user_parentheses_is("2+conj(-3)", Addition::Builder(Rational::Builder(2), Parenthesis::Builder(Conjugate::Builder(Opposite::Builder(Rational::Builder(3))))));
assert_parsed_expression_with_user_parentheses_is("conj(-3)×2", Multiplication::Builder(Conjugate::Builder(Opposite::Builder(Rational::Builder(3))), Rational::Builder(2)));
assert_parsed_expression_with_user_parentheses_is("2×conj(-3)", Multiplication::Builder(Rational::Builder(2), Parenthesis::Builder(Conjugate::Builder(Opposite::Builder(Rational::Builder(3))))));
assert_parsed_expression_with_user_parentheses_is("conj(-3)-2", Subtraction::Builder(Conjugate::Builder(Opposite::Builder(Rational::Builder(3))), Rational::Builder(2)));
assert_parsed_expression_with_user_parentheses_is("2-conj(-3)", Subtraction::Builder(Rational::Builder(2), Parenthesis::Builder(Conjugate::Builder(Opposite::Builder(Rational::Builder(3))))));
assert_parsed_expression_with_user_parentheses_is("conj(2+3)^2", Power::Builder(Parenthesis::Builder(Conjugate::Builder(Addition::Builder(Rational::Builder(2), Rational::Builder(3)))), Rational::Builder(2)));
assert_parsed_expression_with_user_parentheses_is("-conj(2+3)", Opposite::Builder(Parenthesis::Builder(Conjugate::Builder(Addition::Builder(Rational::Builder(2), Rational::Builder(3))))));
assert_parsed_expression_with_user_parentheses_is("conj(2+3)!", Factorial::Builder(Parenthesis::Builder(Conjugate::Builder(Addition::Builder(Rational::Builder(2), Rational::Builder(3))))));
}