mirror of
https://github.com/DanilaFe/abacus
synced 2024-12-22 15:30:09 -08:00
Require applicable interfaces to be passed an implementation they use.
This commit is contained in:
parent
f7c07ca04d
commit
2b700d3911
|
@ -138,16 +138,14 @@ public class Abacus {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a number from a string.
|
* Gets the number implementation.
|
||||||
*
|
* @return the number implementation to use for creating numbers.
|
||||||
* @param numberString the string to create the number from.
|
|
||||||
* @return the resulting number.
|
|
||||||
*/
|
*/
|
||||||
public NumberInterface numberFromString(String numberString) {
|
public NumberImplementation getNumberImplementation(){
|
||||||
NumberImplementation toInstantiate =
|
NumberImplementation selectedImplementation =
|
||||||
pluginManager.numberImplementationFor(configuration.getNumberImplementation());
|
pluginManager.numberImplementationFor(configuration.getNumberImplementation());
|
||||||
if (toInstantiate == null) toInstantiate = DEFAULT_IMPLEMENTATION;
|
if(selectedImplementation != null) return selectedImplementation;
|
||||||
|
return DEFAULT_IMPLEMENTATION;
|
||||||
return toInstantiate.instanceForString(numberString);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,12 +20,13 @@ public class StandardPlugin extends Plugin {
|
||||||
*/
|
*/
|
||||||
public static final NumberOperator OP_ADD = new NumberOperator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 0) {
|
public static final NumberOperator OP_ADD = new NumberOperator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 0) {
|
||||||
@Override
|
@Override
|
||||||
public boolean matchesParams(NumberInterface[] params) {
|
public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return params.length == 2;
|
return params.length == 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NumberInterface applyInternal(NumberInterface[] params) {
|
public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return params[0].add(params[1]);
|
return params[0].add(params[1]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -34,12 +35,13 @@ public class StandardPlugin extends Plugin {
|
||||||
*/
|
*/
|
||||||
public static final NumberOperator OP_SUBTRACT = new NumberOperator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 0) {
|
public static final NumberOperator OP_SUBTRACT = new NumberOperator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 0) {
|
||||||
@Override
|
@Override
|
||||||
public boolean matchesParams(NumberInterface[] params) {
|
public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return params.length == 2;
|
return params.length == 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NumberInterface applyInternal(NumberInterface[] params) {
|
public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return params[0].subtract(params[1]);
|
return params[0].subtract(params[1]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -49,12 +51,13 @@ public class StandardPlugin extends Plugin {
|
||||||
*/
|
*/
|
||||||
public static final NumberOperator OP_NEGATE = new NumberOperator(OperatorAssociativity.LEFT, OperatorType.UNARY_PREFIX, 0) {
|
public static final NumberOperator OP_NEGATE = new NumberOperator(OperatorAssociativity.LEFT, OperatorType.UNARY_PREFIX, 0) {
|
||||||
@Override
|
@Override
|
||||||
public boolean matchesParams(NumberInterface[] params) {
|
public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return params.length == 1;
|
return params.length == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NumberInterface applyInternal(NumberInterface[] params) {
|
public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return params[0].negate();
|
return params[0].negate();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -63,12 +66,13 @@ public class StandardPlugin extends Plugin {
|
||||||
*/
|
*/
|
||||||
public static final NumberOperator OP_MULTIPLY = new NumberOperator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 1) {
|
public static final NumberOperator OP_MULTIPLY = new NumberOperator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 1) {
|
||||||
@Override
|
@Override
|
||||||
public boolean matchesParams(NumberInterface[] params) {
|
public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return params.length == 2;
|
return params.length == 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NumberInterface applyInternal(NumberInterface[] params) {
|
public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return params[0].multiply(params[1]);
|
return params[0].multiply(params[1]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -91,13 +95,14 @@ public class StandardPlugin extends Plugin {
|
||||||
*/
|
*/
|
||||||
public static final NumberFunction FUNCTION_SQRT = new NumberFunction() {
|
public static final NumberFunction FUNCTION_SQRT = new NumberFunction() {
|
||||||
@Override
|
@Override
|
||||||
public boolean matchesParams(NumberInterface[] params) {
|
public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return params.length == 1;
|
return params.length == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NumberInterface applyInternal(NumberInterface[] params) {
|
public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return OP_CARET.apply(params[0], ((new NaiveNumber(0.5)).promoteTo(params[0].getClass())));
|
return OP_CARET.apply(implementation, params[0], ((new NaiveNumber(0.5)).promoteTo(params[0].getClass())));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
|
@ -111,7 +116,7 @@ public class StandardPlugin extends Plugin {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NumberInterface instanceForPi() {
|
public NumberInterface instanceForPi() {
|
||||||
NumberInterface C = FUNCTION_SQRT.apply(new PreciseNumber("10005")).multiply(new PreciseNumber("426880"));
|
NumberInterface C = FUNCTION_SQRT.apply(this, new PreciseNumber("10005")).multiply(new PreciseNumber("426880"));
|
||||||
NumberInterface M = PreciseNumber.ONE;
|
NumberInterface M = PreciseNumber.ONE;
|
||||||
NumberInterface L = new PreciseNumber("13591409");
|
NumberInterface L = new PreciseNumber("13591409");
|
||||||
NumberInterface X = M;
|
NumberInterface X = M;
|
||||||
|
@ -145,12 +150,13 @@ public class StandardPlugin extends Plugin {
|
||||||
*/
|
*/
|
||||||
public static final NumberOperator OP_DIVIDE = new NumberOperator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 1) {
|
public static final NumberOperator OP_DIVIDE = new NumberOperator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 1) {
|
||||||
@Override
|
@Override
|
||||||
public boolean matchesParams(NumberInterface[] params) {
|
public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return params.length == 2 && params[1].compareTo(fromInt(params[0].getClass(), 0)) != 0;
|
return params.length == 2 && params[1].compareTo(fromInt(params[0].getClass(), 0)) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NumberInterface applyInternal(NumberInterface[] params) {
|
public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return params[0].divide(params[1]);
|
return params[0].divide(params[1]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -160,14 +166,15 @@ public class StandardPlugin extends Plugin {
|
||||||
public static final NumberOperator OP_FACTORIAL = new NumberOperator(OperatorAssociativity.RIGHT, OperatorType.UNARY_POSTFIX, 0) {
|
public static final NumberOperator OP_FACTORIAL = new NumberOperator(OperatorAssociativity.RIGHT, OperatorType.UNARY_POSTFIX, 0) {
|
||||||
//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
|
||||||
public boolean matchesParams(NumberInterface[] params) {
|
public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return params.length == 1
|
return params.length == 1
|
||||||
&& params[0].fractionalPart().compareTo(fromInt(params[0].getClass(), 0)) == 0
|
&& params[0].fractionalPart().compareTo(fromInt(params[0].getClass(), 0)) == 0
|
||||||
&& params[0].signum() >= 0;
|
&& params[0].signum() >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NumberInterface applyInternal(NumberInterface[] params) {
|
public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
if (params[0].signum() == 0) {
|
if (params[0].signum() == 0) {
|
||||||
return fromInt(params[0].getClass(), 1);
|
return fromInt(params[0].getClass(), 1);
|
||||||
}
|
}
|
||||||
|
@ -191,13 +198,14 @@ public class StandardPlugin extends Plugin {
|
||||||
*/
|
*/
|
||||||
public static final NumberOperator OP_NPR = new NumberOperator(OperatorAssociativity.RIGHT, OperatorType.BINARY_INFIX, 0) {
|
public static final NumberOperator OP_NPR = new NumberOperator(OperatorAssociativity.RIGHT, OperatorType.BINARY_INFIX, 0) {
|
||||||
@Override
|
@Override
|
||||||
public boolean matchesParams(NumberInterface[] params) {
|
public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return params.length == 2 && params[0].fractionalPart().signum() == 0
|
return params.length == 2 && params[0].fractionalPart().signum() == 0
|
||||||
&& params[1].fractionalPart().signum() == 0;
|
&& params[1].fractionalPart().signum() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NumberInterface applyInternal(NumberInterface[] params) {
|
public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
if (params[0].compareTo(params[1]) < 0 ||
|
if (params[0].compareTo(params[1]) < 0 ||
|
||||||
params[0].signum() < 0 ||
|
params[0].signum() < 0 ||
|
||||||
(params[0].signum() == 0 && params[1].signum() != 0)) return fromInt(params[0].getClass(), 0);
|
(params[0].signum() == 0 && params[1].signum() != 0)) return fromInt(params[0].getClass(), 0);
|
||||||
|
@ -221,14 +229,15 @@ public class StandardPlugin extends Plugin {
|
||||||
*/
|
*/
|
||||||
public static final NumberOperator OP_NCR = new NumberOperator(OperatorAssociativity.RIGHT, OperatorType.BINARY_INFIX, 0) {
|
public static final NumberOperator OP_NCR = new NumberOperator(OperatorAssociativity.RIGHT, OperatorType.BINARY_INFIX, 0) {
|
||||||
@Override
|
@Override
|
||||||
public boolean matchesParams(NumberInterface[] params) {
|
public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return params.length == 2 && params[0].fractionalPart().signum() == 0
|
return params.length == 2 && params[0].fractionalPart().signum() == 0
|
||||||
&& params[1].fractionalPart().signum() == 0;
|
&& params[1].fractionalPart().signum() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NumberInterface applyInternal(NumberInterface[] params) {
|
public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return OP_NPR.apply(params).divide(OP_FACTORIAL.apply(params[1]));
|
return OP_NPR.apply(implementation, params).divide(OP_FACTORIAL.apply(implementation, params[1]));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
|
@ -236,12 +245,13 @@ public class StandardPlugin extends Plugin {
|
||||||
*/
|
*/
|
||||||
public static final NumberFunction FUNCTION_ABS = new NumberFunction() {
|
public static final NumberFunction FUNCTION_ABS = new NumberFunction() {
|
||||||
@Override
|
@Override
|
||||||
public boolean matchesParams(NumberInterface[] params) {
|
public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return params.length == 1;
|
return params.length == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NumberInterface applyInternal(NumberInterface[] params) {
|
public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return params[0].multiply(fromInt(params[0].getClass(), params[0].signum()));
|
return params[0].multiply(fromInt(params[0].getClass(), params[0].signum()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -250,16 +260,17 @@ public class StandardPlugin extends Plugin {
|
||||||
*/
|
*/
|
||||||
public static final NumberFunction FUNCTION_LN = new NumberFunction() {
|
public static final NumberFunction FUNCTION_LN = new NumberFunction() {
|
||||||
@Override
|
@Override
|
||||||
public boolean matchesParams(NumberInterface[] params) {
|
public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return params.length == 1 && params[0].compareTo(fromInt(params[0].getClass(), 0)) > 0;
|
return params.length == 1 && params[0].compareTo(fromInt(params[0].getClass(), 0)) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NumberInterface applyInternal(NumberInterface[] params) {
|
public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
NumberInterface param = params[0];
|
NumberInterface param = params[0];
|
||||||
NumberInterface one = fromInt(param.getClass(), 1);
|
NumberInterface one = fromInt(param.getClass(), 1);
|
||||||
int powersOf2 = 0;
|
int powersOf2 = 0;
|
||||||
while (FUNCTION_ABS.apply(param.subtract(one)).compareTo(new NaiveNumber(0.1).promoteTo(param.getClass())) >= 0) {
|
while (FUNCTION_ABS.apply(implementation, param.subtract(one)).compareTo(new NaiveNumber(0.1).promoteTo(param.getClass())) >= 0) {
|
||||||
if (param.subtract(one).signum() == 1) {
|
if (param.subtract(one).signum() == 1) {
|
||||||
param = param.divide(fromInt(param.getClass(), 2));
|
param = param.divide(fromInt(param.getClass(), 2));
|
||||||
powersOf2++;
|
powersOf2++;
|
||||||
|
@ -276,7 +287,7 @@ public class StandardPlugin extends Plugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return getLog2(param).multiply(fromInt(param.getClass(), powersOf2)).add(getLogPartialSum(param));
|
return getLog2(implementation, param).multiply(fromInt(param.getClass(), powersOf2)).add(getLogPartialSum(implementation, param));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -285,13 +296,13 @@ public class StandardPlugin extends Plugin {
|
||||||
* @param x value at which the series is evaluated. 0 < x < 2. (x=2 is convergent but impractical.)
|
* @param x value at which the series is evaluated. 0 < x < 2. (x=2 is convergent but impractical.)
|
||||||
* @return the partial sum.
|
* @return the partial sum.
|
||||||
*/
|
*/
|
||||||
private NumberInterface getLogPartialSum(NumberInterface x) {
|
private NumberInterface getLogPartialSum(NumberImplementation implementation, NumberInterface x) {
|
||||||
|
|
||||||
NumberInterface maxError = x.getMaxError();
|
NumberInterface maxError = x.getMaxError();
|
||||||
x = x.subtract(fromInt(x.getClass(), 1)); //Terms used are for log(x+1).
|
x = x.subtract(fromInt(x.getClass(), 1)); //Terms used are for log(x+1).
|
||||||
NumberInterface currentNumerator = x, currentTerm = x, sum = x;
|
NumberInterface currentNumerator = x, currentTerm = x, sum = x;
|
||||||
int n = 1;
|
int n = 1;
|
||||||
while (FUNCTION_ABS.apply(currentTerm).compareTo(maxError) > 0) {
|
while (FUNCTION_ABS.apply(implementation, currentTerm).compareTo(maxError) > 0) {
|
||||||
n++;
|
n++;
|
||||||
currentNumerator = currentNumerator.multiply(x).negate();
|
currentNumerator = currentNumerator.multiply(x).negate();
|
||||||
currentTerm = currentNumerator.divide(fromInt(x.getClass(), n));
|
currentTerm = currentNumerator.divide(fromInt(x.getClass(), n));
|
||||||
|
@ -305,7 +316,7 @@ public class StandardPlugin extends Plugin {
|
||||||
* @param number a number of the same type as the return type. (Used for precision.)
|
* @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.
|
* @return the value of log(2) with the appropriate precision.
|
||||||
*/
|
*/
|
||||||
private NumberInterface getLog2(NumberInterface number) {
|
private NumberInterface getLog2(NumberImplementation implementation, NumberInterface number) {
|
||||||
NumberInterface maxError = number.getMaxError();
|
NumberInterface maxError = number.getMaxError();
|
||||||
//NumberInterface errorBound = fromInt(number.getClass(), 1);
|
//NumberInterface errorBound = fromInt(number.getClass(), 1);
|
||||||
//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)
|
||||||
|
@ -330,12 +341,13 @@ public class StandardPlugin extends Plugin {
|
||||||
*/
|
*/
|
||||||
public static final NumberFunction FUNCTION_RAND_INT = new NumberFunction() {
|
public static final NumberFunction FUNCTION_RAND_INT = new NumberFunction() {
|
||||||
@Override
|
@Override
|
||||||
public boolean matchesParams(NumberInterface[] params) {
|
public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return params.length == 1;
|
return params.length == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NumberInterface applyInternal(NumberInterface[] params) {
|
public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return fromInt(params[0].getClass(), (int) Math.round(Math.random() * params[0].floor().intValue()));
|
return fromInt(params[0].getClass(), (int) Math.round(Math.random() * params[0].floor().intValue()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -345,17 +357,18 @@ public class StandardPlugin extends Plugin {
|
||||||
*/
|
*/
|
||||||
public static final NumberFunction FUNCTION_EXP = new NumberFunction() {
|
public static final NumberFunction FUNCTION_EXP = new NumberFunction() {
|
||||||
@Override
|
@Override
|
||||||
public boolean matchesParams(NumberInterface[] params) {
|
public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return params.length == 1;
|
return params.length == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NumberInterface applyInternal(NumberInterface[] params) {
|
public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
NumberInterface maxError = params[0].getMaxError();
|
NumberInterface maxError = params[0].getMaxError();
|
||||||
int n = 0;
|
int n = 0;
|
||||||
if (params[0].signum() < 0) {
|
if (params[0].signum() < 0) {
|
||||||
NumberInterface[] negatedParams = {params[0].negate()};
|
NumberInterface[] negatedParams = {params[0].negate()};
|
||||||
return fromInt(params[0].getClass(), 1).divide(applyInternal(negatedParams));
|
return fromInt(params[0].getClass(), 1).divide(applyInternal(implementation, negatedParams));
|
||||||
} else {
|
} else {
|
||||||
//We need n such that x^(n+1) * 3^ceil(x) <= maxError * (n+1)!.
|
//We need n such that x^(n+1) * 3^ceil(x) <= maxError * (n+1)!.
|
||||||
//right and left refer to lhs and rhs in the above inequality.
|
//right and left refer to lhs and rhs in the above inequality.
|
||||||
|
@ -382,7 +395,7 @@ public class StandardPlugin extends Plugin {
|
||||||
*/
|
*/
|
||||||
public static final NumberOperator OP_CARET = new NumberOperator(OperatorAssociativity.RIGHT, OperatorType.BINARY_INFIX, 2) {
|
public static final NumberOperator OP_CARET = new NumberOperator(OperatorAssociativity.RIGHT, OperatorType.BINARY_INFIX, 2) {
|
||||||
@Override
|
@Override
|
||||||
public boolean matchesParams(NumberInterface[] params) {
|
public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
NumberInterface zero = fromInt(params[0].getClass(), 0);
|
NumberInterface zero = fromInt(params[0].getClass(), 0);
|
||||||
return params.length == 2
|
return params.length == 2
|
||||||
&& !(params[0].compareTo(zero) == 0
|
&& !(params[0].compareTo(zero) == 0
|
||||||
|
@ -390,8 +403,9 @@ public class StandardPlugin extends Plugin {
|
||||||
&& !(params[0].signum() == -1 && params[1].fractionalPart().compareTo(zero) != 0);
|
&& !(params[0].signum() == -1 && params[1].fractionalPart().compareTo(zero) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NumberInterface applyInternal(NumberInterface[] params) {
|
public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
NumberInterface zero = fromInt(params[0].getClass(), 0);
|
NumberInterface zero = fromInt(params[0].getClass(), 0);
|
||||||
if (params[0].compareTo(zero) == 0)
|
if (params[0].compareTo(zero) == 0)
|
||||||
return zero;
|
return zero;
|
||||||
|
@ -399,12 +413,12 @@ public class StandardPlugin extends Plugin {
|
||||||
return fromInt(params[0].getClass(), 1);
|
return fromInt(params[0].getClass(), 1);
|
||||||
//Detect integer bases:
|
//Detect integer bases:
|
||||||
if (params[0].fractionalPart().compareTo(fromInt(params[0].getClass(), 0)) == 0
|
if (params[0].fractionalPart().compareTo(fromInt(params[0].getClass(), 0)) == 0
|
||||||
&& FUNCTION_ABS.apply(params[1]).compareTo(fromInt(params[0].getClass(), Integer.MAX_VALUE)) < 0
|
&& FUNCTION_ABS.apply(implementation, params[1]).compareTo(fromInt(params[0].getClass(), Integer.MAX_VALUE)) < 0
|
||||||
&& FUNCTION_ABS.apply(params[1]).compareTo(fromInt(params[1].getClass(), 1)) >= 0) {
|
&& FUNCTION_ABS.apply(implementation, params[1]).compareTo(fromInt(params[1].getClass(), 1)) >= 0) {
|
||||||
NumberInterface[] newParams = {params[0], params[1].fractionalPart()};
|
NumberInterface[] newParams = {params[0], params[1].fractionalPart()};
|
||||||
return params[0].intPow(params[1].floor().intValue()).multiply(applyInternal(newParams));
|
return params[0].intPow(params[1].floor().intValue()).multiply(applyInternal(implementation, newParams));
|
||||||
}
|
}
|
||||||
return FUNCTION_EXP.apply(FUNCTION_LN.apply(FUNCTION_ABS.apply(params[0])).multiply(params[1]));
|
return FUNCTION_EXP.apply(implementation, FUNCTION_LN.apply(implementation, FUNCTION_ABS.apply(implementation, params[0])).multiply(params[1]));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
|
@ -412,15 +426,16 @@ public class StandardPlugin extends Plugin {
|
||||||
*/
|
*/
|
||||||
public final NumberFunction functionSin = new NumberFunction() {
|
public final NumberFunction functionSin = new NumberFunction() {
|
||||||
@Override
|
@Override
|
||||||
public boolean matchesParams(NumberInterface[] params) {
|
public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return params.length == 1;
|
return params.length == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NumberInterface applyInternal(NumberInterface[] params) {
|
public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
NumberInterface pi = piFor(params[0].getClass());
|
NumberInterface pi = piFor(params[0].getClass());
|
||||||
NumberInterface twoPi = pi.multiply(fromInt(pi.getClass(), 2));
|
NumberInterface twoPi = pi.multiply(fromInt(pi.getClass(), 2));
|
||||||
NumberInterface theta = getSmallAngle(params[0], pi);
|
NumberInterface theta = getSmallAngle(implementation, 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);
|
||||||
|
@ -428,7 +443,7 @@ public class StandardPlugin extends Plugin {
|
||||||
theta = pi.subtract(theta);
|
theta = pi.subtract(theta);
|
||||||
}
|
}
|
||||||
//System.out.println(theta);
|
//System.out.println(theta);
|
||||||
return sinTaylor(theta);
|
return sinTaylor(implementation, theta);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
|
@ -436,13 +451,14 @@ public class StandardPlugin extends Plugin {
|
||||||
*/
|
*/
|
||||||
public final NumberFunction functionCos = new NumberFunction() {
|
public final NumberFunction functionCos = new NumberFunction() {
|
||||||
@Override
|
@Override
|
||||||
public boolean matchesParams(NumberInterface[] params) {
|
public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return params.length == 1;
|
return params.length == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NumberInterface applyInternal(NumberInterface[] params) {
|
public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return functionSin.apply(piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 2))
|
return functionSin.apply(implementation, piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 2))
|
||||||
.subtract(params[0]));
|
.subtract(params[0]));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -451,13 +467,14 @@ public class StandardPlugin extends Plugin {
|
||||||
*/
|
*/
|
||||||
public final NumberFunction functionTan = new NumberFunction() {
|
public final NumberFunction functionTan = new NumberFunction() {
|
||||||
@Override
|
@Override
|
||||||
public boolean matchesParams(NumberInterface[] params) {
|
public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return params.length == 1;
|
return params.length == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NumberInterface applyInternal(NumberInterface[] params) {
|
public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return functionSin.apply(params[0]).divide(functionCos.apply(params[0]));
|
return functionSin.apply(implementation, params[0]).divide(functionCos.apply(implementation, params[0]));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
|
@ -465,13 +482,14 @@ public class StandardPlugin extends Plugin {
|
||||||
*/
|
*/
|
||||||
public final NumberFunction functionSec = new NumberFunction() {
|
public final NumberFunction functionSec = new NumberFunction() {
|
||||||
@Override
|
@Override
|
||||||
public boolean matchesParams(NumberInterface[] params) {
|
public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return params.length == 1;
|
return params.length == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NumberInterface applyInternal(NumberInterface[] params) {
|
public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return fromInt(params[0].getClass(), 1).divide(functionCos.apply(params[0]));
|
return fromInt(params[0].getClass(), 1).divide(functionCos.apply(implementation, params[0]));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
|
@ -479,13 +497,14 @@ public class StandardPlugin extends Plugin {
|
||||||
*/
|
*/
|
||||||
public final NumberFunction functionCsc = new NumberFunction() {
|
public final NumberFunction functionCsc = new NumberFunction() {
|
||||||
@Override
|
@Override
|
||||||
public boolean matchesParams(NumberInterface[] params) {
|
public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return params.length == 1;
|
return params.length == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NumberInterface applyInternal(NumberInterface[] params) {
|
public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return fromInt(params[0].getClass(), 1).divide(functionSin.apply(params[0]));
|
return fromInt(params[0].getClass(), 1).divide(functionSin.apply(implementation, params[0]));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
|
@ -493,13 +512,14 @@ public class StandardPlugin extends Plugin {
|
||||||
*/
|
*/
|
||||||
public final NumberFunction functionCot = new NumberFunction() {
|
public final NumberFunction functionCot = new NumberFunction() {
|
||||||
@Override
|
@Override
|
||||||
public boolean matchesParams(NumberInterface[] params) {
|
public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return params.length == 1;
|
return params.length == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NumberInterface applyInternal(NumberInterface[] params) {
|
public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return functionCos.apply(params[0]).divide(functionSin.apply(params[0]));
|
return functionCos.apply(implementation, params[0]).divide(functionSin.apply(implementation, params[0]));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -508,23 +528,24 @@ public class StandardPlugin extends Plugin {
|
||||||
*/
|
*/
|
||||||
public final NumberFunction functionArcsin = new NumberFunction() {
|
public final NumberFunction functionArcsin = new NumberFunction() {
|
||||||
@Override
|
@Override
|
||||||
public boolean matchesParams(NumberInterface[] params) {
|
public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return params.length == 1
|
return params.length == 1
|
||||||
&& FUNCTION_ABS.apply(params[0]).compareTo(fromInt(params[0].getClass(), 1)) <= 0;
|
&& FUNCTION_ABS.apply(implementation, params[0]).compareTo(fromInt(params[0].getClass(), 1)) <= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NumberInterface applyInternal(NumberInterface[] params) {
|
public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
if (FUNCTION_ABS.apply(params[0]).compareTo(new NaiveNumber(0.8).promoteTo(params[0].getClass())) >= 0) {
|
if (FUNCTION_ABS.apply(implementation, params[0]).compareTo(new NaiveNumber(0.8).promoteTo(params[0].getClass())) >= 0) {
|
||||||
NumberInterface[] newParams = {FUNCTION_SQRT.apply(fromInt(params[0].getClass(), 1).subtract(params[0].multiply(params[0])))};
|
NumberInterface[] newParams = {FUNCTION_SQRT.apply(implementation, fromInt(params[0].getClass(), 1).subtract(params[0].multiply(params[0])))};
|
||||||
return piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 2))
|
return piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 2))
|
||||||
.subtract(applyInternal(newParams)).multiply(fromInt(params[0].getClass(), params[0].signum()));
|
.subtract(applyInternal(implementation, newParams)).multiply(fromInt(params[0].getClass(), params[0].signum()));
|
||||||
}
|
}
|
||||||
NumberInterface currentTerm = params[0], sum = currentTerm,
|
NumberInterface currentTerm = params[0], sum = currentTerm,
|
||||||
multiplier = currentTerm.multiply(currentTerm), summandBound = sum.getMaxError().multiply(fromInt(sum.getClass(), 1).subtract(multiplier)),
|
multiplier = currentTerm.multiply(currentTerm), summandBound = sum.getMaxError().multiply(fromInt(sum.getClass(), 1).subtract(multiplier)),
|
||||||
power = currentTerm, coefficient = fromInt(params[0].getClass(), 1);
|
power = currentTerm, coefficient = fromInt(params[0].getClass(), 1);
|
||||||
int exponent = 1;
|
int exponent = 1;
|
||||||
while (FUNCTION_ABS.apply(currentTerm).compareTo(summandBound) > 0) {
|
while (FUNCTION_ABS.apply(implementation, currentTerm).compareTo(summandBound) > 0) {
|
||||||
exponent += 2;
|
exponent += 2;
|
||||||
power = power.multiply(multiplier);
|
power = power.multiply(multiplier);
|
||||||
coefficient = coefficient.multiply(fromInt(params[0].getClass(), exponent - 2))
|
coefficient = coefficient.multiply(fromInt(params[0].getClass(), exponent - 2))
|
||||||
|
@ -541,14 +562,15 @@ public class StandardPlugin extends Plugin {
|
||||||
*/
|
*/
|
||||||
public final NumberFunction functionArccos = new NumberFunction() {
|
public final NumberFunction functionArccos = new NumberFunction() {
|
||||||
@Override
|
@Override
|
||||||
public boolean matchesParams(NumberInterface[] params) {
|
public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return params.length == 1 && FUNCTION_ABS.apply(params[0]).compareTo(fromInt(params[0].getClass(), 1)) <= 0;
|
return params.length == 1 && FUNCTION_ABS.apply(implementation, params[0]).compareTo(fromInt(params[0].getClass(), 1)) <= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NumberInterface applyInternal(NumberInterface[] params) {
|
public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 2))
|
return piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 2))
|
||||||
.subtract(functionArcsin.apply(params));
|
.subtract(functionArcsin.apply(implementation, params));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -557,14 +579,15 @@ public class StandardPlugin extends Plugin {
|
||||||
*/
|
*/
|
||||||
public final NumberFunction functionArccsc = new NumberFunction() {
|
public final NumberFunction functionArccsc = new NumberFunction() {
|
||||||
@Override
|
@Override
|
||||||
public boolean matchesParams(NumberInterface[] params) {
|
public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return params.length == 1 && FUNCTION_ABS.apply(params[0]).compareTo(fromInt(params[0].getClass(), 1)) >= 0;
|
return params.length == 1 && FUNCTION_ABS.apply(implementation, params[0]).compareTo(fromInt(params[0].getClass(), 1)) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NumberInterface applyInternal(NumberInterface[] params) {
|
public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
NumberInterface[] reciprocalParamArr = {fromInt(params[0].getClass(), 1).divide(params[0])};
|
NumberInterface[] reciprocalParamArr = {fromInt(params[0].getClass(), 1).divide(params[0])};
|
||||||
return functionArcsin.apply(reciprocalParamArr);
|
return functionArcsin.apply(implementation, reciprocalParamArr);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -573,14 +596,15 @@ public class StandardPlugin extends Plugin {
|
||||||
*/
|
*/
|
||||||
public final NumberFunction functionArcsec = new NumberFunction() {
|
public final NumberFunction functionArcsec = new NumberFunction() {
|
||||||
@Override
|
@Override
|
||||||
public boolean matchesParams(NumberInterface[] params) {
|
public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return params.length == 1 && FUNCTION_ABS.apply(params[0]).compareTo(fromInt(params[0].getClass(), 1)) >= 0;
|
return params.length == 1 && FUNCTION_ABS.apply(implementation, params[0]).compareTo(fromInt(params[0].getClass(), 1)) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NumberInterface applyInternal(NumberInterface[] params) {
|
public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
NumberInterface[] reciprocalParamArr = {fromInt(params[0].getClass(), 1).divide(params[0])};
|
NumberInterface[] reciprocalParamArr = {fromInt(params[0].getClass(), 1).divide(params[0])};
|
||||||
return functionArccos.apply(reciprocalParamArr);
|
return functionArccos.apply(implementation, reciprocalParamArr);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -589,20 +613,21 @@ public class StandardPlugin extends Plugin {
|
||||||
*/
|
*/
|
||||||
public final NumberFunction functionArctan = new NumberFunction() {
|
public final NumberFunction functionArctan = new NumberFunction() {
|
||||||
@Override
|
@Override
|
||||||
public boolean matchesParams(NumberInterface[] params) {
|
public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return params.length == 1;
|
return params.length == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NumberInterface applyInternal(NumberInterface[] params) {
|
public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
if (params[0].signum() == -1) {
|
if (params[0].signum() == -1) {
|
||||||
NumberInterface[] negatedParams = {params[0].negate()};
|
NumberInterface[] negatedParams = {params[0].negate()};
|
||||||
return applyInternal(negatedParams).negate();
|
return applyInternal(implementation, negatedParams).negate();
|
||||||
}
|
}
|
||||||
if (params[0].compareTo(fromInt(params[0].getClass(), 1)) > 0) {
|
if (params[0].compareTo(fromInt(params[0].getClass(), 1)) > 0) {
|
||||||
NumberInterface[] reciprocalParams = {fromInt(params[0].getClass(), 1).divide(params[0])};
|
NumberInterface[] reciprocalParams = {fromInt(params[0].getClass(), 1).divide(params[0])};
|
||||||
return piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 2))
|
return piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 2))
|
||||||
.subtract(applyInternal(reciprocalParams));
|
.subtract(applyInternal(implementation, reciprocalParams));
|
||||||
}
|
}
|
||||||
if (params[0].compareTo(fromInt(params[0].getClass(), 1)) == 0) {
|
if (params[0].compareTo(fromInt(params[0].getClass(), 1)) == 0) {
|
||||||
return piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 4));
|
return piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 4));
|
||||||
|
@ -610,12 +635,12 @@ public class StandardPlugin extends Plugin {
|
||||||
if (params[0].compareTo(new NaiveNumber(0.9).promoteTo(params[0].getClass())) >= 0) {
|
if (params[0].compareTo(new NaiveNumber(0.9).promoteTo(params[0].getClass())) >= 0) {
|
||||||
NumberInterface[] newParams = {params[0].multiply(fromInt(params[0].getClass(), 2))
|
NumberInterface[] newParams = {params[0].multiply(fromInt(params[0].getClass(), 2))
|
||||||
.divide(fromInt(params[0].getClass(), 1).subtract(params[0].multiply(params[0])))};
|
.divide(fromInt(params[0].getClass(), 1).subtract(params[0].multiply(params[0])))};
|
||||||
return applyInternal(newParams).divide(fromInt(params[0].getClass(), 2));
|
return applyInternal(implementation, newParams).divide(fromInt(params[0].getClass(), 2));
|
||||||
}
|
}
|
||||||
NumberInterface currentPower = params[0], currentTerm = currentPower, sum = currentTerm,
|
NumberInterface currentPower = params[0], currentTerm = currentPower, sum = currentTerm,
|
||||||
maxError = params[0].getMaxError(), multiplier = currentPower.multiply(currentPower).negate();
|
maxError = params[0].getMaxError(), multiplier = currentPower.multiply(currentPower).negate();
|
||||||
int n = 1;
|
int n = 1;
|
||||||
while (FUNCTION_ABS.apply(currentTerm).compareTo(maxError) > 0) {
|
while (FUNCTION_ABS.apply(implementation, currentTerm).compareTo(maxError) > 0) {
|
||||||
n += 2;
|
n += 2;
|
||||||
currentPower = currentPower.multiply(multiplier);
|
currentPower = currentPower.multiply(multiplier);
|
||||||
currentTerm = currentPower.divide(fromInt(currentPower.getClass(), n));
|
currentTerm = currentPower.divide(fromInt(currentPower.getClass(), n));
|
||||||
|
@ -630,14 +655,14 @@ public class StandardPlugin extends Plugin {
|
||||||
*/
|
*/
|
||||||
public final NumberFunction functionArccot = new NumberFunction() {
|
public final NumberFunction functionArccot = new NumberFunction() {
|
||||||
@Override
|
@Override
|
||||||
public boolean matchesParams(NumberInterface[] params) {
|
public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return params.length == 1;
|
return params.length == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NumberInterface applyInternal(NumberInterface[] params) {
|
public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 2))
|
return piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 2))
|
||||||
.subtract(functionArctan.apply(params));
|
.subtract(functionArctan.apply(implementation, params));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -690,7 +715,7 @@ public class StandardPlugin extends Plugin {
|
||||||
* @param x where the series is evaluated.
|
* @param x where the series is evaluated.
|
||||||
* @return the value of the series
|
* @return the value of the series
|
||||||
*/
|
*/
|
||||||
private static NumberInterface sinTaylor(NumberInterface x) {
|
private static NumberInterface sinTaylor(NumberImplementation implementation, NumberInterface x) {
|
||||||
NumberInterface power = x, multiplier = x.multiply(x).negate(), currentTerm = x, sum = x;
|
NumberInterface power = x, multiplier = x.multiply(x).negate(), currentTerm = x, sum = x;
|
||||||
NumberInterface maxError = x.getMaxError();
|
NumberInterface maxError = x.getMaxError();
|
||||||
int n = 1;
|
int n = 1;
|
||||||
|
@ -699,7 +724,7 @@ public class StandardPlugin extends Plugin {
|
||||||
power = power.multiply(multiplier);
|
power = power.multiply(multiplier);
|
||||||
currentTerm = power.divide(factorial(x.getClass(), n));
|
currentTerm = power.divide(factorial(x.getClass(), n));
|
||||||
sum = sum.add(currentTerm);
|
sum = sum.add(currentTerm);
|
||||||
} while (FUNCTION_ABS.apply(currentTerm).compareTo(maxError) > 0);
|
} while (FUNCTION_ABS.apply(implementation, currentTerm).compareTo(maxError) > 0);
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -709,10 +734,10 @@ public class StandardPlugin extends Plugin {
|
||||||
* @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, NumberInterface pi) {
|
private static NumberInterface getSmallAngle(NumberImplementation implementation, NumberInterface phi, NumberInterface pi) {
|
||||||
NumberInterface twoPi = pi.multiply(fromInt(pi.getClass(), 2));
|
NumberInterface twoPi = pi.multiply(fromInt(pi.getClass(), 2));
|
||||||
NumberInterface theta = FUNCTION_ABS.apply(phi).subtract(twoPi
|
NumberInterface theta = FUNCTION_ABS.apply(implementation, phi).subtract(twoPi
|
||||||
.multiply(FUNCTION_ABS.apply(phi).divide(twoPi).floor())); //Now theta is in [0, 2pi).
|
.multiply(FUNCTION_ABS.apply(implementation, phi).divide(twoPi).floor())); //Now theta is in [0, 2pi).
|
||||||
if (phi.signum() < 0) {
|
if (phi.signum() < 0) {
|
||||||
theta = twoPi.subtract(theta);
|
theta = twoPi.subtract(theta);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@ package org.nwapw.abacus.tree;
|
||||||
import org.nwapw.abacus.Abacus;
|
import org.nwapw.abacus.Abacus;
|
||||||
import org.nwapw.abacus.function.*;
|
import org.nwapw.abacus.function.*;
|
||||||
import org.nwapw.abacus.number.NumberInterface;
|
import org.nwapw.abacus.number.NumberInterface;
|
||||||
|
import org.nwapw.abacus.number.PromotionManager;
|
||||||
|
import org.nwapw.abacus.number.PromotionResult;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A reducer implementation that turns a tree into a single number.
|
* A reducer implementation that turns a tree into a single number.
|
||||||
|
@ -26,19 +28,22 @@ public class NumberReducer implements Reducer<NumberInterface> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NumberInterface reduceNode(TreeNode node, Object... children) {
|
public NumberInterface reduceNode(TreeNode node, Object... children) {
|
||||||
|
PromotionManager manager = abacus.getPromotionManager();
|
||||||
if (node instanceof NumberNode) {
|
if (node instanceof NumberNode) {
|
||||||
return abacus.numberFromString(((NumberNode) node).getNumber());
|
return abacus.getNumberImplementation().instanceForString(((NumberNode) node).getNumber());
|
||||||
} else if(node instanceof VariableNode) {
|
} else if(node instanceof VariableNode) {
|
||||||
return abacus.numberFromString("0");
|
return abacus.getNumberImplementation().instanceForString("0");
|
||||||
} else if (node instanceof NumberBinaryNode) {
|
} else if (node instanceof NumberBinaryNode) {
|
||||||
NumberInterface left = (NumberInterface) children[0];
|
NumberInterface left = (NumberInterface) children[0];
|
||||||
NumberInterface right = (NumberInterface) children[1];
|
NumberInterface right = (NumberInterface) children[1];
|
||||||
NumberOperator operator = abacus.getPluginManager().operatorFor(((BinaryNode) node).getOperation());
|
NumberOperator operator = abacus.getPluginManager().operatorFor(((BinaryNode) node).getOperation());
|
||||||
return operator.apply(left, right);
|
PromotionResult result = manager.promote(left, right);
|
||||||
|
if(result == null) return null;
|
||||||
|
return operator.apply(result.getPromotedTo(), result.getItems());
|
||||||
} else if (node instanceof NumberUnaryNode) {
|
} else if (node instanceof NumberUnaryNode) {
|
||||||
NumberInterface child = (NumberInterface) children[0];
|
NumberInterface child = (NumberInterface) children[0];
|
||||||
NumberOperator operator = abacus.getPluginManager().operatorFor(((UnaryNode) node).getOperation());
|
NumberOperator operator = abacus.getPluginManager().operatorFor(((UnaryNode) node).getOperation());
|
||||||
return operator.apply(child);
|
return operator.apply(abacus.getPluginManager().interfaceImplementationFor(child.getClass()), child);
|
||||||
} else if (node instanceof FunctionNode) {
|
} else if (node instanceof FunctionNode) {
|
||||||
NumberInterface[] convertedChildren = new NumberInterface[children.length];
|
NumberInterface[] convertedChildren = new NumberInterface[children.length];
|
||||||
for (int i = 0; i < convertedChildren.length; i++) {
|
for (int i = 0; i < convertedChildren.length; i++) {
|
||||||
|
@ -46,7 +51,9 @@ public class NumberReducer implements Reducer<NumberInterface> {
|
||||||
}
|
}
|
||||||
NumberFunction function = abacus.getPluginManager().functionFor(((FunctionNode) node).getCallTo());
|
NumberFunction function = abacus.getPluginManager().functionFor(((FunctionNode) node).getCallTo());
|
||||||
if (function == null) return null;
|
if (function == null) return null;
|
||||||
return function.apply(convertedChildren);
|
PromotionResult result = manager.promote(convertedChildren);
|
||||||
|
if(result == null) return null;
|
||||||
|
return function.apply(result.getPromotedTo(), result.getItems());
|
||||||
} else if (node instanceof TreeValueFunctionNode){
|
} else if (node instanceof TreeValueFunctionNode){
|
||||||
CallNode callNode = (CallNode) node;
|
CallNode callNode = (CallNode) node;
|
||||||
TreeNode[] realChildren = new TreeNode[callNode.getChildren().size()];
|
TreeNode[] realChildren = new TreeNode[callNode.getChildren().size()];
|
||||||
|
@ -56,19 +63,19 @@ public class NumberReducer implements Reducer<NumberInterface> {
|
||||||
TreeValueFunction function =
|
TreeValueFunction function =
|
||||||
abacus.getPluginManager().treeValueFunctionFor(callNode.getCallTo());
|
abacus.getPluginManager().treeValueFunctionFor(callNode.getCallTo());
|
||||||
if(function == null) return null;
|
if(function == null) return null;
|
||||||
return function.applyWithReducer(this, realChildren);
|
return function.applyWithReducer(abacus.getNumberImplementation(), this, realChildren);
|
||||||
} else if (node instanceof TreeValueBinaryNode) {
|
} else if (node instanceof TreeValueBinaryNode) {
|
||||||
BinaryNode binaryNode = (BinaryNode) node;
|
BinaryNode binaryNode = (BinaryNode) node;
|
||||||
TreeValueOperator operator = abacus.getPluginManager()
|
TreeValueOperator operator = abacus.getPluginManager()
|
||||||
.treeValueOperatorFor(binaryNode.getOperation());
|
.treeValueOperatorFor(binaryNode.getOperation());
|
||||||
if(operator == null) return null;
|
if(operator == null) return null;
|
||||||
return operator.applyWithReducer(this, binaryNode.getLeft(), binaryNode.getRight());
|
return operator.applyWithReducer(abacus.getNumberImplementation(), this, binaryNode.getLeft(), binaryNode.getRight());
|
||||||
} else if(node instanceof TreeValueUnaryNode) {
|
} else if(node instanceof TreeValueUnaryNode) {
|
||||||
UnaryNode unaryNode = (UnaryNode) node;
|
UnaryNode unaryNode = (UnaryNode) node;
|
||||||
TreeValueOperator operator = abacus.getPluginManager()
|
TreeValueOperator operator = abacus.getPluginManager()
|
||||||
.treeValueOperatorFor(unaryNode.getOperation());
|
.treeValueOperatorFor(unaryNode.getOperation());
|
||||||
if(operator == null) return null;
|
if(operator == null) return null;
|
||||||
return operator.applyWithReducer(this, unaryNode.getApplyTo());
|
return operator.applyWithReducer(abacus.getNumberImplementation(), this, unaryNode.getApplyTo());
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package org.nwapw.abacus.function.applicable
|
package org.nwapw.abacus.function.applicable
|
||||||
|
|
||||||
|
import org.nwapw.abacus.plugin.NumberImplementation
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class that can be applied to arguments.
|
* A class that can be applied to arguments.
|
||||||
*
|
*
|
||||||
|
@ -15,7 +17,7 @@ interface Applicable<in T : Any, out O : Any> {
|
||||||
* @param params the parameter array to verify for compatibility.
|
* @param params the parameter array to verify for compatibility.
|
||||||
* @return whether the array can be used with applyInternal.
|
* @return whether the array can be used with applyInternal.
|
||||||
*/
|
*/
|
||||||
fun matchesParams(params: Array<out T>): Boolean
|
fun matchesParams(implementation: NumberImplementation, params: Array<out T>): Boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies the applicable object to the given parameters,
|
* Applies the applicable object to the given parameters,
|
||||||
|
@ -23,7 +25,7 @@ interface Applicable<in T : Any, out O : Any> {
|
||||||
* @param params the parameters to apply to.
|
* @param params the parameters to apply to.
|
||||||
* @return the result of the application.
|
* @return the result of the application.
|
||||||
*/
|
*/
|
||||||
fun applyInternal(params: Array<out T>): O?
|
fun applyInternal(implementation: NumberImplementation, params: Array<out T>): O?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the parameters can be used with this applicable, returns
|
* If the parameters can be used with this applicable, returns
|
||||||
|
@ -32,9 +34,9 @@ interface Applicable<in T : Any, out O : Any> {
|
||||||
* @param params the parameters to apply to.
|
* @param params the parameters to apply to.
|
||||||
* @return the result of the operation, or null if parameters do not match.
|
* @return the result of the operation, or null if parameters do not match.
|
||||||
*/
|
*/
|
||||||
fun apply(vararg params: T): O? {
|
fun apply(implementation: NumberImplementation, vararg params: T): O? {
|
||||||
if (!matchesParams(params)) return null
|
if (!matchesParams(implementation, params)) return null
|
||||||
return applyInternal(params)
|
return applyInternal(implementation, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package org.nwapw.abacus.function.applicable
|
package org.nwapw.abacus.function.applicable
|
||||||
|
|
||||||
|
import org.nwapw.abacus.plugin.NumberImplementation
|
||||||
import org.nwapw.abacus.tree.Reducer
|
import org.nwapw.abacus.tree.Reducer
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -18,7 +19,7 @@ interface ReducerApplicable<in T : Any, out O : Any, in R : Any> {
|
||||||
* given parameters.
|
* given parameters.
|
||||||
* @param params the parameters to check.
|
* @param params the parameters to check.
|
||||||
*/
|
*/
|
||||||
fun matchesParams(params: Array<out T>): Boolean
|
fun matchesParams(implementation: NumberImplementation, params: Array<out T>): Boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies this applicable to the given arguments, and reducer.
|
* Applies this applicable to the given arguments, and reducer.
|
||||||
|
@ -26,7 +27,7 @@ interface ReducerApplicable<in T : Any, out O : Any, in R : Any> {
|
||||||
* @param params the arguments to apply to.
|
* @param params the arguments to apply to.
|
||||||
* @return the result of the application.
|
* @return the result of the application.
|
||||||
*/
|
*/
|
||||||
fun applyWithReducerInternal(reducer: Reducer<R>, params: Array<out T>): O?
|
fun applyWithReducerInternal(implementation: NumberImplementation, reducer: Reducer<R>, params: Array<out T>): O?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies this applicable to the given arguments, and reducer,
|
* Applies this applicable to the given arguments, and reducer,
|
||||||
|
@ -35,9 +36,9 @@ interface ReducerApplicable<in T : Any, out O : Any, in R : Any> {
|
||||||
* @param params the arguments to apply to.
|
* @param params the arguments to apply to.
|
||||||
* @return the result of the application, or null if the arguments are incompatible.
|
* @return the result of the application, or null if the arguments are incompatible.
|
||||||
*/
|
*/
|
||||||
fun applyWithReducer(reducer: Reducer<R>, vararg params: T): O? {
|
fun applyWithReducer(implementation: NumberImplementation, reducer: Reducer<R>, vararg params: T): O? {
|
||||||
if (!matchesParams(params)) return null
|
if (!matchesParams(implementation, params)) return null
|
||||||
return applyWithReducerInternal(reducer, params)
|
return applyWithReducerInternal(implementation, reducer, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -25,15 +25,15 @@ class PromotionManager(val abacus: Abacus) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fun promote(vararg numbers: NumberInterface): Array<NumberInterface>? {
|
fun promote(vararg numbers: NumberInterface): PromotionResult? {
|
||||||
val pluginManager = abacus.pluginManager
|
val pluginManager = abacus.pluginManager
|
||||||
val implementations = numbers.map { pluginManager.interfaceImplementationFor(it.javaClass) }
|
val implementations = numbers.map { pluginManager.interfaceImplementationFor(it.javaClass) }
|
||||||
val highestPriority = implementations.sortedBy { it.priority }.last()
|
val highestPriority = implementations.sortedBy { it.priority }.last()
|
||||||
return numbers.map {
|
return PromotionResult(items = numbers.map {
|
||||||
if(it.javaClass == highestPriority.implementation) it
|
if(it.javaClass == highestPriority.implementation) it
|
||||||
else getPathBetween(pluginManager.interfaceImplementationFor(it.javaClass), highestPriority)
|
else getPathBetween(pluginManager.interfaceImplementationFor(it.javaClass), highestPriority)
|
||||||
?.promote(it) ?: return null
|
?.promote(it) ?: return null
|
||||||
}.toTypedArray()
|
}.toTypedArray(), promotedTo = highestPriority)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package org.nwapw.abacus.number
|
||||||
|
|
||||||
|
import org.nwapw.abacus.plugin.NumberImplementation
|
||||||
|
|
||||||
|
data class PromotionResult(val promotedTo: NumberImplementation, val items: Array<NumberInterface>)
|
|
@ -9,6 +9,7 @@ import org.nwapw.abacus.function.*;
|
||||||
import org.nwapw.abacus.lexing.pattern.Match;
|
import org.nwapw.abacus.lexing.pattern.Match;
|
||||||
import org.nwapw.abacus.number.NumberInterface;
|
import org.nwapw.abacus.number.NumberInterface;
|
||||||
import org.nwapw.abacus.parsing.LexerTokenizer;
|
import org.nwapw.abacus.parsing.LexerTokenizer;
|
||||||
|
import org.nwapw.abacus.plugin.NumberImplementation;
|
||||||
import org.nwapw.abacus.plugin.Plugin;
|
import org.nwapw.abacus.plugin.Plugin;
|
||||||
import org.nwapw.abacus.tree.TokenType;
|
import org.nwapw.abacus.tree.TokenType;
|
||||||
|
|
||||||
|
@ -20,12 +21,12 @@ public class TokenizerTests {
|
||||||
private static LexerTokenizer lexerTokenizer = new LexerTokenizer();
|
private static LexerTokenizer lexerTokenizer = new LexerTokenizer();
|
||||||
private static NumberFunction subtractFunction = new NumberFunction() {
|
private static NumberFunction subtractFunction = new NumberFunction() {
|
||||||
@Override
|
@Override
|
||||||
public boolean matchesParams(NumberInterface[] params) {
|
public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return params.length == 2;
|
return params.length == 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NumberInterface applyInternal(NumberInterface[] params) {
|
public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return params[0].subtract(params[1]);
|
return params[0].subtract(params[1]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -36,26 +37,26 @@ public class TokenizerTests {
|
||||||
0) {
|
0) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean matchesParams(NumberInterface[] params) {
|
public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NumberInterface applyInternal(NumberInterface[] params) {
|
public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return subtractFunction.apply(params);
|
return subtractFunction.apply(implementation, params);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
registerOperator("-", new NumberOperator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX,
|
registerOperator("-", new NumberOperator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX,
|
||||||
0) {
|
0) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean matchesParams(NumberInterface[] params) {
|
public boolean matchesParams(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NumberInterface applyInternal(NumberInterface[] params) {
|
public NumberInterface applyInternal(NumberImplementation implementation, NumberInterface[] params) {
|
||||||
return subtractFunction.apply(params);
|
return subtractFunction.apply(implementation, params);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
registerFunction("subtract", subtractFunction);
|
registerFunction("subtract", subtractFunction);
|
||||||
|
|
|
@ -14,8 +14,7 @@ import org.nwapw.abacus.Abacus;
|
||||||
import org.nwapw.abacus.config.Configuration;
|
import org.nwapw.abacus.config.Configuration;
|
||||||
import org.nwapw.abacus.function.Documentation;
|
import org.nwapw.abacus.function.Documentation;
|
||||||
import org.nwapw.abacus.function.DocumentationType;
|
import org.nwapw.abacus.function.DocumentationType;
|
||||||
import org.nwapw.abacus.number.ComputationInterruptedException;
|
import org.nwapw.abacus.number.*;
|
||||||
import org.nwapw.abacus.number.NumberInterface;
|
|
||||||
import org.nwapw.abacus.plugin.ClassFinder;
|
import org.nwapw.abacus.plugin.ClassFinder;
|
||||||
import org.nwapw.abacus.plugin.PluginListener;
|
import org.nwapw.abacus.plugin.PluginListener;
|
||||||
import org.nwapw.abacus.plugin.PluginManager;
|
import org.nwapw.abacus.plugin.PluginManager;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user