mirror of
https://github.com/DanilaFe/abacus
synced 2024-12-24 00:10:09 -08:00
Move all functions to a static context, stopping unnecessary lookups.
This commit is contained in:
parent
6b8d8497e2
commit
03eb669eb3
|
@ -16,16 +16,7 @@ import java.util.function.BiFunction;
|
||||||
*/
|
*/
|
||||||
public class StandardPlugin extends Plugin {
|
public class StandardPlugin extends Plugin {
|
||||||
|
|
||||||
public StandardPlugin(PluginManager manager) {
|
public static final Operator OP_ADD = new Operator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 0, new Function() {
|
||||||
super(manager);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onEnable() {
|
|
||||||
registerNumber("naive", NaiveNumber.class);
|
|
||||||
registerNumber("precise", PreciseNumber.class);
|
|
||||||
|
|
||||||
registerOperator("+", new Operator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 0, new Function() {
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean matchesParams(NumberInterface[] params) {
|
protected boolean matchesParams(NumberInterface[] params) {
|
||||||
return params.length >= 1;
|
return params.length >= 1;
|
||||||
|
@ -39,9 +30,8 @@ public class StandardPlugin extends Plugin {
|
||||||
}
|
}
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
}));
|
});
|
||||||
|
public static final Operator OP_SUBTRACT = new Operator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 0, new Function() {
|
||||||
registerOperator("-", new Operator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 0, new Function() {
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean matchesParams(NumberInterface[] params) {
|
protected boolean matchesParams(NumberInterface[] params) {
|
||||||
return params.length == 2;
|
return params.length == 2;
|
||||||
|
@ -51,9 +41,8 @@ public class StandardPlugin extends Plugin {
|
||||||
protected NumberInterface applyInternal(NumberInterface[] params) {
|
protected NumberInterface applyInternal(NumberInterface[] params) {
|
||||||
return params[0].subtract(params[1]);
|
return params[0].subtract(params[1]);
|
||||||
}
|
}
|
||||||
}));
|
});
|
||||||
|
public static final Operator OP_MULTIPLY = new Operator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX,1, new Function() {
|
||||||
registerOperator("*", new Operator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX,1, new Function() {
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean matchesParams(NumberInterface[] params) {
|
protected boolean matchesParams(NumberInterface[] params) {
|
||||||
return params.length >= 1;
|
return params.length >= 1;
|
||||||
|
@ -67,9 +56,23 @@ public class StandardPlugin extends Plugin {
|
||||||
}
|
}
|
||||||
return product;
|
return product;
|
||||||
}
|
}
|
||||||
}));
|
});
|
||||||
|
public static final Operator OP_DIVIDE = new Operator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX,1, new Function() {
|
||||||
|
@Override
|
||||||
|
protected boolean matchesParams(NumberInterface[] params) {
|
||||||
|
return params.length >= 1;
|
||||||
|
}
|
||||||
|
|
||||||
registerOperator("/", new Operator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX,1, new Function() {
|
@Override
|
||||||
|
protected NumberInterface applyInternal(NumberInterface[] params) {
|
||||||
|
NumberInterface product = params[0];
|
||||||
|
for(int i = 1; i < params.length; i++){
|
||||||
|
product = product.multiply(params[i]);
|
||||||
|
}
|
||||||
|
return product;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
public static final Operator OP_CARET = new Operator(OperatorAssociativity.RIGHT, OperatorType.BINARY_INFIX, 2, new Function() {
|
||||||
@Override
|
@Override
|
||||||
protected boolean matchesParams(NumberInterface[] params) {
|
protected boolean matchesParams(NumberInterface[] params) {
|
||||||
return params.length == 2;
|
return params.length == 2;
|
||||||
|
@ -77,23 +80,10 @@ public class StandardPlugin extends Plugin {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected NumberInterface applyInternal(NumberInterface[] params) {
|
protected NumberInterface applyInternal(NumberInterface[] params) {
|
||||||
return params[0].divide(params[1]);
|
return FUNCTION_EXP.apply(FUNCTION_LN.apply(params[0]).multiply(params[1]));
|
||||||
}
|
}
|
||||||
}));
|
});
|
||||||
|
public static final Operator OP_FACTORIAL = new Operator(OperatorAssociativity.RIGHT, OperatorType.UNARY_POSTFIX, 0, new Function() {
|
||||||
registerOperator("^", new Operator(OperatorAssociativity.RIGHT, OperatorType.BINARY_INFIX, 2, new Function() {
|
|
||||||
@Override
|
|
||||||
protected boolean matchesParams(NumberInterface[] params) {
|
|
||||||
return params.length == 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected NumberInterface applyInternal(NumberInterface[] params) {
|
|
||||||
return StandardPlugin.this.getFunction("exp").apply(StandardPlugin.this.getFunction("ln").apply(params[0]).multiply(params[1]));
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
registerOperator("!", new Operator(OperatorAssociativity.RIGHT, OperatorType.UNARY_POSTFIX, 0, new Function() {
|
|
||||||
//private HashMap<Class<? extends NumberInterface>, ArrayList<NumberInterface>> storedList = new HashMap<Class<? extends NumberInterface>, ArrayList<NumberInterface>>();
|
//private HashMap<Class<? extends NumberInterface>, ArrayList<NumberInterface>> storedList = new HashMap<Class<? extends NumberInterface>, ArrayList<NumberInterface>>();
|
||||||
@Override
|
@Override
|
||||||
protected boolean matchesParams(NumberInterface[] params) {
|
protected boolean matchesParams(NumberInterface[] params) {
|
||||||
|
@ -118,9 +108,8 @@ public class StandardPlugin extends Plugin {
|
||||||
storedList.get(params[0].getClass()).add(NaiveNumber.ONE.promoteTo(params[0].getClass()));
|
storedList.get(params[0].getClass()).add(NaiveNumber.ONE.promoteTo(params[0].getClass()));
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
}));
|
});
|
||||||
|
public static final Function FUNCTION_ABS = new Function() {
|
||||||
registerFunction("abs", new Function() {
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean matchesParams(NumberInterface[] params) {
|
protected boolean matchesParams(NumberInterface[] params) {
|
||||||
return params.length == 1;
|
return params.length == 1;
|
||||||
|
@ -130,9 +119,8 @@ public class StandardPlugin extends Plugin {
|
||||||
protected NumberInterface applyInternal(NumberInterface[] params) {
|
protected NumberInterface applyInternal(NumberInterface[] params) {
|
||||||
return params[0].multiply((new NaiveNumber(params[0].signum())).promoteTo(params[0].getClass()));
|
return params[0].multiply((new NaiveNumber(params[0].signum())).promoteTo(params[0].getClass()));
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
public static final Function FUNCTION_EXP = new Function() {
|
||||||
registerFunction("exp", new Function() {
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean matchesParams(NumberInterface[] params) {
|
protected boolean matchesParams(NumberInterface[] params) {
|
||||||
return params.length == 1;
|
return params.length == 1;
|
||||||
|
@ -141,16 +129,15 @@ public class StandardPlugin extends Plugin {
|
||||||
@Override
|
@Override
|
||||||
protected NumberInterface applyInternal(NumberInterface[] params) {
|
protected NumberInterface applyInternal(NumberInterface[] params) {
|
||||||
boolean takeReciprocal = params[0].signum() == -1;
|
boolean takeReciprocal = params[0].signum() == -1;
|
||||||
params[0] = StandardPlugin.this.getFunction("abs").apply(params[0]);
|
params[0] = FUNCTION_ABS.apply(params[0]);
|
||||||
NumberInterface sum = sumSeries(params[0], StandardPlugin.this::getExpSeriesTerm, getNTermsExp(getMaxError(params[0]), params[0]));
|
NumberInterface sum = sumSeries(params[0], StandardPlugin::getExpSeriesTerm, getNTermsExp(getMaxError(params[0]), params[0]));
|
||||||
if(takeReciprocal){
|
if(takeReciprocal){
|
||||||
sum = NaiveNumber.ONE.promoteTo(sum.getClass()).divide(sum);
|
sum = NaiveNumber.ONE.promoteTo(sum.getClass()).divide(sum);
|
||||||
}
|
}
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
public static final Function FUNCTION_LN = new Function() {
|
||||||
registerFunction("ln", new Function() {
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean matchesParams(NumberInterface[] params) {
|
protected boolean matchesParams(NumberInterface[] params) {
|
||||||
return params.length == 1;
|
return params.length == 1;
|
||||||
|
@ -160,7 +147,7 @@ public class StandardPlugin extends Plugin {
|
||||||
protected NumberInterface applyInternal(NumberInterface[] params) {
|
protected NumberInterface applyInternal(NumberInterface[] params) {
|
||||||
NumberInterface param = params[0];
|
NumberInterface param = params[0];
|
||||||
int powersOf2 = 0;
|
int powersOf2 = 0;
|
||||||
while(StandardPlugin.this.getFunction("abs").apply(param.subtract(NaiveNumber.ONE.promoteTo(param.getClass()))).compareTo((new NaiveNumber(0.1)).promoteTo(param.getClass())) >= 0){
|
while(FUNCTION_ABS.apply(param.subtract(NaiveNumber.ONE.promoteTo(param.getClass()))).compareTo((new NaiveNumber(0.1)).promoteTo(param.getClass())) >= 0){
|
||||||
if(param.subtract(NaiveNumber.ONE.promoteTo(param.getClass())).signum() == 1) {
|
if(param.subtract(NaiveNumber.ONE.promoteTo(param.getClass())).signum() == 1) {
|
||||||
param = param.divide(new NaiveNumber(2).promoteTo(param.getClass()));
|
param = param.divide(new NaiveNumber(2).promoteTo(param.getClass()));
|
||||||
powersOf2++;
|
powersOf2++;
|
||||||
|
@ -188,11 +175,11 @@ public class StandardPlugin extends Plugin {
|
||||||
* @return the partial sum.
|
* @return the partial sum.
|
||||||
*/
|
*/
|
||||||
private NumberInterface getLogPartialSum(NumberInterface x){
|
private NumberInterface getLogPartialSum(NumberInterface x){
|
||||||
NumberInterface maxError = StandardPlugin.this.getMaxError(x);
|
NumberInterface maxError = getMaxError(x);
|
||||||
x = x.subtract(NaiveNumber.ONE.promoteTo(x.getClass())); //Terms used are for log(x+1).
|
x = x.subtract(NaiveNumber.ONE.promoteTo(x.getClass())); //Terms used are for log(x+1).
|
||||||
NumberInterface currentTerm = x, sum = x;
|
NumberInterface currentTerm = x, sum = x;
|
||||||
int n = 1;
|
int n = 1;
|
||||||
while(StandardPlugin.this.getFunction("abs").apply(currentTerm).compareTo(maxError) > 0){
|
while(FUNCTION_ABS.apply(currentTerm).compareTo(maxError) > 0){
|
||||||
n++;
|
n++;
|
||||||
currentTerm = currentTerm.multiply(x).multiply((new NaiveNumber(n-1)).promoteTo(x.getClass())).divide((new NaiveNumber(n)).promoteTo(x.getClass())).negate();
|
currentTerm = currentTerm.multiply(x).multiply((new NaiveNumber(n-1)).promoteTo(x.getClass())).divide((new NaiveNumber(n)).promoteTo(x.getClass())).negate();
|
||||||
sum = sum.add(currentTerm);
|
sum = sum.add(currentTerm);
|
||||||
|
@ -206,7 +193,7 @@ public class StandardPlugin extends Plugin {
|
||||||
* @return the value of log(2) with the appropriate precision.
|
* @return the value of log(2) with the appropriate precision.
|
||||||
*/
|
*/
|
||||||
private NumberInterface getLog2(NumberInterface number){
|
private NumberInterface getLog2(NumberInterface number){
|
||||||
NumberInterface maxError = StandardPlugin.this.getMaxError(number);
|
NumberInterface maxError = getMaxError(number);
|
||||||
//NumberInterface errorBound = (new NaiveNumber(1)).promoteTo(number.getClass());
|
//NumberInterface errorBound = (new NaiveNumber(1)).promoteTo(number.getClass());
|
||||||
//We'll use the series \sigma_{n >= 1) ((1/3^n + 1/4^n) * 1/n)
|
//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.
|
//In the following, a=1/3^n, b=1/4^n, c = 1/n.
|
||||||
|
@ -223,9 +210,8 @@ public class StandardPlugin extends Plugin {
|
||||||
}
|
}
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
public static final Function FUNCTION_SQRT = new Function() {
|
||||||
registerFunction("sqrt", new Function() {
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean matchesParams(NumberInterface[] params) {
|
protected boolean matchesParams(NumberInterface[] params) {
|
||||||
return params.length == 1;
|
return params.length == 1;
|
||||||
|
@ -233,9 +219,30 @@ public class StandardPlugin extends Plugin {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected NumberInterface applyInternal(NumberInterface[] params) {
|
protected NumberInterface applyInternal(NumberInterface[] params) {
|
||||||
return StandardPlugin.this.getOperator("^").getFunction().apply(params[0], ((new NaiveNumber(0.5)).promoteTo(params[0].getClass())));
|
return OP_CARET.getFunction().apply(params[0], ((new NaiveNumber(0.5)).promoteTo(params[0].getClass())));
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
|
public StandardPlugin(PluginManager manager) {
|
||||||
|
super(manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnable() {
|
||||||
|
registerNumber("naive", NaiveNumber.class);
|
||||||
|
registerNumber("precise", PreciseNumber.class);
|
||||||
|
|
||||||
|
registerOperator("+", OP_ADD);
|
||||||
|
registerOperator("-", OP_SUBTRACT);
|
||||||
|
registerOperator("*", OP_MULTIPLY);
|
||||||
|
registerOperator("/", OP_DIVIDE);
|
||||||
|
registerOperator("^", OP_CARET);
|
||||||
|
registerOperator("!", OP_FACTORIAL);
|
||||||
|
|
||||||
|
registerFunction("abs", FUNCTION_ABS);
|
||||||
|
registerFunction("exp", FUNCTION_EXP);
|
||||||
|
registerFunction("ln", FUNCTION_LN);
|
||||||
|
registerFunction("sqrt",FUNCTION_SQRT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -249,8 +256,8 @@ public class StandardPlugin extends Plugin {
|
||||||
* @param x the real number at which the series is evaluated.
|
* @param x the real number at which the series is evaluated.
|
||||||
* @return the nth term of the series.
|
* @return the nth term of the series.
|
||||||
*/
|
*/
|
||||||
private NumberInterface getExpSeriesTerm(int n, NumberInterface x){
|
private static NumberInterface getExpSeriesTerm(int n, NumberInterface x){
|
||||||
return x.intPow(n).divide(this.getOperator("!").getFunction().apply((new NaiveNumber(n)).promoteTo(x.getClass())));
|
return x.intPow(n).divide(OP_FACTORIAL.getFunction().apply((new NaiveNumber(n)).promoteTo(x.getClass())));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -260,11 +267,11 @@ public class StandardPlugin extends Plugin {
|
||||||
* @param x where the function is evaluated.
|
* @param x where the function is evaluated.
|
||||||
* @return the number of terms needed to evaluated the exponential function.
|
* @return the number of terms needed to evaluated the exponential function.
|
||||||
*/
|
*/
|
||||||
private int getNTermsExp(NumberInterface maxError, NumberInterface x) {
|
private static int getNTermsExp(NumberInterface maxError, NumberInterface x) {
|
||||||
//We need n such that |x^(n+1)| <= (n+1)! * maxError
|
//We need n such that |x^(n+1)| <= (n+1)! * maxError
|
||||||
//The variables LHS and RHS refer to the above inequality.
|
//The variables LHS and RHS refer to the above inequality.
|
||||||
int n = 0;
|
int n = 0;
|
||||||
x = this.getFunction("abs").apply(x);
|
x = FUNCTION_ABS.apply(x);
|
||||||
NumberInterface LHS = x, RHS = maxError;
|
NumberInterface LHS = x, RHS = maxError;
|
||||||
while (LHS.compareTo(RHS) > 0) {
|
while (LHS.compareTo(RHS) > 0) {
|
||||||
n++;
|
n++;
|
||||||
|
@ -282,7 +289,7 @@ public class StandardPlugin extends Plugin {
|
||||||
* @param n the number of terms in the partial sum.
|
* @param n the number of terms in the partial sum.
|
||||||
* @return the value of the partial sum that has the same class as x.
|
* @return the value of the partial sum that has the same class as x.
|
||||||
*/
|
*/
|
||||||
private NumberInterface sumSeries(NumberInterface x, BiFunction<Integer, NumberInterface, NumberInterface> nthTermFunction, int n){
|
private static NumberInterface sumSeries(NumberInterface x, BiFunction<Integer, NumberInterface, NumberInterface> nthTermFunction, int n){
|
||||||
NumberInterface sum = NaiveNumber.ZERO.promoteTo(x.getClass());
|
NumberInterface sum = NaiveNumber.ZERO.promoteTo(x.getClass());
|
||||||
for(int i = 0; i <= n; i++){
|
for(int i = 0; i <= n; i++){
|
||||||
sum = sum.add(nthTermFunction.apply(i, x));
|
sum = sum.add(nthTermFunction.apply(i, x));
|
||||||
|
@ -295,7 +302,7 @@ public class StandardPlugin extends Plugin {
|
||||||
* @param number Any instance of the NumberInterface in question (should return an appropriate precision).
|
* @param number Any instance of the NumberInterface in question (should return an appropriate precision).
|
||||||
* @return the maximum error.
|
* @return the maximum error.
|
||||||
*/
|
*/
|
||||||
private NumberInterface getMaxError(NumberInterface number){
|
private static NumberInterface getMaxError(NumberInterface number){
|
||||||
return (new NaiveNumber(10)).promoteTo(number.getClass()).intPow(-number.getMaxPrecision());
|
return (new NaiveNumber(10)).promoteTo(number.getClass()).intPow(-number.getMaxPrecision());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user