1
0
mirror of https://github.com/DanilaFe/abacus synced 2026-01-23 07:15:19 +00:00

Merge branch 'provider-rewrite' into sin

# Conflicts:
#	src/main/java/org/nwapw/abacus/plugin/StandardPlugin.java
This commit is contained in:
2017-08-04 11:54:12 -07:00
7 changed files with 271 additions and 133 deletions

View File

@@ -8,7 +8,6 @@ import org.nwapw.abacus.number.NaiveNumber;
import org.nwapw.abacus.number.NumberInterface;
import org.nwapw.abacus.number.PreciseNumber;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.function.BiFunction;
@@ -20,7 +19,6 @@ import java.util.function.BiFunction;
public class StandardPlugin extends Plugin {
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, +
@@ -287,7 +285,7 @@ public class StandardPlugin extends Plugin {
/**
* The sine function (the argument is interpreted in radians).
*/
public static final Function FUNCTION_SIN = new Function() {
public final Function functionSin = new Function() {
@Override
protected boolean matchesParams(NumberInterface[] params) {
return params.length == 1;
@@ -297,7 +295,7 @@ public class StandardPlugin extends Plugin {
protected NumberInterface applyInternal(NumberInterface[] params) {
NumberInterface pi = getPi(params[0].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);
if(theta.compareTo(pi.multiply(new NaiveNumber(1.5).promoteTo(twoPi.getClass()))) >= 0){
theta = theta.subtract(twoPi);
@@ -310,7 +308,7 @@ public class StandardPlugin extends Plugin {
}
};
public static final Function FUNCTION_COS = new Function() {
public final Function functionCos = new Function() {
@Override
protected boolean matchesParams(NumberInterface[] params) {
return params.length == 1;
@@ -318,12 +316,12 @@ public class StandardPlugin extends Plugin {
@Override
protected NumberInterface applyInternal(NumberInterface[] params) {
return FUNCTION_SIN.apply(getPi(params[0].getClass()).divide(new NaiveNumber(2).promoteTo(params[0].getClass()))
return functionSin.apply(getPi(params[0].getClass()).divide(new NaiveNumber(2).promoteTo(params[0].getClass()))
.subtract(params[0]));
}
};
public static final Function FUNCTION_TAN = new Function() {
public final Function functionTan = new Function() {
@Override
protected boolean matchesParams(NumberInterface[] params) {
return params.length == 1;
@@ -331,11 +329,11 @@ public class StandardPlugin extends Plugin {
@Override
protected NumberInterface applyInternal(NumberInterface[] params) {
return FUNCTION_SIN.apply(params[0]).divide(FUNCTION_COS.apply(params[0]));
return functionSin.apply(params[0]).divide(functionCos.apply(params[0]));
}
};
public static final Function FUNCTION_SEC = new Function() {
public final Function functionSec = new Function() {
@Override
protected boolean matchesParams(NumberInterface[] params) {
return params.length == 1;
@@ -343,11 +341,11 @@ public class StandardPlugin extends Plugin {
@Override
protected NumberInterface applyInternal(NumberInterface[] params) {
return NaiveNumber.ONE.promoteTo(params[0].getClass()).divide(FUNCTION_COS.apply(params[0]));
return NaiveNumber.ONE.promoteTo(params[0].getClass()).divide(functionCos.apply(params[0]));
}
};
public static final Function FUNCTION_CSC = new Function() {
public final Function functionCsc = new Function() {
@Override
protected boolean matchesParams(NumberInterface[] params) {
return params.length == 1;
@@ -355,11 +353,11 @@ public class StandardPlugin extends Plugin {
@Override
protected NumberInterface applyInternal(NumberInterface[] params) {
return NaiveNumber.ONE.promoteTo(params[0].getClass()).divide(FUNCTION_SIN.apply(params[0]));
return NaiveNumber.ONE.promoteTo(params[0].getClass()).divide(functionSin.apply(params[0]));
}
};
public static final Function FUNCTION_COT = new Function() {
public final Function functionCot = new Function() {
@Override
protected boolean matchesParams(NumberInterface[] params) {
return params.length == 1;
@@ -367,7 +365,59 @@ public class StandardPlugin extends Plugin {
@Override
protected NumberInterface applyInternal(NumberInterface[] params) {
return FUNCTION_COS.apply(params[0]).divide(FUNCTION_COS.apply(params[0]));
return functionCos.apply(params[0]).divide(functionCos.apply(params[0]));
}
};
/**
* 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 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);
}
};
@@ -403,8 +453,8 @@ public class StandardPlugin extends Plugin {
@Override
public void onEnable() {
registerNumber("naive", NaiveNumber.class);
registerNumber("precise", PreciseNumber.class);
registerNumberImplementation("naive", IMPLEMENTATION_NAIVE);
registerNumberImplementation("precise", IMPLEMENTATION_PRECISE);
registerOperator("+", OP_ADD);
registerOperator("-", OP_SUBTRACT);
@@ -417,12 +467,12 @@ public class StandardPlugin extends Plugin {
registerFunction("exp", FUNCTION_EXP);
registerFunction("ln", FUNCTION_LN);
registerFunction("sqrt", FUNCTION_SQRT);
registerFunction("sin", FUNCTION_SIN);
registerFunction("cos", FUNCTION_COS);
registerFunction("tan", FUNCTION_TAN);
registerFunction("sec", FUNCTION_SEC);
registerFunction("csc", FUNCTION_CSC);
registerFunction("cot", FUNCTION_COT);
registerFunction("sin", functionSin);
registerFunction("cos", functionCos);
registerFunction("tan", functionTan);
registerFunction("sec", functionSec);
registerFunction("csc", functionCsc);
registerFunction("cot", functionCot);
}
@Override
@@ -470,48 +520,13 @@ public class StandardPlugin extends Plugin {
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)
* @param phi an angle (in radians).
* @return theta in [0, 2pi) that differs from phi by a multiple of 2pi.
*/
private static NumberInterface getSmallAngle(NumberInterface phi){
NumberInterface twoPi = getPi(phi.getClass()).multiply(new NaiveNumber("2").promoteTo(phi.getClass()));
private static NumberInterface getSmallAngle(NumberInterface phi, NumberInterface pi){
NumberInterface twoPi = pi.multiply(new NaiveNumber("2").promoteTo(phi.getClass()));
NumberInterface theta = FUNCTION_ABS.apply(phi).subtract(twoPi
.multiply(FUNCTION_ABS.apply(phi).divide(twoPi).floor())); //Now theta is in [0, 2pi).
if(phi.signum() < 0){