mirror of
https://github.com/DanilaFe/abacus
synced 2024-12-23 16:00:09 -08:00
Implement a getPi function for the plugin, and use the new pi value.
This commit is contained in:
parent
b06e9fcbee
commit
276b6719fd
|
@ -1,7 +1,6 @@
|
||||||
package org.nwapw.abacus.number;
|
package org.nwapw.abacus.number;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.MathContext;
|
|
||||||
import java.math.RoundingMode;
|
import java.math.RoundingMode;
|
||||||
|
|
||||||
public class PreciseNumber implements NumberInterface {
|
public class PreciseNumber implements NumberInterface {
|
||||||
|
@ -9,15 +8,15 @@ public class PreciseNumber implements NumberInterface {
|
||||||
/**
|
/**
|
||||||
* The number one.
|
* The number one.
|
||||||
*/
|
*/
|
||||||
static final PreciseNumber ONE = new PreciseNumber(BigDecimal.ONE);
|
public static final PreciseNumber ONE = new PreciseNumber(BigDecimal.ONE);
|
||||||
/**
|
/**
|
||||||
* The number zero.
|
* The number zero.
|
||||||
*/
|
*/
|
||||||
static final PreciseNumber ZERO = new PreciseNumber(BigDecimal.ZERO);
|
public static final PreciseNumber ZERO = new PreciseNumber(BigDecimal.ZERO);
|
||||||
/**
|
/**
|
||||||
* The number ten.
|
* The number ten.
|
||||||
*/
|
*/
|
||||||
static final PreciseNumber TEN = new PreciseNumber(BigDecimal.TEN);
|
public static final PreciseNumber TEN = new PreciseNumber(BigDecimal.TEN);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The value of the PreciseNumber.
|
* The value of the PreciseNumber.
|
||||||
|
|
|
@ -2,6 +2,7 @@ package org.nwapw.abacus.plugin;
|
||||||
|
|
||||||
import org.nwapw.abacus.function.Function;
|
import org.nwapw.abacus.function.Function;
|
||||||
import org.nwapw.abacus.function.Operator;
|
import org.nwapw.abacus.function.Operator;
|
||||||
|
import org.nwapw.abacus.number.NumberInterface;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -177,6 +178,10 @@ public abstract class Plugin {
|
||||||
return manager.numberImplementationFor(name);
|
return manager.numberImplementationFor(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected final NumberInterface getPi(Class<? extends NumberInterface> forClass){
|
||||||
|
return manager.interfaceImplementationFor(forClass).instanceForPi();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract method to be overridden by plugin implementation, in which the plugins
|
* Abstract method to be overridden by plugin implementation, in which the plugins
|
||||||
* are supposed to register the functions they provide and do any other
|
* are supposed to register the functions they provide and do any other
|
||||||
|
|
|
@ -19,7 +19,6 @@ import java.util.function.BiFunction;
|
||||||
public class StandardPlugin extends Plugin {
|
public class StandardPlugin extends Plugin {
|
||||||
|
|
||||||
private static HashMap<Class<? extends NumberInterface>, ArrayList<NumberInterface>> factorialLists = new HashMap<Class<? extends NumberInterface>, ArrayList<NumberInterface>>();
|
private static HashMap<Class<? extends NumberInterface>, ArrayList<NumberInterface>> factorialLists = new HashMap<Class<? extends NumberInterface>, ArrayList<NumberInterface>>();
|
||||||
static HashMap<Class<? extends NumberInterface>, NumberInterface> piValues = new HashMap<Class<? extends NumberInterface>, NumberInterface>();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The addition operator, +
|
* The addition operator, +
|
||||||
|
@ -284,7 +283,7 @@ public class StandardPlugin extends Plugin {
|
||||||
/**
|
/**
|
||||||
* The sine function (the argument is interpreted in radians).
|
* The sine function (the argument is interpreted in radians).
|
||||||
*/
|
*/
|
||||||
public static final Function FUNCTION_SIN = new Function() {
|
public final Function functionSin = new Function() {
|
||||||
@Override
|
@Override
|
||||||
protected boolean matchesParams(NumberInterface[] params) {
|
protected boolean matchesParams(NumberInterface[] params) {
|
||||||
return params.length == 1;
|
return params.length == 1;
|
||||||
|
@ -294,7 +293,7 @@ public class StandardPlugin extends Plugin {
|
||||||
protected NumberInterface applyInternal(NumberInterface[] params) {
|
protected NumberInterface applyInternal(NumberInterface[] params) {
|
||||||
NumberInterface pi = getPi(params[0].getClass());
|
NumberInterface pi = getPi(params[0].getClass());
|
||||||
NumberInterface twoPi = pi.multiply(new NaiveNumber(2).promoteTo(pi.getClass()));
|
NumberInterface twoPi = pi.multiply(new NaiveNumber(2).promoteTo(pi.getClass()));
|
||||||
NumberInterface theta = getSmallAngle(params[0]);
|
NumberInterface theta = getSmallAngle(params[0], pi);
|
||||||
//System.out.println(theta);
|
//System.out.println(theta);
|
||||||
if(theta.compareTo(pi.multiply(new NaiveNumber(1.5).promoteTo(twoPi.getClass()))) >= 0){
|
if(theta.compareTo(pi.multiply(new NaiveNumber(1.5).promoteTo(twoPi.getClass()))) >= 0){
|
||||||
theta = theta.subtract(twoPi);
|
theta = theta.subtract(twoPi);
|
||||||
|
@ -327,7 +326,29 @@ public class StandardPlugin extends Plugin {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NumberInterface instanceForPi() {
|
public NumberInterface instanceForPi() {
|
||||||
return null;
|
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 NaiveNumber(12*i+2).promoteTo(PreciseNumber.class))
|
||||||
|
.multiply(new NaiveNumber(12*i+6).promoteTo(PreciseNumber.class))
|
||||||
|
.multiply(new NaiveNumber(12*i+10).promoteTo(PreciseNumber.class))
|
||||||
|
.divide(new NaiveNumber(Math.pow(i+1,3)).promoteTo(PreciseNumber.class));
|
||||||
|
L = L.add(lSummand);
|
||||||
|
X = X.multiply(xMultiplier);
|
||||||
|
sum = sum.add(M.multiply(L).divide(X));
|
||||||
|
}
|
||||||
|
return C.divide(sum);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -377,7 +398,7 @@ public class StandardPlugin extends Plugin {
|
||||||
registerFunction("exp", FUNCTION_EXP);
|
registerFunction("exp", FUNCTION_EXP);
|
||||||
registerFunction("ln", FUNCTION_LN);
|
registerFunction("ln", FUNCTION_LN);
|
||||||
registerFunction("sqrt", FUNCTION_SQRT);
|
registerFunction("sqrt", FUNCTION_SQRT);
|
||||||
registerFunction("sin", FUNCTION_SIN);
|
registerFunction("sin", functionSin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -425,48 +446,13 @@ public class StandardPlugin extends Plugin {
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an approximation of Pi, with appropriate accuracy for given number class.
|
|
||||||
* @param numClass type of number.
|
|
||||||
* @return A number of class numClass, with value approximately Pi = 3.1415...
|
|
||||||
*/
|
|
||||||
public static NumberInterface getPi(Class<? extends NumberInterface> numClass){
|
|
||||||
if(!piValues.containsKey(numClass)){
|
|
||||||
//https://en.wikipedia.org/wiki/Chudnovsky_algorithm
|
|
||||||
NumberInterface C = FUNCTION_SQRT.apply(new NaiveNumber(10005).promoteTo(numClass)).multiply(new NaiveNumber(426880).promoteTo(numClass));
|
|
||||||
NumberInterface M = NaiveNumber.ONE.promoteTo(numClass);
|
|
||||||
NumberInterface L = new NaiveNumber(13591409).promoteTo(numClass);
|
|
||||||
NumberInterface X = M;
|
|
||||||
NumberInterface sum = L;
|
|
||||||
int termsNeeded = C.getMaxPrecision()/13 + 1;
|
|
||||||
|
|
||||||
NumberInterface lSummand = new NaiveNumber(545140134).promoteTo(L.getClass());
|
|
||||||
NumberInterface xMultiplier = new NaiveNumber(262537412).promoteTo(X.getClass())
|
|
||||||
.multiply(new NaiveNumber(1000000000).promoteTo(X.getClass()))
|
|
||||||
.add(new NaiveNumber(640768000).promoteTo(X.getClass()))
|
|
||||||
.negate();
|
|
||||||
for(int i = 0; i < termsNeeded; i++){
|
|
||||||
M = M
|
|
||||||
.multiply(new NaiveNumber(12*i+2).promoteTo(M.getClass()))
|
|
||||||
.multiply(new NaiveNumber(12*i+6).promoteTo(M.getClass()))
|
|
||||||
.multiply(new NaiveNumber(12*i+10).promoteTo(M.getClass()))
|
|
||||||
.divide(new NaiveNumber(Math.pow(i+1,3)).promoteTo(M.getClass()));
|
|
||||||
L = L.add(lSummand);
|
|
||||||
X = X.multiply(xMultiplier);
|
|
||||||
sum = sum.add(M.multiply(L).divide(X));
|
|
||||||
}
|
|
||||||
piValues.put(numClass, C.divide(sum));
|
|
||||||
}
|
|
||||||
return piValues.get(numClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an equivalent angle in the interval [0, 2pi)
|
* Returns an equivalent angle in the interval [0, 2pi)
|
||||||
* @param phi an angle (in radians).
|
* @param phi an angle (in radians).
|
||||||
* @return theta in [0, 2pi) that differs from phi by a multiple of 2pi.
|
* @return theta in [0, 2pi) that differs from phi by a multiple of 2pi.
|
||||||
*/
|
*/
|
||||||
private static NumberInterface getSmallAngle(NumberInterface phi){
|
private static NumberInterface getSmallAngle(NumberInterface phi, NumberInterface pi){
|
||||||
NumberInterface twoPi = getPi(phi.getClass()).multiply(new NaiveNumber("2").promoteTo(phi.getClass()));
|
NumberInterface twoPi = pi.multiply(new NaiveNumber("2").promoteTo(phi.getClass()));
|
||||||
NumberInterface theta = FUNCTION_ABS.apply(phi).subtract(twoPi
|
NumberInterface theta = FUNCTION_ABS.apply(phi).subtract(twoPi
|
||||||
.multiply(FUNCTION_ABS.apply(phi).divide(twoPi).floor())); //Now theta is in [0, 2pi).
|
.multiply(FUNCTION_ABS.apply(phi).divide(twoPi).floor())); //Now theta is in [0, 2pi).
|
||||||
if(phi.signum() < 0){
|
if(phi.signum() < 0){
|
||||||
|
|
Loading…
Reference in New Issue
Block a user