mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
[poincare] Fix childNeedsUserParentheses with Conjugate expressions
This commit is contained in:
@@ -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); }
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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, "+");
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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--) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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))))));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user