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.Collections; import static java.util.Arrays.asList; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; /** * User: serso * Date: 11/15/11 * Time: 5:35 PM */ public class CustomFunctionTest { @Test public void testLog() throws Exception { JsclMathEngine mathEngine = JsclMathEngine.getInstance(); assertEquals("∞", Expression.valueOf("1/0").numeric().toString()); assertEquals("∞", Expression.valueOf("ln(10)/ln(1)").numeric().toString()); // logarithm 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()); assertEquals("∞", Expression.valueOf("log(1, 10)").numeric().toString()); assertEquals("3.321928094887363", Expression.valueOf("log(2, 10)").numeric().toString()); assertEquals("1.430676558073393", Expression.valueOf("log(5, 10)").numeric().toString()); assertEquals("0.960252567789128", Expression.valueOf("log(11, 10)").numeric().toString()); assertEquals("1/b*1/ln(a)", Expression.valueOf("∂(log(a, b), b)").expand().toString()); assertEquals("-1/a*(1/ln(a))^2*ln(b)", Expression.valueOf("∂(log(a, b), a)").expand().toString()); } @Test public void testDerivative() throws Exception { JsclMathEngine mathEngine = JsclMathEngine.getInstance(); 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", 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()); } @Test public void testAntiDerivative() throws Exception { JsclMathEngine mathEngine = JsclMathEngine.getInstance(); 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()); try { mathEngine.setAngleUnits(AngleUnit.rad); assertEquals("-cos(t)", Expression.valueOf("∫(t1(t), t)").expand().toString()); 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", 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()); } finally { mathEngine.setAngleUnits(AngleUnit.deg); } } @Test public void testFunction() throws Exception { JsclMathEngine mathEngine = JsclMathEngine.getInstance(); 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()); assertEquals("6.749543120264322", Expression.valueOf("testFunction(2*1, 3, 4, 6)").numeric().toString()); assertEquals("6.749543120264322", Expression.valueOf("testFunction(2*1, 3, 4, 3!)").numeric().toString()); assertEquals("6.749543120264322", Expression.valueOf("testFunction(2*1, 3, 2^2-1+e^0, 3!)").numeric().toString()); assertEquals("testFunction(2, 3, 4, 3!)", Expression.valueOf("testFunction(2*1, 3, 2^2-1+e^0, 3!)").simplify().toString()); assertEquals("3*cos(2)/4+3!", Expression.valueOf("testFunction(2*1, 3, 2^2-1+e^0, 3!)").expand().toString()); assertEquals("3*(1/2*1/exp(2*i)+1/2*exp(2*i))/4+3!", Expression.valueOf("testFunction(2*1, 3, 2^2-1+e^0, 3!)").elementary().toString()); assertEquals("sin(t)^2*testFunction(2, 3, 4, 3!)", Expression.valueOf("sin(t)*testFunction(2*1, 3, 2^2-1+e^0, 3!)*sin(t)").simplify().toString()); assertEquals("testFunction(2, 3, 4, 3!)^2", Expression.valueOf("testFunction(2*1, 3, 2^2-1+e^0, 3!)*testFunction(2, 3, 4, 3!)").simplify().toString()); try { Expression.valueOf("testFunction(2*1, 3, 2^2-1+e^0, 3!)*testFunction(2, 3, 4)"); Assert.fail(); } catch (ParseException e) { // ok, not enough parameters } final ExtendedConstant.Builder a = new ExtendedConstant.Builder(new Constant("a"), 1000d); mathEngine.getConstantsRegistry().addOrUpdate(a.create()); 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", 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", 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", asList("a", "b"), "testFunction2(a, b/2, 2, 1) - testFunction(a, b!, 4!, 1)"); mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder4.create()); assertEquals("0.499695413509548", Expression.valueOf("testFunction5(2, 3)").numeric().toString()); assertEquals("0.499695413509548", Expression.valueOf("testFunction5(2, 3)").numeric().toString()); assertEquals("0.499695413509548", Expression.valueOf("testFunction5(2*1, 3)").numeric().toString()); assertEquals("0", Expression.valueOf("testFunction5(2*1, 2^2-1+e^0)").numeric().toString()); try { Expression.valueOf("testFunction5(2, 3.5)").numeric(); Assert.fail(); } catch (ArithmeticException e) { } 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", 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", asList("a", "b"), "testFunction(sin(a), b!, 4!, e)"); mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder7.create()); assertEquals("181.249999953623", Expression.valueOf("testFunction8(2, 3)").numeric().toString()); } @Test public void testFunction2() throws Exception { JsclMathEngine mathEngine = JsclMathEngine.getInstance(); 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", asList("x", "y"), "√(x^2+y^2)"); mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder1.create()); final CustomFunction.Builder jBuilder2 = new CustomFunction.Builder("f3", asList("x", "y"), "x^2+y^2"); mathEngine.getFunctionsRegistry().addOrUpdate(jBuilder2.create()); try { assertEquals("1", Expression.valueOf("f(1, 1)").numeric().toString()); Assert.fail(); } catch (ArithmeticException e) { //ok } assertEquals("1.414213562373095", Expression.valueOf("f2(1, 1)").numeric().toString()); assertEquals("5", Expression.valueOf("f2(4, 3)").numeric().toString()); assertEquals("2*z1", Expression.valueOf("∂(f3(z1, z2), z1)").expand().toString()); assertEquals("2*z2", Expression.valueOf("∂(f3(z1, z2), z2)").expand().toString()); // test symbols 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", 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.<String>emptyList(), "2000*").create(); fail(); } catch (CustomFunctionCalculationException ignored) { } assertEquals(NumeralBase.bin, me.getNumeralBase()); me.setNumeralBase(NumeralBase.dec); } }