From 205d5dbc77f8e7b7deb7f92561511a4465a8c86d Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Mon, 14 Aug 2017 19:03:52 -0700 Subject: [PATCH] Format code. --- build.gradle | 2 +- .../nwapw/abacus/config/Configuration.java | 4 +- .../ComputationInterruptedException.java | 2 +- .../org/nwapw/abacus/number/NaiveNumber.java | 2 +- .../nwapw/abacus/number/NumberInterface.java | 25 +- .../nwapw/abacus/number/PreciseNumber.java | 8 +- .../abacus/parsing/ShuntingYardParser.java | 2 +- .../java/org/nwapw/abacus/plugin/Plugin.java | 9 +- .../nwapw/abacus/plugin/PluginManager.java | 52 ++-- .../nwapw/abacus/plugin/StandardPlugin.java | 289 +++++++++--------- .../org/nwapw/abacus/tree/FunctionNode.kt | 4 +- .../kotlin/org/nwapw/abacus/tree/Reducer.kt | 4 +- .../kotlin/org/nwapw/abacus/tree/TreeNode.kt | 2 +- .../nwapw/abacus/tests/CalculationTests.java | 28 +- fx/build.gradle | 4 +- .../nwapw/abacus/fx/AbacusApplication.java | 8 +- .../org/nwapw/abacus/fx/AbacusController.java | 67 ++-- .../nwapw/abacus/fx/DocumentationCell.java | 4 +- .../org/nwapw/abacus/fx/HistoryModel.kt | 2 +- .../org/nwapw/abacus/fx/ToggleablePlugin.kt | 2 +- 20 files changed, 261 insertions(+), 259 deletions(-) diff --git a/build.gradle b/build.gradle index db469a9..ee5a968 100644 --- a/build.gradle +++ b/build.gradle @@ -3,7 +3,7 @@ subprojects { apply plugin: 'java' repositories { - mavenCentral() + mavenCentral() } dependencies { diff --git a/core/src/main/java/org/nwapw/abacus/config/Configuration.java b/core/src/main/java/org/nwapw/abacus/config/Configuration.java index 1bc7aa2..284e80d 100644 --- a/core/src/main/java/org/nwapw/abacus/config/Configuration.java +++ b/core/src/main/java/org/nwapw/abacus/config/Configuration.java @@ -48,7 +48,7 @@ public class Configuration { * * @param copyFrom the configuration to copy. */ - public Configuration(Configuration copyFrom){ + public Configuration(Configuration copyFrom) { copyFrom(copyFrom); } @@ -106,7 +106,7 @@ public class Configuration { * * @return the string that represents this configuration. */ - public String asTomlString(){ + public String asTomlString() { return TOML_WRITER.write(this); } diff --git a/core/src/main/java/org/nwapw/abacus/number/ComputationInterruptedException.java b/core/src/main/java/org/nwapw/abacus/number/ComputationInterruptedException.java index cc3e9e1..2f7b3fd 100644 --- a/core/src/main/java/org/nwapw/abacus/number/ComputationInterruptedException.java +++ b/core/src/main/java/org/nwapw/abacus/number/ComputationInterruptedException.java @@ -9,7 +9,7 @@ public class ComputationInterruptedException extends RuntimeException { /** * Creates a new exception of this type. */ - public ComputationInterruptedException(){ + public ComputationInterruptedException() { super("Computation interrupted by user."); } diff --git a/core/src/main/java/org/nwapw/abacus/number/NaiveNumber.java b/core/src/main/java/org/nwapw/abacus/number/NaiveNumber.java index 05dcc33..cd17c89 100755 --- a/core/src/main/java/org/nwapw/abacus/number/NaiveNumber.java +++ b/core/src/main/java/org/nwapw/abacus/number/NaiveNumber.java @@ -129,7 +129,7 @@ public class NaiveNumber extends NumberInterface { } @Override - public NumberInterface getMaxError(){ + public NumberInterface getMaxError() { return new NaiveNumber(Math.pow(10, -18)); } } diff --git a/core/src/main/java/org/nwapw/abacus/number/NumberInterface.java b/core/src/main/java/org/nwapw/abacus/number/NumberInterface.java index c534225..adf401d 100755 --- a/core/src/main/java/org/nwapw/abacus/number/NumberInterface.java +++ b/core/src/main/java/org/nwapw/abacus/number/NumberInterface.java @@ -9,10 +9,11 @@ public abstract class NumberInterface { * Check if the thread was interrupted and * throw an exception to end the computation. */ - private static void checkInterrupted(){ - if(Thread.currentThread().isInterrupted()) + private static void checkInterrupted() { + if (Thread.currentThread().isInterrupted()) throw new ComputationInterruptedException(); } + /** * The maximum precision to which this number operates. * @@ -38,7 +39,7 @@ public abstract class NumberInterface { * @param multiplier the multiplier * @return the result of the multiplication. */ - public final NumberInterface multiply(NumberInterface multiplier){ + public final NumberInterface multiply(NumberInterface multiplier) { checkInterrupted(); return multiplyInternal(multiplier); } @@ -61,7 +62,7 @@ public abstract class NumberInterface { * @param divisor the divisor * @return the result of the division. */ - public final NumberInterface divide(NumberInterface divisor){ + public final NumberInterface divide(NumberInterface divisor) { checkInterrupted(); return divideInternal(divisor); } @@ -84,7 +85,7 @@ public abstract class NumberInterface { * @param summand the summand * @return the result of the summation. */ - public final NumberInterface add(NumberInterface summand){ + public final NumberInterface add(NumberInterface summand) { checkInterrupted(); return addInternal(summand); } @@ -107,7 +108,7 @@ public abstract class NumberInterface { * @param subtrahend the subtrahend. * @return the result of the subtraction. */ - public final NumberInterface subtract(NumberInterface subtrahend){ + public final NumberInterface subtract(NumberInterface subtrahend) { checkInterrupted(); return subtractInternal(subtrahend); } @@ -129,7 +130,7 @@ public abstract class NumberInterface { * * @return the new instance. */ - public final NumberInterface negate(){ + public final NumberInterface negate() { checkInterrupted(); return negateInternal(); } @@ -150,7 +151,7 @@ public abstract class NumberInterface { * @param exponent the exponent to which to take the number. * @return the resulting value. */ - public final NumberInterface intPow(int exponent){ + public final NumberInterface intPow(int exponent) { checkInterrupted(); return intPowInternal(exponent); } @@ -184,7 +185,7 @@ public abstract class NumberInterface { * * @return the least integer bigger or equal to the number. */ - public final NumberInterface ceiling(){ + public final NumberInterface ceiling() { checkInterrupted(); return ceilingInternal(); } @@ -203,7 +204,7 @@ public abstract class NumberInterface { * * @return the greatest int smaller than or equal to the number. */ - public final NumberInterface floor(){ + public final NumberInterface floor() { checkInterrupted(); return floorInternal(); } @@ -219,9 +220,10 @@ public abstract class NumberInterface { * Returns the fractional part of the number, specifically x - floor(x). * Also, checks if the thread has been interrupted, * and if so, throws an exception. + * * @return the fractional part of the number. */ - public final NumberInterface fractionalPart(){ + public final NumberInterface fractionalPart() { checkInterrupted(); return fractionalPartInternal(); } @@ -260,6 +262,7 @@ public abstract class NumberInterface { /** * Returns the smallest error this instance can tolerate depending * on its precision and value. + * * @return the smallest error that should be permitted in calculations. */ public abstract NumberInterface getMaxError(); diff --git a/core/src/main/java/org/nwapw/abacus/number/PreciseNumber.java b/core/src/main/java/org/nwapw/abacus/number/PreciseNumber.java index 094e5a9..f6f5afe 100755 --- a/core/src/main/java/org/nwapw/abacus/number/PreciseNumber.java +++ b/core/src/main/java/org/nwapw/abacus/number/PreciseNumber.java @@ -35,7 +35,7 @@ public class PreciseNumber extends NumberInterface { /** * MathContext that is actually used in calculations. */ - private static MathContext internalContext = new MathContext(outputContext.getPrecision()+numExtraInternalSigFigs); + private static MathContext internalContext = new MathContext(outputContext.getPrecision() + numExtraInternalSigFigs); /** * The value of the PreciseNumber. @@ -129,7 +129,7 @@ public class PreciseNumber extends NumberInterface { int decimalIndex = str.indexOf('.'); if (decimalIndex != -1) { NumberInterface floor = new PreciseNumber(str.substring(0, decimalIndex)); - if(signum() == -1){ + if (signum() == -1) { floor = floor.subtract(ONE); } return floor; @@ -166,7 +166,7 @@ public class PreciseNumber extends NumberInterface { } @Override - public NumberInterface getMaxError(){ - return new PreciseNumber(value.ulp()).multiplyInternal(TEN.intPowInternal(value.precision()-internalContext.getPrecision())); + public NumberInterface getMaxError() { + return new PreciseNumber(value.ulp()).multiplyInternal(TEN.intPowInternal(value.precision() - internalContext.getPrecision())); } } diff --git a/core/src/main/java/org/nwapw/abacus/parsing/ShuntingYardParser.java b/core/src/main/java/org/nwapw/abacus/parsing/ShuntingYardParser.java index 5d35032..c7a5615 100644 --- a/core/src/main/java/org/nwapw/abacus/parsing/ShuntingYardParser.java +++ b/core/src/main/java/org/nwapw/abacus/parsing/ShuntingYardParser.java @@ -162,7 +162,7 @@ public class ShuntingYardParser implements Parser>, PluginListe @Override public TreeNode constructTree(List> tokens) { tokens = intoPostfix(new ArrayList<>(tokens)); - if(tokens == null) return null; + if (tokens == null) return null; Collections.reverse(tokens); TreeNode constructedTree = constructRecursive(tokens); return tokens.size() == 0 ? constructedTree : null; diff --git a/core/src/main/java/org/nwapw/abacus/plugin/Plugin.java b/core/src/main/java/org/nwapw/abacus/plugin/Plugin.java index b92a9f4..4907131 100644 --- a/core/src/main/java/org/nwapw/abacus/plugin/Plugin.java +++ b/core/src/main/java/org/nwapw/abacus/plugin/Plugin.java @@ -6,10 +6,6 @@ import org.nwapw.abacus.function.Function; import org.nwapw.abacus.function.Operator; import org.nwapw.abacus.number.NumberInterface; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - /** * A plugin class that can be externally implemented and loaded via the * plugin manager. Plugins provide functionality to the calculator @@ -99,9 +95,10 @@ public abstract class Plugin { /** * To be used in load(). Registers a documentation instance * used to explain some element of the plugin to the user. + * * @param documentation the documentation instance. */ - protected final void registerDocumentation(Documentation documentation){ + protected final void registerDocumentation(Documentation documentation) { manager.registerDocumentation(documentation); } @@ -148,7 +145,7 @@ public abstract class Plugin { * @param type the type of documentation to search for. * @return the found documentation, or null if none was found. */ - protected final Documentation documentationFor(String name, DocumentationType type){ + protected final Documentation documentationFor(String name, DocumentationType type) { return manager.documentationFor(name, type); } diff --git a/core/src/main/java/org/nwapw/abacus/plugin/PluginManager.java b/core/src/main/java/org/nwapw/abacus/plugin/PluginManager.java index 78d4cb9..b808411 100644 --- a/core/src/main/java/org/nwapw/abacus/plugin/PluginManager.java +++ b/core/src/main/java/org/nwapw/abacus/plugin/PluginManager.java @@ -8,7 +8,10 @@ import org.nwapw.abacus.function.Operator; import org.nwapw.abacus.number.NumberInterface; import java.lang.reflect.InvocationTargetException; -import java.util.*; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; /** * A class that controls instances of plugins, allowing for them @@ -79,82 +82,90 @@ public class PluginManager { /** * Registers a function under the given name. - * @param name the name of the function. + * + * @param name the name of the function. * @param function the function to register. */ - public void registerFunction(String name, Function function){ + public void registerFunction(String name, Function function) { registeredFunctions.put(name, function); } /** * Registers an operator under the given name. - * @param name the name of the operator. + * + * @param name the name of the operator. * @param operator the operator to register. */ - public void registerOperator(String name, Operator operator){ + public void registerOperator(String name, Operator operator) { registeredOperators.put(name, operator); } /** * Registers a number implementation under the given name. - * @param name the name of the number implementation. + * + * @param name the name of the number implementation. * @param implementation the number implementation to register. */ - public void registerNumberImplementation(String name, NumberImplementation implementation){ + public void registerNumberImplementation(String name, NumberImplementation implementation) { registeredNumberImplementations.put(name, implementation); } /** * Registers the given documentation with the plugin manager, * making it accessible to the plugin manager etc. + * * @param documentation the documentation to register. */ - public void registerDocumentation(Documentation documentation){ + public void registerDocumentation(Documentation documentation) { registeredDocumentation.add(documentation); } /** * Gets the function registered under the given name. + * * @param name the name of the function. * @return the function, or null if it was not found. */ - public Function functionFor(String name){ + public Function functionFor(String name) { return registeredFunctions.get(name); } /** * Gets the operator registered under the given name. + * * @param name the name of the operator. * @return the operator, or null if it was not found. */ - public Operator operatorFor(String name){ + public Operator operatorFor(String name) { return registeredOperators.get(name); } /** * Gets the number implementation registered under the given name. + * * @param name the name of the number implementation. * @return the number implementation, or null if it was not found. */ - public NumberImplementation numberImplementationFor(String name){ + public NumberImplementation numberImplementationFor(String name) { return registeredNumberImplementations.get(name); } /** * Gets the documentation for the given entity of the given type. + * * @param name the name of the entity to search for. * @param type the type that this entity is, to filter out similarly named documentation. * @return the documentation object. */ - public Documentation documentationFor(String name, DocumentationType type){ + public Documentation documentationFor(String name, DocumentationType type) { Documentation toReturn = null; - for(Documentation entry : registeredDocumentation){ - if(entry.getCodeName().equals(name) && entry.getType() == type) { + for (Documentation entry : registeredDocumentation) { + if (entry.getCodeName().equals(name) && entry.getType() == type) { toReturn = entry; break; } } - if(toReturn == null){ + if (toReturn == null) { toReturn = new Documentation(name, "", "", "", type); registerDocumentation(toReturn); } @@ -170,9 +181,9 @@ public class PluginManager { public NumberImplementation interfaceImplementationFor(Class name) { if (cachedInterfaceImplementations.containsKey(name)) return cachedInterfaceImplementations.get(name); NumberImplementation toReturn = null; - for(String key : registeredNumberImplementations.keySet()){ + for (String key : registeredNumberImplementations.keySet()) { NumberImplementation implementation = registeredNumberImplementations.get(key); - if(implementation.getImplementation() == name) { + if (implementation.getImplementation() == name) { toReturn = implementation; break; } @@ -226,10 +237,11 @@ public class PluginManager { /** * Removes the plugin with the given class from the manager. + * * @param toRemove the plugin to remove. */ - public void removeClass(Class toRemove){ - if(!loadedPluginClasses.contains(toRemove)) return; + public void removeClass(Class toRemove) { + if (!loadedPluginClasses.contains(toRemove)) return; plugins.removeIf(plugin -> plugin.getClass() == toRemove); loadedPluginClasses.remove(toRemove); } @@ -237,7 +249,7 @@ public class PluginManager { /** * Removes all plugins from this plugin manager. */ - public void removeAll(){ + public void removeAll() { loadedPluginClasses.clear(); plugins.clear(); } diff --git a/core/src/main/java/org/nwapw/abacus/plugin/StandardPlugin.java b/core/src/main/java/org/nwapw/abacus/plugin/StandardPlugin.java index 4e3e1fc..cc2db4b 100755 --- a/core/src/main/java/org/nwapw/abacus/plugin/StandardPlugin.java +++ b/core/src/main/java/org/nwapw/abacus/plugin/StandardPlugin.java @@ -1,19 +1,12 @@ package org.nwapw.abacus.plugin; import org.nwapw.abacus.function.*; -import org.nwapw.abacus.lexing.pattern.Match; import org.nwapw.abacus.number.NaiveNumber; import org.nwapw.abacus.number.NumberInterface; import org.nwapw.abacus.number.PreciseNumber; -import org.nwapw.abacus.parsing.Parser; -import org.nwapw.abacus.parsing.ShuntingYardParser; -import org.nwapw.abacus.tree.TokenType; -import org.nwapw.abacus.tree.TreeNode; import java.util.ArrayList; -import java.util.Date; import java.util.HashMap; -import java.util.List; import java.util.function.BiFunction; /** @@ -22,11 +15,6 @@ import java.util.function.BiFunction; */ public class StandardPlugin extends Plugin { - /** - * Stores objects of NumberInterface with integer values for reuse. - */ - private final static HashMap, HashMap> integerValues = new HashMap<>(); - /** * The addition operator, + */ @@ -92,6 +80,75 @@ public class StandardPlugin extends Plugin { return product; } }); + /** + * The combination operator. + */ + public static final Operator OP_NCR = new Operator(OperatorAssociativity.RIGHT, OperatorType.BINARY_INFIX, 0, new Function() { + @Override + protected boolean matchesParams(NumberInterface[] params) { + return params.length == 2 && params[0].fractionalPart().signum() == 0 + && params[1].fractionalPart().signum() == 0; + } + + @Override + protected NumberInterface applyInternal(NumberInterface[] params) { + return OP_NPR.getFunction().apply(params).divide(OP_FACTORIAL.getFunction().apply(params[1])); + } + }); + /** + * The implementation for double-based naive numbers. + */ + public static final NumberImplementation IMPLEMENTATION_NAIVE = new NumberImplementation(NaiveNumber.class, 0) { + @Override + public NumberInterface instanceForString(String string) { + return new NaiveNumber(string); + } + + @Override + public NumberInterface instanceForPi() { + return new NaiveNumber(Math.PI); + } + }; + /** + * The implementation for the infinite-precision BigDecimal. + */ + public static final NumberImplementation IMPLEMENTATION_PRECISE = new NumberImplementation(PreciseNumber.class, 0) { + @Override + public NumberInterface instanceForString(String string) { + return new PreciseNumber(string); + } + + @Override + public NumberInterface instanceForPi() { + NumberInterface C = FUNCTION_SQRT.apply(new PreciseNumber("10005")).multiply(new PreciseNumber("426880")); + NumberInterface M = PreciseNumber.ONE; + NumberInterface L = new PreciseNumber("13591409"); + NumberInterface X = M; + NumberInterface sum = L; + int termsNeeded = C.getMaxPrecision() / 13 + 1; + + NumberInterface lSummand = new PreciseNumber("545140134"); + NumberInterface xMultiplier = new PreciseNumber("262537412") + .multiply(new PreciseNumber("1000000000")) + .add(new PreciseNumber("640768000")) + .negate(); + for (int i = 0; i < termsNeeded; i++) { + M = M + .multiply(new PreciseNumber((12 * i + 2) + "")) + .multiply(new PreciseNumber((12 * i + 6) + "")) + .multiply(new PreciseNumber((12 * i + 10) + "")) + .divide(new PreciseNumber(Math.pow(i + 1, 3) + "")); + L = L.add(lSummand); + X = X.multiply(xMultiplier); + sum = sum.add(M.multiply(L).divide(X)); + } + return C.divide(sum); + } + }; + /** + * Stores objects of NumberInterface with integer values for reuse. + */ + private final static HashMap, HashMap> integerValues = new HashMap<>(); /** * The division operator, / */ @@ -150,17 +207,17 @@ public class StandardPlugin extends Plugin { @Override protected NumberInterface applyInternal(NumberInterface[] params) { - if(params[0].compareTo(params[1]) < 0 || + if (params[0].compareTo(params[1]) < 0 || params[0].signum() < 0 || (params[0].signum() == 0 && params[1].signum() != 0)) return fromInt(params[0].getClass(), 0); NumberInterface total = fromInt(params[0].getClass(), 1); NumberInterface multiplyBy = params[0]; NumberInterface remainingMultiplications = params[1]; NumberInterface halfway = params[0].divide(fromInt(params[0].getClass(), 2)); - if(remainingMultiplications.compareTo(halfway) > 0){ + if (remainingMultiplications.compareTo(halfway) > 0) { remainingMultiplications = params[0].subtract(remainingMultiplications); } - while(remainingMultiplications.signum() > 0){ + while (remainingMultiplications.signum() > 0) { total = total.multiply(multiplyBy); remainingMultiplications = remainingMultiplications.subtract(fromInt(params[0].getClass(), 1)); multiplyBy = multiplyBy.subtract(fromInt(params[0].getClass(), 1)); @@ -168,21 +225,6 @@ public class StandardPlugin extends Plugin { return total; } }); - /** - * The combination operator. - */ - public static final Operator OP_NCR = new Operator(OperatorAssociativity.RIGHT, OperatorType.BINARY_INFIX, 0, new Function() { - @Override - protected boolean matchesParams(NumberInterface[] params) { - return params.length == 2 && params[0].fractionalPart().signum() == 0 - && params[1].fractionalPart().signum() == 0; - } - - @Override - protected NumberInterface applyInternal(NumberInterface[] params) { - return OP_NPR.getFunction().apply(params).divide(OP_FACTORIAL.getFunction().apply(params[1])); - } - }); /** * The absolute value function, abs(-3) = 3 */ @@ -277,20 +319,6 @@ public class StandardPlugin extends Plugin { return sum; } }; - /** - * The square root function. - */ - public static final Function FUNCTION_SQRT = new Function() { - @Override - protected boolean matchesParams(NumberInterface[] params) { - return params.length == 1; - } - - @Override - protected NumberInterface applyInternal(NumberInterface[] params) { - return OP_CARET.getFunction().apply(params[0], ((new NaiveNumber(0.5)).promoteTo(params[0].getClass()))); - } - }; /** * Gets a random number smaller or equal to the given number's integer value. */ @@ -305,94 +333,6 @@ public class StandardPlugin extends Plugin { return fromInt(params[0].getClass(), (int) Math.round(Math.random() * params[0].floor().intValue())); } }; - /** - * The implementation for double-based naive numbers. - */ - public static final NumberImplementation IMPLEMENTATION_NAIVE = new NumberImplementation(NaiveNumber.class, 0) { - @Override - public NumberInterface instanceForString(String string) { - return new NaiveNumber(string); - } - - @Override - public NumberInterface instanceForPi() { - return new NaiveNumber(Math.PI); - } - }; - /** - * The implementation for the infinite-precision BigDecimal. - */ - public static final NumberImplementation IMPLEMENTATION_PRECISE = new NumberImplementation(PreciseNumber.class, 0) { - @Override - public NumberInterface instanceForString(String string) { - return new PreciseNumber(string); - } - - @Override - public NumberInterface instanceForPi() { - NumberInterface C = FUNCTION_SQRT.apply(new PreciseNumber("10005")).multiply(new PreciseNumber("426880")); - NumberInterface M = PreciseNumber.ONE; - NumberInterface L = new PreciseNumber("13591409"); - NumberInterface X = M; - NumberInterface sum = L; - int termsNeeded = C.getMaxPrecision() / 13 + 1; - - NumberInterface lSummand = new PreciseNumber("545140134"); - NumberInterface xMultiplier = new PreciseNumber("262537412") - .multiply(new PreciseNumber("1000000000")) - .add(new PreciseNumber("640768000")) - .negate(); - for (int i = 0; i < termsNeeded; i++) { - M = M - .multiply(new PreciseNumber((12 * i + 2) + "")) - .multiply(new PreciseNumber((12 * i + 6) + "")) - .multiply(new PreciseNumber((12 * i + 10) + "")) - .divide(new PreciseNumber(Math.pow(i + 1, 3) + "")); - L = L.add(lSummand); - X = X.multiply(xMultiplier); - sum = sum.add(M.multiply(L).divide(X)); - } - return C.divide(sum); - } - }; - private static final HashMap, ArrayList> FACTORIAL_LISTS = new HashMap<>(); - /** - * The exponential function, exp(1) = e^1 = 2.71... - */ - public static final Function FUNCTION_EXP = new Function() { - @Override - protected boolean matchesParams(NumberInterface[] params) { - return params.length == 1; - } - - @Override - protected NumberInterface applyInternal(NumberInterface[] params) { - NumberInterface maxError = params[0].getMaxError(); - int n = 0; - if (params[0].signum() < 0) { - NumberInterface[] negatedParams = {params[0].negate()}; - return fromInt(params[0].getClass(), 1).divide(applyInternal(negatedParams)); - } else { - //We need n such that x^(n+1) * 3^ceil(x) <= maxError * (n+1)!. - //right and left refer to lhs and rhs in the above inequality. - NumberInterface sum = fromInt(params[0].getClass(), 1); - NumberInterface nextNumerator = params[0]; - NumberInterface left = params[0].multiply(fromInt(params[0].getClass(), 3).intPow(params[0].ceiling().intValue())), right = maxError; - do { - sum = sum.add(nextNumerator.divide(factorial(params[0].getClass(), n + 1))); - n++; - nextNumerator = nextNumerator.multiply(params[0]); - left = left.multiply(params[0]); - NumberInterface nextN = fromInt(params[0].getClass(), n + 1); - right = right.multiply(nextN); - //System.out.println(left + ", " + right); - } - while (left.compareTo(right) > 0); - //System.out.println(n+1); - return sum; - } - } - }; /** * The caret / pow operator, ^ */ @@ -414,15 +354,67 @@ public class StandardPlugin extends Plugin { else if (params[1].compareTo(zero) == 0) return fromInt(params[0].getClass(), 1); //Detect integer bases: - if(params[0].fractionalPart().compareTo(fromInt(params[0].getClass(), 0)) == 0 + if (params[0].fractionalPart().compareTo(fromInt(params[0].getClass(), 0)) == 0 && FUNCTION_ABS.apply(params[1]).compareTo(fromInt(params[0].getClass(), Integer.MAX_VALUE)) < 0 - && FUNCTION_ABS.apply(params[1]).compareTo(fromInt(params[1].getClass(), 1)) >= 0){ + && FUNCTION_ABS.apply(params[1]).compareTo(fromInt(params[1].getClass(), 1)) >= 0) { NumberInterface[] newParams = {params[0], params[1].fractionalPart()}; return params[0].intPow(params[1].floor().intValue()).multiply(applyInternal(newParams)); } return FUNCTION_EXP.apply(FUNCTION_LN.apply(FUNCTION_ABS.apply(params[0])).multiply(params[1])); } }); + /** + * The square root function. + */ + public static final Function FUNCTION_SQRT = new Function() { + @Override + protected boolean matchesParams(NumberInterface[] params) { + return params.length == 1; + } + + @Override + protected NumberInterface applyInternal(NumberInterface[] params) { + return OP_CARET.getFunction().apply(params[0], ((new NaiveNumber(0.5)).promoteTo(params[0].getClass()))); + } + }; + private static final HashMap, ArrayList> FACTORIAL_LISTS = new HashMap<>(); + /** + * The exponential function, exp(1) = e^1 = 2.71... + */ + public static final Function FUNCTION_EXP = new Function() { + @Override + protected boolean matchesParams(NumberInterface[] params) { + return params.length == 1; + } + + @Override + protected NumberInterface applyInternal(NumberInterface[] params) { + NumberInterface maxError = params[0].getMaxError(); + int n = 0; + if (params[0].signum() < 0) { + NumberInterface[] negatedParams = {params[0].negate()}; + return fromInt(params[0].getClass(), 1).divide(applyInternal(negatedParams)); + } else { + //We need n such that x^(n+1) * 3^ceil(x) <= maxError * (n+1)!. + //right and left refer to lhs and rhs in the above inequality. + NumberInterface sum = fromInt(params[0].getClass(), 1); + NumberInterface nextNumerator = params[0]; + NumberInterface left = params[0].multiply(fromInt(params[0].getClass(), 3).intPow(params[0].ceiling().intValue())), right = maxError; + do { + sum = sum.add(nextNumerator.divide(factorial(params[0].getClass(), n + 1))); + n++; + nextNumerator = nextNumerator.multiply(params[0]); + left = left.multiply(params[0]); + NumberInterface nextN = fromInt(params[0].getClass(), n + 1); + right = right.multiply(nextN); + //System.out.println(left + ", " + right); + } + while (left.compareTo(right) > 0); + //System.out.println(n+1); + return sum; + } + } + }; /** * The sine function (the argument is interpreted in radians). */ @@ -531,7 +523,7 @@ public class StandardPlugin extends Plugin { @Override protected NumberInterface applyInternal(NumberInterface[] params) { - if(FUNCTION_ABS.apply(params[0]).compareTo(new NaiveNumber(0.8).promoteTo(params[0].getClass())) >= 0){ + if (FUNCTION_ABS.apply(params[0]).compareTo(new NaiveNumber(0.8).promoteTo(params[0].getClass())) >= 0) { NumberInterface[] newParams = {FUNCTION_SQRT.apply(fromInt(params[0].getClass(), 1).subtract(params[0].multiply(params[0])))}; return piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 2)) .subtract(applyInternal(newParams)).multiply(fromInt(params[0].getClass(), params[0].signum())); @@ -540,10 +532,10 @@ public class StandardPlugin extends Plugin { multiplier = currentTerm.multiply(currentTerm), summandBound = sum.getMaxError().multiply(fromInt(sum.getClass(), 1).subtract(multiplier)), power = currentTerm, coefficient = fromInt(params[0].getClass(), 1); int exponent = 1; - while(FUNCTION_ABS.apply(currentTerm).compareTo(summandBound) > 0){ + while (FUNCTION_ABS.apply(currentTerm).compareTo(summandBound) > 0) { exponent += 2; power = power.multiply(multiplier); - coefficient = coefficient.multiply(fromInt(params[0].getClass(), exponent-2)) + coefficient = coefficient.multiply(fromInt(params[0].getClass(), exponent - 2)) .divide(fromInt(params[0].getClass(), exponent - 1)); currentTerm = power.multiply(coefficient).divide(fromInt(power.getClass(), exponent)); sum = sum.add(currentTerm); @@ -611,27 +603,27 @@ public class StandardPlugin extends Plugin { @Override protected NumberInterface applyInternal(NumberInterface[] params) { - if(params[0].signum() == -1){ + if (params[0].signum() == -1) { NumberInterface[] negatedParams = {params[0].negate()}; return applyInternal(negatedParams).negate(); } - if(params[0].compareTo(fromInt(params[0].getClass(), 1)) > 0){ + if (params[0].compareTo(fromInt(params[0].getClass(), 1)) > 0) { NumberInterface[] reciprocalParams = {fromInt(params[0].getClass(), 1).divide(params[0])}; return piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 2)) .subtract(applyInternal(reciprocalParams)); } - if(params[0].compareTo(fromInt(params[0].getClass(), 1)) == 0){ + if (params[0].compareTo(fromInt(params[0].getClass(), 1)) == 0) { return piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 4)); } - if(params[0].compareTo(new NaiveNumber(0.9).promoteTo(params[0].getClass())) >= 0){ - NumberInterface[] newParams = {params[0].multiply(fromInt(params[0].getClass(),2 )) - .divide(fromInt(params[0].getClass(), 1).subtract(params[0].multiply(params[0])))}; + if (params[0].compareTo(new NaiveNumber(0.9).promoteTo(params[0].getClass())) >= 0) { + NumberInterface[] newParams = {params[0].multiply(fromInt(params[0].getClass(), 2)) + .divide(fromInt(params[0].getClass(), 1).subtract(params[0].multiply(params[0])))}; return applyInternal(newParams).divide(fromInt(params[0].getClass(), 2)); } NumberInterface currentPower = params[0], currentTerm = currentPower, sum = currentTerm, maxError = params[0].getMaxError(), multiplier = currentPower.multiply(currentPower).negate(); int n = 1; - while(FUNCTION_ABS.apply(currentTerm).compareTo(maxError) > 0){ + while (FUNCTION_ABS.apply(currentTerm).compareTo(maxError) > 0) { n += 2; currentPower = currentPower.multiply(multiplier); currentTerm = currentPower.divide(fromInt(currentPower.getClass(), n)); @@ -737,15 +729,16 @@ public class StandardPlugin extends Plugin { /** * Returns a number of class numType with value n. + * * @param numType class of number to return. - * @param n value of returned number. + * @param n value of returned number. * @return numClass instance with value n. */ - private static NumberInterface fromInt(Class numType, int n){ - if(!integerValues.containsKey(numType)){ + private static NumberInterface fromInt(Class numType, int n) { + if (!integerValues.containsKey(numType)) { integerValues.put(numType, new HashMap<>()); } - if(!integerValues.get(numType).containsKey(n)){ + if (!integerValues.get(numType).containsKey(n)) { integerValues.get(numType).put(n, new NaiveNumber(n).promoteTo(numType)); } return integerValues.get(numType).get(n); diff --git a/core/src/main/kotlin/org/nwapw/abacus/tree/FunctionNode.kt b/core/src/main/kotlin/org/nwapw/abacus/tree/FunctionNode.kt index b101792..64c1298 100644 --- a/core/src/main/kotlin/org/nwapw/abacus/tree/FunctionNode.kt +++ b/core/src/main/kotlin/org/nwapw/abacus/tree/FunctionNode.kt @@ -36,7 +36,7 @@ data class FunctionNode(val function: String) : TreeNode() { * * @node the node to append. */ - fun appendChild(node: TreeNode){ + fun appendChild(node: TreeNode) { children.add(node) } @@ -45,7 +45,7 @@ data class FunctionNode(val function: String) : TreeNode() { * * @node the node to prepend. */ - fun prependChild(node: TreeNode){ + fun prependChild(node: TreeNode) { children.add(0, node) } diff --git a/core/src/main/kotlin/org/nwapw/abacus/tree/Reducer.kt b/core/src/main/kotlin/org/nwapw/abacus/tree/Reducer.kt index 4277185..412af29 100644 --- a/core/src/main/kotlin/org/nwapw/abacus/tree/Reducer.kt +++ b/core/src/main/kotlin/org/nwapw/abacus/tree/Reducer.kt @@ -6,7 +6,7 @@ package org.nwapw.abacus.tree * The reducer walks the tree, visiting the children first, converting them into * a value, and then attempts to reduce the parent. Eventually, the single final value is returned. */ -interface Reducer { +interface Reducer { /** * Reduces the given tree node, given its already reduced children. @@ -14,6 +14,6 @@ interface Reducer { * @param treeNode the tree node to reduce. * @param children the list of children, of type T. */ - fun reduceNode(treeNode: TreeNode, vararg children: Any) : T? + fun reduceNode(treeNode: TreeNode, vararg children: Any): T? } \ No newline at end of file diff --git a/core/src/main/kotlin/org/nwapw/abacus/tree/TreeNode.kt b/core/src/main/kotlin/org/nwapw/abacus/tree/TreeNode.kt index bc1ae5e..2017739 100644 --- a/core/src/main/kotlin/org/nwapw/abacus/tree/TreeNode.kt +++ b/core/src/main/kotlin/org/nwapw/abacus/tree/TreeNode.kt @@ -5,6 +5,6 @@ package org.nwapw.abacus.tree */ abstract class TreeNode { - abstract fun reduce(reducer: Reducer) : T? + abstract fun reduce(reducer: Reducer): T? } \ No newline at end of file diff --git a/core/src/test/java/org/nwapw/abacus/tests/CalculationTests.java b/core/src/test/java/org/nwapw/abacus/tests/CalculationTests.java index 938b091..766376c 100755 --- a/core/src/test/java/org/nwapw/abacus/tests/CalculationTests.java +++ b/core/src/test/java/org/nwapw/abacus/tests/CalculationTests.java @@ -14,12 +14,12 @@ public class CalculationTests { private static Abacus abacus = new Abacus(new Configuration(0, "precise", new String[]{})); @BeforeClass - public static void prepareTests(){ + public static void prepareTests() { abacus.getPluginManager().addInstantiated(new StandardPlugin(abacus.getPluginManager())); abacus.getPluginManager().load(); } - private void testOutput(String input, String parseOutput, String output){ + private void testOutput(String input, String parseOutput, String output) { TreeNode parsedTree = abacus.parseString(input); Assert.assertNotNull(parsedTree); Assert.assertEquals(parsedTree.toString(), parseOutput); @@ -28,7 +28,7 @@ public class CalculationTests { Assert.assertTrue(result.toString().startsWith(output)); } - private void testEvalError(String input, String parseOutput){ + private void testEvalError(String input, String parseOutput) { TreeNode parsedTree = abacus.parseString(input); Assert.assertNotNull(parsedTree); Assert.assertEquals(parsedTree.toString(), parseOutput); @@ -36,56 +36,56 @@ public class CalculationTests { } @Test - public void testAddition(){ + public void testAddition() { testOutput("9.5+10", "(9.5+10)", "19.5"); } @Test - public void testSubtraction(){ + public void testSubtraction() { testOutput("9.5-10", "(9.5-10)", "-0.5"); } @Test - public void testMultiplication(){ + public void testMultiplication() { testOutput("9.5*10", "(9.5*10)", "95"); } @Test - public void testDivision(){ + public void testDivision() { testOutput("9.5/2", "(9.5/2)", "4.75"); } @Test - public void testNegation(){ + public void testNegation() { testOutput("-9.5", "(9.5)`", "-9.5"); } @Test - public void testFactorial(){ + public void testFactorial() { testOutput("7!", "(7)!", "5040"); } @Test - public void testAbs(){ + public void testAbs() { testOutput("abs(-1)", "abs((1)`)", "1"); testOutput("abs(1)", "abs(1)", "1"); } @Test - public void testLn(){ + public void testLn() { testEvalError("ln(-1)", "ln((1)`)"); testOutput("ln2", "ln(2)", "0.6931471805599453094172321214581765680755"); } @Test - public void testSqrt(){ + public void testSqrt() { testOutput("sqrt0", "sqrt(0)", "0"); testOutput("sqrt4", "sqrt(4)", "2"); testOutput("sqrt2", "sqrt(2)", "1.4142135623730950488016887242096980785696"); } @Test - public void testExp(){ + public void testExp() { testOutput("exp0", "exp(0)", "1"); testOutput("exp1", "exp(1)", "2.718281828459045235360287471352662497757247"); testOutput("exp300", "exp(300)", "1.9424263952412559365842088360176992193662086"); @@ -93,7 +93,7 @@ public class CalculationTests { } @Test - public void testPow(){ + public void testPow() { testOutput("0^2", "(0^2)", "0"); testOutput("2^0", "(2^0)", "1"); testOutput("2^1", "(2^1)", "2"); diff --git a/fx/build.gradle b/fx/build.gradle index 555ee76..f00f056 100644 --- a/fx/build.gradle +++ b/fx/build.gradle @@ -1,10 +1,10 @@ plugins { - id 'org.jetbrains.kotlin.jvm' version '1.1.3' + id 'org.jetbrains.kotlin.jvm' version '1.1.3' } apply plugin: 'application' dependencies { - compile project(':core') + compile project(':core') } mainClassName = 'org.nwapw.abacus.fx.AbacusApplication' diff --git a/fx/src/main/java/org/nwapw/abacus/fx/AbacusApplication.java b/fx/src/main/java/org/nwapw/abacus/fx/AbacusApplication.java index c4d86f9..92a4b3f 100644 --- a/fx/src/main/java/org/nwapw/abacus/fx/AbacusApplication.java +++ b/fx/src/main/java/org/nwapw/abacus/fx/AbacusApplication.java @@ -17,6 +17,10 @@ public class AbacusApplication extends Application { */ private AbacusController controller; + public static void main(String[] args) { + launch(args); + } + @Override public void start(Stage primaryStage) throws Exception { FXMLLoader loader = new FXMLLoader(getClass().getResource("/abacus.fxml")); @@ -34,8 +38,4 @@ public class AbacusApplication extends Application { controller.performStop(); } - public static void main(String[] args){ - launch(args); - } - } diff --git a/fx/src/main/java/org/nwapw/abacus/fx/AbacusController.java b/fx/src/main/java/org/nwapw/abacus/fx/AbacusController.java index 2e913c9..0194953 100644 --- a/fx/src/main/java/org/nwapw/abacus/fx/AbacusController.java +++ b/fx/src/main/java/org/nwapw/abacus/fx/AbacusController.java @@ -1,13 +1,10 @@ package org.nwapw.abacus.fx; import javafx.application.Platform; -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.collections.transformation.FilteredList; import javafx.fxml.FXML; -import javafx.scene.Node; import javafx.scene.control.*; import javafx.scene.control.cell.CheckBoxListCell; import javafx.scene.text.Text; @@ -136,36 +133,12 @@ public class AbacusController implements PluginListener { * The abacus instance used for changing the plugin configuration. */ private Abacus abacus; - - /** - * Boolean which represents whether changes were made to the configuration. - */ - private boolean changesMade; - /** - * Whether an alert about changes to the configuration was already shown. - */ - private boolean reloadAlertShown; - /** - * The alert shown when a press to "apply" is needed. - */ - private Alert reloadAlert; - /** - * The runnable that takes care of killing computations that take too long. - */ - private final Runnable TIMER_RUNNABLE = () -> { - try { - Configuration abacusConfig = abacus.getConfiguration(); - if(abacusConfig.getComputationDelay() == 0) return; - Thread.sleep((long) (abacusConfig.getComputationDelay() * 1000)); - performStop(); - } catch (InterruptedException e) { } - }; /** * The runnable used to perform the calculation. */ private final Runnable CALCULATION_RUNNABLE = new Runnable() { - private String attemptCalculation(){ + private String attemptCalculation() { try { TreeNode constructedTree = abacus.parseString(inputField.getText()); if (constructedTree == null) { @@ -180,7 +153,7 @@ public class AbacusController implements PluginListener { return resultingString; } catch (ComputationInterruptedException exception) { return ERR_STOP; - } catch (RuntimeException exception){ + } catch (RuntimeException exception) { exception.printStackTrace(); return ERR_EXCEPTION; } @@ -197,6 +170,18 @@ public class AbacusController implements PluginListener { }); } }; + /** + * Boolean which represents whether changes were made to the configuration. + */ + private boolean changesMade; + /** + * Whether an alert about changes to the configuration was already shown. + */ + private boolean reloadAlertShown; + /** + * The alert shown when a press to "apply" is needed. + */ + private Alert reloadAlert; /** * The thread that is waiting to pause the calculation. */ @@ -205,6 +190,18 @@ public class AbacusController implements PluginListener { * The thread in which the computation runs. */ private Thread calculationThread; + /** + * The runnable that takes care of killing computations that take too long. + */ + private final Runnable TIMER_RUNNABLE = () -> { + try { + Configuration abacusConfig = abacus.getConfiguration(); + if (abacusConfig.getComputationDelay() == 0) return; + Thread.sleep((long) (abacusConfig.getComputationDelay() * 1000)); + performStop(); + } catch (InterruptedException e) { + } + }; /** * Alerts the user if the changes they made @@ -265,7 +262,7 @@ public class AbacusController implements PluginListener { computationLimitField.setText(Double.toString(abacus.getConfiguration().getComputationDelay())); computationLimitField.textProperty().addListener((observable, oldValue, newValue) -> { - if(!newValue.matches("(\\d+(\\.\\d*)?)?")) { + if (!newValue.matches("(\\d+(\\.\\d*)?)?")) { computationLimitField.setText(oldValue); } else { changesMade = true; @@ -292,12 +289,12 @@ public class AbacusController implements PluginListener { } @FXML - public void performStop(){ - if(calculationThread != null) { + public void performStop() { + if (calculationThread != null) { calculationThread.interrupt(); calculationThread = null; } - if(computationLimitThread != null){ + if (computationLimitThread != null) { computationLimitThread.interrupt(); computationLimitThread = null; } @@ -312,7 +309,7 @@ public class AbacusController implements PluginListener { } @FXML - public void performScan(){ + public void performScan() { PluginManager abacusPluginManager = abacus.getPluginManager(); abacusPluginManager.removeAll(); abacusPluginManager.addInstantiated(new StandardPlugin(abacus.getPluginManager())); @@ -339,7 +336,7 @@ public class AbacusController implements PluginListener { for (ToggleablePlugin pluginEntry : enabledPlugins) { if (!pluginEntry.isEnabled()) disabledPlugins.add(pluginEntry.getClassName()); } - if(computationLimitField.getText().matches("\\d*(\\.\\d+)?") && computationLimitField.getText().length() != 0) + if (computationLimitField.getText().matches("\\d*(\\.\\d+)?") && computationLimitField.getText().length() != 0) configuration.setComputationDelay(Double.parseDouble(computationLimitField.getText())); configuration.saveTo(CONFIG_FILE); changesMade = false; diff --git a/fx/src/main/java/org/nwapw/abacus/fx/DocumentationCell.java b/fx/src/main/java/org/nwapw/abacus/fx/DocumentationCell.java index fc678fe..016fc69 100644 --- a/fx/src/main/java/org/nwapw/abacus/fx/DocumentationCell.java +++ b/fx/src/main/java/org/nwapw/abacus/fx/DocumentationCell.java @@ -14,7 +14,7 @@ public class DocumentationCell extends ListCell { private Label longDescription; private TitledPane titledPane; - public DocumentationCell(){ + public DocumentationCell() { VBox vbox = new VBox(); vbox.setSpacing(10); titledPane = new TitledPane(); @@ -41,7 +41,7 @@ public class DocumentationCell extends ListCell { @Override protected void updateItem(Documentation item, boolean empty) { super.updateItem(item, empty); - if(empty){ + if (empty) { codeNameLabel.setText(""); nameLabel.setText(""); description.setText(""); diff --git a/fx/src/main/kotlin/org/nwapw/abacus/fx/HistoryModel.kt b/fx/src/main/kotlin/org/nwapw/abacus/fx/HistoryModel.kt index e8b11b6..cc79ad7 100644 --- a/fx/src/main/kotlin/org/nwapw/abacus/fx/HistoryModel.kt +++ b/fx/src/main/kotlin/org/nwapw/abacus/fx/HistoryModel.kt @@ -14,7 +14,7 @@ import javafx.beans.property.SimpleStringProperty * @param parsed the parsed version of the input. * @param output the output string. */ -class HistoryModel(input: String, parsed: String, output: String){ +class HistoryModel(input: String, parsed: String, output: String) { /** * The property that holds the input. diff --git a/fx/src/main/kotlin/org/nwapw/abacus/fx/ToggleablePlugin.kt b/fx/src/main/kotlin/org/nwapw/abacus/fx/ToggleablePlugin.kt index e046209..9b83571 100644 --- a/fx/src/main/kotlin/org/nwapw/abacus/fx/ToggleablePlugin.kt +++ b/fx/src/main/kotlin/org/nwapw/abacus/fx/ToggleablePlugin.kt @@ -12,7 +12,7 @@ import javafx.beans.property.SimpleBooleanProperty * @param className the name of the class that this model concerns. * @param enabled whether or not the model should start enabled. */ -class ToggleablePlugin (val className: String, enabled: Boolean) { +class ToggleablePlugin(val className: String, enabled: Boolean) { /** * The property used to interact with JavaFX components.