[poincare] Fix Symbol

This commit is contained in:
Émilie Feral
2018-08-09 11:57:17 +02:00
parent 49d4fcb77f
commit cd1bb2ecb3
4 changed files with 37 additions and 50 deletions

View File

@@ -16,6 +16,7 @@ objs += $(addprefix poincare/src/,\
opposite.o\
decimal.o\
rational.o\
symbol.o\
)
objsExpected += $(addprefix poincare/src/,\

View File

@@ -17,7 +17,6 @@ class Expression : public TreeByValue {
friend class ExpressionNode;
friend class NAryExpressionNode;
friend class SubtractionNode;
friend class SymbolNode;
public:
/* Constructor & Destructor */
Expression() : Expression(nullptr) {}
@@ -32,6 +31,9 @@ public:
}
/* Hierarchy */
Expression parent() const {
return Expression(static_cast<ExpressionNode *>(TreeByReference::parent().node()));
}
Expression childAtIndex(int i) const {
return Expression(static_cast<ExpressionNode *>(TreeByValue::childAtIndex(i).node()));
}
@@ -102,7 +104,8 @@ public:
/* Simplification */
static Expression ParseAndSimplify(const char * text, Context & context, Preferences::AngleUnit angleUnit);
void simplify(Context & context, Preferences::AngleUnit angleUnit);
Expression simplify(Context & context, Preferences::AngleUnit angleUnit);
Expression deepReduce(Context & context, Preferences::AngleUnit angleUnit) const;
/* Approximation Helper */
template<typename U> Expression approximate(Context& context, Preferences::AngleUnit angleUnit, Preferences::Preferences::ComplexFormat complexFormat) const;
@@ -130,9 +133,8 @@ private:
int getPolynomialCoefficients(char symbolName, Expression coefficients[], Context & context, Preferences::AngleUnit angleUnit) const;
/* Simplification */
Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit);
Expression deepBeautify(Context & context, Preferences::AngleUnit angleUnit);
Expression deepReduce(Context & context, Preferences::AngleUnit angleUnit);
Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) const;
Expression deepBeautify(Context & context, Preferences::AngleUnit angleUnit) const;
/* Approximation */
template<typename U> static U epsilon();

View File

