mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-28 10:09:53 +01:00
[poincare] SymbolAbstract is parent of Symbol and Function
This commit is contained in:
@@ -9,8 +9,8 @@ using namespace Shared;
|
||||
|
||||
namespace Regression {
|
||||
|
||||
const Expression RegressionContext::expressionForSymbol(const Symbol & symbol) {
|
||||
if (Symbol::isRegressionSymbol(symbol.name())) {
|
||||
const Expression RegressionContext::expressionForSymbol(const SymbolAbstract & symbol) {
|
||||
if (symbol.type() == ExpressionNode::Type::Symbol && Symbol::isRegressionSymbol(symbol.name())) {
|
||||
const char * seriesName = symbol.name();
|
||||
assert(strlen(seriesName) == 2);
|
||||
|
||||
@@ -23,9 +23,9 @@ const Expression RegressionContext::expressionForSymbol(const Symbol & symbol) {
|
||||
assert(m_seriesPairIndex >= 0);
|
||||
assert(m_seriesPairIndex < m_store->numberOfPairsOfSeries(series));
|
||||
return Float<double>(m_store->get(series, storeI, m_seriesPairIndex));
|
||||
} else {
|
||||
return m_parentContext->expressionForSymbol(symbol);
|
||||
}
|
||||
} else {
|
||||
return m_parentContext->expressionForSymbol(symbol);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,10 +15,12 @@ CacheContext<T>::CacheContext(Context * parentContext) :
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const Expression CacheContext<T>::expressionForSymbol(const Symbol & symbol) {
|
||||
const Expression CacheContext<T>::expressionForSymbol(const SymbolAbstract & symbol) {
|
||||
// [u|v](n(+1)?)
|
||||
if ((symbol.name()[0] == SequenceStore::k_sequenceNames[0][0] || symbol.name()[0] == SequenceStore::k_sequenceNames[1][0])
|
||||
&& (strcmp(symbol.name()+1, "(n)") == 0 || strcmp(symbol.name()+1, "(n+1)") == 0)) {
|
||||
if (symbol.type() == ExpressionNode::Type::Symbol
|
||||
&& (symbol.name()[0] == SequenceStore::k_sequenceNames[0][0] || symbol.name()[0] == SequenceStore::k_sequenceNames[1][0])
|
||||
&& (strcmp(symbol.name()+1, "(n)") == 0 || strcmp(symbol.name()+1, "(n+1)") == 0))
|
||||
{
|
||||
return Float<T>(m_values[nameIndexForSymbol(symbol)][rankIndexForSymbol(symbol)]);
|
||||
}
|
||||
return VariableContext::expressionForSymbol(symbol);
|
||||
|
||||
@@ -9,8 +9,8 @@ using namespace Shared;
|
||||
|
||||
namespace Statistics {
|
||||
|
||||
const Expression StatisticsContext::expressionForSymbol(const Symbol & symbol) {
|
||||
if (Symbol::isSeriesSymbol(symbol.name())) {
|
||||
const Expression StatisticsContext::expressionForSymbol(const SymbolAbstract & symbol) {
|
||||
if (symbol.type() == ExpressionNode::Type::Symbol && Symbol::isSeriesSymbol(symbol.name())) {
|
||||
const char * seriesName = symbol.name();
|
||||
assert(strlen(seriesName) == 2);
|
||||
|
||||
|
||||
@@ -120,6 +120,7 @@ objs += $(addprefix poincare/src/,\
|
||||
subtraction.o\
|
||||
sum.o\
|
||||
symbol.o\
|
||||
symbol_abstract.o\
|
||||
tangent.o\
|
||||
tree_handle.o\
|
||||
tree_node.o\
|
||||
|
||||
@@ -4,11 +4,12 @@
|
||||
namespace Poincare {
|
||||
|
||||
class Expression;
|
||||
class Symbol;
|
||||
class SymbolAbstract;
|
||||
class Symbol; //TODO remove?
|
||||
|
||||
class Context {
|
||||
public:
|
||||
virtual const Expression expressionForSymbol(const Symbol & symbol) = 0;
|
||||
virtual const Expression expressionForSymbol(const SymbolAbstract & symbol) = 0;
|
||||
virtual void setExpressionForSymbol(const Expression & expression, const Symbol & symbol, Context & context) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
#ifndef POINCARE_FUNCTION_H
|
||||
#define POINCARE_FUNCTION_H
|
||||
|
||||
#include <poincare/symbol.h>
|
||||
#include <poincare/symbol_abstract.h>
|
||||
#include <poincare/variable_context.h>
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
class FunctionNode : public SymbolNode {
|
||||
class FunctionNode : public SymbolAbstractNode {
|
||||
public:
|
||||
// SymbolAbstractNode
|
||||
const char * name() const override { return m_name; }
|
||||
|
||||
// TreeNode
|
||||
void initToMatchSize(size_t goalSize) override;
|
||||
size_t size() const override;
|
||||
int numberOfChildren() const override { return 1; } //TODO allow any number of children? Needs templating
|
||||
#if POINCARE_TREE_LOG
|
||||
@@ -19,6 +23,7 @@ public:
|
||||
|
||||
// Properties
|
||||
Type type() const override { return Type::Function; }
|
||||
Sign sign() const override { return Sign::Unknown; }
|
||||
Expression replaceSymbolWithExpression(const Symbol & symbol, const Expression & expression) override;
|
||||
int polynomialDegree(Context & context, const char * symbolName) const override;
|
||||
int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const override;
|
||||
@@ -26,6 +31,8 @@ public:
|
||||
float characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const override;
|
||||
|
||||
private:
|
||||
char m_name[0]; // MUST be the last member variable
|
||||
|
||||
VariableContext xContext(Context & parentContext) const;
|
||||
// Layout
|
||||
Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
|
||||
@@ -37,10 +44,10 @@ private:
|
||||
Evaluation<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override;
|
||||
};
|
||||
|
||||
class Function : public Symbol {
|
||||
class Function : public SymbolAbstract {
|
||||
public:
|
||||
explicit Function(const char * name);
|
||||
Function(const FunctionNode * n) : Symbol(n) {}
|
||||
Function(const FunctionNode * n) : SymbolAbstract(n) {}
|
||||
explicit Function(const char * name, Expression operand) : Function(name) {
|
||||
replaceChildAtIndexInPlace(0, operand);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ public:
|
||||
static constexpr char expExtension[] = "exp";
|
||||
/* The expression recorded in global context is already a expression.
|
||||
* Otherwise, we would need the context and the angle unit to evaluate it */
|
||||
const Expression expressionForSymbol(const Symbol & symbol) override;
|
||||
const Expression expressionForSymbol(const SymbolAbstract & symbol) override;
|
||||
void setExpressionForSymbol(const Expression & expression, const Symbol & symbol, Context & context) override;
|
||||
static Ion::Storage::Record RecordWithName(const char * name);
|
||||
static bool storageMemoryFull();
|
||||
|
||||
@@ -1,30 +1,16 @@
|
||||
#ifndef POINCARE_SYMBOL_H
|
||||
#define POINCARE_SYMBOL_H
|
||||
|
||||
#include <poincare/expression.h>
|
||||
#include <poincare/symbol_abstract.h>
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
/* TODO: should we keep the size of SymbolNode as a member to speed up TreePool
|
||||
* scan? */
|
||||
|
||||
/* Symbol Node contains an empty member variable "m_name", which is used to get
|
||||
* the string that follows. This means that a SymbolNode's size is sizeo
|
||||
* (SymbolNode) + strlen(string).
|
||||
*
|
||||
* Seen by TreePool: |SymbolNode |
|
||||
* SymbolNode layout: |ExpressionNode|m_name| |
|
||||
* Memory content: |ExpressionNode|S |y|m|b|o|l|N|a|m|e|0|
|
||||
* */
|
||||
|
||||
class SymbolNode final : public ExpressionNode {
|
||||
friend class Store;
|
||||
class SymbolNode final : public SymbolAbstractNode {
|
||||
public:
|
||||
void initToMatchSize(size_t goalSize) override;
|
||||
void setName(const char * name, int length) { strlcpy(m_name, name, length+1); }
|
||||
const char * name() const { return m_name; }
|
||||
const char * name() const override { return m_name; }
|
||||
|
||||
// TreeNode
|
||||
void initToMatchSize(size_t goalSize) override;
|
||||
size_t size() const override;
|
||||
int numberOfChildren() const override { return 0; }
|
||||
#if POINCARE_TREE_LOG
|
||||
@@ -45,10 +31,7 @@ public:
|
||||
int getVariables(Context & context, isVariableTest isVariable, char * variables, int maxSizeVariable) const override;
|
||||
float characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const override;
|
||||
|
||||
/* Comparison */
|
||||
int simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const override;
|
||||
|
||||
/* Layout */
|
||||
/* Layout */
|
||||
Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
|
||||
int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
|
||||
|
||||
@@ -64,14 +47,14 @@ public:
|
||||
bool isPi() const { return isSymbolChar(Ion::Charset::SmallPi); }
|
||||
bool isExponential() const { return isSymbolChar(Ion::Charset::Exponential); }
|
||||
bool isIComplex() const { return isSymbolChar(Ion::Charset::IComplex); }
|
||||
protected:
|
||||
char m_name[0]; // MUST be the last member variable
|
||||
private:
|
||||
char m_name[0]; // MUST be the last member variable
|
||||
|
||||
template<typename T> Evaluation<T> templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
|
||||
bool isSymbolChar(char c) const { const char symbolName[2] = {c, 0}; return strcmp(m_name, symbolName) == 0; }
|
||||
};
|
||||
|
||||
class Symbol final : public Expression {
|
||||
class Symbol final : public SymbolAbstract {
|
||||
friend class Expression;
|
||||
friend class Store;
|
||||
public:
|
||||
@@ -83,7 +66,7 @@ public:
|
||||
};
|
||||
Symbol(const char * name, int length);
|
||||
Symbol(char name);
|
||||
Symbol(const SymbolNode * node) : Expression(node) {}
|
||||
Symbol(const SymbolNode * node) : SymbolAbstract(node) {}
|
||||
|
||||
// Symbol properties
|
||||
bool isPi() const { return node()->isPi(); }
|
||||
@@ -97,9 +80,6 @@ public:
|
||||
Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, bool replaceSymbols = true);
|
||||
Expression replaceSymbolWithExpression(const Symbol & symbol, const Expression & expression);
|
||||
int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const;
|
||||
|
||||
// Symbol
|
||||
const char * name() const { return node()->name(); }
|
||||
private:
|
||||
SymbolNode * node() const { return static_cast<SymbolNode *>(Expression::node()); }
|
||||
};
|
||||
|
||||
53
poincare/include/poincare/symbol_abstract.h
Normal file
53
poincare/include/poincare/symbol_abstract.h
Normal file
@@ -0,0 +1,53 @@
|
||||
#ifndef POINCARE_ABSTRACT_SYMBOL_H
|
||||
#define POINCARE_ABSTRACT_SYMBOL_H
|
||||
|
||||
#include <poincare/expression.h>
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
/* TODO: should we keep the size of SymbolAbstractNode as a member to speed up
|
||||
* TreePool scan? */
|
||||
|
||||
/* SymbolAbstract derived classes must have a char[0] member variable as their
|
||||
* last member variable, so they can access their name, which is the string that
|
||||
* follows the node in memory.
|
||||
* This means that a DerivedSymbolNode's size is sizeof(DerivedSymbolNode) +
|
||||
* strlen(string).
|
||||
*
|
||||
* For instance:
|
||||
* Seen by TreePool: |SymbolNode |
|
||||
* SymbolNode layout: |ExpressionNode|m_name| |
|
||||
* Memory content: |ExpressionNode|S |y|m|b|o|l|N|a|m|e|0|
|
||||
* */
|
||||
|
||||
class SymbolAbstractNode : public ExpressionNode {
|
||||
friend class Store;
|
||||
public:
|
||||
virtual const char * name() const = 0;
|
||||
void setName(const char * newName, int length);
|
||||
|
||||
// ExpressionNode
|
||||
int simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const override;
|
||||
|
||||
// TreeNode
|
||||
#if POINCARE_TREE_LOG
|
||||
virtual void logNodeName(std::ostream & stream) const override {
|
||||
stream << "SymbolAbstract";
|
||||
}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
void initName(size_t nameSize);
|
||||
};
|
||||
|
||||
class SymbolAbstract : public Expression {
|
||||
public:
|
||||
const char * name() const { return node()->name(); }
|
||||
protected:
|
||||
SymbolAbstract(const SymbolAbstractNode * node) : Expression(node) {}
|
||||
SymbolAbstractNode * node() const { return static_cast<SymbolAbstractNode *>(Expression::node()); }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -14,7 +14,7 @@ public:
|
||||
|
||||
// Context
|
||||
void setExpressionForSymbol(const Expression & expression, const Symbol & symbol, Context & context) override;
|
||||
const Expression expressionForSymbol(const Symbol & symbol) override;
|
||||
const Expression expressionForSymbol(const SymbolAbstract & symbol) override;
|
||||
|
||||
private:
|
||||
const char * m_name;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <poincare/rational.h>
|
||||
#include <poincare/serialization_helper.h>
|
||||
#include <poincare/simplification_helper.h>
|
||||
#include <poincare/symbol.h>
|
||||
#include <cmath>
|
||||
|
||||
namespace Poincare {
|
||||
@@ -15,6 +16,15 @@ static size_t NodeSize(size_t nameLength) {
|
||||
return Helpers::AlignedSize(sizeof(FunctionNode)+nameLength+1, 4);
|
||||
}
|
||||
|
||||
void FunctionNode::initToMatchSize(size_t goalSize) {
|
||||
// TODO Factorize with symbol
|
||||
assert(goalSize != sizeof(FunctionNode));
|
||||
assert(goalSize > sizeof(FunctionNode));
|
||||
size_t nameSize = goalSize - sizeof(FunctionNode);
|
||||
SymbolAbstractNode::initName(nameSize);
|
||||
assert(size() == goalSize);
|
||||
}
|
||||
|
||||
size_t FunctionNode::size() const {
|
||||
return NodeSize(strlen(m_name));
|
||||
}
|
||||
@@ -109,7 +119,7 @@ Expression Function::replaceSymbolWithExpression(const Symbol & symbol, const Ex
|
||||
if (symbol.type() == ExpressionNode::Type::Function && strcmp(name(), symbol.name()) == 0) {
|
||||
Expression value = expression.clone();
|
||||
// Replace the unknown in the new expression by the function's child
|
||||
const char x[2] = {SpecialSymbols::UnknownX, 0};
|
||||
const char x[2] = {Symbol::SpecialSymbols::UnknownX, 0};
|
||||
Symbol xSymbol = Symbol(x, 1);
|
||||
Expression xValue = childAtIndex(0);
|
||||
value.replaceSymbolWithExpression(xSymbol, xValue);
|
||||
|
||||
@@ -22,13 +22,16 @@ bool GlobalContext::storageMemoryFull() {
|
||||
|
||||
/**/
|
||||
|
||||
const Expression GlobalContext::expressionForSymbol(const Symbol & symbol) {
|
||||
// Constant symbols
|
||||
if (symbol.isPi()) {
|
||||
return Float<double>(M_PI);
|
||||
}
|
||||
if (symbol.isExponential()) {
|
||||
return Float<double>(M_E);
|
||||
const Expression GlobalContext::expressionForSymbol(const SymbolAbstract & symbol) {
|
||||
if (symbol.type() == ExpressionNode::Type::Symbol) {
|
||||
// Constant symbols
|
||||
Symbol s = static_cast<const Symbol &>(symbol);
|
||||
if (s.isPi()) {
|
||||
return Float<double>(M_PI);
|
||||
}
|
||||
if (s.isExponential()) {
|
||||
return Float<double>(M_E);
|
||||
}
|
||||
}
|
||||
// Look up the file system for symbol
|
||||
return Expression::ExpressionFromRecord(RecordWithName(symbol.name()));
|
||||
|
||||
@@ -17,11 +17,9 @@ constexpr char Symbol::k_ans[];
|
||||
|
||||
void SymbolNode::initToMatchSize(size_t goalSize) {
|
||||
assert(goalSize != sizeof(SymbolNode));
|
||||
int nameSize = goalSize - sizeof(SymbolNode);
|
||||
for (int i = 0; i < nameSize - 1; i++) {
|
||||
m_name[i] = 'a';
|
||||
}
|
||||
m_name[nameSize-1] = 0;
|
||||
assert(goalSize > sizeof(SymbolNode));
|
||||
size_t nameSize = goalSize - sizeof(SymbolNode);
|
||||
SymbolAbstractNode::initName(nameSize);
|
||||
assert(size() == goalSize);
|
||||
}
|
||||
|
||||
@@ -99,11 +97,6 @@ float SymbolNode::characteristicXRange(Context & context, Preferences::AngleUnit
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
int SymbolNode::simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const {
|
||||
assert(e->type() == Type::Symbol);
|
||||
return strcmp(m_name, static_cast<const SymbolNode *>(e)->name());
|
||||
}
|
||||
|
||||
Layout SymbolNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const {
|
||||
if (m_name[0] == Symbol::SpecialSymbols::UnknownX) {
|
||||
assert(m_name[1] == 0);
|
||||
@@ -172,7 +165,7 @@ Evaluation<T> SymbolNode::templatedApproximate(Context& context, Preferences::An
|
||||
return e.approximateToEvaluation<T>(context, angleUnit);
|
||||
}
|
||||
|
||||
Symbol::Symbol(const char * name, int length) : Expression(TreePool::sharedPool()->createTreeNode<SymbolNode>(NodeSize(length))) {
|
||||
Symbol::Symbol(const char * name, int length) : SymbolAbstract(TreePool::sharedPool()->createTreeNode<SymbolNode>(NodeSize(length))) {
|
||||
node()->setName(name, length);
|
||||
}
|
||||
|
||||
|
||||
23
poincare/src/symbol_abstract.cpp
Normal file
23
poincare/src/symbol_abstract.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#include <poincare/symbol_abstract.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
void SymbolAbstractNode::setName(const char * newName, int length) {
|
||||
strlcpy(const_cast<char*>(name()), newName, length+1);
|
||||
}
|
||||
|
||||
int SymbolAbstractNode::simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const {
|
||||
assert(e->type() == Type::Symbol || e->type() == Type::Function);
|
||||
return strcmp(name(), static_cast<const SymbolAbstractNode *>(e)->name());
|
||||
}
|
||||
|
||||
void SymbolAbstractNode::initName(size_t nameSize) {
|
||||
char * modifiableName = const_cast<char *>(name());
|
||||
for (int i = 0; i < nameSize - 1; i++) {
|
||||
modifiableName[i] = 'a';
|
||||
}
|
||||
modifiableName[nameSize-1] = 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -29,7 +29,7 @@ void VariableContext::setExpressionForSymbol(const Expression & expression, cons
|
||||
}
|
||||
}
|
||||
|
||||
const Expression VariableContext::expressionForSymbol(const Symbol & symbol) {
|
||||
const Expression VariableContext::expressionForSymbol(const SymbolAbstract & symbol) {
|
||||
if (strcmp(symbol.name(), m_name) == 0) {
|
||||
return m_value;
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user