if (containsVariables(input))
return ns.simplifyTerms(input);
if (input.length() < 3) {
if (input.getCarType() == ConsType.OPERATOR && input.getNextConsCell().getCarType() == ConsType.NUMBER) {
if ((Character) input.getCar() == '-')
input.getNextConsCell().replaceCar(new ConsCell(((BigDec) input.getNextConsCell().getCar()).multiply(BigDec.MINUSONE), ConsType.NUMBER));
if ((Character) input.getCar() == '/')
input.getNextConsCell().replaceCar(new ConsCell(BigDec.ONE.divide((BigDec) input.getNextConsCell().getCar()), ConsType.NUMBER));
input = input.remove();
}
return input;
}
if (input.getCarType() == ConsType.OPERATOR)
input = new ConsCell(BigDec.ZERO, ConsType.NUMBER, input, ConsType.CONS_CELL);
ConsCell current = input;
char steps[] = {'%', '%', '^', '^', '*', '/', '+', '-'};
for (int i = 0; i < steps.length - 1; i += 2) {
boolean forward = true;
do {
forward = true;
if (current.getNextConsCell(2).isNull() || current.getNextConsCell().isNull())
break;
ConsCell second = current.getNextConsCell(2);
if (current.getNextConsCell().getCarType() == ConsType.OPERATOR && (((Character) current.getNextConsCell().getCar()) == steps[i] || ((Character) current.getNextConsCell().getCar()) == steps[i + 1])) {
char operator = (Character) current.getNextConsCell().getCar();
boolean makeNegative = false;
if (second.getCarType() == ConsType.OPERATOR) {
if (((Character) second.getCar()) == '-')
makeNegative = true;
second.remove();
second = current.getNextConsCell(2);
}
if (current.getCarType() == ConsType.NUMBER && second.getCarType() == ConsType.NUMBER) {
BigDec num1 = (BigDec) current.getCar(), num2 = ((BigDec) second.getCar()).multiply(makeNegative ? BigDec.MINUSONE : BigDec.ONE), output = BigDec.ZERO;
second.remove(); //num2
current.getNextConsCell().remove(); //operator
if (operator == '%')
output = num1.mod(num2);
else if (operator == '^') {
while (current.getNextConsCell().getCarType() == ConsType.OPERATOR && (Character) current.getNextConsCell().getCar() == '^') {
boolean negate = false;
while (current.getNextConsCell(2).getCarType() == ConsType.OPERATOR) {
if ((Character) current.getNextConsCell(2).getCar() == '-')
negate = !negate;
current.getNextConsCell(2).remove();
}
if (current.getNextConsCell(2).getCarType() != ConsType.NUMBER)
throw new UndefinedResultException("For stacked exponents, each subsequent exponent must evaluate to a number", null);
num2 = num2.pow(negate ? ((BigDec) current.getNextConsCell(2).getCar()).multiply(BigDec.MINUSONE) : (BigDec) current.getNextConsCell(2).getCar());
current.getNextConsCell().remove();
current.getNextConsCell().remove();
}
output = num1.pow(num2);
}
else if (operator == '*')
output = num1.multiply(num2);
else if (operator == '/')
output = num1.divide(num2);
else if (operator == '+')
output = num1.add(num2);
else if (operator == '-')
output = num1.subtract(num2);
else
throw new UndefinedResultException(lastPlugin);
current.replaceCar(new ConsCell(output, ConsType.NUMBER));
forward = false;
}
else if ((current.getCarType() == ConsType.STRING || second.getCarType() == ConsType.STRING) &&
!(current.getCarType() == ConsType.NUMBER || second.getCarType() == ConsType.NUMBER)) {
if (operator != '+')
throw new UndefinedResultException(lastPlugin);
current.replaceCar(new ConsCell(current.carToString() + second.carToString(), ConsType.STRING));
second.remove();
current.getNextConsCell().remove();
forward = false;
}
else if (current.getCarType() == ConsType.NUMBER && second.getCarType() == ConsType.STRING) {
if (operator == '+')
current.replaceCar(new ConsCell(current.carToString() + second.carToString(), ConsType.STRING));
else if (operator == '*')
current.replaceCar(new ConsCell(stringMultiplier(second.carToString(), ((BigDec) current.getCar()).intValue()), ConsType.STRING));
else
throw new UndefinedResultException(lastPlugin);
second.remove();
current.getNextConsCell().remove();
forward = false;
}
else if (current.getCarType() == ConsType.STRING && second.getCarType() == ConsType.NUMBER) {
if (operator == '+')
current.replaceCar(new ConsCell(current.carToString() + second.carToString(), ConsType.STRING));
else if (operator == '*')
current.replaceCar(new ConsCell(stringMultiplier(current.carToString(), ((BigDec) second.getCar()).intValue()), ConsType.STRING));
else
throw new UndefinedResultException(lastPlugin);
second.remove();
current.getNextConsCell().remove();
forward = false;
}
else if (current.getCarType() == ConsType.OBJECT && second.getCarType() == ConsType.OBJECT) {
Matrix m1 = currentEqn.matrices.get(Integer.parseInt(((String) current.getCar()).substring(2, ((String) current.getCar()).length() - 1)));
Matrix m2 = currentEqn.matrices.get(Integer.parseInt(((String) second.getCar()).substring(2, ((String) second.getCar()).length() - 1)));
Matrix result = m1.matrixOp(m2, new Character(operator).toString());
currentEqn.matrices.add(result);
second.remove();
current.getNextConsCell().remove();
current.replaceCar(new ConsCell("{M" + (currentEqn.matrices.size() - 1) + "}", ConsType.OBJECT));
forward = false;
}
else if (current.getCarType() == ConsType.NUMBER && second.getCarType() == ConsType.OBJECT) {
if (operator == '/')
throw new UndefinedOperationException(operator + " is not defined for a matrix and a scalar.", lastPlugin);
Matrix m = currentEqn.matrices.get(Integer.parseInt(((String) current.getCar()).substring(2, ((String) current.getCar()).length() - 1)));
Matrix result = m.scalarOp((BigDec) current.getCar(), new Character(operator).toString());
currentEqn.matrices.add(result);
second.remove();
current.getNextConsCell().remove();
current.replaceCar(new ConsCell("{M" + (currentEqn.matrices.size() - 1) + "}", ConsType.OBJECT));
forward = false;
}
else if (current.getCarType() == ConsType.OBJECT && second.getCarType() == ConsType.NUMBER) {
Matrix m = currentEqn.matrices.get(Integer.parseInt(((String) second.getCar()).substring(2, ((String) second.getCar()).length() - 1)));
Matrix result = m.scalarOp((BigDec) second.getCar(), new Character(operator).toString());
currentEqn.matrices.add(result);
second.remove();
current.getNextConsCell().remove();
current.replaceCar(new ConsCell("{M" + (currentEqn.matrices.size() - 1) + "}", ConsType.OBJECT));
forward = false;
}
}
} while (!forward || (forward && !((current = current.getNextConsCell()).isNull()))); //This steps current forward while checking for nulls
current = input;