mirror of
				https://github.com/DanilaFe/abacus
				synced 2025-10-31 09:53:42 -07: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 StandardPlugin(PluginManager manager) { | ||||
|         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() { | ||||
|     public static final Operator OP_ADD = new Operator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 0, new Function() { | ||||
|         @Override | ||||
|         protected boolean matchesParams(NumberInterface[] params) { | ||||
|             return params.length >= 1; | ||||
| @ -39,9 +30,8 @@ public class StandardPlugin extends Plugin { | ||||
|             } | ||||
|             return sum; | ||||
|         } | ||||
|         })); | ||||
| 
 | ||||
|         registerOperator("-", new Operator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 0, new Function() { | ||||
|     }); | ||||
|     public static final Operator OP_SUBTRACT = new Operator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 0, new Function() { | ||||
|         @Override | ||||
|         protected boolean matchesParams(NumberInterface[] params) { | ||||
|             return params.length == 2; | ||||
| @ -51,9 +41,8 @@ public class StandardPlugin extends Plugin { | ||||
|         protected NumberInterface applyInternal(NumberInterface[] params) { | ||||
|             return params[0].subtract(params[1]); | ||||
|         } | ||||
|         })); | ||||
| 
 | ||||
|         registerOperator("*", new Operator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX,1, new Function() { | ||||
|     }); | ||||
|     public static final Operator OP_MULTIPLY = new Operator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX,1, new Function() { | ||||
|         @Override | ||||
|         protected boolean matchesParams(NumberInterface[] params) { | ||||
|             return params.length >= 1; | ||||
| @ -67,9 +56,23 @@ public class StandardPlugin extends Plugin { | ||||
|             } | ||||
|             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 | ||||
|         protected boolean matchesParams(NumberInterface[] params) { | ||||
|             return params.length == 2; | ||||
| @ -77,23 +80,10 @@ public class StandardPlugin extends Plugin { | ||||
| 
 | ||||
|         @Override | ||||
|         protected NumberInterface applyInternal(NumberInterface[] params) { | ||||
|                 return params[0].divide(params[1]); | ||||
|             return FUNCTION_EXP.apply(FUNCTION_LN.apply(params[0]).multiply(params[1])); | ||||
|         } | ||||
|         })); | ||||
| 
 | ||||
|         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() { | ||||
|     }); | ||||
|     public static final Operator OP_FACTORIAL = 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>>(); | ||||
|         @Override | ||||
|         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())); | ||||
|                 }*/ | ||||
|         } | ||||
|         })); | ||||
| 
 | ||||
