Symbol Symbolicate(string formula, int begin, int end, Expression exp)
{
var symbols = new SymbolList();
int i = begin - 1;
int currentTermBegin = formula[begin] == '+' ? begin + 1 : begin;
int currentDepth = 0;
for (;;)
{
i++;
if (i == end || (currentDepth == 0 && i > begin && (formula[i - 1] != '*' && formula[i - 1] != '/') && (formula[i] == '+' || formula[i] == '-')))
{
symbols.Append(SymbolicateMonome(formula, currentTermBegin, i, exp));
if (i == end)
{
break;
}
else
{
// The sign of the term is included in the next monome only if its minus
currentTermBegin = (formula[i] == '-') ? i : i + 1;
symbols.Append(new Symbol(SymbolType.OperatorAdd));
}
}
else if (formula[i] == '(')
{
currentDepth++;
}
else if (formula[i] == ')')
{
currentDepth--;
}
else if (formula[i] == '^')
{
i = SolverTools.ParseUntilEndOfExponent(formula, i + 1, end) - 1;
}
}
// If at this point we only have one real number left, just return it as a simple value.
if (symbols.Length == 1 && symbols.first.type == SymbolType.RealValue)
{
return(symbols.first);
}
// We don't have that single expression, but:
// Now that we are here, we have symbol list which consists of only addition operators and value types. This is a great place to sum constant values together!
double constantSum = 0;
bool addedConstants = false;
for (int j = 0; j < symbols.Length; j++)
{
Symbol s = symbols.getSymbol(j);
if (s.IsImmutableConstant() && s.IsRealValueType())
{
constantSum += s.value;
addedConstants = true;
if (j == symbols.Length - 1)
{
// Destroy preceding +
symbols.symbols.RemoveAt(j);
break;
}
symbols.symbols.RemoveAt(j);
symbols.symbols.RemoveAt(j);
j--;
}
else
{
// Skip the following + symbol
j++;
}
}
if (addedConstants)
{
if (symbols.Length > 0 && symbols.getSymbol(symbols.Length - 1).IsRealValueType())
{
symbols.Append(new Symbol(SymbolType.OperatorAdd));
}
symbols.Append(new Symbol(constantSum));
}
// Finally, if the symbolicated sum is just a single real number, even varying, return just a simple symbol
if (symbols.Length == 1 && symbols.getSymbol(0).type == SymbolType.RealValue)
{
Symbol s = symbols.getSymbol(0);
return(s);
}
// Optimization: get rid of unnecessary jumps to subexpressions
for (int j = 0; j < symbols.Length; j++)
{
var s = symbols.getSymbol(j);
if (s.type == SymbolType.SubExpression)
{
var subExpression = s.subExpression;
int subExpressionLength = subExpression.Length;
s.CopyValuesFrom(subExpression.first);
for (int k = 1; k < subExpressionLength; k++)
{
symbols.InsertBefore(j + k, subExpression.getSymbol(k));
}
j += subExpressionLength;
}
}
// We have turned the formula into a subexpression symbol
Symbol returnSymbol = new Symbol(symbols);
returnSymbol.Simplify();
return(returnSymbol);
}