From cbceee4abcb0863b0b6b3a5bd4a6872567e608cb Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Fri, 1 Sep 2017 17:13:45 -0700 Subject: [PATCH 01/13] Switch number implementation to using Strings. --- .../java/org/nwapw/abacus/plugin/NumberImplementation.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/nwapw/abacus/plugin/NumberImplementation.java b/core/src/main/java/org/nwapw/abacus/plugin/NumberImplementation.java index 70e085e..ad5d1d1 100644 --- a/core/src/main/java/org/nwapw/abacus/plugin/NumberImplementation.java +++ b/core/src/main/java/org/nwapw/abacus/plugin/NumberImplementation.java @@ -14,7 +14,7 @@ public abstract class NumberImplementation { /** * The list of paths through which this implementation can be promoted. */ - private Map, Function> promotionPaths; + private Map> promotionPaths; /** * The implementation class for this implementation. */ @@ -41,7 +41,7 @@ public abstract class NumberImplementation { * * @return the map of documentation paths. */ - public final Map, Function> getPromotionPaths() { + public final Map> getPromotionPaths() { return promotionPaths; } From 7a296e4e8bbfc955fb69c9f9a01fb207c376b8e4 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Fri, 1 Sep 2017 17:14:11 -0700 Subject: [PATCH 02/13] Add the ability to retrieve names of plugin implementations. --- .../nwapw/abacus/plugin/PluginManager.java | 38 +++++++++++-------- 1 file changed, 22 insertions(+), 16 deletions(-) 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 64b3eb3..73908a4 100644 --- a/core/src/main/java/org/nwapw/abacus/plugin/PluginManager.java +++ b/core/src/main/java/org/nwapw/abacus/plugin/PluginManager.java @@ -49,10 +49,13 @@ public class PluginManager { */ private Set registeredDocumentation; /** - * The list of number implementations that have been - * found by their implementation class. + * The list of number implementation names. */ - private Map, NumberImplementation> cachedInterfaceImplementations; + private Map, String> interfaceImplementationNames; + /** + * The list of number implementations. + */ + private Map, NumberImplementation> interfaceImplementations; /** * The pi values for each implementation class that have already been computer. */ @@ -82,7 +85,8 @@ public class PluginManager { registeredTreeValueOperators = new HashMap<>(); registeredNumberImplementations = new HashMap<>(); registeredDocumentation = new HashSet<>(); - cachedInterfaceImplementations = new HashMap<>(); + interfaceImplementations = new HashMap<>(); + interfaceImplementationNames = new HashMap<>(); cachedPi = new HashMap<>(); listeners = new HashSet<>(); } @@ -135,6 +139,8 @@ public class PluginManager { */ public void registerNumberImplementation(String name, NumberImplementation implementation) { registeredNumberImplementations.put(name, implementation); + interfaceImplementationNames.put(implementation.getImplementation(), name); + interfaceImplementations.put(implementation.getImplementation(), implementation); } /** @@ -226,17 +232,17 @@ public class PluginManager { * @return the implementation. */ public NumberImplementation interfaceImplementationFor(Class name) { - if (cachedInterfaceImplementations.containsKey(name)) return cachedInterfaceImplementations.get(name); - NumberImplementation toReturn = null; - for (String key : registeredNumberImplementations.keySet()) { - NumberImplementation implementation = registeredNumberImplementations.get(key); - if (implementation.getImplementation() == name) { - toReturn = implementation; - break; - } - } - cachedInterfaceImplementations.put(name, toReturn); - return toReturn; + return interfaceImplementations.get(name); + } + + /** + * Gets the number implementation name for the given implementation class. + * + * @param name the class for which to find the implementation name. + * @return the implementation name. + */ + public String interfaceImplementationNameFor(Class name){ + return interfaceImplementationNames.get(name); } /** @@ -329,7 +335,7 @@ public class PluginManager { registeredTreeValueOperators.clear(); registeredNumberImplementations.clear(); registeredDocumentation.clear(); - cachedInterfaceImplementations.clear(); + interfaceImplementations.clear(); cachedPi.clear(); listeners.forEach(e -> e.onUnload(this)); } From 453cd0ea7715d98d94e834d1aa47f9f6a0d5b6e4 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Fri, 1 Sep 2017 17:14:54 -0700 Subject: [PATCH 03/13] Add type aliases for Kotlin and a simple extension function. --- .../main/kotlin/org/nwapw/abacus/number/NumberUtils.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 core/src/main/kotlin/org/nwapw/abacus/number/NumberUtils.kt diff --git a/core/src/main/kotlin/org/nwapw/abacus/number/NumberUtils.kt b/core/src/main/kotlin/org/nwapw/abacus/number/NumberUtils.kt new file mode 100644 index 0000000..5503613 --- /dev/null +++ b/core/src/main/kotlin/org/nwapw/abacus/number/NumberUtils.kt @@ -0,0 +1,10 @@ +@file:JvmName("NumberUtils") +package org.nwapw.abacus.number + +typealias PromotionFunction = java.util.function.Function +typealias PromotionPath = List +typealias NumberClass = Class + +fun PromotionPath.promote(from: NumberInterface): NumberInterface { + return fold(from, { current, function -> function.apply(current) }) +} \ No newline at end of file From ecb5139e70bc8b0443b0fd21fbad5bdb40520dda Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Fri, 1 Sep 2017 17:15:14 -0700 Subject: [PATCH 04/13] Add a promotion manager to handle promotion. --- .../nwapw/abacus/number/PromotionManager.kt | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 core/src/main/kotlin/org/nwapw/abacus/number/PromotionManager.kt diff --git a/core/src/main/kotlin/org/nwapw/abacus/number/PromotionManager.kt b/core/src/main/kotlin/org/nwapw/abacus/number/PromotionManager.kt new file mode 100644 index 0000000..e4ccc38 --- /dev/null +++ b/core/src/main/kotlin/org/nwapw/abacus/number/PromotionManager.kt @@ -0,0 +1,39 @@ +package org.nwapw.abacus.number + +import org.nwapw.abacus.Abacus +import org.nwapw.abacus.plugin.NumberImplementation +import java.util.function.Function + +class PromotionManager(val abacus: Abacus) { + + val computePaths = mutableMapOf, PromotionPath?>() + + fun computePathBetween(from: NumberImplementation, to: NumberImplementation): PromotionPath? { + val fromName = abacus.pluginManager.interfaceImplementationNameFor(from.implementation) + val toName = abacus.pluginManager.interfaceImplementationNameFor(to.implementation) + + if(fromName == toName) return listOf(Function { it }) + + if(from.promotionPaths.containsKey(toName)) + return listOf(from.promotionPaths[toName] ?: return null) + return null + } + + fun getPathBetween(from: NumberImplementation, to: NumberImplementation): PromotionPath? { + return computePaths.computeIfAbsent(from to to, { + computePathBetween(it.first, it.second) + }) + } + + fun promote(vararg numbers: NumberInterface): Array? { + val pluginManager = abacus.pluginManager + val implementations = numbers.map { pluginManager.interfaceImplementationFor(it.javaClass) } + val highestPriority = implementations.sortedBy { it.priority }.last() + return numbers.map { + if(it.javaClass == highestPriority.implementation) it + else getPathBetween(pluginManager.interfaceImplementationFor(it.javaClass), highestPriority) + ?.promote(it) ?: return null + }.toTypedArray() + } + +} \ No newline at end of file From f7c07ca04da24dbaf28b95fca8cb8b551ae81a89 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Fri, 1 Sep 2017 17:15:28 -0700 Subject: [PATCH 05/13] Add promotion manager to Abacus. --- .../src/main/java/org/nwapw/abacus/Abacus.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/core/src/main/java/org/nwapw/abacus/Abacus.java b/core/src/main/java/org/nwapw/abacus/Abacus.java index 113bda8..6d4907d 100644 --- a/core/src/main/java/org/nwapw/abacus/Abacus.java +++ b/core/src/main/java/org/nwapw/abacus/Abacus.java @@ -1,7 +1,10 @@ package org.nwapw.abacus; import org.nwapw.abacus.config.Configuration; +import org.nwapw.abacus.number.NaiveNumber; import org.nwapw.abacus.number.NumberInterface; +import org.nwapw.abacus.number.PreciseNumber; +import org.nwapw.abacus.number.PromotionManager; import org.nwapw.abacus.parsing.LexerTokenizer; import org.nwapw.abacus.parsing.ShuntingYardParser; import org.nwapw.abacus.parsing.TreeBuilder; @@ -11,6 +14,8 @@ import org.nwapw.abacus.plugin.StandardPlugin; import org.nwapw.abacus.tree.NumberReducer; import org.nwapw.abacus.tree.TreeNode; +import java.math.BigDecimal; + /** * The main calculator class. This is responsible * for piecing together all of the components, allowing @@ -42,6 +47,10 @@ public class Abacus { * from a string. */ private TreeBuilder treeBuilder; + /** + * Promotion manager responsible for the promotion system. + */ + private PromotionManager promotionManager; /** * Creates a new instance of the Abacus calculator. @@ -55,11 +64,20 @@ public class Abacus { LexerTokenizer lexerTokenizer = new LexerTokenizer(); ShuntingYardParser shuntingYardParser = new ShuntingYardParser(); treeBuilder = new TreeBuilder<>(lexerTokenizer, shuntingYardParser); + promotionManager = new PromotionManager(this); pluginManager.addListener(shuntingYardParser); pluginManager.addListener(lexerTokenizer); } + /** + * Gets the promotion manager. + * @return the promotion manager. + */ + public PromotionManager getPromotionManager() { + return promotionManager; + } + /** * Gets the current tree builder. * From 2b700d3911e849dc531d320ef9bfd37db3089d83 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Fri, 1 Sep 2017 17:45:32 -0700 Subject: [PATCH 06/13] Require applicable interfaces to be passed an implementation they use. --- .../main/java/org/nwapw/abacus/Abacus.java | 16 +- .../nwapw/abacus/plugin/StandardPlugin.java | 211 ++++++++++-------- .../org/nwapw/abacus/tree/NumberReducer.java | 23 +- .../abacus/function/applicable/Applicable.kt | 12 +- .../function/applicable/ReducerApplicable.kt | 11 +- .../nwapw/abacus/number/PromotionManager.kt | 6 +- .../nwapw/abacus/number/PromotionResult.kt | 5 + .../nwapw/abacus/tests/TokenizerTests.java | 21 +- .../org/nwapw/abacus/fx/AbacusController.java | 3 +- 9 files changed, 173 insertions(+), 135 deletions(-) create mode 100644 core/src/main/kotlin/org/nwapw/abacus/number/PromotionResult.kt diff --git a/core/src/main/java/org/nwapw/abacus/Abacus.java b/core/src/main/java/org/nwapw/abacus/Abacus.java index 6d4907d..22c82f4 100644 --- a/core/src/main/java/org/nwapw/abacus/Abacus.java +++ b/core/src/main/java/org/nwapw/abacus/Abacus.java @@ -138,16 +138,14 @@ public class Abacus { } /** - * Creates a number from a string. - * - * @param numberString the string to create the number from. - * @return the resulting number. + * Gets the number implementation. + * @return the number implementation to use for creating numbers. */ - public NumberInterface numberFromString(String numberString) { - NumberImplementation toInstantiate = + public NumberImplementation getNumberImplementation(){ + NumberImplementation selectedImplementation = pluginManager.numberImplementationFor(configuration.getNumberImplementation()); - if (toInstantiate == null) toInstantiate = DEFAULT_IMPLEMENTATION; - - return toInstantiate.instanceForString(numberString); + if(selectedImplementation != null) return selectedImplementation; + return DEFAULT_IMPLEMENTATION; } + } 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 16bbba1..53fcae8 100755 --- a/core/src/main/java/org/nwapw/abacus/plugin/StandardPlugin.java +++ b/core/src/main/java/org/nwapw/abacus/plugin/StandardPlugin.java @@ -20,12 +20,13 @@ public class StandardPlugin extends Plugin { */ public static final NumberOperator OP_ADD = new NumberOperator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 0) { @Override - public boolean matchesParams(NumberInterface[] params) { + public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { return params.length == 2; } + @Override - public NumberInterface applyInternal(NumberInterface[] params) { + public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return params[0].add(params[1]); } }; @@ -34,12 +35,13 @@ public class StandardPlugin extends Plugin { */ public static final NumberOperator OP_SUBTRACT = new NumberOperator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 0) { @Override - public boolean matchesParams(NumberInterface[] params) { + public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { return params.length == 2; } + @Override - public NumberInterface applyInternal(NumberInterface[] params) { + public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return params[0].subtract(params[1]); } @@ -49,12 +51,13 @@ public class StandardPlugin extends Plugin { */ public static final NumberOperator OP_NEGATE = new NumberOperator(OperatorAssociativity.LEFT, OperatorType.UNARY_PREFIX, 0) { @Override - public boolean matchesParams(NumberInterface[] params) { + public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { return params.length == 1; } + @Override - public NumberInterface applyInternal(NumberInterface[] params) { + public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return params[0].negate(); } }; @@ -63,12 +66,13 @@ public class StandardPlugin extends Plugin { */ public static final NumberOperator OP_MULTIPLY = new NumberOperator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 1) { @Override - public boolean matchesParams(NumberInterface[] params) { + public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { return params.length == 2; } + @Override - public NumberInterface applyInternal(NumberInterface[] params) { + public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return params[0].multiply(params[1]); } }; @@ -91,13 +95,14 @@ public class StandardPlugin extends Plugin { */ public static final NumberFunction FUNCTION_SQRT = new NumberFunction() { @Override - public boolean matchesParams(NumberInterface[] params) { + public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { return params.length == 1; } + @Override - public NumberInterface applyInternal(NumberInterface[] params) { - return OP_CARET.apply(params[0], ((new NaiveNumber(0.5)).promoteTo(params[0].getClass()))); + public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { + return OP_CARET.apply(implementation, params[0], ((new NaiveNumber(0.5)).promoteTo(params[0].getClass()))); } }; /** @@ -111,7 +116,7 @@ public class StandardPlugin extends Plugin { @Override public NumberInterface instanceForPi() { - NumberInterface C = FUNCTION_SQRT.apply(new PreciseNumber("10005")).multiply(new PreciseNumber("426880")); + NumberInterface C = FUNCTION_SQRT.apply(this, new PreciseNumber("10005")).multiply(new PreciseNumber("426880")); NumberInterface M = PreciseNumber.ONE; NumberInterface L = new PreciseNumber("13591409"); NumberInterface X = M; @@ -145,12 +150,13 @@ public class StandardPlugin extends Plugin { */ public static final NumberOperator OP_DIVIDE = new NumberOperator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 1) { @Override - public boolean matchesParams(NumberInterface[] params) { + public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { return params.length == 2 && params[1].compareTo(fromInt(params[0].getClass(), 0)) != 0; } + @Override - public NumberInterface applyInternal(NumberInterface[] params) { + public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return params[0].divide(params[1]); } }; @@ -160,14 +166,15 @@ public class StandardPlugin extends Plugin { public static final NumberOperator OP_FACTORIAL = new NumberOperator(OperatorAssociativity.RIGHT, OperatorType.UNARY_POSTFIX, 0) { //private HashMap, ArrayList> storedList = new HashMap, ArrayList>(); @Override - public boolean matchesParams(NumberInterface[] params) { + public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { return params.length == 1 && params[0].fractionalPart().compareTo(fromInt(params[0].getClass(), 0)) == 0 && params[0].signum() >= 0; } + @Override - public NumberInterface applyInternal(NumberInterface[] params) { + public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { if (params[0].signum() == 0) { return fromInt(params[0].getClass(), 1); } @@ -191,13 +198,14 @@ public class StandardPlugin extends Plugin { */ public static final NumberOperator OP_NPR = new NumberOperator(OperatorAssociativity.RIGHT, OperatorType.BINARY_INFIX, 0) { @Override - public boolean matchesParams(NumberInterface[] params) { + public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { return params.length == 2 && params[0].fractionalPart().signum() == 0 && params[1].fractionalPart().signum() == 0; } + @Override - public NumberInterface applyInternal(NumberInterface[] params) { + public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { 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); @@ -221,14 +229,15 @@ public class StandardPlugin extends Plugin { */ public static final NumberOperator OP_NCR = new NumberOperator(OperatorAssociativity.RIGHT, OperatorType.BINARY_INFIX, 0) { @Override - public boolean matchesParams(NumberInterface[] params) { + public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { return params.length == 2 && params[0].fractionalPart().signum() == 0 && params[1].fractionalPart().signum() == 0; } + @Override - public NumberInterface applyInternal(NumberInterface[] params) { - return OP_NPR.apply(params).divide(OP_FACTORIAL.apply(params[1])); + public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { + return OP_NPR.apply(implementation, params).divide(OP_FACTORIAL.apply(implementation, params[1])); } }; /** @@ -236,12 +245,13 @@ public class StandardPlugin extends Plugin { */ public static final NumberFunction FUNCTION_ABS = new NumberFunction() { @Override - public boolean matchesParams(NumberInterface[] params) { + public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { return params.length == 1; } + @Override - public NumberInterface applyInternal(NumberInterface[] params) { + public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return params[0].multiply(fromInt(params[0].getClass(), params[0].signum())); } }; @@ -250,16 +260,17 @@ public class StandardPlugin extends Plugin { */ public static final NumberFunction FUNCTION_LN = new NumberFunction() { @Override - public boolean matchesParams(NumberInterface[] params) { + public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { return params.length == 1 && params[0].compareTo(fromInt(params[0].getClass(), 0)) > 0; } + @Override - public NumberInterface applyInternal(NumberInterface[] params) { + public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { NumberInterface param = params[0]; NumberInterface one = fromInt(param.getClass(), 1); int powersOf2 = 0; - while (FUNCTION_ABS.apply(param.subtract(one)).compareTo(new NaiveNumber(0.1).promoteTo(param.getClass())) >= 0) { + while (FUNCTION_ABS.apply(implementation, param.subtract(one)).compareTo(new NaiveNumber(0.1).promoteTo(param.getClass())) >= 0) { if (param.subtract(one).signum() == 1) { param = param.divide(fromInt(param.getClass(), 2)); powersOf2++; @@ -276,7 +287,7 @@ public class StandardPlugin extends Plugin { } } } - return getLog2(param).multiply(fromInt(param.getClass(), powersOf2)).add(getLogPartialSum(param)); + return getLog2(implementation, param).multiply(fromInt(param.getClass(), powersOf2)).add(getLogPartialSum(implementation, param)); } /** @@ -285,13 +296,13 @@ public class StandardPlugin extends Plugin { * @param x value at which the series is evaluated. 0 < x < 2. (x=2 is convergent but impractical.) * @return the partial sum. */ - private NumberInterface getLogPartialSum(NumberInterface x) { + private NumberInterface getLogPartialSum(NumberImplementation implementation, NumberInterface x) { NumberInterface maxError = x.getMaxError(); x = x.subtract(fromInt(x.getClass(), 1)); //Terms used are for log(x+1). NumberInterface currentNumerator = x, currentTerm = x, sum = x; int n = 1; - while (FUNCTION_ABS.apply(currentTerm).compareTo(maxError) > 0) { + while (FUNCTION_ABS.apply(implementation, currentTerm).compareTo(maxError) > 0) { n++; currentNumerator = currentNumerator.multiply(x).negate(); currentTerm = currentNumerator.divide(fromInt(x.getClass(), n)); @@ -305,7 +316,7 @@ public class StandardPlugin extends Plugin { * @param number a number of the same type as the return type. (Used for precision.) * @return the value of log(2) with the appropriate precision. */ - private NumberInterface getLog2(NumberInterface number) { + private NumberInterface getLog2(NumberImplementation implementation, NumberInterface number) { NumberInterface maxError = number.getMaxError(); //NumberInterface errorBound = fromInt(number.getClass(), 1); //We'll use the series \sigma_{n >= 1) ((1/3^n + 1/4^n) * 1/n) @@ -330,12 +341,13 @@ public class StandardPlugin extends Plugin { */ public static final NumberFunction FUNCTION_RAND_INT = new NumberFunction() { @Override - public boolean matchesParams(NumberInterface[] params) { + public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { return params.length == 1; } + @Override - public NumberInterface applyInternal(NumberInterface[] params) { + public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return fromInt(params[0].getClass(), (int) Math.round(Math.random() * params[0].floor().intValue())); } }; @@ -345,17 +357,18 @@ public class StandardPlugin extends Plugin { */ public static final NumberFunction FUNCTION_EXP = new NumberFunction() { @Override - public boolean matchesParams(NumberInterface[] params) { + public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { return params.length == 1; } + @Override - public NumberInterface applyInternal(NumberInterface[] params) { + public NumberInterface applyInternal(NumberImplementation implementation, 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)); + return fromInt(params[0].getClass(), 1).divide(applyInternal(implementation, 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. @@ -382,7 +395,7 @@ public class StandardPlugin extends Plugin { */ public static final NumberOperator OP_CARET = new NumberOperator(OperatorAssociativity.RIGHT, OperatorType.BINARY_INFIX, 2) { @Override - public boolean matchesParams(NumberInterface[] params) { + public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { NumberInterface zero = fromInt(params[0].getClass(), 0); return params.length == 2 && !(params[0].compareTo(zero) == 0 @@ -390,8 +403,9 @@ public class StandardPlugin extends Plugin { && !(params[0].signum() == -1 && params[1].fractionalPart().compareTo(zero) != 0); } + @Override - public NumberInterface applyInternal(NumberInterface[] params) { + public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { NumberInterface zero = fromInt(params[0].getClass(), 0); if (params[0].compareTo(zero) == 0) return zero; @@ -399,12 +413,12 @@ public class StandardPlugin extends Plugin { return fromInt(params[0].getClass(), 1); //Detect integer bases: 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(implementation, params[1]).compareTo(fromInt(params[0].getClass(), Integer.MAX_VALUE)) < 0 + && FUNCTION_ABS.apply(implementation, 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 params[0].intPow(params[1].floor().intValue()).multiply(applyInternal(implementation, newParams)); } - return FUNCTION_EXP.apply(FUNCTION_LN.apply(FUNCTION_ABS.apply(params[0])).multiply(params[1])); + return FUNCTION_EXP.apply(implementation, FUNCTION_LN.apply(implementation, FUNCTION_ABS.apply(implementation, params[0])).multiply(params[1])); } }; /** @@ -412,15 +426,16 @@ public class StandardPlugin extends Plugin { */ public final NumberFunction functionSin = new NumberFunction() { @Override - public boolean matchesParams(NumberInterface[] params) { + public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { return params.length == 1; } + @Override - public NumberInterface applyInternal(NumberInterface[] params) { + public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { NumberInterface pi = piFor(params[0].getClass()); NumberInterface twoPi = pi.multiply(fromInt(pi.getClass(), 2)); - NumberInterface theta = getSmallAngle(params[0], pi); + NumberInterface theta = getSmallAngle(implementation, params[0], pi); //System.out.println(theta); if (theta.compareTo(pi.multiply(new NaiveNumber(1.5).promoteTo(twoPi.getClass()))) >= 0) { theta = theta.subtract(twoPi); @@ -428,7 +443,7 @@ public class StandardPlugin extends Plugin { theta = pi.subtract(theta); } //System.out.println(theta); - return sinTaylor(theta); + return sinTaylor(implementation, theta); } }; /** @@ -436,13 +451,14 @@ public class StandardPlugin extends Plugin { */ public final NumberFunction functionCos = new NumberFunction() { @Override - public boolean matchesParams(NumberInterface[] params) { + public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { return params.length == 1; } + @Override - public NumberInterface applyInternal(NumberInterface[] params) { - return functionSin.apply(piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 2)) + public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { + return functionSin.apply(implementation, piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 2)) .subtract(params[0])); } }; @@ -451,13 +467,14 @@ public class StandardPlugin extends Plugin { */ public final NumberFunction functionTan = new NumberFunction() { @Override - public boolean matchesParams(NumberInterface[] params) { + public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { return params.length == 1; } + @Override - public NumberInterface applyInternal(NumberInterface[] params) { - return functionSin.apply(params[0]).divide(functionCos.apply(params[0])); + public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { + return functionSin.apply(implementation, params[0]).divide(functionCos.apply(implementation, params[0])); } }; /** @@ -465,13 +482,14 @@ public class StandardPlugin extends Plugin { */ public final NumberFunction functionSec = new NumberFunction() { @Override - public boolean matchesParams(NumberInterface[] params) { + public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { return params.length == 1; } + @Override - public NumberInterface applyInternal(NumberInterface[] params) { - return fromInt(params[0].getClass(), 1).divide(functionCos.apply(params[0])); + public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { + return fromInt(params[0].getClass(), 1).divide(functionCos.apply(implementation, params[0])); } }; /** @@ -479,13 +497,14 @@ public class StandardPlugin extends Plugin { */ public final NumberFunction functionCsc = new NumberFunction() { @Override - public boolean matchesParams(NumberInterface[] params) { + public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { return params.length == 1; } + @Override - public NumberInterface applyInternal(NumberInterface[] params) { - return fromInt(params[0].getClass(), 1).divide(functionSin.apply(params[0])); + public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { + return fromInt(params[0].getClass(), 1).divide(functionSin.apply(implementation, params[0])); } }; /** @@ -493,13 +512,14 @@ public class StandardPlugin extends Plugin { */ public final NumberFunction functionCot = new NumberFunction() { @Override - public boolean matchesParams(NumberInterface[] params) { + public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { return params.length == 1; } + @Override - public NumberInterface applyInternal(NumberInterface[] params) { - return functionCos.apply(params[0]).divide(functionSin.apply(params[0])); + public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { + return functionCos.apply(implementation, params[0]).divide(functionSin.apply(implementation, params[0])); } }; @@ -508,23 +528,24 @@ public class StandardPlugin extends Plugin { */ public final NumberFunction functionArcsin = new NumberFunction() { @Override - public boolean matchesParams(NumberInterface[] params) { + public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { return params.length == 1 - && FUNCTION_ABS.apply(params[0]).compareTo(fromInt(params[0].getClass(), 1)) <= 0; + && FUNCTION_ABS.apply(implementation, params[0]).compareTo(fromInt(params[0].getClass(), 1)) <= 0; } + @Override - public NumberInterface applyInternal(NumberInterface[] params) { - 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])))}; + public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { + if (FUNCTION_ABS.apply(implementation, params[0]).compareTo(new NaiveNumber(0.8).promoteTo(params[0].getClass())) >= 0) { + NumberInterface[] newParams = {FUNCTION_SQRT.apply(implementation, 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())); + .subtract(applyInternal(implementation, newParams)).multiply(fromInt(params[0].getClass(), params[0].signum())); } NumberInterface currentTerm = params[0], sum = currentTerm, 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(implementation, currentTerm).compareTo(summandBound) > 0) { exponent += 2; power = power.multiply(multiplier); coefficient = coefficient.multiply(fromInt(params[0].getClass(), exponent - 2)) @@ -541,14 +562,15 @@ public class StandardPlugin extends Plugin { */ public final NumberFunction functionArccos = new NumberFunction() { @Override - public boolean matchesParams(NumberInterface[] params) { - return params.length == 1 && FUNCTION_ABS.apply(params[0]).compareTo(fromInt(params[0].getClass(), 1)) <= 0; + public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { + return params.length == 1 && FUNCTION_ABS.apply(implementation, params[0]).compareTo(fromInt(params[0].getClass(), 1)) <= 0; } + @Override - public NumberInterface applyInternal(NumberInterface[] params) { + public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 2)) - .subtract(functionArcsin.apply(params)); + .subtract(functionArcsin.apply(implementation, params)); } }; @@ -557,14 +579,15 @@ public class StandardPlugin extends Plugin { */ public final NumberFunction functionArccsc = new NumberFunction() { @Override - public boolean matchesParams(NumberInterface[] params) { - return params.length == 1 && FUNCTION_ABS.apply(params[0]).compareTo(fromInt(params[0].getClass(), 1)) >= 0; + public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { + return params.length == 1 && FUNCTION_ABS.apply(implementation, params[0]).compareTo(fromInt(params[0].getClass(), 1)) >= 0; } + @Override - public NumberInterface applyInternal(NumberInterface[] params) { + public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { NumberInterface[] reciprocalParamArr = {fromInt(params[0].getClass(), 1).divide(params[0])}; - return functionArcsin.apply(reciprocalParamArr); + return functionArcsin.apply(implementation, reciprocalParamArr); } }; @@ -573,14 +596,15 @@ public class StandardPlugin extends Plugin { */ public final NumberFunction functionArcsec = new NumberFunction() { @Override - public boolean matchesParams(NumberInterface[] params) { - return params.length == 1 && FUNCTION_ABS.apply(params[0]).compareTo(fromInt(params[0].getClass(), 1)) >= 0; + public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { + return params.length == 1 && FUNCTION_ABS.apply(implementation, params[0]).compareTo(fromInt(params[0].getClass(), 1)) >= 0; } + @Override - public NumberInterface applyInternal(NumberInterface[] params) { + public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { NumberInterface[] reciprocalParamArr = {fromInt(params[0].getClass(), 1).divide(params[0])}; - return functionArccos.apply(reciprocalParamArr); + return functionArccos.apply(implementation, reciprocalParamArr); } }; @@ -589,20 +613,21 @@ public class StandardPlugin extends Plugin { */ public final NumberFunction functionArctan = new NumberFunction() { @Override - public boolean matchesParams(NumberInterface[] params) { + public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { return params.length == 1; } + @Override - public NumberInterface applyInternal(NumberInterface[] params) { + public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { if (params[0].signum() == -1) { NumberInterface[] negatedParams = {params[0].negate()}; - return applyInternal(negatedParams).negate(); + return applyInternal(implementation, negatedParams).negate(); } 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)); + .subtract(applyInternal(implementation, reciprocalParams)); } if (params[0].compareTo(fromInt(params[0].getClass(), 1)) == 0) { return piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 4)); @@ -610,12 +635,12 @@ public class StandardPlugin extends Plugin { 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)); + return applyInternal(implementation, 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(implementation, currentTerm).compareTo(maxError) > 0) { n += 2; currentPower = currentPower.multiply(multiplier); currentTerm = currentPower.divide(fromInt(currentPower.getClass(), n)); @@ -630,14 +655,14 @@ public class StandardPlugin extends Plugin { */ public final NumberFunction functionArccot = new NumberFunction() { @Override - public boolean matchesParams(NumberInterface[] params) { + public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { return params.length == 1; } @Override - public NumberInterface applyInternal(NumberInterface[] params) { + public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 2)) - .subtract(functionArctan.apply(params)); + .subtract(functionArctan.apply(implementation, params)); } }; @@ -690,7 +715,7 @@ public class StandardPlugin extends Plugin { * @param x where the series is evaluated. * @return the value of the series */ - private static NumberInterface sinTaylor(NumberInterface x) { + private static NumberInterface sinTaylor(NumberImplementation implementation, NumberInterface x) { NumberInterface power = x, multiplier = x.multiply(x).negate(), currentTerm = x, sum = x; NumberInterface maxError = x.getMaxError(); int n = 1; @@ -699,7 +724,7 @@ public class StandardPlugin extends Plugin { power = power.multiply(multiplier); currentTerm = power.divide(factorial(x.getClass(), n)); sum = sum.add(currentTerm); - } while (FUNCTION_ABS.apply(currentTerm).compareTo(maxError) > 0); + } while (FUNCTION_ABS.apply(implementation, currentTerm).compareTo(maxError) > 0); return sum; } @@ -709,10 +734,10 @@ public class StandardPlugin extends Plugin { * @param phi an angle (in radians). * @return theta in [0, 2pi) that differs from phi by a multiple of 2pi. */ - private static NumberInterface getSmallAngle(NumberInterface phi, NumberInterface pi) { + private static NumberInterface getSmallAngle(NumberImplementation implementation, NumberInterface phi, NumberInterface pi) { NumberInterface twoPi = pi.multiply(fromInt(pi.getClass(), 2)); - NumberInterface theta = FUNCTION_ABS.apply(phi).subtract(twoPi - .multiply(FUNCTION_ABS.apply(phi).divide(twoPi).floor())); //Now theta is in [0, 2pi). + NumberInterface theta = FUNCTION_ABS.apply(implementation, phi).subtract(twoPi + .multiply(FUNCTION_ABS.apply(implementation, phi).divide(twoPi).floor())); //Now theta is in [0, 2pi). if (phi.signum() < 0) { theta = twoPi.subtract(theta); } diff --git a/core/src/main/java/org/nwapw/abacus/tree/NumberReducer.java b/core/src/main/java/org/nwapw/abacus/tree/NumberReducer.java index fa73958..8d8dbbc 100644 --- a/core/src/main/java/org/nwapw/abacus/tree/NumberReducer.java +++ b/core/src/main/java/org/nwapw/abacus/tree/NumberReducer.java @@ -3,6 +3,8 @@ package org.nwapw.abacus.tree; import org.nwapw.abacus.Abacus; import org.nwapw.abacus.function.*; import org.nwapw.abacus.number.NumberInterface; +import org.nwapw.abacus.number.PromotionManager; +import org.nwapw.abacus.number.PromotionResult; /** * A reducer implementation that turns a tree into a single number. @@ -26,19 +28,22 @@ public class NumberReducer implements Reducer { @Override public NumberInterface reduceNode(TreeNode node, Object... children) { + PromotionManager manager = abacus.getPromotionManager(); if (node instanceof NumberNode) { - return abacus.numberFromString(((NumberNode) node).getNumber()); + return abacus.getNumberImplementation().instanceForString(((NumberNode) node).getNumber()); } else if(node instanceof VariableNode) { - return abacus.numberFromString("0"); + return abacus.getNumberImplementation().instanceForString("0"); } else if (node instanceof NumberBinaryNode) { NumberInterface left = (NumberInterface) children[0]; NumberInterface right = (NumberInterface) children[1]; NumberOperator operator = abacus.getPluginManager().operatorFor(((BinaryNode) node).getOperation()); - return operator.apply(left, right); + PromotionResult result = manager.promote(left, right); + if(result == null) return null; + return operator.apply(result.getPromotedTo(), result.getItems()); } else if (node instanceof NumberUnaryNode) { NumberInterface child = (NumberInterface) children[0]; NumberOperator operator = abacus.getPluginManager().operatorFor(((UnaryNode) node).getOperation()); - return operator.apply(child); + return operator.apply(abacus.getPluginManager().interfaceImplementationFor(child.getClass()), child); } else if (node instanceof FunctionNode) { NumberInterface[] convertedChildren = new NumberInterface[children.length]; for (int i = 0; i < convertedChildren.length; i++) { @@ -46,7 +51,9 @@ public class NumberReducer implements Reducer { } NumberFunction function = abacus.getPluginManager().functionFor(((FunctionNode) node).getCallTo()); if (function == null) return null; - return function.apply(convertedChildren); + PromotionResult result = manager.promote(convertedChildren); + if(result == null) return null; + return function.apply(result.getPromotedTo(), result.getItems()); } else if (node instanceof TreeValueFunctionNode){ CallNode callNode = (CallNode) node; TreeNode[] realChildren = new TreeNode[callNode.getChildren().size()]; @@ -56,19 +63,19 @@ public class NumberReducer implements Reducer { TreeValueFunction function = abacus.getPluginManager().treeValueFunctionFor(callNode.getCallTo()); if(function == null) return null; - return function.applyWithReducer(this, realChildren); + return function.applyWithReducer(abacus.getNumberImplementation(), this, realChildren); } else if (node instanceof TreeValueBinaryNode) { BinaryNode binaryNode = (BinaryNode) node; TreeValueOperator operator = abacus.getPluginManager() .treeValueOperatorFor(binaryNode.getOperation()); if(operator == null) return null; - return operator.applyWithReducer(this, binaryNode.getLeft(), binaryNode.getRight()); + return operator.applyWithReducer(abacus.getNumberImplementation(), this, binaryNode.getLeft(), binaryNode.getRight()); } else if(node instanceof TreeValueUnaryNode) { UnaryNode unaryNode = (UnaryNode) node; TreeValueOperator operator = abacus.getPluginManager() .treeValueOperatorFor(unaryNode.getOperation()); if(operator == null) return null; - return operator.applyWithReducer(this, unaryNode.getApplyTo()); + return operator.applyWithReducer(abacus.getNumberImplementation(), this, unaryNode.getApplyTo()); } return null; } diff --git a/core/src/main/kotlin/org/nwapw/abacus/function/applicable/Applicable.kt b/core/src/main/kotlin/org/nwapw/abacus/function/applicable/Applicable.kt index 5e219c1..69f0afc 100644 --- a/core/src/main/kotlin/org/nwapw/abacus/function/applicable/Applicable.kt +++ b/core/src/main/kotlin/org/nwapw/abacus/function/applicable/Applicable.kt @@ -1,5 +1,7 @@ package org.nwapw.abacus.function.applicable +import org.nwapw.abacus.plugin.NumberImplementation + /** * A class that can be applied to arguments. * @@ -15,7 +17,7 @@ interface Applicable { * @param params the parameter array to verify for compatibility. * @return whether the array can be used with applyInternal. */ - fun matchesParams(params: Array): Boolean + fun matchesParams(implementation: NumberImplementation, params: Array): Boolean /** * Applies the applicable object to the given parameters, @@ -23,7 +25,7 @@ interface Applicable { * @param params the parameters to apply to. * @return the result of the application. */ - fun applyInternal(params: Array): O? + fun applyInternal(implementation: NumberImplementation, params: Array): O? /** * If the parameters can be used with this applicable, returns @@ -32,9 +34,9 @@ interface Applicable { * @param params the parameters to apply to. * @return the result of the operation, or null if parameters do not match. */ - fun apply(vararg params: T): O? { - if (!matchesParams(params)) return null - return applyInternal(params) + fun apply(implementation: NumberImplementation, vararg params: T): O? { + if (!matchesParams(implementation, params)) return null + return applyInternal(implementation, params) } } \ No newline at end of file diff --git a/core/src/main/kotlin/org/nwapw/abacus/function/applicable/ReducerApplicable.kt b/core/src/main/kotlin/org/nwapw/abacus/function/applicable/ReducerApplicable.kt index 6cef5e1..bdb3276 100644 --- a/core/src/main/kotlin/org/nwapw/abacus/function/applicable/ReducerApplicable.kt +++ b/core/src/main/kotlin/org/nwapw/abacus/function/applicable/ReducerApplicable.kt @@ -1,5 +1,6 @@ package org.nwapw.abacus.function.applicable +import org.nwapw.abacus.plugin.NumberImplementation import org.nwapw.abacus.tree.Reducer /** @@ -18,7 +19,7 @@ interface ReducerApplicable { * given parameters. * @param params the parameters to check. */ - fun matchesParams(params: Array): Boolean + fun matchesParams(implementation: NumberImplementation, params: Array): Boolean /** * Applies this applicable to the given arguments, and reducer. @@ -26,7 +27,7 @@ interface ReducerApplicable { * @param params the arguments to apply to. * @return the result of the application. */ - fun applyWithReducerInternal(reducer: Reducer, params: Array): O? + fun applyWithReducerInternal(implementation: NumberImplementation, reducer: Reducer, params: Array): O? /** * Applies this applicable to the given arguments, and reducer, @@ -35,9 +36,9 @@ interface ReducerApplicable { * @param params the arguments to apply to. * @return the result of the application, or null if the arguments are incompatible. */ - fun applyWithReducer(reducer: Reducer, vararg params: T): O? { - if (!matchesParams(params)) return null - return applyWithReducerInternal(reducer, params) + fun applyWithReducer(implementation: NumberImplementation, reducer: Reducer, vararg params: T): O? { + if (!matchesParams(implementation, params)) return null + return applyWithReducerInternal(implementation, reducer, params) } } \ No newline at end of file diff --git a/core/src/main/kotlin/org/nwapw/abacus/number/PromotionManager.kt b/core/src/main/kotlin/org/nwapw/abacus/number/PromotionManager.kt index e4ccc38..f4bb684 100644 --- a/core/src/main/kotlin/org/nwapw/abacus/number/PromotionManager.kt +++ b/core/src/main/kotlin/org/nwapw/abacus/number/PromotionManager.kt @@ -25,15 +25,15 @@ class PromotionManager(val abacus: Abacus) { }) } - fun promote(vararg numbers: NumberInterface): Array? { + fun promote(vararg numbers: NumberInterface): PromotionResult? { val pluginManager = abacus.pluginManager val implementations = numbers.map { pluginManager.interfaceImplementationFor(it.javaClass) } val highestPriority = implementations.sortedBy { it.priority }.last() - return numbers.map { + return PromotionResult(items = numbers.map { if(it.javaClass == highestPriority.implementation) it else getPathBetween(pluginManager.interfaceImplementationFor(it.javaClass), highestPriority) ?.promote(it) ?: return null - }.toTypedArray() + }.toTypedArray(), promotedTo = highestPriority) } } \ No newline at end of file diff --git a/core/src/main/kotlin/org/nwapw/abacus/number/PromotionResult.kt b/core/src/main/kotlin/org/nwapw/abacus/number/PromotionResult.kt new file mode 100644 index 0000000..2453105 --- /dev/null +++ b/core/src/main/kotlin/org/nwapw/abacus/number/PromotionResult.kt @@ -0,0 +1,5 @@ +package org.nwapw.abacus.number + +import org.nwapw.abacus.plugin.NumberImplementation + +data class PromotionResult(val promotedTo: NumberImplementation, val items: Array) \ No newline at end of file diff --git a/core/src/test/java/org/nwapw/abacus/tests/TokenizerTests.java b/core/src/test/java/org/nwapw/abacus/tests/TokenizerTests.java index 79a7cd2..ace0624 100644 --- a/core/src/test/java/org/nwapw/abacus/tests/TokenizerTests.java +++ b/core/src/test/java/org/nwapw/abacus/tests/TokenizerTests.java @@ -9,6 +9,7 @@ import org.nwapw.abacus.function.*; import org.nwapw.abacus.lexing.pattern.Match; import org.nwapw.abacus.number.NumberInterface; import org.nwapw.abacus.parsing.LexerTokenizer; +import org.nwapw.abacus.plugin.NumberImplementation; import org.nwapw.abacus.plugin.Plugin; import org.nwapw.abacus.tree.TokenType; @@ -20,12 +21,12 @@ public class TokenizerTests { private static LexerTokenizer lexerTokenizer = new LexerTokenizer(); private static NumberFunction subtractFunction = new NumberFunction() { @Override - public boolean matchesParams(NumberInterface[] params) { + public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { return params.length == 2; } @Override - public NumberInterface applyInternal(NumberInterface[] params) { + public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return params[0].subtract(params[1]); } }; @@ -36,26 +37,26 @@ public class TokenizerTests { 0) { @Override - public boolean matchesParams(NumberInterface[] params) { + public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { return true; } - @Override - public NumberInterface applyInternal(NumberInterface[] params) { - return subtractFunction.apply(params); + @Override + public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { + return subtractFunction.apply(implementation, params); } }); registerOperator("-", new NumberOperator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 0) { @Override - public boolean matchesParams(NumberInterface[] params) { + public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { return true; } - @Override - public NumberInterface applyInternal(NumberInterface[] params) { - return subtractFunction.apply(params); + @Override + public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { + return subtractFunction.apply(implementation, params); } }); registerFunction("subtract", subtractFunction); 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 e8096fd..4f62247 100644 --- a/fx/src/main/java/org/nwapw/abacus/fx/AbacusController.java +++ b/fx/src/main/java/org/nwapw/abacus/fx/AbacusController.java @@ -14,8 +14,7 @@ import org.nwapw.abacus.Abacus; import org.nwapw.abacus.config.Configuration; import org.nwapw.abacus.function.Documentation; import org.nwapw.abacus.function.DocumentationType; -import org.nwapw.abacus.number.ComputationInterruptedException; -import org.nwapw.abacus.number.NumberInterface; +import org.nwapw.abacus.number.*; import org.nwapw.abacus.plugin.ClassFinder; import org.nwapw.abacus.plugin.PluginListener; import org.nwapw.abacus.plugin.PluginManager; From e1721084765bd4836dfe253dd0149f2ee2d55d94 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Fri, 1 Sep 2017 18:07:28 -0700 Subject: [PATCH 07/13] Stop using fromInt and the promoteTo function. --- .../org/nwapw/abacus/number/NaiveNumber.java | 9 - .../nwapw/abacus/number/NumberInterface.java | 23 -- .../nwapw/abacus/number/PreciseNumber.java | 8 - .../nwapw/abacus/plugin/StandardPlugin.java | 204 ++++++++---------- 4 files changed, 84 insertions(+), 160 deletions(-) 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 cd17c89..4f03243 100755 --- a/core/src/main/java/org/nwapw/abacus/number/NaiveNumber.java +++ b/core/src/main/java/org/nwapw/abacus/number/NaiveNumber.java @@ -114,15 +114,6 @@ public class NaiveNumber extends NumberInterface { return (int) value; } - @Override - public NumberInterface promoteToInternal(Class toClass) { - if (toClass == this.getClass()) return this; - else if (toClass == PreciseNumber.class) { - return new PreciseNumber(Double.toString(value)); - } - return null; - } - public String toString() { double shiftBy = Math.pow(10, 10); return Double.toString(Math.round(value * shiftBy) / shiftBy); 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 adf401d..4a3fe5c 100755 --- a/core/src/main/java/org/nwapw/abacus/number/NumberInterface.java +++ b/core/src/main/java/org/nwapw/abacus/number/NumberInterface.java @@ -236,29 +236,6 @@ public abstract class NumberInterface { */ public abstract int intValue(); - /** - * Promotes this class to another number class. - * - * @param toClass the class to promote to. - * @return the resulting new instance. - */ - @Deprecated - protected abstract NumberInterface promoteToInternal(Class toClass); - - /** - * Promotes this class to another number class. Also, checks if the - * thread has been interrupted, and if so, throws - * an exception. - * - * @param toClass the class to promote to. - * @return the resulting new instance. - */ - @Deprecated - public final NumberInterface promoteTo(Class toClass) { - checkInterrupted(); - return promoteToInternal(toClass); - } - /** * Returns the smallest error this instance can tolerate depending * on its precision and value. 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 f6f5afe..41e9080 100755 --- a/core/src/main/java/org/nwapw/abacus/number/PreciseNumber.java +++ b/core/src/main/java/org/nwapw/abacus/number/PreciseNumber.java @@ -152,14 +152,6 @@ public class PreciseNumber extends NumberInterface { return new PreciseNumber(value.negate()); } - @Override - public NumberInterface promoteToInternal(Class toClass) { - if (toClass == this.getClass()) { - return this; - } - return null; - } - @Override public String toString() { return value.round(outputContext).toString(); 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 53fcae8..873c45f 100755 --- a/core/src/main/java/org/nwapw/abacus/plugin/StandardPlugin.java +++ b/core/src/main/java/org/nwapw/abacus/plugin/StandardPlugin.java @@ -102,7 +102,7 @@ public class StandardPlugin extends Plugin { @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { - return OP_CARET.apply(implementation, params[0], ((new NaiveNumber(0.5)).promoteTo(params[0].getClass()))); + return OP_CARET.apply(implementation, params[0], implementation.instanceForString(".5")); } }; /** @@ -141,17 +141,13 @@ public class StandardPlugin extends Plugin { return C.divide(sum); } }; - /** - * Stores objects of NumberInterface with integer values for reuse. - */ - private final static HashMap, HashMap> integerValues = new HashMap<>(); /** * The division operator, / */ public static final NumberOperator OP_DIVIDE = new NumberOperator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 1) { @Override public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { - return params.length == 2 && params[1].compareTo(fromInt(params[0].getClass(), 0)) != 0; + return params.length == 2 && params[1].compareTo(implementation.instanceForString(Integer.toString( 0))) != 0; } @@ -168,7 +164,7 @@ public class StandardPlugin extends Plugin { @Override public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { return params.length == 1 - && params[0].fractionalPart().compareTo(fromInt(params[0].getClass(), 0)) == 0 + && params[0].fractionalPart().compareTo(implementation.instanceForString("0")) == 0 && params[0].signum() >= 0; } @@ -176,9 +172,9 @@ public class StandardPlugin extends Plugin { @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { if (params[0].signum() == 0) { - return fromInt(params[0].getClass(), 1); + return implementation.instanceForString("1"); } - NumberInterface one = fromInt(params[0].getClass(), 1); + NumberInterface one = implementation.instanceForString("1"); NumberInterface factorial = params[0]; NumberInterface multiplier = params[0]; //It is necessary to later prevent calls of factorial on anything but non-negative integers. @@ -208,18 +204,18 @@ public class StandardPlugin extends Plugin { public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { 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); + (params[0].signum() == 0 && params[1].signum() != 0)) return implementation.instanceForString("0"); + NumberInterface total = implementation.instanceForString("1"); NumberInterface multiplyBy = params[0]; NumberInterface remainingMultiplications = params[1]; - NumberInterface halfway = params[0].divide(fromInt(params[0].getClass(), 2)); + NumberInterface halfway = params[0].divide(implementation.instanceForString("2")); if (remainingMultiplications.compareTo(halfway) > 0) { remainingMultiplications = params[0].subtract(remainingMultiplications); } while (remainingMultiplications.signum() > 0) { total = total.multiply(multiplyBy); - remainingMultiplications = remainingMultiplications.subtract(fromInt(params[0].getClass(), 1)); - multiplyBy = multiplyBy.subtract(fromInt(params[0].getClass(), 1)); + remainingMultiplications = remainingMultiplications.subtract(implementation.instanceForString("1")); + multiplyBy = multiplyBy.subtract(implementation.instanceForString("1")); } return total; } @@ -252,7 +248,7 @@ public class StandardPlugin extends Plugin { @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { - return params[0].multiply(fromInt(params[0].getClass(), params[0].signum())); + return params[0].multiply(implementation.instanceForString(Integer.toString(params[0].signum()))); } }; /** @@ -261,25 +257,25 @@ public class StandardPlugin extends Plugin { public static final NumberFunction FUNCTION_LN = new NumberFunction() { @Override public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { - return params.length == 1 && params[0].compareTo(fromInt(params[0].getClass(), 0)) > 0; + return params.length == 1 && params[0].compareTo(implementation.instanceForString("0")) > 0; } @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { NumberInterface param = params[0]; - NumberInterface one = fromInt(param.getClass(), 1); + NumberInterface one = implementation.instanceForString("1"); int powersOf2 = 0; - while (FUNCTION_ABS.apply(implementation, param.subtract(one)).compareTo(new NaiveNumber(0.1).promoteTo(param.getClass())) >= 0) { + while (FUNCTION_ABS.apply(implementation, param.subtract(one)).compareTo(implementation.instanceForString(".1")) >= 0) { if (param.subtract(one).signum() == 1) { - param = param.divide(fromInt(param.getClass(), 2)); + param = param.divide(implementation.instanceForString("2")); powersOf2++; if (param.subtract(one).signum() != 1) { break; //No infinite loop for you. } } else { - param = param.multiply(fromInt(param.getClass(), 2)); + param = param.multiply(implementation.instanceForString("2")); powersOf2--; if (param.subtract(one).signum() != -1) { break; @@ -287,7 +283,7 @@ public class StandardPlugin extends Plugin { } } } - return getLog2(implementation, param).multiply(fromInt(param.getClass(), powersOf2)).add(getLogPartialSum(implementation, param)); + return getLog2(implementation, param).multiply(implementation.instanceForString(Integer.toString(powersOf2))).add(getLogPartialSum(implementation, param)); } /** @@ -299,13 +295,13 @@ public class StandardPlugin extends Plugin { private NumberInterface getLogPartialSum(NumberImplementation implementation, NumberInterface x) { NumberInterface maxError = x.getMaxError(); - x = x.subtract(fromInt(x.getClass(), 1)); //Terms used are for log(x+1). + x = x.subtract(implementation.instanceForString("1")); //Terms used are for log(x+1). NumberInterface currentNumerator = x, currentTerm = x, sum = x; int n = 1; while (FUNCTION_ABS.apply(implementation, currentTerm).compareTo(maxError) > 0) { n++; currentNumerator = currentNumerator.multiply(x).negate(); - currentTerm = currentNumerator.divide(fromInt(x.getClass(), n)); + currentTerm = currentNumerator.divide(implementation.instanceForString(Integer.toString(n))); sum = sum.add(currentTerm); } return sum; @@ -318,19 +314,19 @@ public class StandardPlugin extends Plugin { */ private NumberInterface getLog2(NumberImplementation implementation, NumberInterface number) { NumberInterface maxError = number.getMaxError(); - //NumberInterface errorBound = fromInt(number.getClass(), 1); + //NumberInterface errorBound = implementation.instanceForString("1"); //We'll use the series \sigma_{n >= 1) ((1/3^n + 1/4^n) * 1/n) //In the following, a=1/3^n, b=1/4^n, c = 1/n. //a is also an error bound. - NumberInterface a = fromInt(number.getClass(), 1), b = a, c = a; - NumberInterface sum = fromInt(number.getClass(), 0); - NumberInterface one = fromInt(number.getClass(), 1); + NumberInterface a = implementation.instanceForString("1"), b = a, c = a; + NumberInterface sum = implementation.instanceForString("0"); + NumberInterface one = implementation.instanceForString("1"); int n = 0; while (a.compareTo(maxError) >= 1) { n++; - a = a.divide(fromInt(number.getClass(), 3)); - b = b.divide(fromInt(number.getClass(), 4)); - c = one.divide(fromInt(number.getClass(), n)); + a = a.divide(implementation.instanceForString("3")); + b = b.divide(implementation.instanceForString("4")); + c = one.divide(implementation.instanceForString(Integer.toString(n))); sum = sum.add(a.add(b).multiply(c)); } return sum; @@ -348,10 +344,10 @@ public class StandardPlugin extends Plugin { @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { - return fromInt(params[0].getClass(), (int) Math.round(Math.random() * params[0].floor().intValue())); + return implementation.instanceForString(Long.toString(Math.round(Math.random() * params[0].floor().intValue()))); } }; - private static final HashMap, ArrayList> FACTORIAL_LISTS = new HashMap<>(); + private static final HashMap> FACTORIAL_LISTS = new HashMap<>(); /** * The exponential function, exp(1) = e^1 = 2.71... */ @@ -368,19 +364,19 @@ public class StandardPlugin extends Plugin { int n = 0; if (params[0].signum() < 0) { NumberInterface[] negatedParams = {params[0].negate()}; - return fromInt(params[0].getClass(), 1).divide(applyInternal(implementation, negatedParams)); + return implementation.instanceForString("1").divide(applyInternal(implementation, 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 sum = implementation.instanceForString("1"); NumberInterface nextNumerator = params[0]; - NumberInterface left = params[0].multiply(fromInt(params[0].getClass(), 3).intPow(params[0].ceiling().intValue())), right = maxError; + NumberInterface left = params[0].multiply(implementation.instanceForString("3").intPow(params[0].ceiling().intValue())), right = maxError; do { - sum = sum.add(nextNumerator.divide(factorial(params[0].getClass(), n + 1))); + sum = sum.add(nextNumerator.divide(factorial(implementation, n + 1))); n++; nextNumerator = nextNumerator.multiply(params[0]); left = left.multiply(params[0]); - NumberInterface nextN = fromInt(params[0].getClass(), n + 1); + NumberInterface nextN = implementation.instanceForString(Integer.toString(n + 1)); right = right.multiply(nextN); //System.out.println(left + ", " + right); } @@ -396,7 +392,7 @@ public class StandardPlugin extends Plugin { public static final NumberOperator OP_CARET = new NumberOperator(OperatorAssociativity.RIGHT, OperatorType.BINARY_INFIX, 2) { @Override public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { - NumberInterface zero = fromInt(params[0].getClass(), 0); + NumberInterface zero = implementation.instanceForString("0"); return params.length == 2 && !(params[0].compareTo(zero) == 0 && params[1].compareTo(zero) == 0) @@ -406,15 +402,15 @@ public class StandardPlugin extends Plugin { @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { - NumberInterface zero = fromInt(params[0].getClass(), 0); + NumberInterface zero = implementation.instanceForString("0"); if (params[0].compareTo(zero) == 0) return zero; else if (params[1].compareTo(zero) == 0) - return fromInt(params[0].getClass(), 1); + return implementation.instanceForString("1"); //Detect integer bases: - if (params[0].fractionalPart().compareTo(fromInt(params[0].getClass(), 0)) == 0 - && FUNCTION_ABS.apply(implementation, params[1]).compareTo(fromInt(params[0].getClass(), Integer.MAX_VALUE)) < 0 - && FUNCTION_ABS.apply(implementation, params[1]).compareTo(fromInt(params[1].getClass(), 1)) >= 0) { + if (params[0].fractionalPart().compareTo(implementation.instanceForString("0")) == 0 + && FUNCTION_ABS.apply(implementation, params[1]).compareTo(implementation.instanceForString(Integer.toString(Integer.MAX_VALUE))) < 0 + && FUNCTION_ABS.apply(implementation, params[1]).compareTo(implementation.instanceForString("1")) >= 0) { NumberInterface[] newParams = {params[0], params[1].fractionalPart()}; return params[0].intPow(params[1].floor().intValue()).multiply(applyInternal(implementation, newParams)); } @@ -434,12 +430,12 @@ public class StandardPlugin extends Plugin { @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { NumberInterface pi = piFor(params[0].getClass()); - NumberInterface twoPi = pi.multiply(fromInt(pi.getClass(), 2)); + NumberInterface twoPi = pi.multiply(implementation.instanceForString("2")); NumberInterface theta = getSmallAngle(implementation, params[0], pi); //System.out.println(theta); - if (theta.compareTo(pi.multiply(new NaiveNumber(1.5).promoteTo(twoPi.getClass()))) >= 0) { + if (theta.compareTo(pi.multiply(implementation.instanceForString("1.5"))) >= 0) { theta = theta.subtract(twoPi); - } else if (theta.compareTo(pi.divide(fromInt(pi.getClass(), 2))) > 0) { + } else if (theta.compareTo(pi.divide(implementation.instanceForString("2"))) > 0) { theta = pi.subtract(theta); } //System.out.println(theta); @@ -458,7 +454,7 @@ public class StandardPlugin extends Plugin { @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { - return functionSin.apply(implementation, piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 2)) + return functionSin.apply(implementation, piFor(params[0].getClass()).divide(implementation.instanceForString("2")) .subtract(params[0])); } }; @@ -489,7 +485,7 @@ public class StandardPlugin extends Plugin { @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { - return fromInt(params[0].getClass(), 1).divide(functionCos.apply(implementation, params[0])); + return implementation.instanceForString("1").divide(functionCos.apply(implementation, params[0])); } }; /** @@ -504,7 +500,7 @@ public class StandardPlugin extends Plugin { @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { - return fromInt(params[0].getClass(), 1).divide(functionSin.apply(implementation, params[0])); + return implementation.instanceForString("1").divide(functionSin.apply(implementation, params[0])); } }; /** @@ -530,27 +526,27 @@ public class StandardPlugin extends Plugin { @Override public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { return params.length == 1 - && FUNCTION_ABS.apply(implementation, params[0]).compareTo(fromInt(params[0].getClass(), 1)) <= 0; + && FUNCTION_ABS.apply(implementation, params[0]).compareTo(implementation.instanceForString("1")) <= 0; } @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { - if (FUNCTION_ABS.apply(implementation, params[0]).compareTo(new NaiveNumber(0.8).promoteTo(params[0].getClass())) >= 0) { - NumberInterface[] newParams = {FUNCTION_SQRT.apply(implementation, fromInt(params[0].getClass(), 1).subtract(params[0].multiply(params[0])))}; - return piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 2)) - .subtract(applyInternal(implementation, newParams)).multiply(fromInt(params[0].getClass(), params[0].signum())); + if (FUNCTION_ABS.apply(implementation, params[0]).compareTo(implementation.instanceForString(".8")) >= 0) { + NumberInterface[] newParams = {FUNCTION_SQRT.apply(implementation, implementation.instanceForString("1").subtract(params[0].multiply(params[0])))}; + return piFor(params[0].getClass()).divide(implementation.instanceForString("2")) + .subtract(applyInternal(implementation, newParams)).multiply(implementation.instanceForString(Integer.toString(params[0].signum()))); } NumberInterface currentTerm = params[0], sum = currentTerm, - multiplier = currentTerm.multiply(currentTerm), summandBound = sum.getMaxError().multiply(fromInt(sum.getClass(), 1).subtract(multiplier)), - power = currentTerm, coefficient = fromInt(params[0].getClass(), 1); + multiplier = currentTerm.multiply(currentTerm), summandBound = sum.getMaxError().multiply(implementation.instanceForString("1").subtract(multiplier)), + power = currentTerm, coefficient = implementation.instanceForString("1"); int exponent = 1; while (FUNCTION_ABS.apply(implementation, currentTerm).compareTo(summandBound) > 0) { exponent += 2; power = power.multiply(multiplier); - 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)); + coefficient = coefficient.multiply(implementation.instanceForString(Integer.toString( exponent - 2))) + .divide(implementation.instanceForString(Integer.toString( exponent - 1))); + currentTerm = power.multiply(coefficient).divide(implementation.instanceForString(Integer.toString( exponent))); sum = sum.add(currentTerm); } return sum; @@ -563,13 +559,13 @@ public class StandardPlugin extends Plugin { public final NumberFunction functionArccos = new NumberFunction() { @Override public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { - return params.length == 1 && FUNCTION_ABS.apply(implementation, params[0]).compareTo(fromInt(params[0].getClass(), 1)) <= 0; + return params.length == 1 && FUNCTION_ABS.apply(implementation, params[0]).compareTo(implementation.instanceForString("1")) <= 0; } @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { - return piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 2)) + return piFor(params[0].getClass()).divide(implementation.instanceForString("2")) .subtract(functionArcsin.apply(implementation, params)); } }; @@ -580,13 +576,13 @@ public class StandardPlugin extends Plugin { public final NumberFunction functionArccsc = new NumberFunction() { @Override public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { - return params.length == 1 && FUNCTION_ABS.apply(implementation, params[0]).compareTo(fromInt(params[0].getClass(), 1)) >= 0; + return params.length == 1 && FUNCTION_ABS.apply(implementation, params[0]).compareTo(implementation.instanceForString("1")) >= 0; } @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { - NumberInterface[] reciprocalParamArr = {fromInt(params[0].getClass(), 1).divide(params[0])}; + NumberInterface[] reciprocalParamArr = {implementation.instanceForString("1").divide(params[0])}; return functionArcsin.apply(implementation, reciprocalParamArr); } }; @@ -597,13 +593,13 @@ public class StandardPlugin extends Plugin { public final NumberFunction functionArcsec = new NumberFunction() { @Override public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { - return params.length == 1 && FUNCTION_ABS.apply(implementation, params[0]).compareTo(fromInt(params[0].getClass(), 1)) >= 0; + return params.length == 1 && FUNCTION_ABS.apply(implementation, params[0]).compareTo(implementation.instanceForString("1")) >= 0; } @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { - NumberInterface[] reciprocalParamArr = {fromInt(params[0].getClass(), 1).divide(params[0])}; + NumberInterface[] reciprocalParamArr = {implementation.instanceForString("1").divide(params[0])}; return functionArccos.apply(implementation, reciprocalParamArr); } }; @@ -624,18 +620,18 @@ public class StandardPlugin extends Plugin { NumberInterface[] negatedParams = {params[0].negate()}; return applyInternal(implementation, negatedParams).negate(); } - 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)) + if (params[0].compareTo(implementation.instanceForString("1")) > 0) { + NumberInterface[] reciprocalParams = {implementation.instanceForString("1").divide(params[0])}; + return piFor(params[0].getClass()).divide(implementation.instanceForString("2")) .subtract(applyInternal(implementation, reciprocalParams)); } - 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(implementation.instanceForString("1")) == 0) { + return piFor(params[0].getClass()).divide(implementation.instanceForString("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])))}; - return applyInternal(implementation, newParams).divide(fromInt(params[0].getClass(), 2)); + if (params[0].compareTo(implementation.instanceForString(".9")) >= 0) { + NumberInterface[] newParams = {params[0].multiply(implementation.instanceForString("2")) + .divide(implementation.instanceForString("1").subtract(params[0].multiply(params[0])))}; + return applyInternal(implementation, newParams).divide(implementation.instanceForString("2")); } NumberInterface currentPower = params[0], currentTerm = currentPower, sum = currentTerm, maxError = params[0].getMaxError(), multiplier = currentPower.multiply(currentPower).negate(); @@ -643,7 +639,7 @@ public class StandardPlugin extends Plugin { while (FUNCTION_ABS.apply(implementation, currentTerm).compareTo(maxError) > 0) { n += 2; currentPower = currentPower.multiply(multiplier); - currentTerm = currentPower.divide(fromInt(currentPower.getClass(), n)); + currentTerm = currentPower.divide(implementation.instanceForString(Integer.toString( n))); sum = sum.add(currentTerm); } return sum; @@ -661,7 +657,7 @@ public class StandardPlugin extends Plugin { @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { - return piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 2)) + return piFor(params[0].getClass()).divide(implementation.instanceForString("2")) .subtract(functionArctan.apply(implementation, params)); } }; @@ -670,40 +666,25 @@ public class StandardPlugin extends Plugin { super(manager); } - /** - * Returns a partial sum of a series whose terms are given by the nthTermFunction, evaluated at x. - * - * @param x the value at which the series is evaluated. - * @param nthTermFunction the function that returns the nth term of the series, in the format term(x, n). - * @param n the number of terms in the partial sum. - * @return the value of the partial sum that has the same class as x. - */ - private static NumberInterface sumSeries(NumberInterface x, BiFunction nthTermFunction, int n) { - NumberInterface sum = fromInt(x.getClass(), 0); - for (int i = 0; i <= n; i++) { - sum = sum.add(nthTermFunction.apply(i, x)); - } - return sum; - } - /** * A factorial function that uses memoization for each number class; it efficiently * computes factorials of non-negative integers. * - * @param numberClass type of number to return. + * @param implementation type of number to return. * @param n non-negative integer. * @return a number of numClass with value n factorial. */ - public static NumberInterface factorial(Class numberClass, int n) { - if (!FACTORIAL_LISTS.containsKey(numberClass)) { - FACTORIAL_LISTS.put(numberClass, new ArrayList<>()); - FACTORIAL_LISTS.get(numberClass).add(fromInt(numberClass, 1)); - FACTORIAL_LISTS.get(numberClass).add(fromInt(numberClass, 1)); + public static NumberInterface factorial(NumberImplementation implementation, int n) { + + if (!FACTORIAL_LISTS.containsKey(implementation)) { + FACTORIAL_LISTS.put(implementation, new ArrayList<>()); + FACTORIAL_LISTS.get(implementation).add(implementation.instanceForString("1")); + FACTORIAL_LISTS.get(implementation).add(implementation.instanceForString("1")); } - ArrayList list = FACTORIAL_LISTS.get(numberClass); + ArrayList list = FACTORIAL_LISTS.get(implementation); if (n >= list.size()) { while (list.size() < n + 16) { - list.add(list.get(list.size() - 1).multiply(fromInt(numberClass, list.size()))); + list.add(list.get(list.size() - 1).multiply(implementation.instanceForString(Integer.toString( list.size())))); } } return list.get(n); @@ -722,7 +703,7 @@ public class StandardPlugin extends Plugin { do { n += 2; power = power.multiply(multiplier); - currentTerm = power.divide(factorial(x.getClass(), n)); + currentTerm = power.divide(factorial(implementation, n)); sum = sum.add(currentTerm); } while (FUNCTION_ABS.apply(implementation, currentTerm).compareTo(maxError) > 0); return sum; @@ -735,7 +716,7 @@ public class StandardPlugin extends Plugin { * @return theta in [0, 2pi) that differs from phi by a multiple of 2pi. */ private static NumberInterface getSmallAngle(NumberImplementation implementation, NumberInterface phi, NumberInterface pi) { - NumberInterface twoPi = pi.multiply(fromInt(pi.getClass(), 2)); + NumberInterface twoPi = pi.multiply(implementation.instanceForString("2")); NumberInterface theta = FUNCTION_ABS.apply(implementation, phi).subtract(twoPi .multiply(FUNCTION_ABS.apply(implementation, phi).divide(twoPi).floor())); //Now theta is in [0, 2pi). if (phi.signum() < 0) { @@ -744,23 +725,6 @@ public class StandardPlugin extends Plugin { return theta; } - /** - * Returns a number of class numType with value n. - * - * @param numType class of number to return. - * @param n value of returned number. - * @return numClass instance with value n. - */ - private static NumberInterface fromInt(Class numType, int n) { - if (!integerValues.containsKey(numType)) { - integerValues.put(numType, new HashMap<>()); - } - if (!integerValues.get(numType).containsKey(n)) { - integerValues.get(numType).put(n, new NaiveNumber(n).promoteTo(numType)); - } - return integerValues.get(numType).get(n); - } - @Override public void onEnable() { registerNumberImplementation("naive", IMPLEMENTATION_NAIVE); @@ -849,6 +813,6 @@ public class StandardPlugin extends Plugin { @Override public void onDisable() { - + FACTORIAL_LISTS.clear(); } } From 6a65e66935d5839553fc8d22e0aa07655173e33d Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Fri, 1 Sep 2017 18:07:48 -0700 Subject: [PATCH 08/13] Format code. --- .../main/java/org/nwapw/abacus/Abacus.java | 10 +- .../nwapw/abacus/parsing/LexerTokenizer.java | 8 +- .../abacus/parsing/ShuntingYardParser.java | 6 +- .../nwapw/abacus/plugin/PluginManager.java | 2 +- .../nwapw/abacus/plugin/StandardPlugin.java | 151 +++++++++--------- .../org/nwapw/abacus/tree/NumberReducer.java | 23 +-- 6 files changed, 100 insertions(+), 100 deletions(-) diff --git a/core/src/main/java/org/nwapw/abacus/Abacus.java b/core/src/main/java/org/nwapw/abacus/Abacus.java index 22c82f4..c9ecf87 100644 --- a/core/src/main/java/org/nwapw/abacus/Abacus.java +++ b/core/src/main/java/org/nwapw/abacus/Abacus.java @@ -1,9 +1,7 @@ package org.nwapw.abacus; import org.nwapw.abacus.config.Configuration; -import org.nwapw.abacus.number.NaiveNumber; import org.nwapw.abacus.number.NumberInterface; -import org.nwapw.abacus.number.PreciseNumber; import org.nwapw.abacus.number.PromotionManager; import org.nwapw.abacus.parsing.LexerTokenizer; import org.nwapw.abacus.parsing.ShuntingYardParser; @@ -14,8 +12,6 @@ import org.nwapw.abacus.plugin.StandardPlugin; import org.nwapw.abacus.tree.NumberReducer; import org.nwapw.abacus.tree.TreeNode; -import java.math.BigDecimal; - /** * The main calculator class. This is responsible * for piecing together all of the components, allowing @@ -72,6 +68,7 @@ public class Abacus { /** * Gets the promotion manager. + * * @return the promotion manager. */ public PromotionManager getPromotionManager() { @@ -139,12 +136,13 @@ public class Abacus { /** * Gets the number implementation. + * * @return the number implementation to use for creating numbers. */ - public NumberImplementation getNumberImplementation(){ + public NumberImplementation getNumberImplementation() { NumberImplementation selectedImplementation = pluginManager.numberImplementationFor(configuration.getNumberImplementation()); - if(selectedImplementation != null) return selectedImplementation; + if (selectedImplementation != null) return selectedImplementation; return DEFAULT_IMPLEMENTATION; } diff --git a/core/src/main/java/org/nwapw/abacus/parsing/LexerTokenizer.java b/core/src/main/java/org/nwapw/abacus/parsing/LexerTokenizer.java index 2d7b16b..be57744 100644 --- a/core/src/main/java/org/nwapw/abacus/parsing/LexerTokenizer.java +++ b/core/src/main/java/org/nwapw/abacus/parsing/LexerTokenizer.java @@ -50,13 +50,13 @@ public class LexerTokenizer implements Tokenizer>, PluginListen for (String operator : manager.getAllOperators()) { lexer.register(Pattern.sanitize(operator), TokenType.OP); } - for (String operator : manager.getAllTreeValueOperators()){ + for (String operator : manager.getAllTreeValueOperators()) { lexer.register(Pattern.sanitize(operator), TokenType.TREE_VALUE_OP); } for (String function : manager.getAllFunctions()) { lexer.register(Pattern.sanitize(function), TokenType.FUNCTION); } - for (String function : manager.getAllTreeValueFunctions()){ + for (String function : manager.getAllTreeValueFunctions()) { lexer.register(Pattern.sanitize(function), TokenType.TREE_VALUE_FUNCTION); } } @@ -66,13 +66,13 @@ public class LexerTokenizer implements Tokenizer>, PluginListen for (String operator : manager.getAllOperators()) { lexer.unregister(Pattern.sanitize(operator), TokenType.OP); } - for (String operator : manager.getAllTreeValueOperators()){ + for (String operator : manager.getAllTreeValueOperators()) { lexer.unregister(Pattern.sanitize(operator), TokenType.TREE_VALUE_OP); } for (String function : manager.getAllFunctions()) { lexer.unregister(Pattern.sanitize(function), TokenType.FUNCTION); } - for (String function : manager.getAllTreeValueFunctions()){ + for (String function : manager.getAllTreeValueFunctions()) { lexer.unregister(Pattern.sanitize(function), TokenType.TREE_VALUE_FUNCTION); } } 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 7490d96..9d326a8 100644 --- a/core/src/main/java/org/nwapw/abacus/parsing/ShuntingYardParser.java +++ b/core/src/main/java/org/nwapw/abacus/parsing/ShuntingYardParser.java @@ -134,7 +134,7 @@ public class ShuntingYardParser implements Parser>, PluginListe TreeNode right = constructRecursive(matches); TreeNode left = constructRecursive(matches); if (left == null || right == null) return null; - if(matchType == TokenType.OP) { + if (matchType == TokenType.OP) { return new NumberBinaryNode(operator, left, right); } else { return new TreeValueBinaryNode(operator, left, right); @@ -142,7 +142,7 @@ public class ShuntingYardParser implements Parser>, PluginListe } else { TreeNode applyTo = constructRecursive(matches); if (applyTo == null) return null; - if(matchType == TokenType.OP){ + if (matchType == TokenType.OP) { return new NumberUnaryNode(operator, applyTo); } else { return new TreeValueUnaryNode(operator, applyTo); @@ -155,7 +155,7 @@ public class ShuntingYardParser implements Parser>, PluginListe } else if (matchType == TokenType.FUNCTION || matchType == TokenType.TREE_VALUE_FUNCTION) { String functionName = match.getContent(); CallNode node; - if(matchType == TokenType.FUNCTION){ + if (matchType == TokenType.FUNCTION) { node = new FunctionNode(functionName); } else { node = new TreeValueFunctionNode(functionName); 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 73908a4..6dafcda 100644 --- a/core/src/main/java/org/nwapw/abacus/plugin/PluginManager.java +++ b/core/src/main/java/org/nwapw/abacus/plugin/PluginManager.java @@ -241,7 +241,7 @@ public class PluginManager { * @param name the class for which to find the implementation name. * @return the implementation name. */ - public String interfaceImplementationNameFor(Class name){ + public String interfaceImplementationNameFor(Class name) { return interfaceImplementationNames.get(name); } 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 873c45f..c149d4a 100755 --- a/core/src/main/java/org/nwapw/abacus/plugin/StandardPlugin.java +++ b/core/src/main/java/org/nwapw/abacus/plugin/StandardPlugin.java @@ -7,7 +7,6 @@ import org.nwapw.abacus.number.PreciseNumber; import java.util.ArrayList; import java.util.HashMap; -import java.util.function.BiFunction; /** * The plugin providing standard functions such as addition and subtraction to @@ -24,7 +23,7 @@ public class StandardPlugin extends Plugin { return params.length == 2; } - + @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return params[0].add(params[1]); @@ -39,7 +38,7 @@ public class StandardPlugin extends Plugin { return params.length == 2; } - + @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return params[0].subtract(params[1]); @@ -55,7 +54,7 @@ public class StandardPlugin extends Plugin { return params.length == 1; } - + @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return params[0].negate(); @@ -70,7 +69,7 @@ public class StandardPlugin extends Plugin { return params.length == 2; } - + @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return params[0].multiply(params[1]); @@ -90,21 +89,6 @@ public class StandardPlugin extends Plugin { return new NaiveNumber(Math.PI); } }; - /** - * The square root function. - */ - public static final NumberFunction FUNCTION_SQRT = new NumberFunction() { - @Override - public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { - return params.length == 1; - } - - - @Override - public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { - return OP_CARET.apply(implementation, params[0], implementation.instanceForString(".5")); - } - }; /** * The implementation for the infinite-precision BigDecimal. */ @@ -147,10 +131,10 @@ public class StandardPlugin extends Plugin { public static final NumberOperator OP_DIVIDE = new NumberOperator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 1) { @Override public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { - return params.length == 2 && params[1].compareTo(implementation.instanceForString(Integer.toString( 0))) != 0; + return params.length == 2 && params[1].compareTo(implementation.instanceForString(Integer.toString(0))) != 0; } - + @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return params[0].divide(params[1]); @@ -168,7 +152,7 @@ public class StandardPlugin extends Plugin { && params[0].signum() >= 0; } - + @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { if (params[0].signum() == 0) { @@ -199,7 +183,7 @@ public class StandardPlugin extends Plugin { && params[1].fractionalPart().signum() == 0; } - + @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { if (params[0].compareTo(params[1]) < 0 || @@ -230,7 +214,7 @@ public class StandardPlugin extends Plugin { && params[1].fractionalPart().signum() == 0; } - + @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return OP_NPR.apply(implementation, params).divide(OP_FACTORIAL.apply(implementation, params[1])); @@ -245,7 +229,7 @@ public class StandardPlugin extends Plugin { return params.length == 1; } - + @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return params[0].multiply(implementation.instanceForString(Integer.toString(params[0].signum()))); @@ -260,7 +244,7 @@ public class StandardPlugin extends Plugin { return params.length == 1 && params[0].compareTo(implementation.instanceForString("0")) > 0; } - + @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { NumberInterface param = params[0]; @@ -341,12 +325,58 @@ public class StandardPlugin extends Plugin { return params.length == 1; } - + @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return implementation.instanceForString(Long.toString(Math.round(Math.random() * params[0].floor().intValue()))); } }; + /** + * The caret / pow operator, ^ + */ + public static final NumberOperator OP_CARET = new NumberOperator(OperatorAssociativity.RIGHT, OperatorType.BINARY_INFIX, 2) { + @Override + public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { + NumberInterface zero = implementation.instanceForString("0"); + return params.length == 2 + && !(params[0].compareTo(zero) == 0 + && params[1].compareTo(zero) == 0) + && !(params[0].signum() == -1 && params[1].fractionalPart().compareTo(zero) != 0); + } + + + @Override + public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { + NumberInterface zero = implementation.instanceForString("0"); + if (params[0].compareTo(zero) == 0) + return zero; + else if (params[1].compareTo(zero) == 0) + return implementation.instanceForString("1"); + //Detect integer bases: + if (params[0].fractionalPart().compareTo(implementation.instanceForString("0")) == 0 + && FUNCTION_ABS.apply(implementation, params[1]).compareTo(implementation.instanceForString(Integer.toString(Integer.MAX_VALUE))) < 0 + && FUNCTION_ABS.apply(implementation, params[1]).compareTo(implementation.instanceForString("1")) >= 0) { + NumberInterface[] newParams = {params[0], params[1].fractionalPart()}; + return params[0].intPow(params[1].floor().intValue()).multiply(applyInternal(implementation, newParams)); + } + return FUNCTION_EXP.apply(implementation, FUNCTION_LN.apply(implementation, FUNCTION_ABS.apply(implementation, params[0])).multiply(params[1])); + } + }; + /** + * The square root function. + */ + public static final NumberFunction FUNCTION_SQRT = new NumberFunction() { + @Override + public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { + return params.length == 1; + } + + + @Override + public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { + return OP_CARET.apply(implementation, params[0], implementation.instanceForString(".5")); + } + }; private static final HashMap> FACTORIAL_LISTS = new HashMap<>(); /** * The exponential function, exp(1) = e^1 = 2.71... @@ -357,7 +387,7 @@ public class StandardPlugin extends Plugin { return params.length == 1; } - + @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { NumberInterface maxError = params[0].getMaxError(); @@ -386,37 +416,6 @@ public class StandardPlugin extends Plugin { } } }; - /** - * The caret / pow operator, ^ - */ - public static final NumberOperator OP_CARET = new NumberOperator(OperatorAssociativity.RIGHT, OperatorType.BINARY_INFIX, 2) { - @Override - public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) { - NumberInterface zero = implementation.instanceForString("0"); - return params.length == 2 - && !(params[0].compareTo(zero) == 0 - && params[1].compareTo(zero) == 0) - && !(params[0].signum() == -1 && params[1].fractionalPart().compareTo(zero) != 0); - } - - - @Override - public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { - NumberInterface zero = implementation.instanceForString("0"); - if (params[0].compareTo(zero) == 0) - return zero; - else if (params[1].compareTo(zero) == 0) - return implementation.instanceForString("1"); - //Detect integer bases: - if (params[0].fractionalPart().compareTo(implementation.instanceForString("0")) == 0 - && FUNCTION_ABS.apply(implementation, params[1]).compareTo(implementation.instanceForString(Integer.toString(Integer.MAX_VALUE))) < 0 - && FUNCTION_ABS.apply(implementation, params[1]).compareTo(implementation.instanceForString("1")) >= 0) { - NumberInterface[] newParams = {params[0], params[1].fractionalPart()}; - return params[0].intPow(params[1].floor().intValue()).multiply(applyInternal(implementation, newParams)); - } - return FUNCTION_EXP.apply(implementation, FUNCTION_LN.apply(implementation, FUNCTION_ABS.apply(implementation, params[0])).multiply(params[1])); - } - }; /** * The sine function (the argument is interpreted in radians). */ @@ -426,7 +425,7 @@ public class StandardPlugin extends Plugin { return params.length == 1; } - + @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { NumberInterface pi = piFor(params[0].getClass()); @@ -451,7 +450,7 @@ public class StandardPlugin extends Plugin { return params.length == 1; } - + @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return functionSin.apply(implementation, piFor(params[0].getClass()).divide(implementation.instanceForString("2")) @@ -467,7 +466,7 @@ public class StandardPlugin extends Plugin { return params.length == 1; } - + @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return functionSin.apply(implementation, params[0]).divide(functionCos.apply(implementation, params[0])); @@ -482,7 +481,7 @@ public class StandardPlugin extends Plugin { return params.length == 1; } - + @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return implementation.instanceForString("1").divide(functionCos.apply(implementation, params[0])); @@ -497,7 +496,7 @@ public class StandardPlugin extends Plugin { return params.length == 1; } - + @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return implementation.instanceForString("1").divide(functionSin.apply(implementation, params[0])); @@ -512,7 +511,7 @@ public class StandardPlugin extends Plugin { return params.length == 1; } - + @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return functionCos.apply(implementation, params[0]).divide(functionSin.apply(implementation, params[0])); @@ -529,7 +528,7 @@ public class StandardPlugin extends Plugin { && FUNCTION_ABS.apply(implementation, params[0]).compareTo(implementation.instanceForString("1")) <= 0; } - + @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { if (FUNCTION_ABS.apply(implementation, params[0]).compareTo(implementation.instanceForString(".8")) >= 0) { @@ -544,9 +543,9 @@ public class StandardPlugin extends Plugin { while (FUNCTION_ABS.apply(implementation, currentTerm).compareTo(summandBound) > 0) { exponent += 2; power = power.multiply(multiplier); - coefficient = coefficient.multiply(implementation.instanceForString(Integer.toString( exponent - 2))) - .divide(implementation.instanceForString(Integer.toString( exponent - 1))); - currentTerm = power.multiply(coefficient).divide(implementation.instanceForString(Integer.toString( exponent))); + coefficient = coefficient.multiply(implementation.instanceForString(Integer.toString(exponent - 2))) + .divide(implementation.instanceForString(Integer.toString(exponent - 1))); + currentTerm = power.multiply(coefficient).divide(implementation.instanceForString(Integer.toString(exponent))); sum = sum.add(currentTerm); } return sum; @@ -562,7 +561,7 @@ public class StandardPlugin extends Plugin { return params.length == 1 && FUNCTION_ABS.apply(implementation, params[0]).compareTo(implementation.instanceForString("1")) <= 0; } - + @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return piFor(params[0].getClass()).divide(implementation.instanceForString("2")) @@ -579,7 +578,7 @@ public class StandardPlugin extends Plugin { return params.length == 1 && FUNCTION_ABS.apply(implementation, params[0]).compareTo(implementation.instanceForString("1")) >= 0; } - + @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { NumberInterface[] reciprocalParamArr = {implementation.instanceForString("1").divide(params[0])}; @@ -596,7 +595,7 @@ public class StandardPlugin extends Plugin { return params.length == 1 && FUNCTION_ABS.apply(implementation, params[0]).compareTo(implementation.instanceForString("1")) >= 0; } - + @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { NumberInterface[] reciprocalParamArr = {implementation.instanceForString("1").divide(params[0])}; @@ -639,7 +638,7 @@ public class StandardPlugin extends Plugin { while (FUNCTION_ABS.apply(implementation, currentTerm).compareTo(maxError) > 0) { n += 2; currentPower = currentPower.multiply(multiplier); - currentTerm = currentPower.divide(implementation.instanceForString(Integer.toString( n))); + currentTerm = currentPower.divide(implementation.instanceForString(Integer.toString(n))); sum = sum.add(currentTerm); } return sum; @@ -671,7 +670,7 @@ public class StandardPlugin extends Plugin { * computes factorials of non-negative integers. * * @param implementation type of number to return. - * @param n non-negative integer. + * @param n non-negative integer. * @return a number of numClass with value n factorial. */ public static NumberInterface factorial(NumberImplementation implementation, int n) { @@ -684,7 +683,7 @@ public class StandardPlugin extends Plugin { ArrayList list = FACTORIAL_LISTS.get(implementation); if (n >= list.size()) { while (list.size() < n + 16) { - list.add(list.get(list.size() - 1).multiply(implementation.instanceForString(Integer.toString( list.size())))); + list.add(list.get(list.size() - 1).multiply(implementation.instanceForString(Integer.toString(list.size())))); } } return list.get(n); diff --git a/core/src/main/java/org/nwapw/abacus/tree/NumberReducer.java b/core/src/main/java/org/nwapw/abacus/tree/NumberReducer.java index 8d8dbbc..5d497ec 100644 --- a/core/src/main/java/org/nwapw/abacus/tree/NumberReducer.java +++ b/core/src/main/java/org/nwapw/abacus/tree/NumberReducer.java @@ -1,7 +1,10 @@ package org.nwapw.abacus.tree; import org.nwapw.abacus.Abacus; -import org.nwapw.abacus.function.*; +import org.nwapw.abacus.function.NumberFunction; +import org.nwapw.abacus.function.NumberOperator; +import org.nwapw.abacus.function.TreeValueFunction; +import org.nwapw.abacus.function.TreeValueOperator; import org.nwapw.abacus.number.NumberInterface; import org.nwapw.abacus.number.PromotionManager; import org.nwapw.abacus.number.PromotionResult; @@ -31,14 +34,14 @@ public class NumberReducer implements Reducer { PromotionManager manager = abacus.getPromotionManager(); if (node instanceof NumberNode) { return abacus.getNumberImplementation().instanceForString(((NumberNode) node).getNumber()); - } else if(node instanceof VariableNode) { + } else if (node instanceof VariableNode) { return abacus.getNumberImplementation().instanceForString("0"); } else if (node instanceof NumberBinaryNode) { NumberInterface left = (NumberInterface) children[0]; NumberInterface right = (NumberInterface) children[1]; NumberOperator operator = abacus.getPluginManager().operatorFor(((BinaryNode) node).getOperation()); PromotionResult result = manager.promote(left, right); - if(result == null) return null; + if (result == null) return null; return operator.apply(result.getPromotedTo(), result.getItems()); } else if (node instanceof NumberUnaryNode) { NumberInterface child = (NumberInterface) children[0]; @@ -52,29 +55,29 @@ public class NumberReducer implements Reducer { NumberFunction function = abacus.getPluginManager().functionFor(((FunctionNode) node).getCallTo()); if (function == null) return null; PromotionResult result = manager.promote(convertedChildren); - if(result == null) return null; + if (result == null) return null; return function.apply(result.getPromotedTo(), result.getItems()); - } else if (node instanceof TreeValueFunctionNode){ + } else if (node instanceof TreeValueFunctionNode) { CallNode callNode = (CallNode) node; TreeNode[] realChildren = new TreeNode[callNode.getChildren().size()]; - for(int i = 0; i < realChildren.length; i++){ + for (int i = 0; i < realChildren.length; i++) { realChildren[i] = callNode.getChildren().get(i); } TreeValueFunction function = abacus.getPluginManager().treeValueFunctionFor(callNode.getCallTo()); - if(function == null) return null; + if (function == null) return null; return function.applyWithReducer(abacus.getNumberImplementation(), this, realChildren); } else if (node instanceof TreeValueBinaryNode) { BinaryNode binaryNode = (BinaryNode) node; TreeValueOperator operator = abacus.getPluginManager() .treeValueOperatorFor(binaryNode.getOperation()); - if(operator == null) return null; + if (operator == null) return null; return operator.applyWithReducer(abacus.getNumberImplementation(), this, binaryNode.getLeft(), binaryNode.getRight()); - } else if(node instanceof TreeValueUnaryNode) { + } else if (node instanceof TreeValueUnaryNode) { UnaryNode unaryNode = (UnaryNode) node; TreeValueOperator operator = abacus.getPluginManager() .treeValueOperatorFor(unaryNode.getOperation()); - if(operator == null) return null; + if (operator == null) return null; return operator.applyWithReducer(abacus.getNumberImplementation(), this, unaryNode.getApplyTo()); } return null; From ce82fd56ddaee30aa2195f24ef15960446de6bd2 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Fri, 1 Sep 2017 18:11:19 -0700 Subject: [PATCH 09/13] Remove newlines generated by IntelliJ's addition of @Nullable. --- .../nwapw/abacus/plugin/StandardPlugin.java | 25 ------------------- 1 file changed, 25 deletions(-) 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 c149d4a..36ac473 100755 --- a/core/src/main/java/org/nwapw/abacus/plugin/StandardPlugin.java +++ b/core/src/main/java/org/nwapw/abacus/plugin/StandardPlugin.java @@ -23,7 +23,6 @@ public class StandardPlugin extends Plugin { return params.length == 2; } - @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return params[0].add(params[1]); @@ -38,7 +37,6 @@ public class StandardPlugin extends Plugin { return params.length == 2; } - @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return params[0].subtract(params[1]); @@ -54,7 +52,6 @@ public class StandardPlugin extends Plugin { return params.length == 1; } - @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return params[0].negate(); @@ -69,7 +66,6 @@ public class StandardPlugin extends Plugin { return params.length == 2; } - @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return params[0].multiply(params[1]); @@ -134,7 +130,6 @@ public class StandardPlugin extends Plugin { return params.length == 2 && params[1].compareTo(implementation.instanceForString(Integer.toString(0))) != 0; } - @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return params[0].divide(params[1]); @@ -152,7 +147,6 @@ public class StandardPlugin extends Plugin { && params[0].signum() >= 0; } - @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { if (params[0].signum() == 0) { @@ -183,7 +177,6 @@ public class StandardPlugin extends Plugin { && params[1].fractionalPart().signum() == 0; } - @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { if (params[0].compareTo(params[1]) < 0 || @@ -214,7 +207,6 @@ public class StandardPlugin extends Plugin { && params[1].fractionalPart().signum() == 0; } - @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return OP_NPR.apply(implementation, params).divide(OP_FACTORIAL.apply(implementation, params[1])); @@ -229,7 +221,6 @@ public class StandardPlugin extends Plugin { return params.length == 1; } - @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return params[0].multiply(implementation.instanceForString(Integer.toString(params[0].signum()))); @@ -244,7 +235,6 @@ public class StandardPlugin extends Plugin { return params.length == 1 && params[0].compareTo(implementation.instanceForString("0")) > 0; } - @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { NumberInterface param = params[0]; @@ -325,7 +315,6 @@ public class StandardPlugin extends Plugin { return params.length == 1; } - @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return implementation.instanceForString(Long.toString(Math.round(Math.random() * params[0].floor().intValue()))); @@ -344,7 +333,6 @@ public class StandardPlugin extends Plugin { && !(params[0].signum() == -1 && params[1].fractionalPart().compareTo(zero) != 0); } - @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { NumberInterface zero = implementation.instanceForString("0"); @@ -371,7 +359,6 @@ public class StandardPlugin extends Plugin { return params.length == 1; } - @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return OP_CARET.apply(implementation, params[0], implementation.instanceForString(".5")); @@ -387,7 +374,6 @@ public class StandardPlugin extends Plugin { return params.length == 1; } - @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { NumberInterface maxError = params[0].getMaxError(); @@ -425,7 +411,6 @@ public class StandardPlugin extends Plugin { return params.length == 1; } - @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { NumberInterface pi = piFor(params[0].getClass()); @@ -450,7 +435,6 @@ public class StandardPlugin extends Plugin { return params.length == 1; } - @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return functionSin.apply(implementation, piFor(params[0].getClass()).divide(implementation.instanceForString("2")) @@ -466,7 +450,6 @@ public class StandardPlugin extends Plugin { return params.length == 1; } - @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return functionSin.apply(implementation, params[0]).divide(functionCos.apply(implementation, params[0])); @@ -481,7 +464,6 @@ public class StandardPlugin extends Plugin { return params.length == 1; } - @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return implementation.instanceForString("1").divide(functionCos.apply(implementation, params[0])); @@ -496,7 +478,6 @@ public class StandardPlugin extends Plugin { return params.length == 1; } - @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return implementation.instanceForString("1").divide(functionSin.apply(implementation, params[0])); @@ -511,7 +492,6 @@ public class StandardPlugin extends Plugin { return params.length == 1; } - @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return functionCos.apply(implementation, params[0]).divide(functionSin.apply(implementation, params[0])); @@ -528,7 +508,6 @@ public class StandardPlugin extends Plugin { && FUNCTION_ABS.apply(implementation, params[0]).compareTo(implementation.instanceForString("1")) <= 0; } - @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { if (FUNCTION_ABS.apply(implementation, params[0]).compareTo(implementation.instanceForString(".8")) >= 0) { @@ -561,7 +540,6 @@ public class StandardPlugin extends Plugin { return params.length == 1 && FUNCTION_ABS.apply(implementation, params[0]).compareTo(implementation.instanceForString("1")) <= 0; } - @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return piFor(params[0].getClass()).divide(implementation.instanceForString("2")) @@ -578,7 +556,6 @@ public class StandardPlugin extends Plugin { return params.length == 1 && FUNCTION_ABS.apply(implementation, params[0]).compareTo(implementation.instanceForString("1")) >= 0; } - @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { NumberInterface[] reciprocalParamArr = {implementation.instanceForString("1").divide(params[0])}; @@ -595,7 +572,6 @@ public class StandardPlugin extends Plugin { return params.length == 1 && FUNCTION_ABS.apply(implementation, params[0]).compareTo(implementation.instanceForString("1")) >= 0; } - @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { NumberInterface[] reciprocalParamArr = {implementation.instanceForString("1").divide(params[0])}; @@ -612,7 +588,6 @@ public class StandardPlugin extends Plugin { return params.length == 1; } - @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { if (params[0].signum() == -1) { From e62722ce2f1175a5d665bf1df7507509345b1d0e Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Fri, 1 Sep 2017 18:32:41 -0700 Subject: [PATCH 10/13] Add comments. --- .../org/nwapw/abacus/number/NumberUtils.kt | 6 ++++ .../nwapw/abacus/number/PromotionManager.kt | 36 +++++++++++++++++++ .../nwapw/abacus/number/PromotionResult.kt | 6 ++++ 3 files changed, 48 insertions(+) diff --git a/core/src/main/kotlin/org/nwapw/abacus/number/NumberUtils.kt b/core/src/main/kotlin/org/nwapw/abacus/number/NumberUtils.kt index 5503613..03c46fd 100644 --- a/core/src/main/kotlin/org/nwapw/abacus/number/NumberUtils.kt +++ b/core/src/main/kotlin/org/nwapw/abacus/number/NumberUtils.kt @@ -5,6 +5,12 @@ typealias PromotionFunction = java.util.function.Function typealias NumberClass = Class +/** + * Promote a number through this path. The functions in this path + * are applied in order to the number, and the final result is returned. + * + * @param from the number to start from. + */ fun PromotionPath.promote(from: NumberInterface): NumberInterface { return fold(from, { current, function -> function.apply(current) }) } \ No newline at end of file diff --git a/core/src/main/kotlin/org/nwapw/abacus/number/PromotionManager.kt b/core/src/main/kotlin/org/nwapw/abacus/number/PromotionManager.kt index f4bb684..22e9489 100644 --- a/core/src/main/kotlin/org/nwapw/abacus/number/PromotionManager.kt +++ b/core/src/main/kotlin/org/nwapw/abacus/number/PromotionManager.kt @@ -2,12 +2,31 @@ package org.nwapw.abacus.number import org.nwapw.abacus.Abacus import org.nwapw.abacus.plugin.NumberImplementation +import org.nwapw.abacus.plugin.PluginListener +import org.nwapw.abacus.plugin.PluginManager import java.util.function.Function class PromotionManager(val abacus: Abacus) { +/** + * A class that handles promotions based on priority and the + * transition paths each implementation provides. + * + * @property abacus the Abacus instance to use to access other components. + */ +class PromotionManager(val abacus: Abacus) : PluginListener { + /** + * The already computed paths + */ val computePaths = mutableMapOf, PromotionPath?>() + /** + * Computes a path between a starting and an ending implementation. + * + * @param from the implementation to start from. + * @param to the implementation to get to. + * @return the resulting promotion path, or null if it is not found + */ fun computePathBetween(from: NumberImplementation, to: NumberImplementation): PromotionPath? { val fromName = abacus.pluginManager.interfaceImplementationNameFor(from.implementation) val toName = abacus.pluginManager.interfaceImplementationNameFor(to.implementation) @@ -19,12 +38,29 @@ class PromotionManager(val abacus: Abacus) { return null } + /** + * If a path between the given implementations has already been computed, uses + * the already calculated path. Otherwise, calls [computePathBetween] to compute a new + * path. + * + * @param from the implementation to start from. + * @param to the implementation to get to. + * @return the resulting promotion path, or null if it is not found + */ fun getPathBetween(from: NumberImplementation, to: NumberImplementation): PromotionPath? { return computePaths.computeIfAbsent(from to to, { computePathBetween(it.first, it.second) }) } + /** + * Promote all the numbers in the list to the same number implementation, to ensure + * they can be used with each other. Finds the highest priority implementation + * in the list, and promotes all other numbers to it. + * + * @param numbers the numbers to promote. + * @return the resulting promotion result. + */ fun promote(vararg numbers: NumberInterface): PromotionResult? { val pluginManager = abacus.pluginManager val implementations = numbers.map { pluginManager.interfaceImplementationFor(it.javaClass) } diff --git a/core/src/main/kotlin/org/nwapw/abacus/number/PromotionResult.kt b/core/src/main/kotlin/org/nwapw/abacus/number/PromotionResult.kt index 2453105..51623fb 100644 --- a/core/src/main/kotlin/org/nwapw/abacus/number/PromotionResult.kt +++ b/core/src/main/kotlin/org/nwapw/abacus/number/PromotionResult.kt @@ -2,4 +2,10 @@ package org.nwapw.abacus.number import org.nwapw.abacus.plugin.NumberImplementation +/** + * The result of promoting an array of NumberInterfaces. + * + * @param promotedTo the implementation to which the numbers were promoted. + * @param items the items the items resulting from the promotion. + */ data class PromotionResult(val promotedTo: NumberImplementation, val items: Array) \ No newline at end of file From 1f6aa70230871e5b434efec4ce4e917ef75dd99d Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Fri, 1 Sep 2017 18:33:12 -0700 Subject: [PATCH 11/13] Ensure PromotionManager clears its implementation cache. --- core/src/main/java/org/nwapw/abacus/Abacus.java | 1 + .../kotlin/org/nwapw/abacus/number/PromotionManager.kt | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/nwapw/abacus/Abacus.java b/core/src/main/java/org/nwapw/abacus/Abacus.java index c9ecf87..1b1dc49 100644 --- a/core/src/main/java/org/nwapw/abacus/Abacus.java +++ b/core/src/main/java/org/nwapw/abacus/Abacus.java @@ -64,6 +64,7 @@ public class Abacus { pluginManager.addListener(shuntingYardParser); pluginManager.addListener(lexerTokenizer); + pluginManager.addListener(promotionManager); } /** diff --git a/core/src/main/kotlin/org/nwapw/abacus/number/PromotionManager.kt b/core/src/main/kotlin/org/nwapw/abacus/number/PromotionManager.kt index 22e9489..421d642 100644 --- a/core/src/main/kotlin/org/nwapw/abacus/number/PromotionManager.kt +++ b/core/src/main/kotlin/org/nwapw/abacus/number/PromotionManager.kt @@ -6,7 +6,6 @@ import org.nwapw.abacus.plugin.PluginListener import org.nwapw.abacus.plugin.PluginManager import java.util.function.Function -class PromotionManager(val abacus: Abacus) { /** * A class that handles promotions based on priority and the * transition paths each implementation provides. @@ -72,4 +71,13 @@ class PromotionManager(val abacus: Abacus) : PluginListener { }.toTypedArray(), promotedTo = highestPriority) } + override fun onLoad(manager: PluginManager?) { + + } + + override fun onUnload(manager: PluginManager?) { + computePaths.clear() + } + + } \ No newline at end of file From bc4a26aafbe02ac95619d02fe570590c30ce8e26 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Fri, 1 Sep 2017 18:43:07 -0700 Subject: [PATCH 12/13] Fix weird alignment. --- core/src/test/java/org/nwapw/abacus/tests/TokenizerTests.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/test/java/org/nwapw/abacus/tests/TokenizerTests.java b/core/src/test/java/org/nwapw/abacus/tests/TokenizerTests.java index ace0624..660be2f 100644 --- a/core/src/test/java/org/nwapw/abacus/tests/TokenizerTests.java +++ b/core/src/test/java/org/nwapw/abacus/tests/TokenizerTests.java @@ -41,7 +41,7 @@ public class TokenizerTests { return true; } - @Override + @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return subtractFunction.apply(implementation, params); } @@ -54,7 +54,7 @@ public class TokenizerTests { return true; } - @Override + @Override public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) { return subtractFunction.apply(implementation, params); } From 9ddfeb02cf37bbd1b8d6afe53025a3847f90f20e Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Mon, 4 Sep 2017 12:51:53 -0700 Subject: [PATCH 13/13] Fix not clearing an important map during reset. --- core/src/main/java/org/nwapw/abacus/plugin/PluginManager.java | 1 + 1 file changed, 1 insertion(+) 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 6dafcda..0c99c58 100644 --- a/core/src/main/java/org/nwapw/abacus/plugin/PluginManager.java +++ b/core/src/main/java/org/nwapw/abacus/plugin/PluginManager.java @@ -335,6 +335,7 @@ public class PluginManager { registeredTreeValueOperators.clear(); registeredNumberImplementations.clear(); registeredDocumentation.clear(); + interfaceImplementationNames.clear(); interfaceImplementations.clear(); cachedPi.clear(); listeners.forEach(e -> e.onUnload(this));