mirror of
				https://github.com/DanilaFe/abacus
				synced 2025-10-30 17:33:42 -07:00 
			
		
		
		
	Merge branch 'master' of github.com:DanilaFe/abacus
This commit is contained in:
		
						commit
						b84ca8a121
					
				| @ -29,7 +29,7 @@ public class NaiveNumber implements NumberInterface { | |||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public int precision() { |     public int precision() { | ||||||
|         return 15; |         return 18; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|  | |||||||
| @ -4,6 +4,9 @@ import org.nwapw.abacus.function.Function; | |||||||
| import org.nwapw.abacus.number.NaiveNumber; | import org.nwapw.abacus.number.NaiveNumber; | ||||||
| import org.nwapw.abacus.number.NumberInterface; | import org.nwapw.abacus.number.NumberInterface; | ||||||
| 
 | 
 | ||||||
|  | import javax.print.attribute.standard.MediaSize; | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.HashMap; | ||||||
| import java.util.function.BiFunction; | import java.util.function.BiFunction; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @ -75,6 +78,7 @@ public class StandardPlugin extends Plugin { | |||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         registerFunction("!", new Function() { |         registerFunction("!", new Function() { | ||||||
|  |             //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) { | ||||||
|                 return params.length == 1; |                 return params.length == 1; | ||||||
| @ -92,6 +96,23 @@ public class StandardPlugin extends Plugin { | |||||||
|                     factorial = factorial.multiply(multiplier); |                     factorial = factorial.multiply(multiplier); | ||||||
|                 } |                 } | ||||||
|                 return factorial; |                 return factorial; | ||||||
|  |                 /*if(!storedList.containsKey(params[0].getClass())){ | ||||||
|  |                     storedList.put(params[0].getClass(), new ArrayList<NumberInterface>()); | ||||||
|  |                     storedList.get(params[0].getClass()).add(NaiveNumber.ONE.promoteTo(params[0].getClass())); | ||||||
|  |                     storedList.get(params[0].getClass()).add(NaiveNumber.ONE.promoteTo(params[0].getClass())); | ||||||
|  |                 }*/ | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         registerFunction("abs", new Function() { | ||||||
|  |             @Override | ||||||
|  |             protected boolean matchesParams(NumberInterface[] params) { | ||||||
|  |                 return params.length == 1; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             @Override | ||||||
|  |             protected NumberInterface applyInternal(NumberInterface[] params) { | ||||||
|  |                 return params[0].multiply((new NaiveNumber(params[0].signum())).promoteTo(params[0].getClass())); | ||||||
|             } |             } | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
| @ -103,7 +124,112 @@ public class StandardPlugin extends Plugin { | |||||||
| 
 | 
 | ||||||
|             @Override |             @Override | ||||||
|             protected NumberInterface applyInternal(NumberInterface[] params) { |             protected NumberInterface applyInternal(NumberInterface[] params) { | ||||||
|                 return sumSeries(params[0], StandardPlugin.this::getExpSeriesTerm, getNTermsExp(getMaxError(params[0]), params[0])); |                 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])); | ||||||
|  |                 if(takeReciprocal){ | ||||||
|  |                     sum = NaiveNumber.ONE.promoteTo(sum.getClass()).divide(sum); | ||||||
|  |                 } | ||||||
|  |                 return sum; | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         registerFunction("ln", new Function() { | ||||||
|  |             @Override | ||||||
|  |             protected boolean matchesParams(NumberInterface[] params) { | ||||||
|  |                 return params.length == 1; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             @Override | ||||||
|  |             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){ | ||||||
|  |                     if(param.subtract(NaiveNumber.ONE.promoteTo(param.getClass())).signum() == 1) { | ||||||
|  |                         param = param.divide(new NaiveNumber(2).promoteTo(param.getClass())); | ||||||
|  |                         powersOf2++; | ||||||
|  |                         if(param.subtract(NaiveNumber.ONE.promoteTo(param.getClass())).signum() != 1) { | ||||||
|  |                             break; | ||||||
|  |                             //No infinite loop for you. | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     else { | ||||||
|  |                         param = param.multiply(new NaiveNumber(2).promoteTo(param.getClass())); | ||||||
|  |                         powersOf2--; | ||||||
|  |                         if(param.subtract(NaiveNumber.ONE.promoteTo(param.getClass())).signum() != 1) { | ||||||
|  |                             break; | ||||||
|  |                             //No infinite loop for you. | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 return getLog2(param).multiply((new NaiveNumber(powersOf2)).promoteTo(param.getClass())).add(getLogPartialSum(param)); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             /** | ||||||
|  |              * Returns the partial sum of the Taylor series for logx (around x=1). | ||||||
|  |              * Automatically determines the number of terms needed based on the precision of x. | ||||||
|  |              * @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){ | ||||||
|  |                 NumberInterface maxError = StandardPlugin.this.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){ | ||||||
|  |                     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); | ||||||
|  |                 } | ||||||
|  |                 return sum; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             /** | ||||||
|  |              * Returns natural log of 2 to the required precision of the class of number. | ||||||
|  |              * @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){ | ||||||
|  |                 NumberInterface maxError = StandardPlugin.this.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. | ||||||
|  |                 //a is also an error bound. | ||||||
|  |                 NumberInterface a = (new NaiveNumber(1)).promoteTo(number.getClass()), b = a, c = a; | ||||||
|  |                 NumberInterface sum = NaiveNumber.ZERO.promoteTo(number.getClass()); | ||||||
|  |                 int n = 0; | ||||||
|  |                 while(a.compareTo(maxError) >= 1){ | ||||||
|  |                     n++; | ||||||
|  |                     a = a.divide((new NaiveNumber(3)).promoteTo(number.getClass())); | ||||||
|  |                     b = b.divide((new NaiveNumber(4)).promoteTo(number.getClass())); | ||||||
|  |                     c = NaiveNumber.ONE.promoteTo(number.getClass()).divide((new NaiveNumber(n)).promoteTo(number.getClass())); | ||||||
|  |                     sum = sum.add(a.add(b).multiply(c)); | ||||||
|  |                 } | ||||||
|  |                 return sum; | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         registerFunction("pow", 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])); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         registerFunction("sqrt", new Function() { | ||||||
|  |             @Override | ||||||
|  |             protected boolean matchesParams(NumberInterface[] params) { | ||||||
|  |                 return params.length == 1; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             @Override | ||||||
|  |             protected NumberInterface applyInternal(NumberInterface[] params) { | ||||||
|  |                 return StandardPlugin.this.getFunction("pow").apply(params[0], (new NaiveNumber(0.5))); | ||||||
|             } |             } | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| @ -125,15 +251,16 @@ public class StandardPlugin extends Plugin { | |||||||
|      * @param x where the function is evaluated. |      * @param x where the function is evaluated. | ||||||
|      * @return |      * @return | ||||||
|      */ |      */ | ||||||
|     private int getNTermsExp(NumberInterface maxError, NumberInterface x){ |     private int getNTermsExp(NumberInterface maxError, NumberInterface x) { | ||||||
|         //We need n such that x^(n+2) <= (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; | ||||||
|         NumberInterface LHS = x.intPow(2), RHS = maxError; |         x = this.getFunction("abs").apply(x); | ||||||
|         while(LHS.compareTo(RHS) > 0){ |         NumberInterface LHS = x, RHS = maxError; | ||||||
|  |         while (LHS.compareTo(RHS) > 0) { | ||||||
|             n++; |             n++; | ||||||
|             LHS = LHS.multiply(x); |             LHS = LHS.multiply(x); | ||||||
|             RHS = RHS.multiply(new NaiveNumber(n).promoteTo(RHS.getClass())); |             RHS = RHS.multiply(new NaiveNumber(n + 1).promoteTo(RHS.getClass())); | ||||||
|         } |         } | ||||||
|         return n; |         return n; | ||||||
|     } |     } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user