input = parser.removeDoubles(input);
return simplifyTerms(distributiveRecursion(distributeExponents(input)));
}
private ConsCell distributiveRecursion(ConsCell input) throws ParserException {
ConsCell current = input, result = input;
do {
if (current.getCarType() == ConsType.CONS_CELL)
current.replaceCar(distributiveRecursion((ConsCell) current.getCar()));
} while (!(current = current.getNextConsCell()).isNull());
current = input;
do {
if (current.getCarType() != ConsType.OPERATOR || (Character) current.getCar() == '+' || (Character) current.getCar() == '^' || (Character) current.getCar() == '%')
continue;
ConsCell next = new ConsCell(), previous = new ConsCell();
ConsCell head = current.getNextConsCell();
do {
next = next.append(head.singular());
if ((head = head.remove()).getCarType() == ConsType.OPERATOR && (Character) head.getCar() == '^')
next = next.append(head.singular());
else
break;
} while (!(head = head.remove()).isNull());
next = next.getFirstConsCell();
if ((Character) current.getCar() != '-') {
head = current.getPreviousConsCell();
do {
previous = previous.isNull() ? head.singular() : new ConsCell(head.getCar(), head.getCarType(), previous, ConsType.CONS_CELL);
if ((head = head.remove().getPreviousConsCell()).getCarType() == ConsType.OPERATOR && (Character) head.getCar() == '^')
previous = new ConsCell('^', ConsType.OPERATOR, previous, ConsType.CONS_CELL);
else
break;
} while (!(head = head.remove().getPreviousConsCell()).isNull());
result = current;
}
switch ((Character) current.getCar()) {
case '-': {
//Invert all signs in the next item
ConsCell insert;
if (!parser.containsVariables(next))
insert = parser.run(new ConsCell(BigDec.MINUSONE, ConsType.NUMBER, new ConsCell('*', ConsType.OPERATOR, new ConsCell(next, ConsType.CONS_CELL))));
else if (next.getCarType() == ConsType.CONS_CELL)
insert = new ConsCell(distributiveRecursion(invertSign((ConsCell) next.getCar())), ConsType.CONS_CELL);
else {
current.insert(next);
continue;
}
current.replaceCar(new ConsCell('+', ConsType.OPERATOR));
ConsCell end = insert.getLastConsCell();
current.insert(insert);
if (current.getPreviousConsCell().isNull())
current = current.remove();
result = current = end;
continue;
}
case '*': {
ArrayList<ConsCell> left = new ArrayList<>(), right = new ArrayList<>();
if (previous.length() != 1)
left.add(previous);
else if (previous.getCarType() == ConsType.CONS_CELL)
left = foldSigns(getTerms((ConsCell) previous.getCar()));
else if (previous.getCarType() == ConsType.OPERATOR)
if ((Character) previous.getCar() == '-')
left.add(new ConsCell(BigDec.MINUSONE, ConsType.NUMBER));
else
left.add(new ConsCell(BigDec.ONE, ConsType.NUMBER));
else
left.add(previous);
if (next.length() != 1)
right.add(next);
else if (next.getCarType() == ConsType.CONS_CELL)
right = foldSigns(getTerms((ConsCell) next.getCar()));
else if (next.getCarType() == ConsType.OPERATOR)
if ((Character) next.getCar() == '-')
right.add(new ConsCell(BigDec.MINUSONE, ConsType.NUMBER));
else
right.add(new ConsCell(BigDec.ONE, ConsType.NUMBER));
else
right.add(next);
ConsCell insert = new ConsCell();
for (ConsCell lTerm : left)
for (ConsCell rTerm : right)
insert = insert.append(lTerm.clone()).append(new ConsCell('*', ConsType.OPERATOR)).append(rTerm.clone()).append(new ConsCell('+', ConsType.OPERATOR));
if (!insert.isNull()) {
insert.remove();
insert = insert.getFirstConsCell();
}
ConsCell end = insert.getLastConsCell();
if (isOneTerm(insert) && insert.length() != 1) {
current.replace(insert);
result = current = end;
}
else
current.replaceCar(insert);
continue;
}
case '/': {
ConsCell insert = previous.length() == 1 && next.length() == 1 ? polynomialDivision(previous, next, new ConsCell(parser.getVars().get(0), ConsType.IDENTIFIER), true) :
new ConsCell("{true}", ConsType.OBJECT);
if (((String) insert.getLastConsCell().getCar()).equals("{false}")) {
insert.getLastConsCell().remove();
current.replaceCar(insert);
}
else
current.replaceCar(new ConsCell(previous.getCar(), previous.getCarType(), new ConsCell('/', ConsType.OPERATOR, new ConsCell(next, ConsType.CONS_CELL))));
continue;
}
}
} while (!(current = current.getNextConsCell()).isNull());
return result.getFirstConsCell();