Numbers in functions should be of decimal base

This commit is contained in:
serso 2016-04-10 21:42:20 +02:00
parent a2d5d89fe4
commit 64a58c2047
2 changed files with 55 additions and 19 deletions

View File

@ -3,6 +3,7 @@ package jscl.math.function;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import jscl.CustomFunctionCalculationException; import jscl.CustomFunctionCalculationException;
import jscl.JsclMathEngine; import jscl.JsclMathEngine;
import jscl.NumeralBase;
import jscl.math.*; import jscl.math.*;
import jscl.text.ParseException; import jscl.text.ParseException;
import jscl.text.msg.JsclMessage; import jscl.text.msg.JsclMessage;
@ -59,11 +60,21 @@ public class CustomFunction extends Function implements IFunction {
@Nullable String description) throws CustomFunctionCalculationException { @Nullable String description) throws CustomFunctionCalculationException {
super(name, new Generic[parameterNames.size()]); super(name, new Generic[parameterNames.size()]);
this.parameterNames = parameterNames; this.parameterNames = parameterNames;
final JsclMathEngine engine = JsclMathEngine.getInstance();
final NumeralBase nb = engine.getNumeralBase();
if (nb != NumeralBase.dec) {
// numbers in functions are only supported in decimal base
engine.setNumeralBase(NumeralBase.dec);
}
try { try {
this.content = Expression.valueOf(content); this.content = Expression.valueOf(content);
ensureNoImplicitFunctions(); ensureNoImplicitFunctions();
} catch (ParseException e) { } catch (ParseException e) {
throw new CustomFunctionCalculationException(this, e); throw new CustomFunctionCalculationException(this, e);
} finally {
if (nb != NumeralBase.dec) {
engine.setNumeralBase(nb);
}
} }
this.description = description; this.description = description;
this.id = counter.incrementAndGet(); this.id = counter.incrementAndGet();

View File

@ -1,15 +1,19 @@
package jscl.math.function; package jscl.math.function;
import jscl.AngleUnit; import jscl.AngleUnit;
import jscl.CustomFunctionCalculationException;
import jscl.JsclMathEngine; import jscl.JsclMathEngine;
import jscl.NumeralBase;
import jscl.math.Expression; import jscl.math.Expression;
import jscl.text.ParseException; import jscl.text.ParseException;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import java.util.Arrays; import java.util.Collections;
import static java.util.Arrays.asList;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
/** /**
* User: serso * User: serso
@ -26,7 +30,7 @@ public class CustomFunctionTest {
assertEquals("", Expression.valueOf("ln(10)/ln(1)").numeric().toString()); assertEquals("", Expression.valueOf("ln(10)/ln(1)").numeric().toString());
// logarithm // logarithm
final CustomFunction.Builder jBuilder = new CustomFunction.Builder(true, "log", Arrays.asList("a", "b"), "ln(b)/ln(a)"); final CustomFunction.Builder jBuilder = new CustomFunction.Builder(true, "log", asList("a", "b"), "ln(b)/ln(a)");
Function function = mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder.create()); Function function = mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder.create());
assertEquals("log(a, b)", function.toString()); assertEquals("log(a, b)", function.toString());
assertEquals("ln(b)/ln(a)", ((CustomFunction) mathEngine.getFunctionsRegistry().get("log")).getContent()); assertEquals("ln(b)/ln(a)", ((CustomFunction) mathEngine.getFunctionsRegistry().get("log")).getContent());
@ -43,14 +47,14 @@ public class CustomFunctionTest {
public void testDerivative() throws Exception { public void testDerivative() throws Exception {
JsclMathEngine mathEngine = JsclMathEngine.getInstance(); JsclMathEngine mathEngine = JsclMathEngine.getInstance();
final CustomFunction.Builder jBuilder = new CustomFunction.Builder("t1", Arrays.asList("a"), "sin(a)"); final CustomFunction.Builder jBuilder = new CustomFunction.Builder("t1", asList("a"), "sin(a)");
mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder.create()); mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder.create());
assertEquals("1", Expression.valueOf("t1(90)").numeric().toString()); assertEquals("1", Expression.valueOf("t1(90)").numeric().toString());
assertEquals("cos(t)", Expression.valueOf("∂(t1(t), t)").expand().toString()); assertEquals("cos(t)", Expression.valueOf("∂(t1(t), t)").expand().toString());
assertEquals("0", Expression.valueOf("∂(t1(t), t2)").expand().toString()); assertEquals("0", Expression.valueOf("∂(t1(t), t2)").expand().toString());
assertEquals("cos(a)", Expression.valueOf("∂(t1(a), a)").expand().toString()); assertEquals("cos(a)", Expression.valueOf("∂(t1(a), a)").expand().toString());
assertEquals("1", Expression.valueOf("∂(t1(a), t1(a))").expand().toString()); assertEquals("1", Expression.valueOf("∂(t1(a), t1(a))").expand().toString());
final CustomFunction.Builder jBuilder1 = new CustomFunction.Builder("t2", Arrays.asList("a", "b"), "b*sin(a)"); final CustomFunction.Builder jBuilder1 = new CustomFunction.Builder("t2", asList("a", "b"), "b*sin(a)");
mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder1.create()); mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder1.create());
assertEquals("y*cos(x)", Expression.valueOf("∂(t2(x, y), x)").expand().toString()); assertEquals("y*cos(x)", Expression.valueOf("∂(t2(x, y), x)").expand().toString());
assertEquals("sin(x)", Expression.valueOf("∂(t2(x, y), y)").expand().toString()); assertEquals("sin(x)", Expression.valueOf("∂(t2(x, y), y)").expand().toString());
@ -60,7 +64,7 @@ public class CustomFunctionTest {
public void testAntiDerivative() throws Exception { public void testAntiDerivative() throws Exception {
JsclMathEngine mathEngine = JsclMathEngine.getInstance(); JsclMathEngine mathEngine = JsclMathEngine.getInstance();
final CustomFunction.Builder jBuilder = new CustomFunction.Builder("t1", Arrays.asList("a"), "sin(a)"); final CustomFunction.Builder jBuilder = new CustomFunction.Builder("t1", asList("a"), "sin(a)");
mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder.create()); mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder.create());
assertEquals("1", Expression.valueOf("t1(90)").numeric().toString()); assertEquals("1", Expression.valueOf("t1(90)").numeric().toString());
@ -71,7 +75,7 @@ public class CustomFunctionTest {
assertEquals("t2*sin(t)", Expression.valueOf("∫(t1(t), t2)").expand().toString()); assertEquals("t2*sin(t)", Expression.valueOf("∫(t1(t), t2)").expand().toString());
assertEquals("-cos(a)", Expression.valueOf("∫(t1(a), a)").expand().toString()); assertEquals("-cos(a)", Expression.valueOf("∫(t1(a), a)").expand().toString());
assertEquals("1/2*sin(a)^2", Expression.valueOf("∫(t1(a), t1(a))").expand().toString()); assertEquals("1/2*sin(a)^2", Expression.valueOf("∫(t1(a), t1(a))").expand().toString());
final CustomFunction.Builder jBuilder1 = new CustomFunction.Builder("t2", Arrays.asList("a", "b"), "b*sin(a)"); final CustomFunction.Builder jBuilder1 = new CustomFunction.Builder("t2", asList("a", "b"), "b*sin(a)");
mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder1.create()); mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder1.create());
assertEquals("-y*cos(x)", Expression.valueOf("∫(t2(x, y), x)").expand().toString()); assertEquals("-y*cos(x)", Expression.valueOf("∫(t2(x, y), x)").expand().toString());
assertEquals("1/2*y^2*sin(x)", Expression.valueOf("∫(t2(x, y), y)").expand().toString()); assertEquals("1/2*y^2*sin(x)", Expression.valueOf("∫(t2(x, y), y)").expand().toString());
@ -85,7 +89,7 @@ public class CustomFunctionTest {
public void testFunction() throws Exception { public void testFunction() throws Exception {
JsclMathEngine mathEngine = JsclMathEngine.getInstance(); JsclMathEngine mathEngine = JsclMathEngine.getInstance();
final CustomFunction.Builder jBuilder = new CustomFunction.Builder("testFunction", Arrays.asList("a", "b", "c", "d"), "b*cos(a)/c+d"); final CustomFunction.Builder jBuilder = new CustomFunction.Builder("testFunction", asList("a", "b", "c", "d"), "b*cos(a)/c+d");
mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder.create()); mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder.create());
assertEquals("6.749543120264322", Expression.valueOf("testFunction(2, 3, 4, 6)").numeric().toString()); assertEquals("6.749543120264322", Expression.valueOf("testFunction(2, 3, 4, 6)").numeric().toString());
assertEquals("7.749543120264322", Expression.valueOf("testFunction(2, 3, 4, 7)").numeric().toString()); assertEquals("7.749543120264322", Expression.valueOf("testFunction(2, 3, 4, 7)").numeric().toString());
@ -106,28 +110,28 @@ public class CustomFunctionTest {
final ExtendedConstant.Builder a = new ExtendedConstant.Builder(new Constant("a"), 1000d); final ExtendedConstant.Builder a = new ExtendedConstant.Builder(new Constant("a"), 1000d);
mathEngine.getConstantsRegistry().addOrUpdate(a.create()); mathEngine.getConstantsRegistry().addOrUpdate(a.create());
final CustomFunction.Builder jBuilder1 = new CustomFunction.Builder("testFunction2", Arrays.asList("a", "b", "c", "d"), "b*cos(a)/c+d"); final CustomFunction.Builder jBuilder1 = new CustomFunction.Builder("testFunction2", asList("a", "b", "c", "d"), "b*cos(a)/c+d");
mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder1.create()); mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder1.create());
assertEquals("6.749543120264322", Expression.valueOf("testFunction2(2, 3, 4, 6)").numeric().toString()); assertEquals("6.749543120264322", Expression.valueOf("testFunction2(2, 3, 4, 6)").numeric().toString());
assertEquals("7.749543120264322", Expression.valueOf("testFunction2(2, 3, 4, 7)").numeric().toString()); assertEquals("7.749543120264322", Expression.valueOf("testFunction2(2, 3, 4, 7)").numeric().toString());
assertEquals("6.749543120264322", Expression.valueOf("testFunction2(2*1, 3, 4, 6)").numeric().toString()); assertEquals("6.749543120264322", Expression.valueOf("testFunction2(2*1, 3, 4, 6)").numeric().toString());
assertEquals("6.749543120264322", Expression.valueOf("testFunction2(2*1, 3, 2^2-1+e^0, 3!)").numeric().toString()); assertEquals("6.749543120264322", Expression.valueOf("testFunction2(2*1, 3, 2^2-1+e^0, 3!)").numeric().toString());
final CustomFunction.Builder jBuilder2 = new CustomFunction.Builder("testFunction3", Arrays.asList("a", "b", "c", "d"), "testFunction2(a, b, c, d) - testFunction(a, b, c, d)"); final CustomFunction.Builder jBuilder2 = new CustomFunction.Builder("testFunction3", asList("a", "b", "c", "d"), "testFunction2(a, b, c, d) - testFunction(a, b, c, d)");
mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder2.create()); mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder2.create());
assertEquals("0", Expression.valueOf("testFunction3(2, 3, 4, 6)").numeric().toString()); assertEquals("0", Expression.valueOf("testFunction3(2, 3, 4, 6)").numeric().toString());
assertEquals("0", Expression.valueOf("testFunction3(2, 3, 4, 7)").numeric().toString()); assertEquals("0", Expression.valueOf("testFunction3(2, 3, 4, 7)").numeric().toString());
assertEquals("0", Expression.valueOf("testFunction3(2*1, 3, 4, 6)").numeric().toString()); assertEquals("0", Expression.valueOf("testFunction3(2*1, 3, 4, 6)").numeric().toString());
assertEquals("0", Expression.valueOf("testFunction3(2*1, 3, 2^2-1+e^0, 3!)").numeric().toString()); assertEquals("0", Expression.valueOf("testFunction3(2*1, 3, 2^2-1+e^0, 3!)").numeric().toString());
final CustomFunction.Builder jBuilder3 = new CustomFunction.Builder("testFunction4", Arrays.asList("a", "b", "c", "d"), "testFunction2(a, b/2, c/3, d/4) - testFunction(a, b!, c, d)"); final CustomFunction.Builder jBuilder3 = new CustomFunction.Builder("testFunction4", asList("a", "b", "c", "d"), "testFunction2(a, b/2, c/3, d/4) - testFunction(a, b!, c, d)");
mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder3.create()); mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder3.create());
assertEquals("-4.874771560132161", Expression.valueOf("testFunction4(2, 3, 4, 6)").numeric().toString()); assertEquals("-4.874771560132161", Expression.valueOf("testFunction4(2, 3, 4, 6)").numeric().toString());
assertEquals("-5.624771560132161", Expression.valueOf("testFunction4(2, 3, 4, 7)").numeric().toString()); assertEquals("-5.624771560132161", Expression.valueOf("testFunction4(2, 3, 4, 7)").numeric().toString());
assertEquals("-4.874771560132161", Expression.valueOf("testFunction4(2*1, 3, 4, 6)").numeric().toString()); assertEquals("-4.874771560132161", Expression.valueOf("testFunction4(2*1, 3, 4, 6)").numeric().toString());
assertEquals("-4.874771560132161", Expression.valueOf("testFunction4(2*1, 3, 2^2-1+e^0, 3!)").numeric().toString()); assertEquals("-4.874771560132161", Expression.valueOf("testFunction4(2*1, 3, 2^2-1+e^0, 3!)").numeric().toString());
final CustomFunction.Builder jBuilder4 = new CustomFunction.Builder("testFunction5", Arrays.asList("a", "b"), "testFunction2(a, b/2, 2, 1) - testFunction(a, b!, 4!, 1)"); final CustomFunction.Builder jBuilder4 = new CustomFunction.Builder("testFunction5", asList("a", "b"), "testFunction2(a, b/2, 2, 1) - testFunction(a, b!, 4!, 1)");
mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder4.create()); mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder4.create());
assertEquals("0.4996954135095478", Expression.valueOf("testFunction5(2, 3)").numeric().toString()); assertEquals("0.4996954135095478", Expression.valueOf("testFunction5(2, 3)").numeric().toString());
assertEquals("0.4996954135095478", Expression.valueOf("testFunction5(2, 3)").numeric().toString()); assertEquals("0.4996954135095478", Expression.valueOf("testFunction5(2, 3)").numeric().toString());
@ -141,19 +145,19 @@ public class CustomFunctionTest {
} }
final CustomFunction.Builder jBuilder5 = new CustomFunction.Builder("testFunction6", Arrays.asList("a", "b"), "testFunction(a, b!, 4!, Π)"); final CustomFunction.Builder jBuilder5 = new CustomFunction.Builder("testFunction6", asList("a", "b"), "testFunction(a, b!, 4!, Π)");
mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder5.create()); mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder5.create());
assertEquals("180.2498477067548", Expression.valueOf("testFunction6(2, 3)").numeric().toString()); assertEquals("180.2498477067548", Expression.valueOf("testFunction6(2, 3)").numeric().toString());
final ExtendedConstant.Builder e = new ExtendedConstant.Builder(new Constant("e"), 181d); final ExtendedConstant.Builder e = new ExtendedConstant.Builder(new Constant("e"), 181d);
mathEngine.getConstantsRegistry().addOrUpdate(e.create()); mathEngine.getConstantsRegistry().addOrUpdate(e.create());
final CustomFunction.Builder jBuilder6 = new CustomFunction.Builder("testFunction7", Arrays.asList("a", "b"), "testFunction(a, b!, 4!, e)"); final CustomFunction.Builder jBuilder6 = new CustomFunction.Builder("testFunction7", asList("a", "b"), "testFunction(a, b!, 4!, e)");
mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder6.create()); mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder6.create());
assertEquals("181.2498477067548", Expression.valueOf("testFunction7(2, 3)").numeric().toString()); assertEquals("181.2498477067548", Expression.valueOf("testFunction7(2, 3)").numeric().toString());
final ExtendedConstant.Builder e1 = new ExtendedConstant.Builder(new Constant("e"), 181d); final ExtendedConstant.Builder e1 = new ExtendedConstant.Builder(new Constant("e"), 181d);
mathEngine.getConstantsRegistry().addOrUpdate(e1.create()); mathEngine.getConstantsRegistry().addOrUpdate(e1.create());
final CustomFunction.Builder jBuilder7 = new CustomFunction.Builder("testFunction8", Arrays.asList("a", "b"), "testFunction(sin(a), b!, 4!, e)"); final CustomFunction.Builder jBuilder7 = new CustomFunction.Builder("testFunction8", asList("a", "b"), "testFunction(sin(a), b!, 4!, e)");
mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder7.create()); mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder7.create());
assertEquals("181.249999953623", Expression.valueOf("testFunction8(2, 3)").numeric().toString()); assertEquals("181.249999953623", Expression.valueOf("testFunction8(2, 3)").numeric().toString());
@ -163,11 +167,11 @@ public class CustomFunctionTest {
public void testFunction2() throws Exception { public void testFunction2() throws Exception {
JsclMathEngine mathEngine = JsclMathEngine.getInstance(); JsclMathEngine mathEngine = JsclMathEngine.getInstance();
final CustomFunction.Builder jBuilder = new CustomFunction.Builder("f", Arrays.asList("x", "y"), "z1/z2*√(x^2+y^2)"); final CustomFunction.Builder jBuilder = new CustomFunction.Builder("f", asList("x", "y"), "z1/z2*√(x^2+y^2)");
mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder.create()); mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder.create());
final CustomFunction.Builder jBuilder1 = new CustomFunction.Builder("f2", Arrays.asList("x", "y"), "√(x^2+y^2)"); final CustomFunction.Builder jBuilder1 = new CustomFunction.Builder("f2", asList("x", "y"), "√(x^2+y^2)");
mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder1.create()); mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder1.create());
final CustomFunction.Builder jBuilder2 = new CustomFunction.Builder("f3", Arrays.asList("x", "y"), "x^2+y^2"); final CustomFunction.Builder jBuilder2 = new CustomFunction.Builder("f3", asList("x", "y"), "x^2+y^2");
mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder2.create()); mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder2.create());
try { try {
@ -184,11 +188,32 @@ public class CustomFunctionTest {
assertEquals("2*z2", Expression.valueOf("∂(f3(z1, z2), z2)").expand().toString()); assertEquals("2*z2", Expression.valueOf("∂(f3(z1, z2), z2)").expand().toString());
// test symbols // test symbols
final CustomFunction.Builder jBuilder3 = new CustomFunction.Builder("f4", Arrays.asList("x", "y"), "2 000*x^2+y^2"); final CustomFunction.Builder jBuilder3 = new CustomFunction.Builder("f4", asList("x", "y"), "2 000*x^2+y^2");
mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder3.create()); mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder3.create());
final CustomFunction.Builder jBuilder4 = new CustomFunction.Builder("f5", Arrays.asList("x", "y"), "2'000* x ^2+y^2\r"); final CustomFunction.Builder jBuilder4 = new CustomFunction.Builder("f5", asList("x", "y"), "2'000* x ^2+y^2\r");
mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder4.create()); mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder4.create());
}
@Test
public void testNumbersAreReadInBinMode() throws Exception {
final JsclMathEngine me = JsclMathEngine.getInstance();
me.setNumeralBase(NumeralBase.bin);
final CustomFunction f = new CustomFunction.Builder("test", asList("x", "y"), "2000*x-0.001*y").create();
assertEquals(NumeralBase.bin, me.getNumeralBase());
me.setNumeralBase(NumeralBase.dec);
assertEquals("2000*x-0.001*y", f.getContent());
}
@Test
public void testInvalidFunctionShouldReturnNumeralBase() throws Exception {
final JsclMathEngine me = JsclMathEngine.getInstance();
me.setNumeralBase(NumeralBase.bin);
try {
new CustomFunction.Builder("test", Collections.<String>emptyList(), "2000*").create();
fail();
} catch (CustomFunctionCalculationException ignored) {
}
assertEquals(NumeralBase.bin, me.getNumeralBase());
me.setNumeralBase(NumeralBase.dec);
} }
} }