Symbol SymbolicateMonome(string formula, int begin, int end, Expression exp)
{
var symbols = new SymbolList();
int sign = 0;
int i = begin - 1;
int currentTermBegin = begin;
int numValues = 0;
int currentDepth = 0;
double constMultiplier = 1.0;
bool divideNext = false;
bool constMultiplierUsed = false;
for (;;)
{
i++;
if (i == end || (currentDepth == 0 && i > begin && (formula[i] == '*' || formula[i] == '/')))
{
numValues++;
// Unless we are dealing with a monome, symbolicate the term
Symbol newSymbol = SymbolicateValue(formula, formula[currentTermBegin] == '-' ? currentTermBegin + 1 : currentTermBegin, i, exp);
// Check if we can simplify the generated symbol
if (newSymbol.IsImmutableConstant() && newSymbol.IsRealValueType())
{
// Constants are multiplied/divided together
if (divideNext)
{
constMultiplier /= GetSymbolValue(newSymbol);
}
else
{
constMultiplier *= GetSymbolValue(newSymbol);
}
constMultiplierUsed = true;
}
else
{
if (divideNext)
{
symbols.Append(new Symbol(SymbolType.OperatorDivide));
}
newSymbol.Simplify();
symbols.Append(newSymbol);
}
if (i == end)
{
break;
}
divideNext = formula[i] == '/';
currentTermBegin = i + 1;
}
else if (formula[i] == '(')
{
currentDepth++;
}
else if (formula[i] == ')')
{
currentDepth--;
}
else if (formula[i] == '-' && currentDepth == 0 && !(i > begin && formula[i - 1] == '^'))
{
sign++;
}
}
// If the generated monome has negative number of minus signs, then we append *-1 to end of the list, or if the preceding symbol is constant real number that is part of a monome, we multiply it.
if (sign % 2 == 1)
{
constMultiplier = -constMultiplier;
}
if (constMultiplierUsed || sign % 2 == 1)
{
// Add the const multiplier to the expression
if (symbols.Length > 0 && symbols.first.type == SymbolType.OperatorDivide)
{
// Put to the begin of the expression we are building
symbols.symbols.Insert(0, new Symbol(constMultiplier));
}
else if (symbols.Length > 0 && symbols.last.type == SymbolType.SubExpression && symbols.last.IsMonome())
{
// Add inside the last subexpression
SymbolList leftSideExpression = symbols.last.subExpression;
if (leftSideExpression.last.type == SymbolType.RealValue && leftSideExpression.last.IsImmutableConstant())
{
leftSideExpression.SetSymbolAtIndex(leftSideExpression.Length - 1, new Symbol(leftSideExpression.last.value * constMultiplier));
}
else
{
leftSideExpression.Append(new Symbol(constMultiplier));
}
}
else
{
// Put to the end of the expression we are building
symbols.Append(new Symbol(constMultiplier));
}
}
// Check if the final monome is just a real number, in which case we don't have to return a subexpression type
if (symbols.Length == 1 && symbols.first.IsImmutableConstant() && symbols.first.IsRealValueType())
{
return(symbols.first.type == SymbolType.RealValue ? symbols.first : new Symbol(GetSymbolValue(symbols.first)));
}
Symbol s = new Symbol(SymbolType.SubExpression);
s.subExpression = symbols;
s.Simplify();
return(s);
}