@@ -8,6 +8,8 @@ namespace Poincare {
class SymbolNode : public ExpressionNode {
friend class Store;
public:
SymbolNode() : m_name(0) {}
static SymbolNode * FailedAllocationStaticNode();
SymbolNode * failedAllocationStaticNode() override { return FailedAllocationStaticNode(); }
@@ -38,20 +40,20 @@ public:
int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
/* Simplification */
Expression shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
bool hasAnExactRepresentation(Context & context) const;
Expression shallowReduce(Context& context, Preferences::AngleUnit angleUnit) const override;
/* Approximation */
Evaluation<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
Evaluation<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
private:
bool hasAnExactRepresentation(Context & context) const;
template<typename T> Evaluation<T> templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
char m_name;
};
class SymbolReference : public Expression {
class Symbol : public Expression {
public:
enum SpecialSymbols : char {
/* We can use characters from 1 to 31 as they do not correspond to usual
@@ -86,11 +88,10 @@ public:
X3,
Y3 = 29
};
SymbolReference(const char name) : Expression(TreePool::sharedPool()->createTreeNode<SymbolNode>()) {
if (!node->isAllocationFailure()) {
static_cast<SymbolNode *>(node)->setName(name);
}
Symbol(const char name) : Expression(TreePool::sharedPool()->createTreeNode<SymbolNode>()) {
node()->setName(name);
}
Symbol(const SymbolNode * node) : Expression(node) {}
// Symbol properties
static const char * textForSpecialSymbols(char name);
@@ -104,11 +105,11 @@ public:
// Expression
Expression shallowReduce(Context& context, Preferences::AngleUnit angleUnit) const;
Expression replaceSymbolWithExpression(char symbol, Expression expression);
Expression replaceSymbolWithExpression(char symbol, Expression expression) const;
int getPolynomialCoefficients(char symbolName, Expression coefficients[]) const;
private:
SymbolNode * node() { return static_cast<SymbolNode *>(Expression::node()); }
char name() { return node()->name(); }
SymbolNode * node() const override { return static_cast<SymbolNode *>(Expression::node()); }
char name() const { return node()->name(); }
};
}

View File

@@ -33,14 +33,7 @@ ExpressionNode::Sign SymbolNode::sign() const {
}
Expression SymbolNode::replaceSymbolWithExpression(char symbol, Expression expression) const {
if (m_name == symbol) {
Expression value = expression.clone();
if (parent() && value.needsParenthesesWithParent(parent())) {
value = ParenthesisReference(value);
}
return value;
}
return Expression(this);
return Symbol(this).replaceSymbolWithExpression(symbol, expression);
}
int SymbolNode::polynomialDegree(char symbol) const {
@@ -51,13 +44,7 @@ int SymbolNode::polynomialDegree(char symbol) const {
}
int SymbolNode::getPolynomialCoefficients(char symbolName, Expression coefficients[]) const {
if (m_name == symbolName) {
coefficients[0] = RationalReference(0);
coefficients[1] = RationalReference(1);
return 1;
}
coefficients[0] = SymbolReference(m_name);
return 0;
return Symbol(this).getPolynomialCoefficients(symbolName, coefficients);
}
int SymbolNode::getVariables(isVariableTest isVariable, char * variables) const {
@@ -131,7 +118,7 @@ LayoutRef SymbolNode::createLayout(Preferences::PrintFloatMode floatDisplayMode,
VerticalOffsetLayoutNode::Type::Subscript));
}
if (Symbol::isMatrixSymbol(m_name) || Symbol::isSeriesSymbol(m_name) || Symbol::isRegressionSymbol(m_name)) {
return LayoutHelper::String(SymbolReference::textForSpecialSymbols(m_name), 2);
return LayoutHelper::String(Symbol::textForSpecialSymbols(m_name), 2);
}
return LayoutHelper::String(&m_name, 1);
}
@@ -153,17 +140,8 @@ int SymbolNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloat
return 1;
}
Expression SymbolNode::shallowReduce(Context& context, Preferences::AngleUnit angleUnit) {
// Do not replace symbols in expression of type: 3->A
if (parent() && parent()->type() == Type::Store && parent()->childAtIndex(1) == this) {
return this;
}
const Expression e = context.expressionForSymbol(SymbolReference(m_name));
if (e.isDefined() && hasAnExactRepresentation(context)) { // TODO: later AZ should be replaced.
/* The stored expression had been beautified which forces to call deepReduce. */
return e.clone().deepReduce(context, angleUnit);
}
return Expression(this);
Expression SymbolNode::shallowReduce(Context& context, Preferences::AngleUnit angleUnit) const {
return Symbol(this).shallowReduce(context, angleUnit);
}
bool SymbolNode::hasAnExactRepresentation(Context & context) const {
@@ -176,7 +154,7 @@ Evaluation<T> SymbolNode::templatedApproximate(Context& context, Preferences::An
if (m_name == Ion::Charset::IComplex) {
return Complex<T>(0.0, 1.0);
}
const Expression e = context.expressionForSymbol(SymbolReference(m_name));
const Expression e = context.expressionForSymbol(Symbol(m_name));
if (e.isDefined()) {
return e.node()->approximate(T(), context, angleUnit);
}
@@ -316,26 +294,31 @@ bool Symbol::isApproximate(char c, Context & context) {
return false;
}
Expression Symbol::shallowReduce(Context& context, Preferences::AngleUnit angleUnit) {
Expression Symbol::shallowReduce(Context& context, Preferences::AngleUnit angleUnit) const {
// TODO: avoid ExpressionRef comparison ? 2 solutions:
// - Compare identifiant
// - virtualize deepReduce to do nothing on the second child of Store?
#if 0
// Do not replace symbols in expression of type: 3->A
Expression p = parent();
if (p.isDefined() && p.type() == Type::Store && p.childAtIndex(1) == *this) {
if (p.isDefined() && p.type() == ExpressionNode::Type::Store && p.childAtIndex(1) == *this) {
return *this;
}
#endif
const Expression e = context.expressionForSymbol(*this);
if (e.isDefined() && hasAnExactRepresentation(context)) {
if (e.isDefined() && node()->hasAnExactRepresentation(context)) {
// TODO: later AZ should be replaced.
/* The stored expression had been beautified which forces to call deepReduce. */
return e.clone().deepReduce(context, angleUnit);
return e.deepReduce(context, angleUnit);
}
return *this;
}
Expression Symbol::replaceSymbolWithExpression(char symbol, Expression expression) {
Expression Symbol::replaceSymbolWithExpression(char symbol, Expression expression) const {
if (name() == symbol) {
Expression value = expression.clone();
Expression value = expression;
Expression p = parent();
if (p.isDefined() && value.needsParenthesesWithParent(p)) {
if (p.isDefined() && value.node()->needsParenthesesWithParent(p.node())) {
value = Parenthesis(value);
}
return value;