|         registerFunction("abs", new Function() { | ||||
|     }); | ||||
|     public static final Function FUNCTION_ABS = new Function() { | ||||
|         @Override | ||||
|         protected boolean matchesParams(NumberInterface[] params) { | ||||
|             return params.length == 1; | ||||
| @ -130,9 +119,8 @@ public class StandardPlugin extends Plugin { | ||||
|         protected NumberInterface applyInternal(NumberInterface[] params) { | ||||
|             return params[0].multiply((new NaiveNumber(params[0].signum())).promoteTo(params[0].getClass())); | ||||
|         } | ||||
|         }); | ||||
| 
 | ||||
|         registerFunction("exp", new Function() { | ||||
|     }; | ||||
|     public static final Function FUNCTION_EXP = new Function() { | ||||
|         @Override | ||||
|         protected boolean matchesParams(NumberInterface[] params) { | ||||
|             return params.length == 1; | ||||
| @ -141,16 +129,15 @@ public class StandardPlugin extends Plugin { | ||||
|         @Override | ||||
|         protected NumberInterface applyInternal(NumberInterface[] params) { | ||||
|             boolean takeReciprocal = params[0].signum() == -1; | ||||
|                 params[0] = StandardPlugin.this.getFunction("abs").apply(params[0]); | ||||
|                 NumberInterface sum = sumSeries(params[0], StandardPlugin.this::getExpSeriesTerm, getNTermsExp(getMaxError(params[0]), params[0])); | ||||
|             params[0] = FUNCTION_ABS.apply(params[0]); | ||||
|             NumberInterface sum = sumSeries(params[0], StandardPlugin::getExpSeriesTerm, getNTermsExp(getMaxError(params[0]), params[0])); | ||||
|             if(takeReciprocal){ | ||||
|                 sum = NaiveNumber.ONE.promoteTo(sum.getClass()).divide(sum); | ||||
|             } | ||||
|             return sum; | ||||
|         } | ||||
|         }); | ||||
| 
 | ||||
|         registerFunction("ln", new Function() { | ||||
|     }; | ||||
|     public static final Function FUNCTION_LN = new Function() { | ||||
|         @Override | ||||
|         protected boolean matchesParams(NumberInterface[] params) { | ||||
|             return params.length == 1; | ||||
| @ -160,7 +147,7 @@ public class StandardPlugin extends Plugin { | ||||
|         protected NumberInterface applyInternal(NumberInterface[] params) { | ||||
|             NumberInterface param = params[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) { | ||||
|                     param = param.divide(new NaiveNumber(2).promoteTo(param.getClass())); | ||||
|                     powersOf2++; | ||||
| @ -188,11 +175,11 @@ public class StandardPlugin extends Plugin { | ||||
|          * @return the partial sum. | ||||
|          */ | ||||
|         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). | ||||
|             NumberInterface currentTerm = x, sum = x; | ||||
|             int n = 1; | ||||
|                 while(StandardPlugin.this.getFunction("abs").apply(currentTerm).compareTo(maxError) > 0){ | ||||
|             while(FUNCTION_ABS.apply(currentTerm).compareTo(maxError) > 0){ | ||||
|                 n++; | ||||
|                 currentTerm = currentTerm.multiply(x).multiply((new NaiveNumber(n-1)).promoteTo(x.getClass())).divide((new NaiveNumber(n)).promoteTo(x.getClass())).negate(); | ||||
|                 sum = sum.add(currentTerm); | ||||
| @ -206,7 +193,7 @@ public class StandardPlugin extends Plugin { | ||||
|          * @return the value of log(2) with the appropriate precision. | ||||
|          */ | ||||
|         private NumberInterface getLog2(NumberInterface number){ | ||||
|                 NumberInterface maxError = StandardPlugin.this.getMaxError(number); | ||||
|             NumberInterface maxError = getMaxError(number); | ||||
|             //NumberInterface errorBound = (new NaiveNumber(1)).promoteTo(number.getClass()); | ||||
|             //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. | ||||
| @ -223,9 +210,8 @@ public class StandardPlugin extends Plugin { | ||||
|             } | ||||
|             return sum; | ||||
|         } | ||||
|         }); | ||||
| 
 | ||||
|         registerFunction("sqrt", new Function() { | ||||
|     }; | ||||
|     public static final Function FUNCTION_SQRT = new Function() { | ||||
|         @Override | ||||
|         protected boolean matchesParams(NumberInterface[] params) { | ||||
|             return params.length == 1; | ||||
| @ -233,9 +219,30 @@ public class StandardPlugin extends Plugin { | ||||
| 
 | ||||
|         @Override | ||||
|         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 | ||||
| @ -249,8 +256,8 @@ public class StandardPlugin extends Plugin { | ||||
|      * @param x the real number at which the series is evaluated. | ||||
|      * @return the nth term of the series. | ||||
|      */ | ||||
|     private NumberInterface getExpSeriesTerm(int n, NumberInterface x){ | ||||
|         return x.intPow(n).divide(this.getOperator("!").getFunction().apply((new NaiveNumber(n)).promoteTo(x.getClass()))); | ||||
|     private static NumberInterface getExpSeriesTerm(int n, NumberInterface x){ | ||||
|         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. | ||||
|      * @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 | ||||
|         //The variables LHS and RHS refer to the above inequality. | ||||
|         int n = 0; | ||||
|         x = this.getFunction("abs").apply(x); | ||||
|         x = FUNCTION_ABS.apply(x); | ||||
|         NumberInterface LHS = x, RHS = maxError; | ||||
|         while (LHS.compareTo(RHS) > 0) { | ||||
|             n++; | ||||
| @ -282,7 +289,7 @@ public class StandardPlugin extends Plugin { | ||||
|      * @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 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()); | ||||
|         for(int i = 0; i <= n; i++){ | ||||
|             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). | ||||
|      * @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()); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user