diff --git a/jscl/src/main/java/jscl/math/function/CustomFunction.java b/jscl/src/main/java/jscl/math/function/CustomFunction.java index e6327656..0ef7d8e9 100644 --- a/jscl/src/main/java/jscl/math/function/CustomFunction.java +++ b/jscl/src/main/java/jscl/math/function/CustomFunction.java @@ -3,6 +3,7 @@ package jscl.math.function; import com.google.common.collect.Lists; import jscl.CustomFunctionCalculationException; import jscl.JsclMathEngine; +import jscl.NumeralBase; import jscl.math.*; import jscl.text.ParseException; import jscl.text.msg.JsclMessage; @@ -59,11 +60,21 @@ public class CustomFunction extends Function implements IFunction { @Nullable String description) throws CustomFunctionCalculationException { super(name, new Generic[parameterNames.size()]); 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 { this.content = Expression.valueOf(content); ensureNoImplicitFunctions(); } catch (ParseException e) { throw new CustomFunctionCalculationException(this, e); + } finally { + if (nb != NumeralBase.dec) { + engine.setNumeralBase(nb); + } } this.description = description; this.id = counter.incrementAndGet(); diff --git a/jscl/src/test/java/jscl/math/function/CustomFunctionTest.java b/jscl/src/test/java/jscl/math/function/CustomFunctionTest.java index 009a91fc..3d03fc7b 100644 --- a/jscl/src/test/java/jscl/math/function/CustomFunctionTest.java +++ b/jscl/src/test/java/jscl/math/function/CustomFunctionTest.java @@ -1,15 +1,19 @@ package jscl.math.function; import jscl.AngleUnit; +import jscl.CustomFunctionCalculationException; import jscl.JsclMathEngine; +import jscl.NumeralBase; import jscl.math.Expression; import jscl.text.ParseException; import org.junit.Assert; 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.fail; /** * User: serso @@ -26,7 +30,7 @@ public class CustomFunctionTest { assertEquals("∞", Expression.valueOf("ln(10)/ln(1)").numeric().toString()); // 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()); assertEquals("log(a, b)", function.toString()); assertEquals("ln(b)/ln(a)", ((CustomFunction) mathEngine.getFunctionsRegistry().get("log")).getContent()); @@ -43,14 +47,14 @@ public class CustomFunctionTest { public void testDerivative() throws Exception { 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()); assertEquals("1", Expression.valueOf("t1(90)").numeric().toString()); assertEquals("cos(t)", Expression.valueOf("∂(t1(t), t)").expand().toString()); assertEquals("0", Expression.valueOf("∂(t1(t), t2)").expand().toString()); assertEquals("cos(a)", Expression.valueOf("∂(t1(a), 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()); assertEquals("y*cos(x)", Expression.valueOf("∂(t2(x, y), x)").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 { 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()); 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("-cos(a)", Expression.valueOf("∫(t1(a), 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()); 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()); @@ -85,7 +89,7 @@ public class CustomFunctionTest { public void testFunction() throws Exception { 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()); assertEquals("6.749543120264322", Expression.valueOf("testFunction(2, 3, 4, 6)").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); 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()); 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("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()); - 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()); 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*1, 3, 4, 6)").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()); 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("-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()); - 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()); 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()); assertEquals("180.2498477067548", Expression.valueOf("testFunction6(2, 3)").numeric().toString()); final ExtendedConstant.Builder e = new ExtendedConstant.Builder(new Constant("e"), 181d); 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()); assertEquals("181.2498477067548", Expression.valueOf("testFunction7(2, 3)").numeric().toString()); final ExtendedConstant.Builder e1 = new ExtendedConstant.Builder(new Constant("e"), 181d); 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()); assertEquals("181.249999953623", Expression.valueOf("testFunction8(2, 3)").numeric().toString()); @@ -163,11 +167,11 @@ public class CustomFunctionTest { public void testFunction2() throws Exception { 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()); - 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()); - 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()); try { @@ -184,11 +188,32 @@ public class CustomFunctionTest { assertEquals("2*z2", Expression.valueOf("∂(f3(z1, z2), z2)").expand().toString()); // 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()); - 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()); + } + @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.emptyList(), "2000*").create(); + fail(); + } catch (CustomFunctionCalculationException ignored) { + } + assertEquals(NumeralBase.bin, me.getNumeralBase()); + me.setNumeralBase(NumeralBase.dec); } }