Format code.

This commit is contained in:
Danila Fedorin 2017-08-14 19:03:52 -07:00
parent d861444d13
commit 205d5dbc77
20 changed files with 261 additions and 259 deletions

View File

@ -3,7 +3,7 @@ subprojects {
apply plugin: 'java'
repositories {
mavenCentral()
mavenCentral()
}
dependencies {

View File

@ -48,7 +48,7 @@ public class Configuration {
*
* @param copyFrom the configuration to copy.
*/
public Configuration(Configuration copyFrom){
public Configuration(Configuration copyFrom) {
copyFrom(copyFrom);
}
@ -106,7 +106,7 @@ public class Configuration {
*
* @return the string that represents this configuration.
*/
public String asTomlString(){
public String asTomlString() {
return TOML_WRITER.write(this);
}

View File

@ -9,7 +9,7 @@ public class ComputationInterruptedException extends RuntimeException {
/**
* Creates a new exception of this type.
*/
public ComputationInterruptedException(){
public ComputationInterruptedException() {
super("Computation interrupted by user.");
}

View File

@ -129,7 +129,7 @@ public class NaiveNumber extends NumberInterface {
}
@Override
public NumberInterface getMaxError(){
public NumberInterface getMaxError() {
return new NaiveNumber(Math.pow(10, -18));
}
}

View File

@ -9,10 +9,11 @@ public abstract class NumberInterface {
* Check if the thread was interrupted and
* throw an exception to end the computation.
*/
private static void checkInterrupted(){
if(Thread.currentThread().isInterrupted())
private static void checkInterrupted() {
if (Thread.currentThread().isInterrupted())
throw new ComputationInterruptedException();
}
/**
* The maximum precision to which this number operates.
*
@ -38,7 +39,7 @@ public abstract class NumberInterface {
* @param multiplier the multiplier
* @return the result of the multiplication.
*/
public final NumberInterface multiply(NumberInterface multiplier){
public final NumberInterface multiply(NumberInterface multiplier) {
checkInterrupted();
return multiplyInternal(multiplier);
}
@ -61,7 +62,7 @@ public abstract class NumberInterface {
* @param divisor the divisor
* @return the result of the division.
*/
public final NumberInterface divide(NumberInterface divisor){
public final NumberInterface divide(NumberInterface divisor) {
checkInterrupted();
return divideInternal(divisor);
}
@ -84,7 +85,7 @@ public abstract class NumberInterface {
* @param summand the summand
* @return the result of the summation.
*/
public final NumberInterface add(NumberInterface summand){
public final NumberInterface add(NumberInterface summand) {
checkInterrupted();
return addInternal(summand);
}
@ -107,7 +108,7 @@ public abstract class NumberInterface {
* @param subtrahend the subtrahend.
* @return the result of the subtraction.
*/
public final NumberInterface subtract(NumberInterface subtrahend){
public final NumberInterface subtract(NumberInterface subtrahend) {
checkInterrupted();
return subtractInternal(subtrahend);
}
@ -129,7 +130,7 @@ public abstract class NumberInterface {
*
* @return the new instance.
*/
public final NumberInterface negate(){
public final NumberInterface negate() {
checkInterrupted();
return negateInternal();
}
@ -150,7 +151,7 @@ public abstract class NumberInterface {
* @param exponent the exponent to which to take the number.
* @return the resulting value.
*/
public final NumberInterface intPow(int exponent){
public final NumberInterface intPow(int exponent) {
checkInterrupted();
return intPowInternal(exponent);
}
@ -184,7 +185,7 @@ public abstract class NumberInterface {
*
* @return the least integer bigger or equal to the number.
*/
public final NumberInterface ceiling(){
public final NumberInterface ceiling() {
checkInterrupted();
return ceilingInternal();
}
@ -203,7 +204,7 @@ public abstract class NumberInterface {
*
* @return the greatest int smaller than or equal to the number.
*/
public final NumberInterface floor(){
public final NumberInterface floor() {
checkInterrupted();
return floorInternal();
}
@ -219,9 +220,10 @@ public abstract class NumberInterface {
* Returns the fractional part of the number, specifically x - floor(x).
* Also, checks if the thread has been interrupted,
* and if so, throws an exception.
*
* @return the fractional part of the number.
*/
public final NumberInterface fractionalPart(){
public final NumberInterface fractionalPart() {
checkInterrupted();
return fractionalPartInternal();
}
@ -260,6 +262,7 @@ public abstract class NumberInterface {
/**
* Returns the smallest error this instance can tolerate depending
* on its precision and value.
*
* @return the smallest error that should be permitted in calculations.
*/
public abstract NumberInterface getMaxError();

View File

@ -35,7 +35,7 @@ public class PreciseNumber extends NumberInterface {
/**
* MathContext that is actually used in calculations.
*/
private static MathContext internalContext = new MathContext(outputContext.getPrecision()+numExtraInternalSigFigs);
private static MathContext internalContext = new MathContext(outputContext.getPrecision() + numExtraInternalSigFigs);
/**
* The value of the PreciseNumber.
@ -129,7 +129,7 @@ public class PreciseNumber extends NumberInterface {
int decimalIndex = str.indexOf('.');
if (decimalIndex != -1) {
NumberInterface floor = new PreciseNumber(str.substring(0, decimalIndex));
if(signum() == -1){
if (signum() == -1) {
floor = floor.subtract(ONE);
}
return floor;
@ -166,7 +166,7 @@ public class PreciseNumber extends NumberInterface {
}
@Override
public NumberInterface getMaxError(){
return new PreciseNumber(value.ulp()).multiplyInternal(TEN.intPowInternal(value.precision()-internalContext.getPrecision()));
public NumberInterface getMaxError() {
return new PreciseNumber(value.ulp()).multiplyInternal(TEN.intPowInternal(value.precision() - internalContext.getPrecision()));
}
}

View File

@ -162,7 +162,7 @@ public class ShuntingYardParser implements Parser<Match<TokenType>>, PluginListe
@Override
public TreeNode constructTree(List<Match<TokenType>> tokens) {
tokens = intoPostfix(new ArrayList<>(tokens));
if(tokens == null) return null;
if (tokens == null) return null;
Collections.reverse(tokens);
TreeNode constructedTree = constructRecursive(tokens);
return tokens.size() == 0 ? constructedTree : null;

View File

@ -6,10 +6,6 @@ import org.nwapw.abacus.function.Function;
import org.nwapw.abacus.function.Operator;
import org.nwapw.abacus.number.NumberInterface;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* A plugin class that can be externally implemented and loaded via the
* plugin manager. Plugins provide functionality to the calculator
@ -99,9 +95,10 @@ public abstract class Plugin {
/**
* To be used in load(). Registers a documentation instance
* used to explain some element of the plugin to the user.
*
* @param documentation the documentation instance.
*/
protected final void registerDocumentation(Documentation documentation){
protected final void registerDocumentation(Documentation documentation) {
manager.registerDocumentation(documentation);
}
@ -148,7 +145,7 @@ public abstract class Plugin {
* @param type the type of documentation to search for.
* @return the found documentation, or null if none was found.
*/
protected final Documentation documentationFor(String name, DocumentationType type){
protected final Documentation documentationFor(String name, DocumentationType type) {
return manager.documentationFor(name, type);
}

View File

@ -8,7 +8,10 @@ import org.nwapw.abacus.function.Operator;
import org.nwapw.abacus.number.NumberInterface;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* A class that controls instances of plugins, allowing for them
@ -79,82 +82,90 @@ public class PluginManager {
/**
* Registers a function under the given name.
* @param name the name of the function.
*
* @param name the name of the function.
* @param function the function to register.
*/
public void registerFunction(String name, Function function){
public void registerFunction(String name, Function function) {
registeredFunctions.put(name, function);
}
/**
* Registers an operator under the given name.
* @param name the name of the operator.
*
* @param name the name of the operator.
* @param operator the operator to register.
*/
public void registerOperator(String name, Operator operator){
public void registerOperator(String name, Operator operator) {
registeredOperators.put(name, operator);
}
/**
* Registers a number implementation under the given name.
* @param name the name of the number implementation.
*
* @param name the name of the number implementation.
* @param implementation the number implementation to register.
*/
public void registerNumberImplementation(String name, NumberImplementation implementation){
public void registerNumberImplementation(String name, NumberImplementation implementation) {
registeredNumberImplementations.put(name, implementation);
}
/**
* Registers the given documentation with the plugin manager,
* making it accessible to the plugin manager etc.
*
* @param documentation the documentation to register.
*/
public void registerDocumentation(Documentation documentation){
public void registerDocumentation(Documentation documentation) {
registeredDocumentation.add(documentation);
}
/**
* Gets the function registered under the given name.
*
* @param name the name of the function.
* @return the function, or null if it was not found.
*/
public Function functionFor(String name){
public Function functionFor(String name) {
return registeredFunctions.get(name);
}
/**
* Gets the operator registered under the given name.
*
* @param name the name of the operator.
* @return the operator, or null if it was not found.
*/
public Operator operatorFor(String name){
public Operator operatorFor(String name) {
return registeredOperators.get(name);
}
/**
* Gets the number implementation registered under the given name.
*
* @param name the name of the number implementation.
* @return the number implementation, or null if it was not found.
*/
public NumberImplementation numberImplementationFor(String name){
public NumberImplementation numberImplementationFor(String name) {
return registeredNumberImplementations.get(name);
}
/**
* Gets the documentation for the given entity of the given type.
*
* @param name the name of the entity to search for.
* @param type the type that this entity is, to filter out similarly named documentation.
* @return the documentation object.
*/
public Documentation documentationFor(String name, DocumentationType type){
public Documentation documentationFor(String name, DocumentationType type) {
Documentation toReturn = null;
for(Documentation entry : registeredDocumentation){
if(entry.getCodeName().equals(name) && entry.getType() == type) {
for (Documentation entry : registeredDocumentation) {
if (entry.getCodeName().equals(name) && entry.getType() == type) {
toReturn = entry;
break;
}
}
if(toReturn == null){
if (toReturn == null) {
toReturn = new Documentation(name, "", "", "", type);
registerDocumentation(toReturn);
}
@ -170,9 +181,9 @@ public class PluginManager {
public NumberImplementation interfaceImplementationFor(Class<? extends NumberInterface> name) {
if (cachedInterfaceImplementations.containsKey(name)) return cachedInterfaceImplementations.get(name);
NumberImplementation toReturn = null;
for(String key : registeredNumberImplementations.keySet()){
for (String key : registeredNumberImplementations.keySet()) {
NumberImplementation implementation = registeredNumberImplementations.get(key);
if(implementation.getImplementation() == name) {
if (implementation.getImplementation() == name) {
toReturn = implementation;
break;
}
@ -226,10 +237,11 @@ public class PluginManager {
/**
* Removes the plugin with the given class from the manager.
*
* @param toRemove the plugin to remove.
*/
public void removeClass(Class<? extends Plugin> toRemove){
if(!loadedPluginClasses.contains(toRemove)) return;
public void removeClass(Class<? extends Plugin> toRemove) {
if (!loadedPluginClasses.contains(toRemove)) return;
plugins.removeIf(plugin -> plugin.getClass() == toRemove);
loadedPluginClasses.remove(toRemove);
}
@ -237,7 +249,7 @@ public class PluginManager {
/**
* Removes all plugins from this plugin manager.
*/
public void removeAll(){
public void removeAll() {
loadedPluginClasses.clear();
plugins.clear();
}

View File

@ -1,19 +1,12 @@
package org.nwapw.abacus.plugin;
import org.nwapw.abacus.function.*;
import org.nwapw.abacus.lexing.pattern.Match;
import org.nwapw.abacus.number.NaiveNumber;
import org.nwapw.abacus.number.NumberInterface;
import org.nwapw.abacus.number.PreciseNumber;
import org.nwapw.abacus.parsing.Parser;
import org.nwapw.abacus.parsing.ShuntingYardParser;
import org.nwapw.abacus.tree.TokenType;
import org.nwapw.abacus.tree.TreeNode;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.function.BiFunction;
/**
@ -22,11 +15,6 @@ import java.util.function.BiFunction;
*/
public class StandardPlugin extends Plugin {
/**
* Stores objects of NumberInterface with integer values for reuse.
*/
private final static HashMap<Class<? extends NumberInterface>, HashMap<Integer, NumberInterface>> integerValues = new HashMap<>();
/**
* The addition operator, +
*/
@ -92,6 +80,75 @@ public class StandardPlugin extends Plugin {
return product;
}
});
/**
* The combination operator.
*/
public static final Operator OP_NCR = new Operator(OperatorAssociativity.RIGHT, OperatorType.BINARY_INFIX, 0, new Function() {
@Override
protected boolean matchesParams(NumberInterface[] params) {
return params.length == 2 && params[0].fractionalPart().signum() == 0
&& params[1].fractionalPart().signum() == 0;
}
@Override
protected NumberInterface applyInternal(NumberInterface[] params) {
return OP_NPR.getFunction().apply(params).divide(OP_FACTORIAL.getFunction().apply(params[1]));
}
});
/**
* The implementation for double-based naive numbers.
*/
public static final NumberImplementation IMPLEMENTATION_NAIVE = new NumberImplementation(NaiveNumber.class, 0) {
@Override
public NumberInterface instanceForString(String string) {
return new NaiveNumber(string);
}
@Override
public NumberInterface instanceForPi() {
return new NaiveNumber(Math.PI);
}
};
/**
* The implementation for the infinite-precision BigDecimal.
*/
public static final NumberImplementation IMPLEMENTATION_PRECISE = new NumberImplementation(PreciseNumber.class, 0) {
@Override
public NumberInterface instanceForString(String string) {
return new PreciseNumber(string);
}
@Override
public NumberInterface instanceForPi() {
NumberInterface C = FUNCTION_SQRT.apply(new PreciseNumber("10005")).multiply(new PreciseNumber("426880"));
NumberInterface M = PreciseNumber.ONE;
NumberInterface L = new PreciseNumber("13591409");
NumberInterface X = M;
NumberInterface sum = L;
int termsNeeded = C.getMaxPrecision() / 13 + 1;
NumberInterface lSummand = new PreciseNumber("545140134");
NumberInterface xMultiplier = new PreciseNumber("262537412")
.multiply(new PreciseNumber("1000000000"))
.add(new PreciseNumber("640768000"))
.negate();
for (int i = 0; i < termsNeeded; i++) {
M = M
.multiply(new PreciseNumber((12 * i + 2) + ""))
.multiply(new PreciseNumber((12 * i + 6) + ""))
.multiply(new PreciseNumber((12 * i + 10) + ""))
.divide(new PreciseNumber(Math.pow(i + 1, 3) + ""));
L = L.add(lSummand);
X = X.multiply(xMultiplier);
sum = sum.add(M.multiply(L).divide(X));
}
return C.divide(sum);
}
};
/**
* Stores objects of NumberInterface with integer values for reuse.
*/
private final static HashMap<Class<? extends NumberInterface>, HashMap<Integer, NumberInterface>> integerValues = new HashMap<>();
/**
* The division operator, /
*/
@ -150,17 +207,17 @@ public class StandardPlugin extends Plugin {
@Override
protected NumberInterface applyInternal(NumberInterface[] params) {
if(params[0].compareTo(params[1]) < 0 ||
if (params[0].compareTo(params[1]) < 0 ||
params[0].signum() < 0 ||
(params[0].signum() == 0 && params[1].signum() != 0)) return fromInt(params[0].getClass(), 0);
NumberInterface total = fromInt(params[0].getClass(), 1);
NumberInterface multiplyBy = params[0];
NumberInterface remainingMultiplications = params[1];
NumberInterface halfway = params[0].divide(fromInt(params[0].getClass(), 2));
if(remainingMultiplications.compareTo(halfway) > 0){
if (remainingMultiplications.compareTo(halfway) > 0) {
remainingMultiplications = params[0].subtract(remainingMultiplications);
}
while(remainingMultiplications.signum() > 0){
while (remainingMultiplications.signum() > 0) {
total = total.multiply(multiplyBy);
remainingMultiplications = remainingMultiplications.subtract(fromInt(params[0].getClass(), 1));
multiplyBy = multiplyBy.subtract(fromInt(params[0].getClass(), 1));
@ -168,21 +225,6 @@ public class StandardPlugin extends Plugin {
return total;
}
});
/**
* The combination operator.
*/
public static final Operator OP_NCR = new Operator(OperatorAssociativity.RIGHT, OperatorType.BINARY_INFIX, 0, new Function() {
@Override
protected boolean matchesParams(NumberInterface[] params) {
return params.length == 2 && params[0].fractionalPart().signum() == 0
&& params[1].fractionalPart().signum() == 0;
}
@Override
protected NumberInterface applyInternal(NumberInterface[] params) {
return OP_NPR.getFunction().apply(params).divide(OP_FACTORIAL.getFunction().apply(params[1]));
}
});
/**
* The absolute value function, abs(-3) = 3
*/
@ -277,20 +319,6 @@ public class StandardPlugin extends Plugin {
return sum;
}
};
/**
* The square root function.
*/
public static final Function FUNCTION_SQRT = new Function() {
@Override
protected boolean matchesParams(NumberInterface[] params) {
return params.length == 1;
}
@Override
protected NumberInterface applyInternal(NumberInterface[] params) {
return OP_CARET.getFunction().apply(params[0], ((new NaiveNumber(0.5)).promoteTo(params[0].getClass())));
}
};
/**
* Gets a random number smaller or equal to the given number's integer value.
*/
@ -305,94 +333,6 @@ public class StandardPlugin extends Plugin {
return fromInt(params[0].getClass(), (int) Math.round(Math.random() * params[0].floor().intValue()));
}
};
/**
* The implementation for double-based naive numbers.
*/
public static final NumberImplementation IMPLEMENTATION_NAIVE = new NumberImplementation(NaiveNumber.class, 0) {
@Override
public NumberInterface instanceForString(String string) {
return new NaiveNumber(string);
}
@Override
public NumberInterface instanceForPi() {
return new NaiveNumber(Math.PI);
}
};
/**
* The implementation for the infinite-precision BigDecimal.
*/
public static final NumberImplementation IMPLEMENTATION_PRECISE = new NumberImplementation(PreciseNumber.class, 0) {
@Override
public NumberInterface instanceForString(String string) {
return new PreciseNumber(string);
}
@Override
public NumberInterface instanceForPi() {
NumberInterface C = FUNCTION_SQRT.apply(new PreciseNumber("10005")).multiply(new PreciseNumber("426880"));
NumberInterface M = PreciseNumber.ONE;
NumberInterface L = new PreciseNumber("13591409");
NumberInterface X = M;
NumberInterface sum = L;
int termsNeeded = C.getMaxPrecision() / 13 + 1;
NumberInterface lSummand = new PreciseNumber("545140134");
NumberInterface xMultiplier = new PreciseNumber("262537412")
.multiply(new PreciseNumber("1000000000"))
.add(new PreciseNumber("640768000"))
.negate();
for (int i = 0; i < termsNeeded; i++) {
M = M
.multiply(new PreciseNumber((12 * i + 2) + ""))
.multiply(new PreciseNumber((12 * i + 6) + ""))
.multiply(new PreciseNumber((12 * i + 10) + ""))
.divide(new PreciseNumber(Math.pow(i + 1, 3) + ""));
L = L.add(lSummand);
X = X.multiply(xMultiplier);
sum = sum.add(M.multiply(L).divide(X));
}
return C.divide(sum);
}
};
private static final HashMap<Class<? extends NumberInterface>, ArrayList<NumberInterface>> FACTORIAL_LISTS = new HashMap<>();
/**
* The exponential function, exp(1) = e^1 = 2.71...
*/
public static final Function FUNCTION_EXP = new Function() {
@Override
protected boolean matchesParams(NumberInterface[] params) {
return params.length == 1;
}
@Override
protected NumberInterface applyInternal(NumberInterface[] params) {
NumberInterface maxError = params[0].getMaxError();
int n = 0;
if (params[0].signum() < 0) {
NumberInterface[] negatedParams = {params[0].negate()};
return fromInt(params[0].getClass(), 1).divide(applyInternal(negatedParams));
} else {
//We need n such that x^(n+1) * 3^ceil(x) <= maxError * (n+1)!.
//right and left refer to lhs and rhs in the above inequality.
NumberInterface sum = fromInt(params[0].getClass(), 1);
NumberInterface nextNumerator = params[0];
NumberInterface left = params[0].multiply(fromInt(params[0].getClass(), 3).intPow(params[0].ceiling().intValue())), right = maxError;
do {
sum = sum.add(nextNumerator.divide(factorial(params[0].getClass(), n + 1)));
n++;
nextNumerator = nextNumerator.multiply(params[0]);
left = left.multiply(params[0]);
NumberInterface nextN = fromInt(params[0].getClass(), n + 1);
right = right.multiply(nextN);
//System.out.println(left + ", " + right);
}
while (left.compareTo(right) > 0);
//System.out.println(n+1);
return sum;
}
}
};
/**
* The caret / pow operator, ^
*/
@ -414,15 +354,67 @@ public class StandardPlugin extends Plugin {
else if (params[1].compareTo(zero) == 0)
return fromInt(params[0].getClass(), 1);
//Detect integer bases:
if(params[0].fractionalPart().compareTo(fromInt(params[0].getClass(), 0)) == 0
if (params[0].fractionalPart().compareTo(fromInt(params[0].getClass(), 0)) == 0
&& FUNCTION_ABS.apply(params[1]).compareTo(fromInt(params[0].getClass(), Integer.MAX_VALUE)) < 0
&& FUNCTION_ABS.apply(params[1]).compareTo(fromInt(params[1].getClass(), 1)) >= 0){
&& FUNCTION_ABS.apply(params[1]).compareTo(fromInt(params[1].getClass(), 1)) >= 0) {
NumberInterface[] newParams = {params[0], params[1].fractionalPart()};
return params[0].intPow(params[1].floor().intValue()).multiply(applyInternal(newParams));
}
return FUNCTION_EXP.apply(FUNCTION_LN.apply(FUNCTION_ABS.apply(params[0])).multiply(params[1]));
}
});
/**
* The square root function.
*/
public static final Function FUNCTION_SQRT = new Function() {
@Override
protected boolean matchesParams(NumberInterface[] params) {
return params.length == 1;
}
@Override
protected NumberInterface applyInternal(NumberInterface[] params) {
return OP_CARET.getFunction().apply(params[0], ((new NaiveNumber(0.5)).promoteTo(params[0].getClass())));
}
};
private static final HashMap<Class<? extends NumberInterface>, ArrayList<NumberInterface>> FACTORIAL_LISTS = new HashMap<>();
/**
* The exponential function, exp(1) = e^1 = 2.71...
*/
public static final Function FUNCTION_EXP = new Function() {
@Override
protected boolean matchesParams(NumberInterface[] params) {
return params.length == 1;
}
@Override
protected NumberInterface applyInternal(NumberInterface[] params) {
NumberInterface maxError = params[0].getMaxError();
int n = 0;
if (params[0].signum() < 0) {
NumberInterface[] negatedParams = {params[0].negate()};
return fromInt(params[0].getClass(), 1).divide(applyInternal(negatedParams));
} else {
//We need n such that x^(n+1) * 3^ceil(x) <= maxError * (n+1)!.
//right and left refer to lhs and rhs in the above inequality.
NumberInterface sum = fromInt(params[0].getClass(), 1);
NumberInterface nextNumerator = params[0];
NumberInterface left = params[0].multiply(fromInt(params[0].getClass(), 3).intPow(params[0].ceiling().intValue())), right = maxError;
do {
sum = sum.add(nextNumerator.divide(factorial(params[0].getClass(), n + 1)));
n++;
nextNumerator = nextNumerator.multiply(params[0]);
left = left.multiply(params[0]);
NumberInterface nextN = fromInt(params[0].getClass(), n + 1);
right = right.multiply(nextN);
//System.out.println(left + ", " + right);
}
while (left.compareTo(right) > 0);
//System.out.println(n+1);
return sum;
}
}
};
/**
* The sine function (the argument is interpreted in radians).
*/
@ -531,7 +523,7 @@ public class StandardPlugin extends Plugin {
@Override
protected NumberInterface applyInternal(NumberInterface[] params) {
if(FUNCTION_ABS.apply(params[0]).compareTo(new NaiveNumber(0.8).promoteTo(params[0].getClass())) >= 0){
if (FUNCTION_ABS.apply(params[0]).compareTo(new NaiveNumber(0.8).promoteTo(params[0].getClass())) >= 0) {
NumberInterface[] newParams = {FUNCTION_SQRT.apply(fromInt(params[0].getClass(), 1).subtract(params[0].multiply(params[0])))};
return piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 2))
.subtract(applyInternal(newParams)).multiply(fromInt(params[0].getClass(), params[0].signum()));
@ -540,10 +532,10 @@ public class StandardPlugin extends Plugin {
multiplier = currentTerm.multiply(currentTerm), summandBound = sum.getMaxError().multiply(fromInt(sum.getClass(), 1).subtract(multiplier)),
power = currentTerm, coefficient = fromInt(params[0].getClass(), 1);
int exponent = 1;
while(FUNCTION_ABS.apply(currentTerm).compareTo(summandBound) > 0){
while (FUNCTION_ABS.apply(currentTerm).compareTo(summandBound) > 0) {
exponent += 2;
power = power.multiply(multiplier);
coefficient = coefficient.multiply(fromInt(params[0].getClass(), exponent-2))
coefficient = coefficient.multiply(fromInt(params[0].getClass(), exponent - 2))
.divide(fromInt(params[0].getClass(), exponent - 1));
currentTerm = power.multiply(coefficient).divide(fromInt(power.getClass(), exponent));
sum = sum.add(currentTerm);
@ -611,27 +603,27 @@ public class StandardPlugin extends Plugin {
@Override
protected NumberInterface applyInternal(NumberInterface[] params) {
if(params[0].signum() == -1){
if (params[0].signum() == -1) {
NumberInterface[] negatedParams = {params[0].negate()};
return applyInternal(negatedParams).negate();
}
if(params[0].compareTo(fromInt(params[0].getClass(), 1)) > 0){
if (params[0].compareTo(fromInt(params[0].getClass(), 1)) > 0) {
NumberInterface[] reciprocalParams = {fromInt(params[0].getClass(), 1).divide(params[0])};
return piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 2))
.subtract(applyInternal(reciprocalParams));
}
if(params[0].compareTo(fromInt(params[0].getClass(), 1)) == 0){
if (params[0].compareTo(fromInt(params[0].getClass(), 1)) == 0) {
return piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 4));
}
if(params[0].compareTo(new NaiveNumber(0.9).promoteTo(params[0].getClass())) >= 0){
NumberInterface[] newParams = {params[0].multiply(fromInt(params[0].getClass(),2 ))
.divide(fromInt(params[0].getClass(), 1).subtract(params[0].multiply(params[0])))};
if (params[0].compareTo(new NaiveNumber(0.9).promoteTo(params[0].getClass())) >= 0) {
NumberInterface[] newParams = {params[0].multiply(fromInt(params[0].getClass(), 2))
.divide(fromInt(params[0].getClass(), 1).subtract(params[0].multiply(params[0])))};
return applyInternal(newParams).divide(fromInt(params[0].getClass(), 2));
}
NumberInterface currentPower = params[0], currentTerm = currentPower, sum = currentTerm,
maxError = params[0].getMaxError(), multiplier = currentPower.multiply(currentPower).negate();
int n = 1;
while(FUNCTION_ABS.apply(currentTerm).compareTo(maxError) > 0){
while (FUNCTION_ABS.apply(currentTerm).compareTo(maxError) > 0) {
n += 2;
currentPower = currentPower.multiply(multiplier);
currentTerm = currentPower.divide(fromInt(currentPower.getClass(), n));
@ -737,15 +729,16 @@ public class StandardPlugin extends Plugin {
/**
* Returns a number of class numType with value n.
*
* @param numType class of number to return.
* @param n value of returned number.
* @param n value of returned number.
* @return numClass instance with value n.
*/
private static NumberInterface fromInt(Class<? extends NumberInterface> numType, int n){
if(!integerValues.containsKey(numType)){
private static NumberInterface fromInt(Class<? extends NumberInterface> numType, int n) {
if (!integerValues.containsKey(numType)) {
integerValues.put(numType, new HashMap<>());
}
if(!integerValues.get(numType).containsKey(n)){
if (!integerValues.get(numType).containsKey(n)) {
integerValues.get(numType).put(n, new NaiveNumber(n).promoteTo(numType));
}
return integerValues.get(numType).get(n);

View File

@ -36,7 +36,7 @@ data class FunctionNode(val function: String) : TreeNode() {
*
* @node the node to append.
*/
fun appendChild(node: TreeNode){
fun appendChild(node: TreeNode) {
children.add(node)
}
@ -45,7 +45,7 @@ data class FunctionNode(val function: String) : TreeNode() {
*
* @node the node to prepend.
*/
fun prependChild(node: TreeNode){
fun prependChild(node: TreeNode) {
children.add(0, node)
}

View File

@ -6,7 +6,7 @@ package org.nwapw.abacus.tree
* The reducer walks the tree, visiting the children first, converting them into
* a value, and then attempts to reduce the parent. Eventually, the single final value is returned.
*/
interface Reducer <out T> {
interface Reducer<out T> {
/**
* Reduces the given tree node, given its already reduced children.
@ -14,6 +14,6 @@ interface Reducer <out T> {
* @param treeNode the tree node to reduce.
* @param children the list of children, of type T.
*/
fun reduceNode(treeNode: TreeNode, vararg children: Any) : T?
fun reduceNode(treeNode: TreeNode, vararg children: Any): T?
}

View File

@ -5,6 +5,6 @@ package org.nwapw.abacus.tree
*/
abstract class TreeNode {
abstract fun <T: Any> reduce(reducer: Reducer<T>) : T?
abstract fun <T : Any> reduce(reducer: Reducer<T>): T?
}

View File

@ -14,12 +14,12 @@ public class CalculationTests {
private static Abacus abacus = new Abacus(new Configuration(0, "precise", new String[]{}));
@BeforeClass
public static void prepareTests(){
public static void prepareTests() {
abacus.getPluginManager().addInstantiated(new StandardPlugin(abacus.getPluginManager()));
abacus.getPluginManager().load();
}
private void testOutput(String input, String parseOutput, String output){
private void testOutput(String input, String parseOutput, String output) {
TreeNode parsedTree = abacus.parseString(input);
Assert.assertNotNull(parsedTree);
Assert.assertEquals(parsedTree.toString(), parseOutput);
@ -28,7 +28,7 @@ public class CalculationTests {
Assert.assertTrue(result.toString().startsWith(output));
}
private void testEvalError(String input, String parseOutput){
private void testEvalError(String input, String parseOutput) {
TreeNode parsedTree = abacus.parseString(input);
Assert.assertNotNull(parsedTree);
Assert.assertEquals(parsedTree.toString(), parseOutput);
@ -36,56 +36,56 @@ public class CalculationTests {
}
@Test
public void testAddition(){
public void testAddition() {
testOutput("9.5+10", "(9.5+10)", "19.5");
}
@Test
public void testSubtraction(){
public void testSubtraction() {
testOutput("9.5-10", "(9.5-10)", "-0.5");
}
@Test
public void testMultiplication(){
public void testMultiplication() {
testOutput("9.5*10", "(9.5*10)", "95");
}
@Test
public void testDivision(){
public void testDivision() {
testOutput("9.5/2", "(9.5/2)", "4.75");
}
@Test
public void testNegation(){
public void testNegation() {
testOutput("-9.5", "(9.5)`", "-9.5");
}
@Test
public void testFactorial(){
public void testFactorial() {
testOutput("7!", "(7)!", "5040");
}
@Test
public void testAbs(){
public void testAbs() {
testOutput("abs(-1)", "abs((1)`)", "1");
testOutput("abs(1)", "abs(1)", "1");
}
@Test
public void testLn(){
public void testLn() {
testEvalError("ln(-1)", "ln((1)`)");
testOutput("ln2", "ln(2)", "0.6931471805599453094172321214581765680755");
}
@Test
public void testSqrt(){
public void testSqrt() {
testOutput("sqrt0", "sqrt(0)", "0");
testOutput("sqrt4", "sqrt(4)", "2");
testOutput("sqrt2", "sqrt(2)", "1.4142135623730950488016887242096980785696");
}
@Test
public void testExp(){
public void testExp() {
testOutput("exp0", "exp(0)", "1");
testOutput("exp1", "exp(1)", "2.718281828459045235360287471352662497757247");
testOutput("exp300", "exp(300)", "1.9424263952412559365842088360176992193662086");
@ -93,7 +93,7 @@ public class CalculationTests {
}
@Test
public void testPow(){
public void testPow() {
testOutput("0^2", "(0^2)", "0");
testOutput("2^0", "(2^0)", "1");
testOutput("2^1", "(2^1)", "2");

View File

@ -1,10 +1,10 @@
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.1.3'
id 'org.jetbrains.kotlin.jvm' version '1.1.3'
}
apply plugin: 'application'
dependencies {
compile project(':core')
compile project(':core')
}
mainClassName = 'org.nwapw.abacus.fx.AbacusApplication'

View File

@ -17,6 +17,10 @@ public class AbacusApplication extends Application {
*/
private AbacusController controller;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/abacus.fxml"));
@ -34,8 +38,4 @@ public class AbacusApplication extends Application {
controller.performStop();
}
public static void main(String[] args){
launch(args);
}
}

View File

@ -1,13 +1,10 @@
package org.nwapw.abacus.fx;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.scene.control.cell.CheckBoxListCell;
import javafx.scene.text.Text;
@ -136,36 +133,12 @@ public class AbacusController implements PluginListener {
* The abacus instance used for changing the plugin configuration.
*/
private Abacus abacus;
/**
* Boolean which represents whether changes were made to the configuration.
*/
private boolean changesMade;
/**
* Whether an alert about changes to the configuration was already shown.
*/
private boolean reloadAlertShown;
/**
* The alert shown when a press to "apply" is needed.
*/
private Alert reloadAlert;
/**
* The runnable that takes care of killing computations that take too long.
*/
private final Runnable TIMER_RUNNABLE = () -> {
try {
Configuration abacusConfig = abacus.getConfiguration();
if(abacusConfig.getComputationDelay() == 0) return;
Thread.sleep((long) (abacusConfig.getComputationDelay() * 1000));
performStop();
} catch (InterruptedException e) { }
};
/**
* The runnable used to perform the calculation.
*/
private final Runnable CALCULATION_RUNNABLE = new Runnable() {
private String attemptCalculation(){
private String attemptCalculation() {
try {
TreeNode constructedTree = abacus.parseString(inputField.getText());
if (constructedTree == null) {
@ -180,7 +153,7 @@ public class AbacusController implements PluginListener {
return resultingString;
} catch (ComputationInterruptedException exception) {
return ERR_STOP;
} catch (RuntimeException exception){
} catch (RuntimeException exception) {
exception.printStackTrace();
return ERR_EXCEPTION;
}
@ -197,6 +170,18 @@ public class AbacusController implements PluginListener {
});
}
};
/**
* Boolean which represents whether changes were made to the configuration.
*/
private boolean changesMade;
/**
* Whether an alert about changes to the configuration was already shown.
*/
private boolean reloadAlertShown;
/**
* The alert shown when a press to "apply" is needed.
*/
private Alert reloadAlert;
/**
* The thread that is waiting to pause the calculation.
*/
@ -205,6 +190,18 @@ public class AbacusController implements PluginListener {
* The thread in which the computation runs.
*/
private Thread calculationThread;
/**
* The runnable that takes care of killing computations that take too long.
*/
private final Runnable TIMER_RUNNABLE = () -> {
try {
Configuration abacusConfig = abacus.getConfiguration();
if (abacusConfig.getComputationDelay() == 0) return;
Thread.sleep((long) (abacusConfig.getComputationDelay() * 1000));
performStop();
} catch (InterruptedException e) {
}
};
/**
* Alerts the user if the changes they made
@ -265,7 +262,7 @@ public class AbacusController implements PluginListener {
computationLimitField.setText(Double.toString(abacus.getConfiguration().getComputationDelay()));
computationLimitField.textProperty().addListener((observable, oldValue, newValue) -> {
if(!newValue.matches("(\\d+(\\.\\d*)?)?")) {
if (!newValue.matches("(\\d+(\\.\\d*)?)?")) {
computationLimitField.setText(oldValue);
} else {
changesMade = true;
@ -292,12 +289,12 @@ public class AbacusController implements PluginListener {
}
@FXML
public void performStop(){
if(calculationThread != null) {
public void performStop() {
if (calculationThread != null) {
calculationThread.interrupt();
calculationThread = null;
}
if(computationLimitThread != null){
if (computationLimitThread != null) {
computationLimitThread.interrupt();
computationLimitThread = null;
}
@ -312,7 +309,7 @@ public class AbacusController implements PluginListener {
}
@FXML
public void performScan(){
public void performScan() {
PluginManager abacusPluginManager = abacus.getPluginManager();
abacusPluginManager.removeAll();
abacusPluginManager.addInstantiated(new StandardPlugin(abacus.getPluginManager()));
@ -339,7 +336,7 @@ public class AbacusController implements PluginListener {
for (ToggleablePlugin pluginEntry : enabledPlugins) {
if (!pluginEntry.isEnabled()) disabledPlugins.add(pluginEntry.getClassName());
}
if(computationLimitField.getText().matches("\\d*(\\.\\d+)?") && computationLimitField.getText().length() != 0)
if (computationLimitField.getText().matches("\\d*(\\.\\d+)?") && computationLimitField.getText().length() != 0)
configuration.setComputationDelay(Double.parseDouble(computationLimitField.getText()));
configuration.saveTo(CONFIG_FILE);
changesMade = false;

View File

@ -14,7 +14,7 @@ public class DocumentationCell extends ListCell<Documentation> {
private Label longDescription;
private TitledPane titledPane;
public DocumentationCell(){
public DocumentationCell() {
VBox vbox = new VBox();
vbox.setSpacing(10);
titledPane = new TitledPane();
@ -41,7 +41,7 @@ public class DocumentationCell extends ListCell<Documentation> {
@Override
protected void updateItem(Documentation item, boolean empty) {
super.updateItem(item, empty);
if(empty){
if (empty) {
codeNameLabel.setText("");
nameLabel.setText("");
description.setText("");

View File

@ -14,7 +14,7 @@ import javafx.beans.property.SimpleStringProperty
* @param parsed the parsed version of the input.
* @param output the output string.
*/
class HistoryModel(input: String, parsed: String, output: String){
class HistoryModel(input: String, parsed: String, output: String) {
/**
* The property that holds the input.

View File

@ -12,7 +12,7 @@ import javafx.beans.property.SimpleBooleanProperty
* @param className the name of the class that this model concerns.
* @param enabled whether or not the model should start enabled.
*/
class ToggleablePlugin (val className: String, enabled: Boolean) {
class ToggleablePlugin(val className: String, enabled: Boolean) {
/**
* The property used to interact with JavaFX components.