mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-18 21:30:38 +01:00
[poincare] Symbol replacements limit for functions
This commit is contained in:
@@ -172,6 +172,7 @@ public:
|
||||
void reduceChildren(Context & context, Preferences::AngleUnit angleUnit, bool replaceSymbols) {
|
||||
return node()->reduceChildren(context, angleUnit, replaceSymbols);
|
||||
}
|
||||
static Expression ExpressionWithoutSymbols(Expression expressionWithSymbols, Context & context);
|
||||
|
||||
/* Approximation Helper */
|
||||
template<typename U> static U epsilon();
|
||||
@@ -256,6 +257,8 @@ protected:
|
||||
Expression setSign(ExpressionNode::Sign s, Context & context, Preferences::AngleUnit angleUnit);
|
||||
|
||||
private:
|
||||
static constexpr int k_maxSymbolReplacementsCount = 30;
|
||||
|
||||
/* Simplification */
|
||||
Expression deepReduce(Context & context, Preferences::AngleUnit angleUnit, bool replaceSymbols = true);
|
||||
void deepReduceChildren(Context & context, Preferences::AngleUnit angleUnit, bool replaceSymbols) {
|
||||
|
||||
@@ -63,7 +63,6 @@ public:
|
||||
}
|
||||
constexpr static size_t k_maxNameSize = 8;
|
||||
protected:
|
||||
static constexpr int k_maxReplacementsCount = 100;
|
||||
SymbolAbstract(const SymbolAbstractNode * node) : Expression(node) {}
|
||||
SymbolAbstractNode * node() const { return static_cast<SymbolAbstractNode *>(Expression::node()); }
|
||||
private:
|
||||
|
||||
@@ -322,6 +322,24 @@ Expression Expression::simplify(Context & context, Preferences::AngleUnit angleU
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression Expression::ExpressionWithoutSymbols(Expression e, Context & context) {
|
||||
if (e.isUninitialized()) {
|
||||
return e;
|
||||
}
|
||||
/* Replace all the symbols iteratively. If we make too many replacements, the
|
||||
* symbols are likely to be defined circularly, in which case we return an
|
||||
* uninitialized expression.*/
|
||||
int replacementCount = 0;
|
||||
while (e.hasSymbols(context)) {
|
||||
replacementCount++;
|
||||
if (replacementCount > k_maxSymbolReplacementsCount) {
|
||||
return Expression();
|
||||
}
|
||||
e = e.replaceSymbols(context);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression Expression::reduce(Context & context, Preferences::AngleUnit angleUnit, bool replaceSymbols) {
|
||||
return deepReduce(context, angleUnit, replaceSymbols);
|
||||
}
|
||||
|
||||
@@ -15,16 +15,18 @@ Expression FunctionNode::replaceSymbolWithExpression(const SymbolAbstract & symb
|
||||
|
||||
int FunctionNode::polynomialDegree(Context & context, const char * symbolName) const {
|
||||
Expression e = context.expressionForSymbol(Function(this));
|
||||
e = Expression::ExpressionWithoutSymbols(e, context);
|
||||
if (e.isUninitialized()) {
|
||||
return -1;
|
||||
}
|
||||
/*TODO Context should be float or double ?*/
|
||||
// TODO Context should be float or double ?
|
||||
VariableContext newContext = xContext(context);
|
||||
return e.polynomialDegree(newContext, symbolName);
|
||||
}
|
||||
|
||||
int FunctionNode::getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const {
|
||||
Expression e = context.expressionForSymbol(Function(this));
|
||||
e = Expression::ExpressionWithoutSymbols(e, context);
|
||||
if (e.isUninitialized()) {
|
||||
return -1;
|
||||
}
|
||||
@@ -34,6 +36,7 @@ int FunctionNode::getPolynomialCoefficients(Context & context, const char * symb
|
||||
|
||||
int FunctionNode::getVariables(Context & context, isVariableTest isVariable, char * variables, int maxSizeVariable) const {
|
||||
Expression e = context.expressionForSymbol(Function(this));
|
||||
e = Expression::ExpressionWithoutSymbols(e, context);
|
||||
if (e.isUninitialized()) {
|
||||
return 0;
|
||||
}
|
||||
@@ -43,6 +46,7 @@ int FunctionNode::getVariables(Context & context, isVariableTest isVariable, cha
|
||||
|
||||
float FunctionNode::characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const {
|
||||
Expression e = context.expressionForSymbol(Function(this));
|
||||
e = Expression::ExpressionWithoutSymbols(e, context);
|
||||
if (e.isUninitialized()) {
|
||||
return 0.0f;
|
||||
}
|
||||
@@ -80,6 +84,7 @@ Evaluation<double> FunctionNode::approximate(DoublePrecision p, Context& context
|
||||
template<typename T>
|
||||
Evaluation<T> FunctionNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const {
|
||||
Expression e = context.expressionForSymbol(Function(this));
|
||||
e = Expression::ExpressionWithoutSymbols(e, context);
|
||||
if (e.isUninitialized()) {
|
||||
return Complex<T>::Undefined();
|
||||
}
|
||||
@@ -116,7 +121,8 @@ Expression Function::shallowReduce(Context & context, Preferences::AngleUnit ang
|
||||
if (!replaceSymbols) {
|
||||
return *this;
|
||||
}
|
||||
const Expression e = context.expressionForSymbol(*this);
|
||||
Expression e = context.expressionForSymbol(*this);
|
||||
e = ExpressionWithoutSymbols(e, context);
|
||||
if (!e.isUninitialized()) {
|
||||
// We need to replace the unknown with the child
|
||||
Expression result = e.clone();
|
||||
|
||||
@@ -127,20 +127,10 @@ Expression SymbolNode::replaceSymbols(Context & context) {
|
||||
template<typename T>
|
||||
Evaluation<T> SymbolNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const {
|
||||
Expression e = context.expressionForSymbol(Symbol(this));
|
||||
e = Expression::ExpressionWithoutSymbols(e, context);
|
||||
if (e.isUninitialized()) {
|
||||
return Complex<T>::Undefined();
|
||||
}
|
||||
|
||||
int replacementCount = 0;
|
||||
/* First, replace all the symbols iteratively. This prevents a memory
|
||||
* failure symbols are defined circularly. */
|
||||
while (e.hasSymbols(context)) {
|
||||
replacementCount++;
|
||||
if (replacementCount > Symbol::k_maxReplacementsCount) {
|
||||
return Complex<T>::Undefined();
|
||||
}
|
||||
e = e.replaceSymbols(context);
|
||||
}
|
||||
return e.approximateToEvaluation<T>(context, angleUnit);
|
||||
}
|
||||
|
||||
@@ -168,18 +158,7 @@ bool Symbol::isRegressionSymbol(const char * c) {
|
||||
|
||||
bool Symbol::matches(ExpressionTest test, Context & context) const {
|
||||
Expression e = context.expressionForSymbol(*this);
|
||||
if (!e.isUninitialized()) {
|
||||
/* First, replace all the symbols iteratively. This prevents a memory
|
||||
* failure symbols are defined circularly. */
|
||||
int replacementCount = 0;
|
||||
while (e.hasSymbols(context)) {
|
||||
replacementCount++;
|
||||
if (replacementCount > k_maxReplacementsCount) {
|
||||
return false; //TODO
|
||||
}
|
||||
e = e.replaceSymbols(context);
|
||||
}
|
||||
}
|
||||
e = ExpressionWithoutSymbols(e, context);
|
||||
return !e.isUninitialized() && test(e, context);
|
||||
}
|
||||
|
||||
@@ -188,24 +167,16 @@ Expression Symbol::shallowReduce(Context & context, Preferences::AngleUnit angle
|
||||
if (!replaceSymbols) {
|
||||
return *this;
|
||||
}
|
||||
const Expression e = context.expressionForSymbol(*this);
|
||||
if (!e.isUninitialized()) {
|
||||
// The stored expression is beautified, so we need to call reduce
|
||||
Expression result = e;
|
||||
/* First, replace all the symbols iteratively. This prevents a memory
|
||||
* failure symbols are defined circularly. */
|
||||
int replacementCount = 0;
|
||||
while (result.hasSymbols(context)) {
|
||||
replacementCount++;
|
||||
if (replacementCount > k_maxReplacementsCount) {
|
||||
return *this;
|
||||
}
|
||||
result = result.replaceSymbols(context);
|
||||
}
|
||||
replaceWithInPlace(result);
|
||||
return result.deepReduce(context, angleUnit);
|
||||
Expression result = context.expressionForSymbol(*this);
|
||||
// The stored expression is beautified, so we need to call reduce
|
||||
/* First, replace all the symbols iteratively. This prevents a memory
|
||||
* failure symbols are defined circularly. */
|
||||
result = ExpressionWithoutSymbols(result, context);
|
||||
if (result.isUninitialized()) {
|
||||
return *this;
|
||||
}
|
||||
return *this;
|
||||
replaceWithInPlace(result);
|
||||
return result.deepReduce(context, angleUnit);
|
||||
}
|
||||
|
||||
Expression Symbol::replaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression & expression) {
|
||||
|
||||
Reference in New Issue
Block a user