mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-20 14:20:39 +01:00
[poincare] Fix Symbol
This commit is contained in:
@@ -16,6 +16,7 @@ objs += $(addprefix poincare/src/,\
|
||||
opposite.o\
|
||||
decimal.o\
|
||||
rational.o\
|
||||
symbol.o\
|
||||
)
|
||||
|
||||
objsExpected += $(addprefix poincare/src/,\
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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(); }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user