WarpPI/core/src/main/java/it/cavallium/warppi/math/functions/Expression.java

627 lines
28 KiB
Java
Raw Normal View History

package it.cavallium.warppi.math.functions;
import it.cavallium.warppi.gui.expression.blocks.Block;
import it.cavallium.warppi.gui.expression.blocks.BlockContainer;
import it.cavallium.warppi.gui.expression.blocks.BlockParenthesis;
import it.cavallium.warppi.math.Function;
import it.cavallium.warppi.math.FunctionSingle;
import it.cavallium.warppi.math.MathContext;
import it.cavallium.warppi.math.functions.trigonometry.ArcCosine;
import it.cavallium.warppi.math.functions.trigonometry.ArcSine;
import it.cavallium.warppi.math.functions.trigonometry.ArcTangent;
import it.cavallium.warppi.math.functions.trigonometry.Cosine;
import it.cavallium.warppi.math.functions.trigonometry.Sine;
import it.cavallium.warppi.math.functions.trigonometry.Tangent;
import it.cavallium.warppi.util.Error;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
2017-06-09 22:47:30 +02:00
public class Expression extends FunctionSingle {
2016-09-02 20:32:37 +02:00
2018-09-22 11:17:30 +02:00
public Expression(final MathContext root) {
2017-01-17 22:32:40 +01:00
super(root);
2016-09-02 20:32:37 +02:00
}
2018-09-22 11:17:30 +02:00
public Expression(final MathContext root, final Function value) {
2017-06-09 22:47:30 +02:00
super(root, value);
2017-02-02 12:49:31 +01:00
}
2018-05-12 21:18:29 +02:00
private final boolean initialParenthesis = false;
2016-09-02 20:32:37 +02:00
2017-06-09 22:47:30 +02:00
@Deprecated
2018-09-22 11:17:30 +02:00
public Expression(final MathContext root, final String string) throws Error {
2017-01-17 22:32:40 +01:00
this(root, string, "", true);
2016-09-02 20:32:37 +02:00
}
2017-06-09 22:47:30 +02:00
@Deprecated
2018-09-22 11:17:30 +02:00
public Expression(final MathContext root, final String string, final String debugSpaces, final boolean initialParenthesis) throws Error {
2017-01-17 22:32:40 +01:00
super(root);
2017-06-09 22:47:30 +02:00
/*
super(root);
this.initialParenthesis = initialParenthesis;
2016-09-02 20:32:37 +02:00
boolean isNumber = false;
2018-09-28 11:39:28 +02:00
// Determine if the expression is already a number:
2016-09-02 20:32:37 +02:00
// Determina se l'espressione è già un numero:
try {
2017-01-17 22:32:40 +01:00
new Number(root, string);
2016-09-02 20:32:37 +02:00
isNumber = true;
} catch (final NumberFormatException ex) {
2016-09-02 20:32:37 +02:00
isNumber = false;
}
2018-09-28 11:39:28 +02:00
2016-09-02 20:32:37 +02:00
String processExpression = string;
Utils.debug.println(debugSpaces + "•Analyzing expression:" + processExpression);
2018-09-28 11:39:28 +02:00
2016-11-02 21:56:40 +01:00
isNumber = false; //TODO: rimuovere isNumber, alcune semplificazione come la divisione per zero altrimenti verrebbero saltate.
2018-09-28 11:39:28 +02:00
if (isNumber) {
// If the expression is already a number:
2016-09-02 20:32:37 +02:00
// Se l'espressione è già un numero:
final Number t = new Number(root, string);
2017-06-09 22:47:30 +02:00
parameter = t;
2016-09-02 20:32:37 +02:00
Utils.debug.println(debugSpaces + "•Result:" + t.toString());
} else {
// Else prepare the expression:
2016-09-02 20:32:37 +02:00
// Altrimenti prepara l'espressione:
debugSpaces += " ";
2018-09-28 11:39:28 +02:00
// IF the expression is not a number:
2016-09-02 20:32:37 +02:00
// Se l'espressione non è già un numero:
2018-09-28 11:39:28 +02:00
// Check if there are more than one equal symbol (=)
// Controlla se ci sono più di un uguale (=)
2016-09-02 20:32:37 +02:00
int equationsFound = 0;
int systemsFound = 0;
for (final char c : processExpression.toCharArray()) {
if (("" + c).equals(MathematicalSymbols.EQUATION)) {
2016-09-02 20:32:37 +02:00
equationsFound += 1;
}
if (("" + c).equals(MathematicalSymbols.SYSTEM)) {
2016-09-02 20:32:37 +02:00
equationsFound += 1;
}
}
if (equationsFound == 1 && systemsFound == 0) {
processExpression = MathematicalSymbols.SYSTEM + processExpression;
2016-09-02 20:32:37 +02:00
systemsFound += 1;
}
if (equationsFound != systemsFound) {
throw new Error(Errors.SYNTAX_ERROR);
2016-09-02 20:32:37 +02:00
}
2018-09-28 11:39:28 +02:00
//Solve the exceeding symbols ++ and --
2016-09-02 20:32:37 +02:00
// Correggi i segni ++ e -- in eccesso
Pattern pattern = Pattern.compile("\\+\\++?|\\-\\-+?");
Matcher matcher = pattern.matcher(processExpression);
boolean symbolsChanged = false;
2016-09-02 20:32:37 +02:00
while (matcher.find()) {
symbolsChanged = true;
final String correzione = "+";
2016-11-02 21:56:40 +01:00
processExpression = processExpression.substring(0, matcher.start(0)) + correzione + processExpression.substring(matcher.start(0) + matcher.group(0).length(), processExpression.length());
2016-09-02 20:32:37 +02:00
matcher = pattern.matcher(processExpression);
}
2018-09-28 11:39:28 +02:00
// Correct the exceeding symbols +- and -+
2016-09-02 20:32:37 +02:00
// Correggi i segni +- e -+ in eccesso
pattern = Pattern.compile("\\+\\-|\\-\\+");
matcher = pattern.matcher(processExpression);
while (matcher.find()) {
symbolsChanged = true;
final String correzione = "-";
2016-09-02 20:32:37 +02:00
processExpression = processExpression.substring(0, matcher.start(0)) + correzione + processExpression.substring(matcher.start(0) + matcher.group(0).length(), processExpression.length());
matcher = pattern.matcher(processExpression);
}
2018-09-28 11:39:28 +02:00
2016-09-02 20:32:37 +02:00
// Rimuovi i segni appena dopo le parentesi
if (processExpression.contains("(+")) {
symbolsChanged = true;
2016-09-02 20:32:37 +02:00
processExpression = processExpression.replace("(+", "(");
}
2018-09-28 11:39:28 +02:00
// // Cambia i segni appena prima le parentesi
// if (processExpression.contains("-(")) {
// symbolsChanged = true;
// processExpression = processExpression.replace("-(", "-1*(");
// }
2018-09-28 11:39:28 +02:00
2016-09-02 20:32:37 +02:00
// Rimuovi i segni appena dopo l'inizio
if (processExpression.startsWith("+")) {
symbolsChanged = true;
2016-09-02 20:32:37 +02:00
processExpression = processExpression.substring(1, processExpression.length());
}
2018-09-28 11:39:28 +02:00
2016-09-02 20:32:37 +02:00
// Rimuovi i + in eccesso
pattern = Pattern.compile("[" + ArrayToRegex(Utils.add(concat(MathematicalSymbols.signums(true), MathematicalSymbols.functions), '(')) + "]\\+[^" + ArrayToRegex(concat(concat(MathematicalSymbols.signums(true), MathematicalSymbols.functions), new char[] { '(', ')' })) + "]+?[" + ArrayToRegex(concat(MathematicalSymbols.signums(true), MathematicalSymbols.functions)) + "]|[" + ArrayToRegex(concat(MathematicalSymbols.signums(true), MathematicalSymbols.functions)) + "]+?\\+[^" + ArrayToRegex(concat(concat(MathematicalSymbols.signums(true), MathematicalSymbols.functions), new char[] { '(', ')' })) + "]");
2016-09-02 20:32:37 +02:00
matcher = pattern.matcher(processExpression);
symbolsChanged = false;
2016-09-02 20:32:37 +02:00
while (matcher.find()) {
symbolsChanged = true;
final String correzione = matcher.group(0).replaceFirst(Matcher.quoteReplacement("+"), "");
2016-09-02 20:32:37 +02:00
processExpression = processExpression.substring(0, matcher.start(0) + 1) + correzione + processExpression.substring(matcher.start(0) + matcher.group(0).length(), processExpression.length());
matcher = pattern.matcher(processExpression);
}
2018-09-28 11:39:28 +02:00
2016-11-02 21:56:40 +01:00
// Correggi i segni - in −
processExpression = processExpression.replace('-', MathematicalSymbols.SUBTRACTION);
2018-09-28 11:39:28 +02:00
2016-11-02 21:56:40 +01:00
// Correggi i segni − dopo di espressioni o funzioni SN in -
pattern = Pattern.compile("[" + Utils.ArrayToRegex(concat(concat(MathematicalSymbols.functions, new char[] { MathematicalSymbols.PARENTHESIS_OPEN }), MathematicalSymbols.signums(true))) + "]" + MathematicalSymbols.SUBTRACTION);
2016-09-02 20:32:37 +02:00
matcher = pattern.matcher(processExpression);
while (matcher.find()) {
symbolsChanged = true;
final char correzione = MathematicalSymbols.MINUS;
2016-11-02 21:56:40 +01:00
processExpression = processExpression.substring(0, matcher.start(0) + 1) + correzione + processExpression.substring(matcher.start(0) + 2, processExpression.length());
2016-09-02 20:32:37 +02:00
matcher = pattern.matcher(processExpression);
}
2018-09-28 11:39:28 +02:00
2016-11-02 21:56:40 +01:00
// Cambia il segno iniziale − in -
if (processExpression.startsWith("−")) {
symbolsChanged = true;
processExpression = "-" + processExpression.substring(1, processExpression.length());
}
2018-09-28 11:39:28 +02:00
if (symbolsChanged) {
2016-09-02 20:32:37 +02:00
Utils.debug.println(debugSpaces + "•Resolved signs:" + processExpression);
}
2018-09-28 11:39:28 +02:00
// // Aggiungi le parentesi implicite per le potenze con una incognita
// pattern = Pattern.compile("(?<!(?:\\(|^))(["+Utils.ArrayToRegex(MathematicalSymbols.variables())+"]+"+MathematicalSymbols.POWER+"[^" + Utils.ArrayToRegex(Utils.add(concat(MathematicalSymbols.functionsNSN(), concat(MathematicalSymbols.signums(true), MathematicalSymbols.genericSyntax())), ")")) + "])(?!\\))");
// matcher = pattern.matcher(processExpression);
// symbolsChanged = false;
// while (matcher.find()) {
// symbolsChanged = true;
// String correzione = matcher.group().replace(MathematicalSymbols.POWER, "â‘´");
// processExpression = processExpression.substring(0, matcher.start(0)) + correzione + processExpression.substring(matcher.start(0) + matcher.group(0).length(), processExpression.length());
// matcher = pattern.matcher(processExpression);
// }
//
// processExpression = processExpression.replace("â‘´", MathematicalSymbols.POWER);
2018-09-28 11:39:28 +02:00
2016-09-02 20:32:37 +02:00
// Aggiungi i segni * accanto alle parentesi
pattern = Pattern.compile("\\([^\\(]+?\\)");
matcher = pattern.matcher(processExpression);
while (matcher.find()) {
symbolsChanged = true;
2016-09-02 20:32:37 +02:00
// sistema i segni * impliciti prima e dopo l'espressione.
String beforeexp = processExpression.substring(0, matcher.start(0));
final String newexp = matcher.group(0).substring(1, matcher.group(0).length() - 1);
2016-09-02 20:32:37 +02:00
String afterexp = processExpression.substring(matcher.start(0) + matcher.group(0).length(), processExpression.length());
if (Pattern.compile("[^\\-" + Utils.ArrayToRegex(Utils.add(concat(MathematicalSymbols.functions, concat(MathematicalSymbols.signums(true), MathematicalSymbols.genericSyntax)), '(')) + "]$").matcher(beforeexp).find()) {
2016-09-02 20:32:37 +02:00
// Se la stringa precedente finisce con un numero
beforeexp += MathematicalSymbols.MULTIPLICATION;
2016-09-02 20:32:37 +02:00
}
if (Pattern.compile("^[^\\-" + Utils.ArrayToRegex(Utils.add(concat(MathematicalSymbols.functions, concat(MathematicalSymbols.signums(true), MathematicalSymbols.genericSyntax)), ')')) + "]").matcher(afterexp).find()) {
2016-09-02 20:32:37 +02:00
// Se la stringa successiva inizia con un numero
afterexp = MathematicalSymbols.MULTIPLICATION + afterexp;
2016-09-02 20:32:37 +02:00
}
processExpression = beforeexp + "⑴" + newexp + "⑵" + afterexp;
matcher = pattern.matcher(processExpression);
}
2018-09-28 11:39:28 +02:00
2016-09-02 20:32:37 +02:00
processExpression = processExpression.replace("⑴", "(").replace("⑵", ")");
2018-09-28 11:39:28 +02:00
if (symbolsChanged) {
2016-09-02 20:32:37 +02:00
Utils.debug.println(debugSpaces + "•Added implicit multiplications:" + processExpression);
}
2018-09-28 11:39:28 +02:00
2016-09-02 20:32:37 +02:00
Utils.debug.println(debugSpaces + "•Subdivision in classes:");
2018-09-28 11:39:28 +02:00
2016-09-02 20:32:37 +02:00
debugSpaces += " ";
2018-09-28 11:39:28 +02:00
// Convert the expression to a list of objects
Expression imputRawParenthesis = new Expression(root);
2017-06-09 22:47:30 +02:00
imputRawParenthesis = (Expression) imputRawParenthesis.setParameter(null);
2016-09-02 20:32:37 +02:00
String tmp = "";
final char[] functions = concat(concat(concat(concat(MathematicalSymbols.functions, MathematicalSymbols.parentheses), MathematicalSymbols.signums(true)), MathematicalSymbols.variables), MathematicalSymbols.genericSyntax);
2016-09-02 20:32:37 +02:00
for (int i = 0; i < processExpression.length(); i++) {
// Per ogni carattere cerca se è un numero o una funzione:
final char charI = processExpression.charAt(i);
if (Utils.isInArray(charI, functions)) {
2018-09-28 11:39:28 +02:00
// Finds the type of function fron the following list
2016-09-02 20:32:37 +02:00
// Cerca il tipo di funzione tra le esistenti
Function f = null;
2016-09-02 20:32:37 +02:00
switch (charI) {
case MathematicalSymbols.SUM:
2017-01-17 22:32:40 +01:00
f = new Sum(root, null, null);
2016-09-02 20:32:37 +02:00
break;
case MathematicalSymbols.SUM_SUBTRACTION:
2017-01-17 22:32:40 +01:00
f = new SumSubtraction(root, null, null);
2016-11-02 21:56:40 +01:00
break;
case MathematicalSymbols.SUBTRACTION:
2017-01-17 22:32:40 +01:00
f = new Subtraction(root, null, null);
2016-11-02 21:56:40 +01:00
break;
case MathematicalSymbols.MINUS:
2017-01-17 22:32:40 +01:00
f = new Negative(root, null);
break;
case MathematicalSymbols.MULTIPLICATION:
2017-01-17 22:32:40 +01:00
f = new Multiplication(root, null, null);
2016-09-02 20:32:37 +02:00
break;
case MathematicalSymbols.DIVISION:
2017-01-17 22:32:40 +01:00
f = new Division(root, null, null);
2016-09-02 20:32:37 +02:00
break;
case MathematicalSymbols.NTH_ROOT:
2017-01-17 22:32:40 +01:00
f = new Root(root, null, null);
2016-09-02 20:32:37 +02:00
break;
case MathematicalSymbols.SQUARE_ROOT:
2017-01-17 22:32:40 +01:00
f = new RootSquare(root, null);
2016-09-02 20:32:37 +02:00
break;
case MathematicalSymbols.POWER:
2017-01-17 22:32:40 +01:00
f = new Power(root, null, null);
2016-09-02 20:32:37 +02:00
break;
2016-12-04 22:22:16 +01:00
case MathematicalSymbols.SINE:
2017-01-17 22:32:40 +01:00
f = new Sine(root, null);
2016-12-04 22:22:16 +01:00
break;
case MathematicalSymbols.COSINE:
2017-01-17 22:32:40 +01:00
f = new Cosine(root, null);
2016-12-04 22:22:16 +01:00
break;
case MathematicalSymbols.TANGENT:
2017-01-17 22:32:40 +01:00
f = new Tangent(root, null);
2016-12-04 22:22:16 +01:00
break;
case MathematicalSymbols.ARC_SINE:
2017-01-17 22:32:40 +01:00
f = new ArcSine(root, null);
2016-12-04 22:22:16 +01:00
break;
case MathematicalSymbols.ARC_COSINE:
2017-01-17 22:32:40 +01:00
f = new ArcCosine(root, null);
2016-12-04 22:22:16 +01:00
break;
case MathematicalSymbols.ARC_TANGENT:
2017-01-17 22:32:40 +01:00
f = new ArcTangent(root, null);
2016-12-04 22:22:16 +01:00
break;
case MathematicalSymbols.PARENTHESIS_OPEN:
// Find the last closed parenthesis
2016-09-02 20:32:37 +02:00
// cerca l'ultima parentesi chiusa
int startIndex = i;
int endIndex = -1;
int jumps = -1;
for (int i2 = startIndex; i2 < processExpression.length(); i2++) {
if ((processExpression.charAt(i2) + "").equals(MathematicalSymbols.PARENTHESIS_CLOSE)) {
2016-09-02 20:32:37 +02:00
if (jumps == 0) {
endIndex = i2;
break;
} else if (jumps > 0) {
jumps -= 1;
} else if (jumps < 0) {
throw new Error(Errors.UNBALANCED_STACK);
2016-09-02 20:32:37 +02:00
}
} else if ((processExpression.charAt(i2) + "").equals(MathematicalSymbols.PARENTHESIS_OPEN)) {
2016-09-02 20:32:37 +02:00
jumps += 1;
}
}
if (endIndex == -1 || endIndex < startIndex) {
throw new Error(Errors.UNBALANCED_STACK);
2016-09-02 20:32:37 +02:00
}
startIndex += 1;
i = startIndex;
2018-09-28 11:39:28 +02:00
2016-09-02 20:32:37 +02:00
String tmpExpr = "";
while (i < endIndex) {
tmpExpr += processExpression.charAt(i);
i++;
}
2017-01-17 22:32:40 +01:00
f = new Expression(root, tmpExpr, debugSpaces, false);
2016-09-02 20:32:37 +02:00
break;
default:
if (Utils.isInArray(charI, MathematicalSymbols.variables)) {
f = new Variable(root, charI, Variable.V_TYPE.UNKNOWN);
2016-09-02 20:32:37 +02:00
} else {
if (charI == '(' || charI == ')') {
throw new Error(Errors.UNBALANCED_STACK);
} else {
2017-01-17 22:32:40 +01:00
System.err.println("Unexpected character while parsing expression: " + charI);
throw new Error(Errors.SYNTAX_ERROR);
}
// throw new java.lang.RuntimeException("Il carattere " + charI + " non è tra le funzioni designate!\nAggiungerlo ad esse o rimuovere il carattere dall'espressione!");
2016-09-02 20:32:37 +02:00
}
}
if (f instanceof Expression) {
2016-09-02 20:32:37 +02:00
tmp = "";
} else if (f instanceof Variable) {
if (imputRawParenthesis.getParametersLength() == 0) {
2016-09-02 20:32:37 +02:00
if (tmp.length() > 0) {
imputRawParenthesis = (Expression) imputRawParenthesis.appendParameter(new Number(root, tmp));
Utils.debug.println(debugSpaces + "•Added number to expression:" + tmp);
imputRawParenthesis = (Expression) imputRawParenthesis.appendParameter(new Multiplication(root, null, null));
Utils.debug.println(debugSpaces + "•Added multiplication to expression:" + new Multiplication(root, null, null).getClass().getSimpleName());
2016-09-02 20:32:37 +02:00
}
} else {
final Function precedentFunction = imputRawParenthesis.getParameter(imputRawParenthesis.getParametersLength() - 1);
2016-09-02 20:32:37 +02:00
if (tmp.length() > 0) {
if (precedentFunction instanceof Number || precedentFunction instanceof Variable) {
imputRawParenthesis = (Expression) imputRawParenthesis.appendParameter(new Multiplication(root, null, null));
Utils.debug.println(debugSpaces + "•Added multiplication to expression:" + new Multiplication(root, null, null).getClass().getSimpleName());
2016-09-02 20:32:37 +02:00
}
if (tmp.equals("-")) {
imputRawParenthesis = (Expression) imputRawParenthesis.appendParameter(new Subtraction(root, null, null));
2016-11-02 21:56:40 +01:00
} else {
imputRawParenthesis = (Expression) imputRawParenthesis.appendParameter(new Number(root, tmp));
Utils.debug.println(debugSpaces + "•Added number to expression:" + tmp);
2016-09-02 20:32:37 +02:00
}
}
if (tmp.length() > 0 || (precedentFunction instanceof Number || precedentFunction instanceof Variable)) {
imputRawParenthesis = (Expression) imputRawParenthesis.appendParameter(new Multiplication(root, null, null));
Utils.debug.println(debugSpaces + "•Added multiplication to expression:" + new Multiplication(root, null, null).getClass().getSimpleName());
2016-09-02 20:32:37 +02:00
}
}
} else {
if (tmp.length() != 0) {
2016-11-02 21:56:40 +01:00
if (tmp.equals("-")) {
if (tmp.equals("-")) {
tmp = "-1";
}
}
imputRawParenthesis = (Expression) imputRawParenthesis.appendParameter(new Number(root, tmp));
Utils.debug.println(debugSpaces + "•Added number to expression:" + tmp);
2016-09-02 20:32:37 +02:00
}
}
imputRawParenthesis = (Expression) imputRawParenthesis.appendParameter(f);
Utils.debug.println(debugSpaces + "•Added variable to expression:" + f.getClass().getSimpleName() + (f instanceof Number ? " (number)" : " (variable)"));
2016-09-02 20:32:37 +02:00
tmp = "";
} else {
try {
if (charI != '-' && charI != '.') {
2016-09-02 20:32:37 +02:00
new BigDecimal(tmp + charI);
}
// Se il carattere è un numero intero, un segno
// negativo, o un punto
tmp += charI;
} catch (final Exception exc) {
2016-09-02 20:32:37 +02:00
throw new java.lang.RuntimeException("Il carattere " + tmp + charI + " non è nè un numero nè un espressione presente nella lista completa!\nAggiungerlo ad essa o rimuovere il carattere dall'espressione!");
}
}
}
if (tmp.length() > 0) {
Utils.debug.println(debugSpaces + "•Added variable to expression:" + tmp);
try {
imputRawParenthesis = (Expression) imputRawParenthesis.appendParameter(new Number(root, tmp));
} catch (final NumberFormatException ex) {
throw new Error(Errors.SYNTAX_ERROR);
2016-09-02 20:32:37 +02:00
}
tmp = "";
}
2018-09-28 11:39:28 +02:00
2016-09-02 20:32:37 +02:00
int dsl = debugSpaces.length();
debugSpaces = "";
for (int i = 0; i < dsl - 2; i++) {
debugSpaces += " ";
}
Utils.debug.println(debugSpaces + "•Finished the subdivision in classes.");
// Fine suddivisione di insieme
2018-09-28 11:39:28 +02:00
2016-09-02 20:32:37 +02:00
Utils.debug.println(debugSpaces + "•Removing useless parentheses");
for (int i = 0; i < imputRawParenthesis.getParametersLength(); i++) {
if (imputRawParenthesis.getParameter(i) instanceof Expression) {
final Expression par = (Expression) imputRawParenthesis.getParameter(i);
if (par.getParametersLength() == 1) {
final Function subFunz = par.getParameter(0);
if (subFunz instanceof Expression || subFunz instanceof Number || subFunz instanceof Variable) {
imputRawParenthesis = (Expression) imputRawParenthesis.setParameter(i, subFunz);
2016-09-02 20:32:37 +02:00
Utils.debug.println(debugSpaces + " •Useless parentheses removed");
}
}
}
}
2018-09-28 11:39:28 +02:00
2016-09-02 20:32:37 +02:00
// Inizia l'affinazione dell'espressione
Utils.debug.println(debugSpaces + "•Pushing classes...");
2018-09-28 11:39:28 +02:00
final Function[] oldFunctionsArray = imputRawParenthesis.getParameters();
final ObjectArrayList<Function> oldFunctionsList = new ObjectArrayList<>();
for (int i = 0; i < oldFunctionsArray.length; i++) {
Function funzione = oldFunctionsArray[i];
2016-09-02 20:32:37 +02:00
if (funzione != null) {
//Affinazione
if (funzione instanceof Root) {
if ((i - 1) >= 0 && oldFunctionsArray[i - 1] instanceof Number && ((Number) oldFunctionsArray[i - 1]).getTerm().compareTo(new BigDecimal(2)) == 0) {
oldFunctionsArray[i] = null;
oldFunctionsArray[i - 1] = null;
oldFunctionsList.remove(oldFunctionsList.size() - 1);
2016-09-02 20:32:37 +02:00
i -= 1;
2017-01-17 22:32:40 +01:00
funzione = new RootSquare(root, null);
2016-09-02 20:32:37 +02:00
}
}
//Aggiunta della funzione alla lista grezza
oldFunctionsList.add(funzione);
2016-09-02 20:32:37 +02:00
}
}
2018-09-28 11:39:28 +02:00
if (oldFunctionsList.size() > 1) {
2016-09-02 20:32:37 +02:00
Utils.debug.println(debugSpaces + " •Correcting classes:");
2018-09-28 11:39:28 +02:00
2016-09-02 20:32:37 +02:00
int before = 0;
String step = "SN Functions";
2016-09-02 20:32:37 +02:00
int n = 0;
do {
before = oldFunctionsList.size();
2016-09-02 20:32:37 +02:00
int i = 0;
boolean change = false;
if (Utils.areThereOnlyEmptySNFunctions(oldFunctionsList)) {
step = "SN Functions"; // SECONDA FASE
} else if (Utils.areThereOnlyEmptyNSNFunctions(oldFunctionsList)) {
step = "NSN Functions"; // TERZA FASE
} else if (Utils.areThereEmptyMultiplications(oldFunctionsList)) {
step = "multiplications"; // QUARTA FASE
} else if (Utils.areThereEmptySums(oldFunctionsList)) {
step = "sums"; // QUINTA FASE
2016-09-02 20:32:37 +02:00
} else {
// fase = "errore";
2016-09-02 20:32:37 +02:00
System.out.println("WARN: ---> POSSIBILE ERRORE????? <---");// BOH
// throw new Errore(Errori.SYNTAX_ERROR);
while (oldFunctionsList.size() > 1) {
2017-01-17 22:32:40 +01:00
oldFunctionsList.set(0, new Multiplication(root, oldFunctionsList.get(0), oldFunctionsList.remove(1)));
2016-09-02 20:32:37 +02:00
}
}
Utils.debug.println(debugSpaces + " •Phase: " + step);
while (i < oldFunctionsList.size() && change == false && oldFunctionsList.size() > 1) {
Function funzioneTMP = oldFunctionsList.get(i);
if (funzioneTMP instanceof FunctionOperator) {
if (step != "SN Functions") {
if ((step == "sums" && (funzioneTMP instanceof Sum || funzioneTMP instanceof SumSubtraction || funzioneTMP instanceof Subtraction) == true && ((funzioneTMP instanceof FunctionSingle && ((FunctionSingle) funzioneTMP).getParameter() == null) || (funzioneTMP instanceof FunctionOperator && ((FunctionOperator) funzioneTMP).getParameter1() == null && ((FunctionOperator) funzioneTMP).getParameter2() == null) || (!(funzioneTMP instanceof FunctionSingle) && !(funzioneTMP instanceof FunctionOperator)))) || (step.equals("multiplications") && ((funzioneTMP instanceof Multiplication) || (funzioneTMP instanceof Division)) && ((FunctionOperator) funzioneTMP).getParameter1() == null && ((FunctionOperator) funzioneTMP).getParameter2() == null) || (step == "NSN Functions" && (funzioneTMP instanceof Sum) == false && (funzioneTMP instanceof SumSubtraction) == false && (funzioneTMP instanceof Subtraction) == false && (funzioneTMP instanceof Multiplication) == false && (funzioneTMP instanceof Division) == false && ((funzioneTMP instanceof FunctionSingle && ((FunctionSingle) funzioneTMP).getParameter() == null) || (funzioneTMP instanceof FunctionOperator && ((FunctionOperator) funzioneTMP).getParameter1() == null && ((FunctionOperator) funzioneTMP).getParameter2() == null) || (!(funzioneTMP instanceof FunctionSingle) && !(funzioneTMP instanceof FunctionOperator))))) {
2016-09-02 20:32:37 +02:00
change = true;
2018-09-28 11:39:28 +02:00
if (i + 1 < oldFunctionsList.size() && i - 1 >= 0) {
funzioneTMP = ((FunctionOperator) funzioneTMP).setParameter1(oldFunctionsList.get(i - 1));
funzioneTMP = ((FunctionOperator) funzioneTMP).setParameter2(oldFunctionsList.get(i + 1));
oldFunctionsList.set(i, funzioneTMP);
2018-09-28 11:39:28 +02:00
2016-09-02 20:32:37 +02:00
// è importante togliere prima gli elementi
// in fondo e poi quelli davanti, perché gli
// indici scalano da destra a sinistra.
oldFunctionsList.remove(i + 1);
oldFunctionsList.remove(i - 1);
2018-09-28 11:39:28 +02:00
Utils.debug.println(debugSpaces + " •Set variable to expression:" + funzioneTMP.getClass().getSimpleName());
2016-09-02 20:32:37 +02:00
try {
Utils.debug.println(debugSpaces + " " + "var1=" + ((FunctionOperator) funzioneTMP).getParameter1().toString());
} catch (final NullPointerException ex2) {}
2016-09-02 20:32:37 +02:00
try {
Utils.debug.println(debugSpaces + " " + "var2=" + ((FunctionOperator) funzioneTMP).getParameter2().toString());
} catch (final NullPointerException ex2) {}
2016-09-02 20:32:37 +02:00
try {
Utils.debug.println(debugSpaces + " " + "(result)=" + ((FunctionOperator) funzioneTMP).toString());
} catch (final NullPointerException ex2) {}
2018-09-28 11:39:28 +02:00
2016-09-02 20:32:37 +02:00
} else {
throw new Error(Errors.SYNTAX_ERROR);
2016-09-02 20:32:37 +02:00
}
}
}
} else if (funzioneTMP instanceof FunctionSingle) {
if ((step == "SN Functions" && ((FunctionSingle) funzioneTMP).getParameter() == null)) {
if (i + 1 < oldFunctionsList.size()) {
final Function nextFunc = oldFunctionsList.get(i + 1);
if (nextFunc instanceof FunctionSingle && ((FunctionSingle) nextFunc).getParameter() == null) {
2018-09-28 11:39:28 +02:00
2016-09-02 20:32:37 +02:00
} else {
change = true;
funzioneTMP = ((FunctionSingle) funzioneTMP).setParameter(nextFunc);
oldFunctionsList.set(i, funzioneTMP);
2018-09-28 11:39:28 +02:00
2016-09-02 20:32:37 +02:00
// è importante togliere prima gli elementi in
// fondo e poi quelli davanti, perché gli indici
// scalano da destra a sinistra.
oldFunctionsList.remove(i + 1);
2018-09-28 11:39:28 +02:00
Utils.debug.println(debugSpaces + " •Set variable to expression:" + funzioneTMP.getClass().getSimpleName());
final Function var = ((FunctionSingle) funzioneTMP).getParameter();
2016-09-02 20:32:37 +02:00
if (var == null) {
Utils.debug.println(debugSpaces + " " + "var=null");
} else {
Utils.debug.println(debugSpaces + " " + "var=" + var.toString());
}
}
} else {
throw new Error(Errors.SYNTAX_ERROR);
2016-09-02 20:32:37 +02:00
}
}
} else if (funzioneTMP instanceof Number || funzioneTMP instanceof Variable || funzioneTMP instanceof Expression) {
2016-09-02 20:32:37 +02:00
if (n < 300) {
// Utils.debug.println(debugSpaces+" •Set variable
// to number:"+funzioneTMP.calcola());
}
} else {
throw new java.lang.RuntimeException("Tipo sconosciuto");
}
i++;
n++;
}
} while (((oldFunctionsList.size() != before || step != "sums") && oldFunctionsList.size() > 1));
2016-09-02 20:32:37 +02:00
}
if (oldFunctionsList.isEmpty()) {
super.functions = new Function[] { new Number(root, 0) };
2016-12-04 22:22:16 +01:00
} else {
super.functions = oldFunctionsList.toArray(new Function[oldFunctionsList.size()]);
2016-12-04 22:22:16 +01:00
}
2018-09-28 11:39:28 +02:00
2016-09-02 20:32:37 +02:00
dsl = debugSpaces.length();
debugSpaces = "";
for (int i = 0; i < dsl - 2; i++) {
debugSpaces += " ";
}
Utils.debug.println(debugSpaces + "•Finished correcting classes.");
2018-09-28 11:39:28 +02:00
final String result = toString();
2016-09-02 20:32:37 +02:00
Utils.debug.println(debugSpaces + "•Result:" + result);
}
2017-06-09 22:47:30 +02:00
*/
2016-09-02 20:32:37 +02:00
}
public boolean parenthesisNeeded() {
boolean parenthesisneeded = true;
2018-09-28 11:39:28 +02:00
if (initialParenthesis) {
parenthesisneeded = false;
2018-09-28 11:39:28 +02:00
} else {
2017-06-09 22:47:30 +02:00
final Function f = getParameter(0);
2018-09-28 11:39:28 +02:00
if (f instanceof Number || f instanceof Variable || f instanceof Expression || f instanceof Division || f instanceof Joke || f instanceof Undefined || f instanceof Power || f instanceof Sine || f instanceof Cosine || f instanceof Tangent || f instanceof ArcSine || f instanceof ArcCosine || f instanceof ArcTangent || f instanceof RootSquare) {
2017-06-09 22:47:30 +02:00
parenthesisneeded = false;
2018-09-28 11:39:28 +02:00
}
if (f instanceof Multiplication) {
if (((Multiplication) f).getParameter1() instanceof Number) {
2017-06-09 22:47:30 +02:00
parenthesisneeded = !(((Multiplication) f).getParameter2() instanceof Variable);
2018-09-28 11:39:28 +02:00
} else if (((Multiplication) f).getParameter2() instanceof Number) {
2017-06-09 22:47:30 +02:00
parenthesisneeded = !(((Multiplication) f).getParameter1() instanceof Variable);
2018-09-28 11:39:28 +02:00
} else if (((Multiplication) f).getParameter1() instanceof Variable || ((Multiplication) f).getParameter2() instanceof Variable) {
parenthesisneeded = false;
2018-09-28 11:39:28 +02:00
}
}
2016-09-02 20:32:37 +02:00
}
return parenthesisneeded;
2016-09-02 20:32:37 +02:00
}
@Override
2018-09-22 11:17:30 +02:00
public ObjectArrayList<Block> toBlock(final MathContext context) throws Error {
2018-05-12 21:18:29 +02:00
final ObjectArrayList<Block> result = new ObjectArrayList<>();
final ObjectArrayList<Block> sub = getParameter(0).toBlock(context);
final BlockParenthesis bp = new BlockParenthesis();
final BlockContainer bpc = bp.getNumberContainer();
2018-09-28 11:39:28 +02:00
for (final Block b : sub) {
bpc.appendBlockUnsafe(b);
2018-09-28 11:39:28 +02:00
}
bpc.recomputeDimensions();
bp.recomputeDimensions();
result.add(bp);
return result;
}
@Override
public <Argument, Result> Result accept(final Function.Visitor<Argument, Result> visitor, final Argument argument) {
return visitor.visit(this, argument);
}
@Override
public String toString() {
String s = "(";
2018-09-28 11:39:28 +02:00
if (parameter == null) {
2017-06-09 22:47:30 +02:00
s += "null";
2018-09-28 11:39:28 +02:00
} else {
2017-06-09 22:47:30 +02:00
s += parameter.toString();
2018-09-28 11:39:28 +02:00
}
s += ")";
return s;
}
@Override
2018-09-22 11:17:30 +02:00
public boolean equals(final Object o) {
2018-09-28 11:39:28 +02:00
if (parameter == null | o == null) {
2017-06-09 22:47:30 +02:00
return parameter == o;
2018-09-28 11:39:28 +02:00
} else {
final Function f = (Function) o;
2018-09-28 11:39:28 +02:00
if (f instanceof Expression) {
2018-09-22 11:17:30 +02:00
return getParameter(0).equals(((Expression) f).getParameter(0));
2018-09-28 11:39:28 +02:00
} else {
2018-09-22 11:17:30 +02:00
return getParameter(0).equals(f);
2018-09-28 11:39:28 +02:00
}
}
}
2016-09-02 20:32:37 +02:00
@Override
public Expression clone() {
2018-10-04 23:39:19 +02:00
return new Expression(mathContext, parameter == null ? null : parameter.clone());
}
@Override
public Expression clone(MathContext newContext) {
return new Expression(newContext, parameter == null ? null : parameter.clone(newContext));
}
2016-09-02 20:32:37 +02:00
}