diff options
Diffstat (limited to 'macros/luatex/latex/luacas/tex/test')
20 files changed, 1910 insertions, 0 deletions
diff --git a/macros/luatex/latex/luacas/tex/test/calculus/derivatives.lua b/macros/luatex/latex/luacas/tex/test/calculus/derivatives.lua new file mode 100644 index 0000000000..5d5429f59b --- /dev/null +++ b/macros/luatex/latex/luacas/tex/test/calculus/derivatives.lua @@ -0,0 +1,30 @@ +local a = DD(SymbolExpression("x") * SymbolExpression("y"), SymbolExpression("x")) +local b = DD(Integer(3) * SymbolExpression("x") ^ Integer(2) + Integer(2) * SymbolExpression("x") + Integer(6), SymbolExpression("x")) +local c = DD(E ^ SymbolExpression("x"), SymbolExpression("x")) +local d = DD(FunctionExpression("f", {SymbolExpression("x") ^ Integer(2)})) +local e = DD(SymbolExpression("x") ^ SymbolExpression("x")) +local f = DD(PolynomialRing({Integer(3), Integer(4), Integer(5)}, "x")) +local g = DD(LN(SymbolExpression("y")), SymbolExpression("y")) +local h = DD(SymbolExpression("x") ^ SymbolExpression("n")) +local i = DD(SIN((SymbolExpression("x")))) +local j = DD(SIN(Integer(2) * COS(SymbolExpression("x")))) +local k = DD(ARCTAN(SymbolExpression("x") ^ (Integer(1) / Integer(2)))) +local l = DD(ARCSEC(SymbolExpression("x"))) + +starttest("derivatives") + +testeq(a, dparse("DD(x*y, x)")) +testeq(a:autosimplify(), parse("y"), a) +testeq(b:autosimplify(), parse("6 * x + 2"), b) +testeq(c:autosimplify(), parse("e^x"), c) +testeq(d:autosimplify(), (Integer(2) * SymbolExpression("x") * FunctionExpression("f", {SymbolExpression("x")^Integer(2)}, {Integer(1)})):autosimplify(), d) +testeq(e:autosimplify(), parse("x^x * (1 + ln(x))"), e) +testeq(f:autosimplify(), parse("4 + 10 * x"), f) +testeq(g:autosimplify(), parse("y ^ -1"), g) +testeq(h:autosimplify(), parse("n * x ^ (-1 + n)"), h) +testeq(i:autosimplify(), parse("cos(x)"), i) +testeq(j:autosimplify(), parse("-2 * cos(2 * cos(x)) * sin(x)"), j) +testeq(k:autosimplify(), parse("1/2 * x^(-1/2) * (1+x) ^ -1"), k) +testeq(l:autosimplify(), parse("abs(x)^-1 * (1 + -(x^2))^ (-1/2)"), l) + +endtest()
\ No newline at end of file diff --git a/macros/luatex/latex/luacas/tex/test/calculus/integrals.lua b/macros/luatex/latex/luacas/tex/test/calculus/integrals.lua new file mode 100644 index 0000000000..0c12f7a787 --- /dev/null +++ b/macros/luatex/latex/luacas/tex/test/calculus/integrals.lua @@ -0,0 +1,54 @@ +local a = dparse("int(x^2, x)") +local b = dparse("int(x^-1, x, 1, e)") +local c = dparse("int(3*x^2+2*x+6, x)") +local d = dparse("int(sin(x)*cos(x), x)") +local e = dparse("int(2*x*cos(x^2), x)") +local f = dparse("int(sin(2*x), x)") +local g = dparse("int(e^sin(x), x)") +local h = dparse("int((1 / (1 + (1 / x))), x)") +local i = dparse("int(e^(x^(1/2)), x)") +local j = dparse("int((x^3+1)/(x-2), x)") +local k = dparse("int((x^2-x+1)/(x^3+3*x^2+3*x+1), x)") +local l = dparse("int(1 / (x^3+6*x), x)") +local m = dparse("int(1/(x^2+x+1), x)") +local n = dparse("int(1/(x^3+2*x+2), x, 0, 1)") + +local o = dparse("int(x^2*e^x, x)") +local p = dparse("int((x^2+6*x+3)*sin(x), x)") +local q = dparse("int(x*e^x*sin(x),x)") +local r = dparse("int(cos(x)^3, x)") +local s = dparse("int(1/(e^x+1), x)") +local t = dparse("int(e^(2*x)*cos(3*x), x)") +local u = dparse("int((x^2-1)^2, x, -1, 1)") + +starttest("integration") +testeq(a, dparse("int(x ^ 2, x)")) +testeq(a:autosimplify(), parse("x^3/3"), a) +testeq(b:autosimplify(), parse("1"), b) +testeq(c:autosimplify(), parse("x^3+x^2+6*x"), c) +testeq(d:autosimplify(), parse("(-1/2 * (cos(x) ^ 2))"), d) +testeq(e:autosimplify(), parse("sin((x ^ 2))"), e) +testeq(f:autosimplify(), parse("(-1/2 * cos((2 * x)))"), f) +-- testeq(g:autosimplify(), dparse("int(e ^ (sin(x)), x)"), g) +testeq(h:autosimplify(), parse("x + (-1 * (log(e, 1 + (x ^ -1)))) + (-1 * (log(e, x)))"), h) +testeq(i:autosimplify(), parse("-2 * (e ^ (x ^ (1/2))) + 2 * (e ^ (x ^ (1/2))) * (x ^ (1/2))"), i) +testeq(j:autosimplify(), parse("((4 * x) + (x ^ 2) + (1/3 * (x ^ 3)) + (9 * log(e, (-2 + x))))"), j) +testeq(k:autosimplify(), parse("((-3/2 * ((1 + x) ^ -2)) + (3 * ((1 + x) ^ -1)) + log(e, (1 + x)))"), k) +testeq(l:autosimplify(), parse("((1/6 * log(e, x)) + (-1/12 * log(e, (6 + (x ^ 2)))))"), l) +testeq(m:autosimplify(), parse("2/3 * (3 ^ (1/2)) * (arctan((3 ^ (1/2)) * (1/3 + (2/3 * x))))"), m) +-- test(n:autosimplify(), [[((((6 * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ -1/3)) + (1/420 * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ 1/3))) +-- * log(e, (18 * (((-6 * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ -1/3)) + (-1/420 * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ 1/3))) ^ 2) * (((-18 * ((-264600 + (1/2 +-- * (216040608000 ^ 1/2))) ^ -1/3)) + (-1/140 * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ 1/3)) + (12 * (((-6 * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ -1/3)) + (-1/420 * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ 1/3))) ^ 2))) ^ -1)))) + (((6 * ((-1/2 + (1/2 * (-3 ^ 1/2))) ^ -1) * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ -1/3)) + ((-1/840 + (1/840 * (-3 ^ 1/2))) * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ 1/3))) * log(e, (18 * (((-6 * ((-1/2 + (1/2 * (-3 ^ 1/2))) ^ -1) * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ -1/3)) + ((1/840 + (-1/840 * (-3 ^ 1/2))) * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ 1/3))) ^ 2) * (((-18 * ((-1/2 + (1/2 * (-3 ^ 1/2))) ^ -1) * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ -1/3)) + ((1/280 + (-1/280 * (-3 ^ 1/2))) * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ 1/3)) + (12 * (((-6 * ((-1/2 + (1/2 * (-3 ^ 1/2))) ^ -1) * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ -1/3)) + ((1/840 + (-1/840 * (-3 ^ 1/2))) * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ 1/3))) ^ 2))) ^ -1)))) + (((6 * ((-1/2 + (1/2 * (-3 ^ 1/2))) ^ -2) * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ -1/3)) + (1/420 * ((-1/2 + (1/2 * (-3 ^ 1/2))) ^ 2) * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ 1/3))) * log(e, (18 * (((-6 * ((-1/2 + (1/2 * (-3 ^ 1/2))) ^ -2) * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ -1/3)) + (-1/420 * ((-1/2 + (1/2 * (-3 ^ 1/2))) ^ 2) * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ 1/3))) ^ 2) * (((-18 * ((-1/2 + (1/2 * (-3 ^ 1/2))) ^ -2) * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ -1/3)) + (-1/140 * ((-1/2 + (1/2 * (-3 ^ 1/2))) ^ 2) * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ 1/3)) + (12 * (((-6 * ((-1/2 + (1/2 * (-3 ^ 1/2))) ^ -2) * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ -1/3)) + (-1/420 * ((-1/2 + (1/2 * (-3 ^ 1/2))) ^ 2) * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ 1/3))) ^ 2))) ^ -1)))) + (((-6 * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ -1/3)) + (-1/420 * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ 1/3))) * log(e, (1 + (18 * (((-6 * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ -1/3)) + (-1/420 * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ 1/3))) ^ 2) * (((-18 * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ -1/3)) + (-1/140 * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ 1/3)) + (12 * (((-6 * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ -1/3)) + (-1/420 * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ 1/3))) ^ 2))) ^ -1))))) + (((-6 * ((-1/2 + (1/2 * (-3 ^ 1/2))) ^ -1) * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ -1/3)) + ((1/840 + (-1/840 * (-3 ^ 1/2))) * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ 1/3))) * log(e, (1 + (18 * (((-6 * ((-1/2 + (1/2 * (-3 ^ 1/2))) ^ -1) * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ -1/3)) + ((1/840 + (-1/840 * (-3 ^ 1/2))) * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ 1/3))) ^ 2) * (((-18 * ((-1/2 + (1/2 * (-3 ^ 1/2))) ^ -1) * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ -1/3)) + ((1/280 + (-1/280 * (-3 ^ 1/2))) * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ 1/3)) + (12 * (((-6 * ((-1/2 + (1/2 * (-3 ^ 1/2))) ^ -1) * ((-264600 + (1/2 * (216040608000 +-- ^ 1/2))) ^ -1/3)) + ((1/840 + (-1/840 * (-3 ^ 1/2))) * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ 1/3))) ^ 2))) ^ -1))))) + (((-6 * ((-1/2 + (1/2 * (-3 ^ 1/2))) ^ -2) * +-- ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ -1/3)) + (-1/420 * ((-1/2 + (1/2 * (-3 ^ 1/2))) ^ 2) * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ 1/3))) * log(e, (1 + (18 * +-- (((-6 * ((-1/2 + (1/2 * (-3 ^ 1/2))) ^ -2) * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ -1/3)) + (-1/420 * ((-1/2 + (1/2 * (-3 ^ 1/2))) ^ 2) * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ 1/3))) ^ 2) * (((-18 * ((-1/2 + (1/2 * (-3 ^ 1/2))) ^ -2) * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ -1/3)) + (-1/140 * ((-1/2 + (1/2 * (-3 ^ 1/2))) +-- ^ 2) * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ 1/3)) + (12 * (((-6 * ((-1/2 + (1/2 * (-3 ^ 1/2))) ^ -2) * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ -1/3)) + (-1/420 * ((-1/2 + (1/2 * (-3 ^ 1/2))) ^ 2) * ((-264600 + (1/2 * (216040608000 ^ 1/2))) ^ 1/3))) ^ 2))) ^ -1))))))]], n) + +testeq(o:autosimplify(), parse("((2 * (e ^ x)) + (-2 * (e ^ x) * x) + ((e ^ x) * (x ^ 2)))"), o) +testeq(p:autosimplify(), parse("((2 * cos(x)) + ((-3 + (-6 * x) + (-1 * (x ^ 2))) * cos(x)) + ((6 + (2 * x)) * sin(x)))"), p) +testeq(q:autosimplify(), parse("(1/2 * (e ^ x) * (cos(x))) + (-1/2 * (e ^ x) * x * (cos(x))) + (1/2 * (e ^ x) * x * (sin(x)))"), q) +testeq(r:autosimplify(), parse("((3/4 * sin(x)) + (1/12 * sin((3 * x))))"), r) +testeq(s:autosimplify(), parse("log(e, 1 + (-1 * ((1 + (e ^ x)) ^ -1)))"), s) +testeq(t:autosimplify(), parse("(2/13 * (e ^ (2 * x)) * (cos(3 * x))) + (3/13 * (e ^ (2 * x)) * (sin(3 * x)))"), t) +testeq(u:autosimplify(), parse("16/15"), u) +endtest() diff --git a/macros/luatex/latex/luacas/tex/test/expressions/autosimplify.lua b/macros/luatex/latex/luacas/tex/test/expressions/autosimplify.lua new file mode 100644 index 0000000000..09ad9874cd --- /dev/null +++ b/macros/luatex/latex/luacas/tex/test/expressions/autosimplify.lua @@ -0,0 +1,199 @@ +local a = BinaryOperation.ADDEXP + ({Integer(3), + Integer(5)}) + +local b = BinaryOperation.MULEXP + ({BinaryOperation.ADDEXP + ({Integer(13), + Integer(12)}), + Integer(-4)}) + +local c = BinaryOperation.DIVEXP + ({SymbolExpression("x"), + SymbolExpression("y")}) + +local d = BinaryOperation.DIVEXP + ({BinaryOperation.ADDEXP + ({Integer(4), + Integer(-3)}), + SymbolExpression("y")}) + +local e = BinaryOperation.ADDEXP + ({Integer(3), + Integer(4), + Integer(5), + Integer(6)}) + +starttest("expression construction") +testeq(a, "3 + 5") +testeq(b, "(13 + 12) * -4") +testeq(c, "x / y") +testeq(d, "(4 + -3) / y") +testeq(e, "3 + 4 + 5 + 6") +endtest() + +starttest("expression evaluation...") +testeq(a:evaluate(), dparse("8")) +testeq(b:evaluate(), dparse("-100")) +testeq(c:evaluate(), dparse("(x / y)")) +testeq(d:evaluate(), dparse("(1 / y)")) +testeq(e:evaluate(), dparse("18")) +endtest() + +local g = BinaryOperation.POWEXP + ({Integer(0), + SymbolExpression("x")}) + +local h = BinaryOperation.POWEXP + ({Integer(1), + SymbolExpression("x")}) + +local i = BinaryOperation.POWEXP + ({SymbolExpression("x"), + Integer(0)}) + +local j = BinaryOperation.POWEXP + ({SymbolExpression("x"), + Integer(1)}) + +local k = BinaryOperation.POWEXP + ({SymbolExpression("x"), + SymbolExpression("y")}) + +local l = BinaryOperation.POWEXP + ({BinaryOperation.POWEXP + ({BinaryOperation.POWEXP + ({SymbolExpression("x"), + Integer(3)}), + Integer(4)}), + Integer(5)}) + +local m = BinaryOperation.POWEXP + ({BinaryOperation.MULEXP + ({SymbolExpression("x"), + SymbolExpression("y")}), + SymbolExpression("a")}) + + local n = BinaryOperation.MULEXP + ({SymbolExpression("x"), + SymbolExpression("y"), + Integer(0), + Integer(-2) + }) + +local o = BinaryOperation.MULEXP + ({SymbolExpression("x"), + BinaryOperation.MULEXP + ({SymbolExpression("y"), + SymbolExpression("z")})}) + +local p = BinaryOperation.MULEXP + ({SymbolExpression("x")}) + +local q = BinaryOperation.MULEXP + ({SymbolExpression("x"), SymbolExpression("x"), SymbolExpression("x"), SymbolExpression("x")}) + +local r = BinaryOperation.MULEXP + ({SymbolExpression("x"), Integer(3), SymbolExpression("a")}) + + local s = BinaryOperation.ADDEXP + ({SymbolExpression("x")}) + +local t = BinaryOperation.ADDEXP + ({SymbolExpression("x"), + BinaryOperation.ADDEXP + ({Integer(3), + SymbolExpression("y")})}) + +local u = BinaryOperation.ADDEXP + ({BinaryOperation.MULEXP + ({SymbolExpression("x"), + SymbolExpression("y")}), + BinaryOperation.MULEXP + ({SymbolExpression("y"), + SymbolExpression("x")})}) + +local v = BinaryOperation.ADDEXP + ({Integer(3), + BinaryOperation.ADDEXP + ({BinaryOperation.MULEXP + ({Integer(2), + BinaryOperation.POWEXP + ({SymbolExpression("x"), + Integer(2)})}), + BinaryOperation.ADDEXP + ({BinaryOperation.MULEXP + ({Integer(1), + SymbolExpression("y")}), + BinaryOperation.MULEXP + ({Integer(0), + SymbolExpression("x")})})}), + Integer(6)}) + + local w = BinaryOperation.MULEXP + ({BinaryOperation.DIVEXP + ({Integer(1), + SymbolExpression("x")}), + SymbolExpression("x")}) + +local x = BinaryOperation.MULEXP + ({BinaryOperation.DIVEXP + ({SymbolExpression("y"), + SymbolExpression("x")}), + BinaryOperation.DIVEXP + ({SymbolExpression("x"), + SymbolExpression("y")})}) + +local y = BinaryOperation.MULEXP + ({BinaryOperation.DIVEXP + ({Integer(1), + Integer(3)}), + SymbolExpression("x")}) + +local z = BinaryOperation.ADDEXP + ({SymbolExpression("x"), + SymbolExpression("y"), + BinaryOperation.SUBEXP + ({SymbolExpression("x"), + SymbolExpression("y")})}) + +local A = dparse("(-aa-x)+(x+aa)") + +starttest("expression autosimplification") +testeq(g:autosimplify(), parse("0"), g) +testeq(h:autosimplify(), parse("1"), h) +testeq(i:autosimplify(), parse("1"), i) +testeq(j:autosimplify(), parse("x"), j) +testeq(k:autosimplify(), parse("x ^ y"), k) +testeq(l:autosimplify(), parse("(x ^ 60)"), l) +testeq(m:autosimplify(), parse("((x * y) ^ a)"), m) +testeq(n:autosimplify(), parse("0"), n) +testeq(o:autosimplify(), parse("(x * y * z)"), o) +testeq(p:autosimplify(), parse("x"), p) +testeq(q:autosimplify(), parse("(x ^ 4)"), q) +testeq(r:autosimplify(), parse("(3 * a * x)"), r) +testeq(s:autosimplify(), parse("x"), s) +testeq(t:autosimplify(), parse("(3 + x + y)"), t) +testeq(u:autosimplify(), parse("(2 * x * y)"), u) +testeq(v:autosimplify(), parse("(9 + (2 * (x ^ 2)) + y)"), v) +testeq(w:autosimplify(), parse("1"), w) +testeq(x:autosimplify(), parse("1"), x) +testeq(y:autosimplify(), parse("(1/3 * x)"), y) +testeq(z:autosimplify(), parse("(2 * x)"), z) +testeq(A:autosimplify(), parse("0"), A) +endtest() + + +local aa = SymbolExpression("x") + SymbolExpression("y") + SymbolExpression("z") +local ab = -(SymbolExpression("x") / SymbolExpression("y")) +local ac = Integer(2)*SymbolExpression("x")*SymbolExpression("y") - Integer(3)*SymbolExpression("x")*SymbolExpression("z") + +starttest("metamethod expressions") + +testeq(aa, dparse("(x + y) + z")) +testeq(aa:autosimplify(), parse("(x + y + z)"), aa) +testeq(ab, dparse("- (x / y)")) +testeq(ab:autosimplify(), parse("(-1 * x * (y ^ -1))"), ab) +testeq(ac:autosimplify(), parse("((2 * x * y) + (-3 * x * z))"), ac) + +endtest()
\ No newline at end of file diff --git a/macros/luatex/latex/luacas/tex/test/expressions/collect.lua b/macros/luatex/latex/luacas/tex/test/expressions/collect.lua new file mode 100644 index 0000000000..b40e8e3d09 --- /dev/null +++ b/macros/luatex/latex/luacas/tex/test/expressions/collect.lua @@ -0,0 +1,26 @@ +local x = SymbolExpression("x") +local ex = parse("e^x") +local lnx = parse("ln(x)") + +local a = parse("y^2") +local b = parse("x + y + 1") +local c = parse("x*(y+1)+x+3*x*y^2") +local d = parse("x^2+2*x*y+y^2+x") +local e = parse("(x*y+x)^2+x^2") +local f = parse("-x^2/e^x-2*x/e^x-2/e^x+x^2*e^x-2*x*e^x+2*e^x") +local g = parse("x^(-2)+y*x^(-2)+z*x^2+2*x^2") +local h = parse("a*ln(x)-ln(x)*x-x") + + +starttest("collect method") + +testeq(a:collect(x), parse("y^2"), a) +testeq(b:collect(x), parse("x + y + 1"), b) +testeq(c:collect(x), parse("(3*y^2+y+2)*x"), c) +testeq(d:collect(x), parse("x^2+(2*y+1)*x+y^2"), d) +testeq(e:collect(x), parse("((y+1)^2+1)*x^2"), e) +testeq(f:collect(ex), parse("(x^2-2*x+2)*e^x+(-x^2-2*x-2)/e^x"), f) +testeq(g:collect(x), parse("(y+1)*x^(-2)+(z+2)*x^2"), g) +testeq(h:collect(lnx), parse("(a-x)*ln(x)-x"), h) + +endtest()
\ No newline at end of file diff --git a/macros/luatex/latex/luacas/tex/test/expressions/equations.lua b/macros/luatex/latex/luacas/tex/test/expressions/equations.lua new file mode 100644 index 0000000000..3d6aa131fc --- /dev/null +++ b/macros/luatex/latex/luacas/tex/test/expressions/equations.lua @@ -0,0 +1,17 @@ +local a = Equation(parse("2^x"), parse("1")) +local b = Equation(parse("x^2+2*x+1"), parse("0")) +local c = Equation(parse("2*x^x"), parse("3*y")) +local d = Equation(parse("e^x+1"), parse("y")) +local e = Equation(parse("z*sin(x/2)"), parse("4")) +local f = Equation(parse("4"), parse("0")) + + +starttest("equation solving") +testeq(a:solvefor(parse("x")), Equation(parse("x"), parse("0")), a) +testeq(b:solvefor(parse("x")), Equation(parse("x"), parse("-1")), b) -- This will need to be fixed once set expressions are woring +testeq(c:solvefor(parse("x")), Equation(parse("x^x"), parse("3/2*y")), c) +testeq(c:solvefor(parse("y")), Equation(parse("y"), parse("2/3*x^x")), c) +testeq(d:solvefor(parse("x")), Equation(parse("x"), parse("ln(y - 1)")), d) +testeq(e:solvefor(parse("x")), Equation(parse("x"), parse("2*arcsin(4/z)")), e) +testeq(f:autosimplify(), "false", f) -- Same, with boolean expressions +endtest()
\ No newline at end of file diff --git a/macros/luatex/latex/luacas/tex/test/expressions/functions.lua b/macros/luatex/latex/luacas/tex/test/expressions/functions.lua new file mode 100644 index 0000000000..e2c15096d6 --- /dev/null +++ b/macros/luatex/latex/luacas/tex/test/expressions/functions.lua @@ -0,0 +1,17 @@ +local a = FunctionExpression("f", + {SymbolExpression("x"), + BinaryOperation.MULEXP + ({SymbolExpression("x"), + Integer(2)})}) + +local b = BinaryOperation.ADDEXP + ({FunctionExpression("g", + {SymbolExpression("x")}), + FunctionExpression("f", + {SymbolExpression("x")}), + Integer(4)}) + +starttest("function expressions") +testeq(a:autosimplify(), parse("f(x, (2 * x))"), a) +testeq(b:autosimplify(), parse("(4 + f(x) + g(x))"), b) +endtest()
\ No newline at end of file diff --git a/macros/luatex/latex/luacas/tex/test/expressions/logarithms.lua b/macros/luatex/latex/luacas/tex/test/expressions/logarithms.lua new file mode 100644 index 0000000000..2813a6b8f5 --- /dev/null +++ b/macros/luatex/latex/luacas/tex/test/expressions/logarithms.lua @@ -0,0 +1,26 @@ +local a = LN(SymbolExpression("x")) +local b = LN(BinaryOperation.POWEXP({E, SymbolExpression("x")})) +local c = BinaryOperation.POWEXP({Integer(2), LOG(Integer(2), SymbolExpression("y"))}) +local d = dparse("e^(-x*ln(x))") + +local e = Logarithm(Integer(2), Integer(256)) +local f = Logarithm(Integer(4), Integer(8)) +local g = Logarithm(Integer(1)/Integer(5), Integer((125))) +local h = Logarithm(Integer(1)/Integer(9), Integer(1)/Integer(243)) +local i = Logarithm(Integer(1)/Integer(25), Integer(3125)) + +local k = Logarithm(E, Integer(1)/Integer(9)) + +starttest("logarithms") +testeq(a, "log(e, x)") +testeq(a:autosimplify(), "log(e, x)", a) +testeq(b:autosimplify(), "x", b) +testeq(c:autosimplify(), "y", c) +testeq(d:autosimplify(), parse("x^(-x)"), d) +testeq(e:autosimplify(), parse("8"), e) +testeq(f:autosimplify(), parse("3/2"), f) +testeq(g:autosimplify(), parse("-3"), g) +testeq(h:autosimplify(), parse("5/2"), h) +testeq(i:autosimplify(), parse("-5/2"), i) +testeq(k:autosimplify(), parse("-ln(9)"), k) +endtest()
\ No newline at end of file diff --git a/macros/luatex/latex/luacas/tex/test/expressions/rationalexponent.lua b/macros/luatex/latex/luacas/tex/test/expressions/rationalexponent.lua new file mode 100644 index 0000000000..85690f8c66 --- /dev/null +++ b/macros/luatex/latex/luacas/tex/test/expressions/rationalexponent.lua @@ -0,0 +1,15 @@ +local a = BinaryOperation.POWEXP({Integer(8), Integer(1) / Integer(2)}) +local b = BinaryOperation.POWEXP({Integer(27), Integer(1) / Integer(3)}) +local c = BinaryOperation.POWEXP({Integer(36), Integer(1) / Integer(2)}) +local d = BinaryOperation.POWEXP({Integer(36264691), Integer(1) / Integer(2)}) +local e = BinaryOperation.POWEXP({Integer(357911), Integer(1) / Integer(2)}) +local f = BinaryOperation.ADDEXP({BinaryOperation.POWEXP({Integer(8), Integer(1) / Integer(2)}), BinaryOperation.POWEXP({Integer(32), Integer(1) / Integer(2)})}) + +starttest("rational powers") +testeq(a:autosimplify(), "(2 * (2 ^ 1/2))", a) +testeq(b:autosimplify(), "3", b) +testeq(c:autosimplify(), "6", c) +testeq(d:autosimplify(), "(331 * (331 ^ 1/2))", d) +testeq(e:autosimplify(), "(71 * (71 ^ 1/2))", e) +testeq(f:autosimplify(), "(6 * (2 ^ 1/2))", f) +endtest()
\ No newline at end of file diff --git a/macros/luatex/latex/luacas/tex/test/expressions/simplify.lua b/macros/luatex/latex/luacas/tex/test/expressions/simplify.lua new file mode 100644 index 0000000000..ac5582901d --- /dev/null +++ b/macros/luatex/latex/luacas/tex/test/expressions/simplify.lua @@ -0,0 +1,22 @@ +local a = SymbolExpression("x")*(SymbolExpression("y") + SymbolExpression("z")) +local b = SymbolExpression("x")*(Integer(1)+ SymbolExpression("z")) +local c = parse("((2*x+1)*(3*x-1)+6)*(6*y-z)") +local d = parse("(x+1)*(x+2)*(x+3)") + +local e = parse("x*y*z+x^2") +local f = parse("x + 1/x^2") +local g = parse("e^x - e^x*x^2") + +starttest("expression expansion") +testeq(a:expand(), parse("((x * y) + (x * z))"), a) +testeq(b:expand(), parse("(x + (x * z))"), b) +testeq(c:expand(), parse("((30 * y) + (6 * x * y) + (36 * (x ^ 2) * y) + (-5 * z) + (-1 * x * z) + (-6 * (x ^ 2) * z))"), c) +testeq(d:expand(), parse("(6 + (11 * x) + (6 * (x ^ 2)) + (x ^ 3))")) +endtest() + +starttest("expression factoring beyond monovariate polynomials") +testeq(e:factor(), parse("(x * (x + (y * z)))")) +testeq(f:factor(), parse("((x ^ -2) * (1 + x) * (1 + (-1 * x) + (x ^ 2)))")) +testeq(g:factor(), parse("((e ^ x) * (1 + x) * (1 + (-1 * x)))")) + +endtest()
\ No newline at end of file diff --git a/macros/luatex/latex/luacas/tex/test/expressions/substitute.lua b/macros/luatex/latex/luacas/tex/test/expressions/substitute.lua new file mode 100644 index 0000000000..4d1f3496bf --- /dev/null +++ b/macros/luatex/latex/luacas/tex/test/expressions/substitute.lua @@ -0,0 +1,10 @@ +local a = parse("3*(x+1)^1/2-6*y+3*z^2") +local b = parse("sin(e^x - 1) + e^x") + +starttest("substitution") +testeq(a:substitute({[parse("x")] = Integer(3), + [parse("y")] = Integer(-1), + [parse("z")] = Integer(4)/Integer(3)}):autosimplify(), parse("52/3")) + +testeq(b:substitute({[parse("e^x")] = parse("x^e")}), parse("((x ^ e) + sin((-1 + (x ^ e))))")) +endtest()
\ No newline at end of file diff --git a/macros/luatex/latex/luacas/tex/test/helper.lua b/macros/luatex/latex/luacas/tex/test/helper.lua new file mode 100644 index 0000000000..b550967da9 --- /dev/null +++ b/macros/luatex/latex/luacas/tex/test/helper.lua @@ -0,0 +1,322 @@ +-- helper functions + + + function whatis(a) + if a == nil then + return nil + end + if a:type() == SymbolExpression then + return "Sym" + end + if a:type() == BinaryOperation then + return "BinOp" + end + if a:type() == FunctionExpression then + return "FncExp" + end + if a:type() == TrigExpression then + return "TrigExp" + end + if a:type() == Integer then + return "Int" + end + if a:type() == Rational then + return "Ratl" + end + if a:type() == DerivativeExpression then + return "DervExp" + end + if a:type() == DiffExpression then + return "DiffExp" + end + if a:type() == IntegralExpression then + return "Intgrl" + end + if a:type() == SqrtExpression then + return "Sqrt" + end + if a:type() == PolynomialRing then + return "Poly" + end + if a:type() == AbsExpression then + return "ABS" + end + if a:type() == Logarithm then + return "LOG" + end + if a:type() == RootExpression then + return "RootOf" + end + if a:type() == Equation then + return "=" + end + return "No Clue" +end + +function longwhatis(a) + if a == nil then + return nil + end + if a:type() == SymbolExpression then + return "SymbolExpression" + end + if a:type() == BinaryOperation then + return "BinaryOperation" + end + if a:type() == FunctionExpression then + return "FunctionExpression" + end + if a:type() == TrigExpression then + return "TrigExpression" + end + if a:type() == Integer then + return "Integer" + end + if a:type() == Rational then + return "Rational" + end + if a:type() == DerivativeExpression then + return "DerivativeExpression" + end + if a:type() == DiffExpression then + return "DiffExpression" + end + if a:type() == IntegralExpression then + return "IntegralExpression" + end + if a:type() == SqrtExpression then + return "SqrtExpression" + end + if a:type() == PolynomialRing then + return "PolynomialRing" + end + if a:type() == AbsExpression then + return "AbsExpression" + end + if a:type() == Logarithm then + return "Logarithm" + end + if a:type() == RootExpression then + return "RootExpression" + end + if a:type() == Equation then + return "Equation" + end + return "No Clue" +end + +function whatring(a) + if a:getring() == Rational.makering() then + return "Rational" + end + if a:getring() == PolynomialRing.makering() then + return "PolynomialRing" + end + if a:getring() == Integer.makering() then + return "Integer" + end + if a:getring() == IntegerModN.makering() then + return "IntegerModN" + end + return "No Clue" +end + +function nameof(sym) + if sym == nil then + return nil + end + if sym:type() == BinaryOperation then + local binops = {BinaryOperation.ADD, + BinaryOperation.MUL, + BinaryOperation.SUB, + BinaryOperation.DIV, + BinaryOperation.POW, + BinaryOperation.IDIV, + BinaryOperation.MOD} + local obslab = {"ADD", + "MUL", + "SUB", + "DIV", + "POW", + "IDIV", + "MOD"} + for i,j in pairs(binops) do + if sym.operation == j then + return obslab[i] + end + end + end + if sym:type() == FunctionExpression or sym:type() == TrigExpression then + return tostring(sym.name) + end + if sym:type() == SymbolExpression or sym:type() == Integer then + return tostring(sym) + end + if sym:type() == Rational then + return tostring(sym.numerator).."/"..tostring(sym.denominator) + end + if sym:type() == DerivativeExpression then + return "DD" + end + if sym:type() == DiffExpression then + return "diff" + end + if sym:type() == IntegralExpression then + return "$\\mathtt{\\int}$" + end + if sym:type() == SqrtExpression then + return "$\\mathtt{\\sqrt{\\phantom{x}}}$" + end + if sym:type() == PolynomialRing then + return "Poly" + end + if sym:type() == AbsExpression then + return "abs" + end + if sym:type() == Logarithm then + return "log" + end + if sym:type() == RootExpression then + return "RootOf" + end + if sym:type() == Equation then + return "$\\mathtt{=}$" + end + return "No Clue" +end + +function Expression:getfullsubexpressionsrec() + local result = {} + for _, expression in ipairs(self:subexpressions()) do + result[#result+1] = expression + result = JoinArrays(result, expression:getfullsubexpressionsrec()) + end + return result +end + +function Expression:gettheshrub() + local string = "" + for index, expression in ipairs(self:subexpressions()) do + string = string.."child {node [label=-90:{expr["..tostring(index).."]}] {$\\mathtt{"..expression:tolatex().."}$}}" + end + return string +end + +function Expression:getthetree() + local string = "" + for _, expression in ipairs(self:subexpressions()) do + if expression:isatomic() then + string = string.."child {node{"..nameof(expression).."}}" + else + string = string.."child {node{"..nameof(expression).."}"..expression:getthetree().."}" + end + end + return string +end + +function Expression:gettheforest() + local string = "" + for _, expression in ipairs(self:subexpressions()) do + if expression:isatomic() then + string = string.." [ "..nameof(expression).." ] " + else + string = string.." [ "..nameof(expression)..expression:gettheforest().." ] " + end + end + return string +end + +function Expression:getthefancyshrub() + local string = "" + if self:type() == DiffExpression then + for _, expression in ipairs(self:subexpressions()) do + string = string.." [ $\\mathtt{"..expression:tolatex().."}$, tikz+={\\node[anchor=north,font=\\ttfamily\\footnotesize,gray] at (.south) {.expression};} ] " + end + string = string.." [ $\\mathtt{\\{" + for _,symbol in ipairs(self.symbols) do + if next(self.symbols,_) == nil then + string = string .. symbol:tolatex().."\\}}$, tikz+={\\node[anchor=north,font=\\ttfamily\\footnotesize,gray] at (.south) {.symbols};} ] " + else + string = string .. symbol:tolatex() .. "," + end + end + return string + end + if self:type() == IntegralExpression then + string = string .. " [ $\\mathtt{"..self.expression:tolatex().."}$, tikz+={\\node[anchor=north,font=\\ttfamily\\footnotesize,gray] at (.south) {.expression};} ] " + string = string .. "[ $\\mathtt{"..self.symbol:tolatex().."}$, tikz+={\\node[anchor=north,font=\\ttfamily\\footnotesize,gray] at (.south) {.symbol};} ]" + if self:isdefinite() then + string = string .. "[ $\\mathtt{"..self.lower:tolatex().."}$, tikz+={\\node[anchor=north,font=\\ttfamily\\footnotesize,gray] at (.south) {.lower};} ] " + string = string .. "[ $\\mathtt{"..self.upper:tolatex().."}$, tikz+={\\node[anchor=north,font=\\ttfamily\\footnotesize,gray] at (.south) {.upper};} ] " + return string + end + return string + end + if self:type() == PolynomialRing then + string = string .. " [ $\\mathtt{\\{" + for index=0, self.degree:asnumber() do + string = string .. tostring(self.coefficients[index]) + if index < self.degree:asnumber() then + string = string .. "," + end + end + string = string .. "\\} }$, tikz+={\\node[anchor=north,font=\\ttfamily\\footnotesize,gray] at (.south) {.coefficients}; \\node[anchor=south west, font=\\ttfamily\\footnotesize,gray] at (.north west) {.ring "..whatring(self).."};} ]" + string = string .. " [ $\\mathtt{"..self.symbol.. "}$, tikz+={\\node[anchor=north, font=\\ttfamily\\footnotesize,gray] at (.south) {.symbol};} ]" + return string + end + if self:type() == SqrtExpression then + string = string .. " [ $\\mathtt{"..self.expression:tolatex().."}$, tikz+={\\node[anchor=north,font=\\ttfamily\\footnotesize,gray] at (.south) {.expression};} ]" + string = string .. "[ $\\mathtt{"..self.root:tolatex().."}$, tikz+={\\node[anchor=north,font=\\ttfamily\\footnotesize,gray] at (.south) {.root};} ]" + return string + end + if self:type() == TrigExpression then + string = string .. " [ $\\mathtt{"..self.expression:tolatex().."}$, tikz+={\\node[anchor=north,font=\\ttfamily\\footnotesize,gray] at (.south) {.expression};} ]" + return string + end + if self:type() == AbsExpression then + string = string .. " [ $\\mathtt{"..self.expression:tolatex().."}$, tikz+={\\node[anchor=north,font=\\ttfamily\\footnotesize,gray] at (.south) {.expression};} ] " + return string + end + if self:type() == Logarithm then + string = string .. " [$\\mathtt{" ..self.expression:tolatex().."}$, tikz+={\\node[anchor=north,font=\\ttfamily\\footnotesize,gray] at (.south) {.expression};} ]" + string = string .. " [$\\mathtt{" ..self.base:tolatex().."}$, tikz+={\\node[anchor=north,font=\\ttfamily\\footnotesize,gray] at (.south) {.base};} ]" + return string + end + if self:type() == RootExpression then + string = string .. "[$\\mathtt{" ..self.expression:tolatex().."}$, tikz+={\\node[anchor=north,font=\\ttfamily\\footnotesize,gray] at (.south) {.expression};} ]" + return string + end + if self:type() == FunctionExpression then + local string1 = '' + local string2 = '' + local string3 = '' + for index=1, #self.variables do + string1 = string1 .. tostring(self.expressions[index]) + if index < #self.variables then + string1 = string1 .. "," + end + string2 = string2 .. tostring(self.variables[index]) + if index < #self.variables then + string2 = string2 .. "," + end + string3 = string3 .. tostring(self.derivatives[index]) + if index < #self.variables then + string3 = string3 .. "," + end + end + string = string .. "[$\\mathtt{ \\{" .. string1 .. "\\}}$, tikz+={\\node[anchor=north,font=\\ttfamily\\footnotesize,gray] at (.south) {.expressions};} ]" + string = string .. "[$\\mathtt{ \\{" .. string2 .. "\\}}$, tikz+={\\node[anchor=north,font=\\ttfamily\\footnotesize,gray] at (.south) {.variables};} ]" + string = string .. "[$\\mathtt{ \\{" .. string3 .. "\\}}$, tikz+={\\node[anchor=north,font=\\ttfamily\\footnotesize,gray] at (.south) {.derivatives};} ]" + return string + end + if self:type() == Equation then + string = string .. " [$\\mathtt{" ..self.lhs:tolatex().."}$, tikz+={\\node[anchor=north,font=\\ttfamily\\footnotesize,gray] at (.south) {.lhs};} ]" + string = string .. " [$\\mathtt{" ..self.rhs:tolatex().."}$, tikz+={\\node[anchor=north,font=\\ttfamily\\footnotesize,gray] at (.south) {.rhs};} ]" + return string + end + for index, expression in ipairs(self:subexpressions()) do + string = string.." [ $\\mathtt{"..expression:tolatex().."}$, tikz+={\\node[anchor=north,font=\\ttfamily\\footnotesize,gray] at (.south) {.expression["..index.."]};} ] " + end + return string +end + diff --git a/macros/luatex/latex/luacas/tex/test/main.lua b/macros/luatex/latex/luacas/tex/test/main.lua new file mode 100644 index 0000000000..638f7734b5 --- /dev/null +++ b/macros/luatex/latex/luacas/tex/test/main.lua @@ -0,0 +1,154 @@ +---@diagnostic disable: lowercase-global +-- Runs test code from test files. + +require("calculus._init") +require("_lib.pepperfish") + +-- Stuff required for the basic parser. +local constants = {e="E", pi = "PI", ln = "LN", log = "LOG", Integer = "Integer", DD = "DD", int = "INT", abs = "ABS", fact="FACT"} + +local function parser(s) + if string.find(s, "[0-9]+") then + return "Integer(\"" .. s .. "\")" + end + + if s.find(s, "[%^%\\%[%]]") then + return string.gsub(s, "[^%^%\\%[%]]+", parser) + end + + for string, replace in pairs(constants) do + if s == string then + return replace + end + end + + return "SymbolExpression(\"" .. s .. "\")" +end + +function parse(input) + local parsed = string.gsub(input, "[0-9]+", parser) + parsed = string.gsub(parsed, "[A-z']+", parser) + local exe, err = load("return " .. parsed) + if exe then + return exe():autosimplify() + else + print(err) + end +end + +function dparse(input) + local parsed = string.gsub(input, "[0-9]+", parser) + parsed = string.gsub(parsed, "[A-z']+", parser) + local exe, err = load("return " .. parsed) + if exe then + return exe() + else + print(err) + end +end + +-- Stuff required for test code. +local tests +local failures +local totaltests = 0 +local totalfailures = 0 +function starttest(name) + print("Testing " .. name .. "...") + print() + tests = 0 + failures = 0 +end + +-- Tests two objects for equality, irrespective of order. If the object is a table or expression, the objects may be sorted to ensure the correct order. +function testeq(actual, expected, initial, sort) + if sort and type(actual) == "table" and not actual.type then + table.sort(actual, function (a, b) + return a:order(b) + end) + elseif sort and type(actual) == "table" and actual.type and actual:type() == BinaryOperation and actual:iscommutative() then + table.sort(actual.expressions, function (a, b) + return a:order(b) + end) + end + + if initial then + if ToStringArray(expected) == ToStringArray(actual) then + print(ToStringArray(initial) .. " -> " .. ToStringArray(actual)) + else + print(ToStringArray(initial) .. " -> " .. ToStringArray(actual) .. " (Expected: " .. ToStringArray(expected) .. ")") + failures = failures + 1 + end + else + if ToStringArray(expected) == ToStringArray(actual) then + print("Result: " .. ToStringArray(actual)) + else + print("Result: ".. ToStringArray(actual) .. " (Expected: " .. ToStringArray(expected) .. ")") + failures = failures + 1 + end + end + tests = tests + 1 +end + +-- Tests whether converting an element to a different ring produces the expected object in the expected ring +function testringconvert(expression, toring, expected, expectedring) + testeq(expression:inring(toring), expected, expression) + testeq(expression:inring(toring):getring(), expectedring) +end + +function endtest() + print() + print("Finished test without errors.") + print() + totaltests = totaltests + tests + totalfailures = totalfailures + failures + if failures == 0 then + print("Performed " .. tests .. " tests, all of which passed!") + else + print("Performed tests, " .. failures .. "/" .. tests .. " failed.") + end + print("=====================================================================================================================") +end + +function endall() + if totalfailures == 0 then + print("Performed " .. totaltests .. " tests in total, all of which passed!") + else + print("Performed tests, " .. totalfailures .. "/" .. totaltests .. " failed.") + end +end + + +-- TODO: Add profiling and error catching options. +-- Comment out these lines to only run certain test code. + +-- profiler = newProfiler() +-- profiler:start() + +require("test.calculus.derivatives") +require("test.calculus.integrals") + +require("test.expressions.autosimplify") +require("test.expressions.collect") +require("test.expressions.equations") +require("test.expressions.simplify") +require("test.expressions.functions") +require("test.expressions.logarithms") +-- require("test.expressions.rationalexponent") +require("test.expressions.substitute") + +require("test.polynomials.polynomial") +require("test.polynomials.partialfractions") +require("test.polynomials.polynomialmod") +require("test.polynomials.roots") + +require("test.rings.conversion") +require("test.rings.modulararithmetic") +require("test.rings.number") + +endall() + +-- profiler:stop() + +-- local outfile = io.open( "profile.txt", "w+" ) +-- profiler:report( outfile ) +-- outfile:close()
\ No newline at end of file diff --git a/macros/luatex/latex/luacas/tex/test/parser.lua b/macros/luatex/latex/luacas/tex/test/parser.lua new file mode 100644 index 0000000000..6cb22a1bdb --- /dev/null +++ b/macros/luatex/latex/luacas/tex/test/parser.lua @@ -0,0 +1,323 @@ +-- Rudimentary parser for making the CAS easier to use. Essentially just wraps SymbolExpression() around symbols and Integer() around integers. + + + +require("calculus._init") + +-- Splits a string on a seperator. +function split(str, sep) + local t={} + for match in string.gmatch(str, "([^".. sep .."]+)") do + t[#t+1] = match + end + return t +end + +-- Displays an expression. For use in the parser. +function disp(expression, inline, simple) + if type(expression) ~= "table" then + tex.print(tostring(expression)) + elseif expression.autosimplify then + if inline then + if simple then + tex.print('$' .. expression:autosimplify():tolatex() .. '$') + else + tex.print('$' .. expression:tolatex() .. '$') + end + else + if simple then + tex.print('\\[' .. expression:autosimplify():tolatex() .. '\\]') + else + tex.print('\\[' .. expression:tolatex() .. '\\]') + end + end + else + tex.print(tostring(expression)) + end +end + +-- Displays an expression. For use in the parser. +function displua(expression) + if type(expression) ~= "table" then + print(tostring(expression)) + elseif expression.autosimplify then + print(expression:autosimplify():tolatex()) + else + print(tostring(expression)) + end +end + +function vars(...) + for _, string in ipairs(table.pack(...)) do + if string ~= "_" then + _G[string] = SymbolExpression(string) + end + end +end + +function clearvars() + for index, value in pairs(_G) do + if type(value) == "table" and value.type and value:type() == SymbolExpression then + _G[index] = nil + end + end +end + +function range(a, b, step) + if not b then + b = a + a = Integer.one() + end + step = step or Integer.one() + local f = + step > Integer.zero() and + function(_, lastvalue) + local nextvalue = lastvalue + step + if nextvalue <= b then return nextvalue end + end or + step < Integer.zero() and + function(_, lastvalue) + local nextvalue = lastvalue + step + if nextvalue >= b then return nextvalue end + end or + function(_, lastvalue) return lastvalue end + return f, nil, a - step + end + +function factor(exp,squarefrei) + if exp:type() == Integer then + return exp:primefactorization() + end + if exp:type() == PolynomialRing then + if not squarefrei then + return exp:factor() + else + if exp.ring == Integer.getring() or Rational.getring() then + return exp:squarefreefactorization() + end + if exp.ring == IntegerModN.getring() then + return exp:modularsquarefreefactorization() + end + return exp:factor() + end + end + return exp:autosimplify():factor() +end + +function expand(exp) + return exp:autosimplify():expand() +end + +function simplify(exp) + return exp:simplify() +end + +function exp(x) + return e^x +end + +function substitute(tbl,expr) + return expr:substitute(tbl) +end + +function roots(expression) + poly,ispoly = topoly(expression) + if ispoly then + return poly:roots() + end + return RootExpression(expression) +end + +function combine(expr) + return expr:combine() +end + +function Mod(f,n) + if f:type() == Integer then + return IntegerModN(f,n) + end + if f:type() == PolynomialRing and f.ring == Integer.getring() then + local coeffs = {} + for i=0,f.degree:asnumber() do + coeffs[i] = IntegerModN(f.coefficients[i],n) + end + return PolynomialRing(coeffs,f.symbol,f.degree) + end +end + +function Poly(coefficients,symbol,degree) + local variable = symbol or 'x' + return PolynomialRing:new(coefficients,variable,degree) +end + +function topoly(a) + a = a:expand():autosimplify() + return a:topolynomial() +end + +function gcd(a,b) + if a:type() == Integer and b:type() == Integer then + return Integer.gcd(a,b) + end + if a:type() == PolynomialRing and b:type() == PolynomialRing then + return PolynomialRing.gcd(a,b) + end +end + +function gcdext(a,b) + if a:type() == Integer and b:type() == Integer then + return Integer.extendedgcd(a,b) + end + A, ATF = topoly(a) + B, BTF = topoly(b) + if ATF and BTF then + return PolynomialRing.extendedgcd(A,B) + end + return nil,nil,nil +end + +function parfrac(f,g,ffactor) + local f,check1 = topoly(f) + local g,check2 = topoly(g) + if check1 and check2 then + if f.degree >= g.degree then + local q,r + q,r = f:divremainder(g) + return q + PolynomialRing.partialfractions(r,g,ffactor) + else + return PolynomialRing.partialfractions(f,g,ffactor) + end + else + return f/g + end +end + +function factorial(a) + return FactorialExpression(a) +end + +-- Constants for the CAS. We may not want these in Lua itself, but in the latex end the user probably expects them. +e = E +pi = PI +-- sqrt = SQRT +ln = LN +log = LOG +int = INT +sin = SIN +cos = COS +tan = TAN +csc = CSC +sec = SEC +cot = COT +arcsin = ARCSIN +arccos = ARCCOS +arctan = ARCTAN +arccsc = ARCCSC +arcsec = ARCSEC +arccot = ARCCOT +abs = ABS + +function ZTable(t) + t = t or {} + return setmetatable(t, JoinTables(getmetatable(t), + {__index = function (t, k) + if type(k) == "table" and k.type and k:type() == Integer then + return rawget(t, k:asnumber()) + else + return rawget(t, k) + end + end, + __newindex = function (t, k, v) + if type(k) == "table" and k.type and k:type() == Integer then + rawset(t, k:asnumber(), v) + else + rawset(t, k, v) + end + end})) +end + +function RR(n) + if type(n) == "number" then + return n + end + + if type(n) == "string" then + return tonumber(n) + end + + if type(n) == "table" and n.asnumber then + return n:asnumber() + end + + error("Could not convert to a real number.") +end + +function ZZ(n) + if type(n) == "table" and n.type and n:type() == Rational then + return n.numerator // n.denominator + end + return Integer(n) +end + +function QQ(n) + if type(n) == "table" then + return n + end + + if type(n) == "number" then + n = tostring(n) + end + + if type(n) == "string" then + local parts = split(n, "%.") + if #parts == 1 then + return Integer(parts[1]) + else + return Integer(parts[1])..Integer(parts[2]) + end + end + + error("Could not convert to a rational number.") +end + +--- Parses raw input into Lua code and executes it. +--- @param input string +function CASparse(input) + + -- First, we replace any occurance of a number with an integer or rational version of itself. + local str = string.gsub(input, ".?[0-9]+", function (s) + -- Here, we are part of an identifier, so we don't replace anything + if string.match(string.sub(s, 1, 1), "[A-Z]") or string.match(string.sub(s, 1, 1), "[a-z]") or string.match(string.sub(s, 1, 1), "_") then + return + end + + if string.match(string.sub(s, 1, 1), "[0-9]") then + return "Integer('" .. s .. "')" + end + + return string.sub(s, 1, 1) .. "Integer('" .. string.sub(s, 2, #s) .. "')" + end) + + -------------------------- + -- HERE COMES THE JANK. -- + -------------------------- + + -- Replaces each instance of a decimal with .., so we can use integer metatables to convert it into a rational properly. + str = string.gsub(str, "Integer%('[0-9]+'%)%.Integer%('[0-9]+'%)", function (s) + local ints = split(s, "%.") + return ints[1] .. ".." .. ints[2] + end) + str = string.gsub(str, ".?%.Integer%('[0-9]+'%)", function (s) + if string.sub(s, 1, 2) == ".." then + return + end + return string.sub(s, 1, 1) .. "Integer('0')." .. string.sub(s, 2, #s) + end) + + local exe, err = load(str .. "\n return true") + if exe then + exe() + else + print(err) + end +end
\ No newline at end of file diff --git a/macros/luatex/latex/luacas/tex/test/polynomials/partialfractions.lua b/macros/luatex/latex/luacas/tex/test/polynomials/partialfractions.lua new file mode 100644 index 0000000000..280d4d56f3 --- /dev/null +++ b/macros/luatex/latex/luacas/tex/test/polynomials/partialfractions.lua @@ -0,0 +1,12 @@ +local g1 = parse("x^3+4*x^2-x-2"):topolynomial() +local f1 = parse("x^4-x^2"):topolynomial() + +local g2 = parse("2*x^6-4*x^5+5*x^4-3*x^3+x^2+3*x"):topolynomial() +local f2 = parse("x^7-3*x^6+5*x^5-7*x^4+7*x^3-5*x^2+3*x-1"):topolynomial() + +starttest("partial fraction decomposition") + +testeq(PolynomialRing.partialfractions(g1, f1):autosimplify(), parse("((2 * (x ^ -2)) + (x ^ -1) + ((-1 + x) ^ -1) + (-1 * ((1 + x) ^ -1)))")) +testeq(PolynomialRing.partialfractions(g2, f2):autosimplify(), parse("(((-1 + x) ^ -3) + ((-1 + x) ^ -1) + ((1 + (x ^ 2)) ^ -2) + ((1 + x) * ((1 + (x ^ 2)) ^ -1)))")) + +endtest()
\ No newline at end of file diff --git a/macros/luatex/latex/luacas/tex/test/polynomials/polynomial.lua b/macros/luatex/latex/luacas/tex/test/polynomials/polynomial.lua new file mode 100644 index 0000000000..545538c764 --- /dev/null +++ b/macros/luatex/latex/luacas/tex/test/polynomials/polynomial.lua @@ -0,0 +1,153 @@ + +local a = PolynomialRing({ + Integer(1), + Integer(2), + Integer(3), + Integer(4), + Integer(5) +}, "x") + +local b = PolynomialRing({ + Integer(1) / Integer(3), + Integer(1) / Integer(12), + Integer(6) / Integer(3), +}, "x") + +local c = PolynomialRing({ + Integer(12), + Integer(4) +}, "x") + +local h = PolynomialRing({Integer(2), Integer(3), Integer(1)}, "x") +local i = PolynomialRing({Integer(8), Integer(20), Integer(18), Integer(7), Integer(1)}, "x") +local j = PolynomialRing({Integer(108), Integer(324), Integer(387), Integer(238), Integer(80), Integer(14), Integer(1)}, "x") +local k = PolynomialRing({Integer(30), Integer(11), Integer(1)}, "x") +local l = PolynomialRing({Integer(6), Integer(11), Integer(6), Integer(1)}, "z") +local m = PolynomialRing({Integer(1), Integer(10), Integer(45), Integer(120), Integer(210), Integer(252), Integer(210), Integer(120), Integer(45), Integer(10), Integer(1)}, "x") +local n = PolynomialRing({Integer(24), Integer(50), Integer(35), Integer(10), Integer(1), Integer(0), Integer(24), Integer(50), Integer(35), Integer(10), Integer(1)}, "x") +local o = PolynomialRing({Integer(24), Integer(50), Integer(59), Integer(60), Integer(36), Integer(10), Integer(1)}, "x") +local p = PolynomialRing({Integer(-110592), Integer(59904), Integer(-5760), Integer(720), Integer(-48), Integer(1)}, "x") + +local d = PolynomialRing({Integer(21), Integer(10), Integer(1)}, "x") +local e = PolynomialRing({Integer(-6), Integer(1), Integer(1)}, "x") + +local f = PolynomialRing({Integer(-1), Integer(-2), Integer(15), Integer(36)}, "x") +local g = PolynomialRing({Integer(1), Integer(7), Integer(15), Integer(9)}, "x") + +local q = PolynomialRing({Integer(3), Integer(-9), Integer(27), Integer(-36), Integer(36)}, "z") +local r = PolynomialRing({Integer(0), Integer(0), Integer(0), Integer(0), Integer(0), Integer(0), Integer(4)}, "x"); +local s = PolynomialRing({Integer(1), Integer(0), Integer(-4), Integer(0), Integer(1)}, "x") + +local x = Integer(3) +local y = Integer(-1) / Integer(6) + +local multia = PolynomialRing({Integer(4), + Integer(0), + PolynomialRing({Integer(0), Integer(0), Integer(-6)}, "y"), + PolynomialRing({Integer(1), Integer(3)}, "y")}, "x") +local multib = PolynomialRing({PolynomialRing({Integer(0), Integer(6)}, "y"), + Integer(0), + PolynomialRing({Integer(-4), Integer(12)}, "y")}, "x") + +starttest("polynomial construction") +testeq(a, "5x^4+4x^3+3x^2+2x^1+1x^0") +testeq(a.degree, 4) +testeq(b, "2x^2+1/12x^1+1/3x^0") +testeq(b.degree, 2) +testeq(multia, "(3y^1+1y^0)x^3+(-6y^2+0y^1+0y^0)x^2+(0)x^1+(4)x^0") +testeq(multia.degree, 3) +endtest() + +starttest("polynomial-expression conversion") +testeq(a:tocompoundexpression():autosimplify():topolynomial(), a) +testeq(b:tocompoundexpression():autosimplify():topolynomial(), b) +testeq(c:tocompoundexpression():autosimplify():topolynomial(), c) +endtest() + +starttest("polynomial arithmetic") +testeq(a + a, "10x^4+8x^3+6x^2+4x^1+2x^0") +testeq(a + b, "5x^4+4x^3+5x^2+25/12x^1+4/3x^0") +testeq(b + a, "5x^4+4x^3+5x^2+25/12x^1+4/3x^0") +testeq(a - a, "0x^0") +testeq(a - b, "5x^4+4x^3+1x^2+23/12x^1+2/3x^0") +testeq(b:multiplyDegree(4), "2x^6+1/12x^5+1/3x^4+0x^3+0x^2+0x^1+0x^0") +testeq(a:multiplyDegree(12), "5x^16+4x^15+3x^14+2x^13+1x^12+0x^11+0x^10+0x^9+0x^8+0x^7+0x^6+0x^5+0x^4+0x^3+0x^2+0x^1+0x^0") +testeq(c * c, "16x^2+96x^1+144x^0") +testeq(a * c, "20x^5+76x^4+60x^3+44x^2+28x^1+12x^0") +testeq(c * a, "20x^5+76x^4+60x^3+44x^2+28x^1+12x^0") +testeq(b * c, "8x^3+73/3x^2+7/3x^1+4x^0") +local qq, rr = a:divremainder(c) +testeq(qq, "5/4x^3+-11/4x^2+9x^1+-53/2x^0") +testeq(rr, "319x^0") +qq, rr = a:divremainder(b) +testeq(qq, "5/2x^2+91/48x^1+1157/1152x^0") +testeq(rr, "17755/13824x^1+2299/3456x^0") +endtest() + +starttest("polynomial pseudodivision") +local pq, pr = a:pseudodivide(c) +testeq(pq, "320x^3+-704x^2+2304x^1+-6784x^0") +testeq(pr, "81664x^0") + +pq, pr = multia:pseudodivide(multib) +testeq(pq, "(36y^2+0y^1+-4y^0)x^1+(-72y^3+24y^2+0y^1+0y^0)x^0") +testeq(pr, "(-216y^3+0y^2+24y^1+0y^0)x^1+(432y^4+-144y^3+576y^2+-384y^1+64y^0)x^0") +endtest() + + +starttest("combined polynomial/coefficient operations") +testeq(a + x, "5x^4+4x^3+3x^2+2x^1+4x^0") +testeq(x + a, "5x^4+4x^3+3x^2+2x^1+4x^0") +testeq(b - y, "2x^2+1/12x^1+1/2x^0") +testeq(a * x, "15x^4+12x^3+9x^2+6x^1+3x^0") +testeq(x * a, "15x^4+12x^3+9x^2+6x^1+3x^0") +endtest() + +starttest("polynomial formal derivatives") +testeq(a:derivative(), "20x^3+12x^2+6x^1+2x^0") +testeq(b:derivative(), "4x^1+1/12x^0") +testeq(c:derivative():derivative(), "0x^0") +endtest() + + +starttest("polynomial gcd...") +testeq(PolynomialRing.gcd(d, e), "1x^1+3x^0") +testeq(PolynomialRing.gcd(b, c), "1x^0") +testeq(PolynomialRing.gcd(f, g), "1x^2+2/3x^1+1/9x^0") +endtest() + +starttest("square-free factorization") +testeq(h:squarefreefactorization():autosimplify(), parse("(2 + (3 * x) + (x ^ 2))"), h) +testeq(i:squarefreefactorization():autosimplify(), parse("((1 + x) * ((2 + x) ^ 3))"), i) +testeq((Integer(2)*i):squarefreefactorization():autosimplify(), parse("(((2 + x) ^ 3) * (2 + (2 * x)))"), (Integer(2)*i), true) +testeq(j:squarefreefactorization():autosimplify(), parse("((1 + x) * ((2 + x) ^ 2) * ((3 + x) ^ 3))"), j) +testeq(o:squarefreefactorization():autosimplify(), parse("(24 + (50 * x) + (59 * (x ^ 2)) + (60 * (x ^ 3)) + (36 * (x ^ 4)) + (10 * (x ^ 5)) + (x ^ 6))"), o) +endtest() + +starttest("polynomial factorization") +testeq(c:factor(), BinaryOperation.MULEXP({Integer(4), BinaryOperation.POWEXP({PolynomialRing({Integer(3), Integer(1)}, "x"), Integer(1)})}), c) +testeq(h:factor():autosimplify(), parse("((1 + x) * (2 + x))"), h) +testeq(k:factor():autosimplify(), parse("((5 + x) * (6 + x))"), k) +testeq(j:factor():autosimplify(), parse("((1 + x) * ((2 + x) ^ 2) * ((3 + x) ^ 3))"), j) +testeq(p:factor():autosimplify(), parse("((-24 + x) * (96 + (x ^ 2)) * (48 + (-24 * x) + (x ^ 2)))"), p) +testeq(l:factor():autosimplify(), parse("((1 + z) * (2 + z) * (3 + z))"), l) +testeq(m:factor():autosimplify(), parse("((1 + x) ^ 10)"), m) +testeq(b:factor(), BinaryOperation.MULEXP({Integer(1)/Integer(12), BinaryOperation.POWEXP({PolynomialRing({Integer(4), Integer(1), Integer(24)}, "x"), Integer(1)})}), b) +testeq(o:factor():autosimplify(), parse("((1 + x) * (2 + x) * (3 + x) * (4 + x) * (1 + (x ^ 2)))"), o) +testeq(n:factor():autosimplify(), parse("((1 + x) * (2 + x) * (3 + x) * (4 + x) * (1 + (x ^ 2)) * (1 + (-1 * (x ^ 2)) + (x ^ 4)))"), n) +endtest() + +starttest("polynomial decomposition") +testeq(c:decompose(), "{4x^1+12x^0}", c, true) +testeq(h:decompose(), "{1x^2+3x^1+2x^0}", h, true) +testeq(k:decompose(), "{1x^2+11x^1+30x^0}", k, true) +testeq(j:decompose(), "{1x^6+14x^5+80x^4+238x^3+387x^2+324x^1+108x^0}", j, true) +testeq(l:decompose(), "{1z^3+6z^2+11z^1+6z^0}", l, true) +testeq(m:decompose(), "{1x^5+5x^4+10x^3+10x^2+5x^1+1x^0, 1x^2+2x^1+0x^0}", m, true) +testeq(b:decompose(), "{2x^2+1/12x^1+1/3x^0}", b, true) +testeq(o:decompose(), "{1x^6+10x^5+36x^4+60x^3+59x^2+50x^1+24x^0}", o, true) +testeq(n:decompose(), "{1x^10+10x^9+35x^8+50x^7+24x^6+0x^5+1x^4+10x^3+35x^2+50x^1+24x^0}", n, true) +testeq(q:decompose(), "{36z^2+18z^1+3z^0, 1z^2+-1/2z^1+0z^0}", q, true) +testeq(r:decompose(),"{4x^3+0x^2+0x^1+0x^0, 1x^2+0x^1+0x^0}", r, true) +testeq(s:decompose(), "{1x^2+4x^1+1x^0, 1x^2+0x^1+-4x^0}", s, true) +endtest()
\ No newline at end of file diff --git a/macros/luatex/latex/luacas/tex/test/polynomials/polynomialmod.lua b/macros/luatex/latex/luacas/tex/test/polynomials/polynomialmod.lua new file mode 100644 index 0000000000..1906ad2d72 --- /dev/null +++ b/macros/luatex/latex/luacas/tex/test/polynomials/polynomialmod.lua @@ -0,0 +1,76 @@ +local a = PolynomialRing({IntegerModN(Integer(1), Integer(11)), + IntegerModN(Integer(6), Integer(11)), + IntegerModN(Integer(1), Integer(11)), + IntegerModN(Integer(9), Integer(11)), + IntegerModN(Integer(1), Integer(11))}, "y") + +local b = PolynomialRing({IntegerModN(Integer(7), Integer(11)), + IntegerModN(Integer(7), Integer(11)), + IntegerModN(Integer(6), Integer(11)), + IntegerModN(Integer(2), Integer(11)), + IntegerModN(Integer(1), Integer(11))}, "y") + +local q = PolynomialRing({IntegerModN(Integer(2), Integer(13)), + IntegerModN(Integer(6), Integer(13)), + IntegerModN(Integer(4), Integer(13))}, "z") + +local p = PolynomialRing({IntegerModN(Integer(4), Integer(13)), + IntegerModN(Integer(11), Integer(13)), + IntegerModN(Integer(1), Integer(13)), + IntegerModN(Integer(12), Integer(13)), + IntegerModN(Integer(1), Integer(13))}, "x") + +local r = PolynomialRing({IntegerModN(Integer(1), Integer(3)), + IntegerModN(Integer(0), Integer(3)), + IntegerModN(Integer(0), Integer(3)), + IntegerModN(Integer(2), Integer(3)), + IntegerModN(Integer(0), Integer(3)), + IntegerModN(Integer(0), Integer(3)), + IntegerModN(Integer(1), Integer(3))}, "x") + +local s = PolynomialRing({IntegerModN(Integer(1), Integer(5)), + IntegerModN(Integer(1), Integer(5)), + IntegerModN(Integer(1), Integer(5)), + IntegerModN(Integer(1), Integer(5)), + IntegerModN(Integer(1), Integer(5))}, "x") + +local t = PolynomialRing({IntegerModN(Integer(1), Integer(7))}, "x"):multiplyDegree(7) - PolynomialRing({IntegerModN(Integer(1), Integer(7))}, "x"):multiplyDegree(1) + +local u = PolynomialRing({IntegerModN(Integer(1), Integer(13)), + IntegerModN(Integer(5), Integer(13)), + IntegerModN(Integer(6), Integer(13)), + IntegerModN(Integer(5), Integer(13)), + IntegerModN(Integer(1), Integer(13))}, "x") + +local v = PolynomialRing({IntegerModN(Integer(24), Integer(7)), + IntegerModN(Integer(50), Integer(7)), + IntegerModN(Integer(59), Integer(7)), + IntegerModN(Integer(60), Integer(7)), + IntegerModN(Integer(36), Integer(7)), + IntegerModN(Integer(10), Integer(7)), + IntegerModN(Integer(1), Integer(7))}, "z") + +starttest("modular polynomial operations") +testeq(q*q, "3z^4+9z^3+0z^2+11z^1+4z^0") +testeq(PolynomialRing.gcd(a, b), "1y^0") +local Q, R, S = PolynomialRing.extendedgcd(a, b) +testeq(Q, "1y^0") +testeq(R, "4y^3+5y^2+1y^1+3y^0") +testeq(S, "7y^3+0y^2+7y^1+6y^0") +endtest() + +starttest("modular square free factoring") +testeq(p:squarefreefactorization(), Integer(1) * BinaryOperation.POWEXP({(PolynomialRing({Integer(2), Integer(6), Integer(1)}, SymbolExpression("x"))), Integer(2)})) +testeq(r:squarefreefactorization(), Integer(1) * BinaryOperation.POWEXP({(PolynomialRing({Integer(1), Integer(0), Integer(0), Integer(1)}, SymbolExpression("x"))), Integer(2)})) +testeq(q:squarefreefactorization(), Integer(4) * BinaryOperation.POWEXP({(PolynomialRing({Integer(7), Integer(8), Integer(1)}, SymbolExpression("z"))), Integer(1)})) +testeq(s:squarefreefactorization(), Integer(1) * BinaryOperation.POWEXP({(PolynomialRing({Integer(4), Integer(1)}, SymbolExpression("x"))), Integer(4)})) +endtest() + +starttest("modular polynomial factoring") +testeq(q:factor(), BinaryOperation.MULEXP({Integer(4), BinaryOperation.POWEXP({PolynomialRing({Integer(7), Integer(1)}, SymbolExpression("z")), Integer(1)}), BinaryOperation.POWEXP({PolynomialRing({Integer(1), Integer(1)}, SymbolExpression("z")), Integer(1)})}), q) +testeq(p:factor(), Integer(1) * BinaryOperation.POWEXP({PolynomialRing({Integer(2), Integer(6), Integer(1)}, SymbolExpression("x")), Integer(2)}), p) +testeq(r:factor(), Integer(1) * BinaryOperation.POWEXP({(PolynomialRing({Integer(1), Integer(0), Integer(0), Integer(1)}, SymbolExpression("x"))), Integer(2)}), r) +testeq(t:factor(), BinaryOperation.MULEXP({Integer(1), BinaryOperation.POWEXP({PolynomialRing({Integer(0), Integer(1)}, SymbolExpression("x")), Integer(1)}), BinaryOperation.POWEXP({PolynomialRing({Integer(6), Integer(1)}, SymbolExpression("x")), Integer(1)}), BinaryOperation.POWEXP({PolynomialRing({Integer(5), Integer(1)}, SymbolExpression("x")), Integer(1)}), BinaryOperation.POWEXP({PolynomialRing({Integer(4), Integer(1)}, SymbolExpression("x")), Integer(1)}), BinaryOperation.POWEXP({PolynomialRing({Integer(3), Integer(1)}, SymbolExpression("x")), Integer(1)}), BinaryOperation.POWEXP({PolynomialRing({Integer(2), Integer(1)}, SymbolExpression("x")), Integer(1)}), BinaryOperation.POWEXP({PolynomialRing({Integer(1), Integer(1)}, SymbolExpression("x")), Integer(1)})}), t) +testeq(u:factor(), BinaryOperation.MULEXP({Integer(1), BinaryOperation.POWEXP({PolynomialRing({Integer(11), Integer(1)}, SymbolExpression("x")), Integer(1)}), BinaryOperation.POWEXP({PolynomialRing({Integer(10), Integer(1)}, SymbolExpression("x")), Integer(1)}), BinaryOperation.POWEXP({PolynomialRing({Integer(6), Integer(1)}, SymbolExpression("x")), Integer(1)}), BinaryOperation.POWEXP({PolynomialRing({Integer(4), Integer(1)}, SymbolExpression("x")), Integer(1)})}), u) +testeq(v:factor(), BinaryOperation.MULEXP({Integer(1), BinaryOperation.POWEXP({PolynomialRing({Integer(1), Integer(1)}, SymbolExpression("z")), Integer(1)}), BinaryOperation.POWEXP({PolynomialRing({Integer(2), Integer(1)}, SymbolExpression("z")), Integer(1)}), BinaryOperation.POWEXP({PolynomialRing({Integer(1), Integer(0), Integer(1)}, SymbolExpression("z")), Integer(1)}), BinaryOperation.POWEXP({PolynomialRing({Integer(4), Integer(1)}, SymbolExpression("z")), Integer(1)}), BinaryOperation.POWEXP({PolynomialRing({Integer(3), Integer(1)}, SymbolExpression("z")), Integer(1)})}), v) +endtest()
\ No newline at end of file diff --git a/macros/luatex/latex/luacas/tex/test/polynomials/roots.lua b/macros/luatex/latex/luacas/tex/test/polynomials/roots.lua new file mode 100644 index 0000000000..01975ab1ec --- /dev/null +++ b/macros/luatex/latex/luacas/tex/test/polynomials/roots.lua @@ -0,0 +1,43 @@ +local a = PolynomialRing({Integer(1), Integer(2), Integer(3), Integer(4), Integer(5)}, "x") +local b = PolynomialRing({Integer(1) / Integer(3), Integer(1) / Integer(12), Integer(6) / Integer(3)}, "x") +local c = PolynomialRing({Integer(12), Integer(4)}, "x") +local d = PolynomialRing({Integer(21), Integer(10), Integer(1)}, "x") +local e = PolynomialRing({Integer(-6), Integer(1), Integer(1)}, "x") +local f = PolynomialRing({Integer(-1), Integer(-2), Integer(15), Integer(36)}, "x") +local g = PolynomialRing({Integer(1), Integer(7), Integer(15), Integer(9)}, "x") +local h = PolynomialRing({Integer(2), Integer(3), Integer(1)}, "x") +local i = PolynomialRing({Integer(8), Integer(20), Integer(18), Integer(7), Integer(1)}, "x") +local j = PolynomialRing({Integer(108), Integer(324), Integer(387), Integer(238), Integer(80), Integer(14), Integer(1)}, "x") +local k = PolynomialRing({Integer(30), Integer(11), Integer(1)}, "x") +local l = PolynomialRing({Integer(6), Integer(11), Integer(6), Integer(1)}, "z") +local m = PolynomialRing({Integer(1), Integer(10), Integer(45), Integer(120), Integer(210), Integer(252), Integer(210), Integer(120), Integer(45), Integer(10), Integer(1)}, "x") +local n = PolynomialRing({Integer(24), Integer(50), Integer(35), Integer(10), Integer(1), Integer(0), Integer(24), Integer(50), Integer(35), Integer(10), Integer(1)}, "x") +local o = PolynomialRing({Integer(24), Integer(50), Integer(59), Integer(60), Integer(36), Integer(10), Integer(1)}, "x") +local p = PolynomialRing({Integer(-110592), Integer(59904), Integer(-5760), Integer(720), Integer(-48), Integer(1)}, "x") +local q = PolynomialRing({Integer(3), Integer(-9), Integer(27), Integer(-36), Integer(36)}, "z") +local r = PolynomialRing({Integer(0), Integer(0), Integer(0), Integer(0), Integer(0), Integer(0), Integer(4)}, "x") +local s = PolynomialRing({Integer(1), Integer(0), Integer(-4), Integer(0), Integer(1)}, "x") +local t = PolynomialRing({Integer(1), Integer(-1), Integer(1), Integer(1)}, "t") + +starttest("polynomial root-finding") +testeq(a:roots(), "{Root Of: (5x^4+4x^3+3x^2+2x^1+1x^0)}", a, true) +testeq(b:roots(), "{-1/48 + (-1/48 * (383 ^ (1/2)) * i), -1/48 + (1/48 * (383 ^ (1/2)) * i)}", b, true) +testeq(c:roots(), "{-3}", c, true) +testeq(d:roots(), "{-7, -3}", d, true) +testeq(e:roots(), "{-3, 2}", e, true) +testeq(f:roots(), "{-1/3, 1/4}", f, true) +testeq(g:roots(), "{-1, -1/3}", g, true) +testeq(h:roots(), "{-2, -1}", h, true) +testeq(i:roots(), "{-2, -1}", i, true) +testeq(j:roots(), "{-3, -2, -1}", j, true) +testeq(k:roots(), "{-6, -5}", k, true) +testeq(l:roots(), "{-3, -2, -1}", l, true) +testeq(m:roots(), "{-1}", m, true) +testeq(n:roots(), "{-4, -3, -2, -1, i, -1 * i, -1/2 * ((2 + (-2 * (3 ^ (1/2)) * i)) ^ (1/2)), 1/2 * ((2 + (-2 * (3 ^ (1/2)) * i)) ^ (1/2)), -1/2 * ((2 + (2 * (3 ^ (1/2)) * i)) ^ (1/2)), 1/2 * ((2 + (2 * (3 ^ (1/2)) * i)) ^ (1/2))}", n, true) +testeq(o:roots(), "{-4, -3, -2, -1, i, -1 * i}", o, true) +testeq(p:roots(), "{24, 12 + (-4 * (6 ^ (1/2))), 12 + (4 * (6 ^ (1/2))), -4 * (6 ^ (1/2)) * i, 4 * (6 ^ (1/2)) * i}", p, true) +testeq(q:roots(), "{1/4 + (-1/2 * ((-3/4 + (-1/3 * (3 ^ (1/2)) * i)) ^ (1/2))), 1/4 + (1/2 * ((-3/4 + (-1/3 * (3 ^ (1/2)) * i)) ^ (1/2))), 1/4 + (-1/2 * ((-3/4 + (1/3 * (3 ^ (1/2)) * i)) ^ (1/2))), 1/4 + (1/2 * ((-3/4 + (1/3 * (3 ^ (1/2)) * i)) ^ (1/2)))}", q, true) +testeq(r:roots(), "{0}", r, true) +testeq(s:roots(), "{-1/2 * ((8 + (-4 * (3 ^ (1/2)))) ^ (1/2)), 1/2 * ((8 + (-4 * (3 ^ (1/2)))) ^ (1/2)), -1/2 * ((8 + (4 * (3 ^ (1/2)))) ^ (1/2)), 1/2 * ((8 + (4 * (3 ^ (1/2)))) ^ (1/2))}", s, true) +testeq(t:roots(), "{-1/3 + (-4/3 * ((19 + (3 * (33 ^ (1/2)))) ^ (-1/3))) + (-1/3 * ((19 + (3 * (33 ^ (1/2)))) ^ (1/3))), -1/3 + (-4/3 * ((19 + (3 * (33 ^ (1/2)))) ^ (-1/3)) * ((-1/2 + (1/2 * (3 ^ (1/2)) * i)) ^ -1)) + (-1/3 * ((19 + (3 * (33 ^ (1/2)))) ^ (1/3)) * (-1/2 + (1/2 * (3 ^ (1/2)) * i))), -1/3 + (-4/3 * ((19 + (3 * (33 ^ (1/2)))) ^ (-1/3)) * ((-1/2 + (1/2 * (3 ^ (1/2)) * i)) ^ -2)) + (-1/3 * ((19 + (3 * (33 ^ (1/2)))) ^ (1/3)) * ((-1/2 + (1/2 * (3 ^ (1/2)) * i)) ^ 2))}", t, true) +endtest()
\ No newline at end of file diff --git a/macros/luatex/latex/luacas/tex/test/rings/conversion.lua b/macros/luatex/latex/luacas/tex/test/rings/conversion.lua new file mode 100644 index 0000000000..b9eb523c7a --- /dev/null +++ b/macros/luatex/latex/luacas/tex/test/rings/conversion.lua @@ -0,0 +1,273 @@ +local a = Integer(12) +local b = Integer(3) / Integer(2) +local c = IntegerModN(Integer(4), Integer(7)) +local d = IntegerModN(Integer(8), Integer(14)) +local e = PolynomialRing({Integer(6), Integer(0), Integer(3)}, SymbolExpression("x")) +local f = PolynomialRing({Integer(4)/Integer(5), Integer(12)}, SymbolExpression("x")) +local g = PolynomialRing({ + PolynomialRing({ + PolynomialRing({Integer(-4), Integer(12), Integer(1)}, SymbolExpression("x")), + PolynomialRing({Integer(0)}, SymbolExpression("x")), + PolynomialRing({Integer(8)}, SymbolExpression("x")) + }, + SymbolExpression("y")), + PolynomialRing({ + PolynomialRing({Integer(8), Integer(7), Integer(6), Integer(5)}, SymbolExpression("x")), + PolynomialRing({Integer(-1)}, SymbolExpression("x")), + }, + SymbolExpression("y")), + PolynomialRing({ + PolynomialRing({Integer(0)}, SymbolExpression("x")), + PolynomialRing({Integer(2), Integer(8), Integer(1)}, SymbolExpression("x")), + PolynomialRing({Integer(-16), Integer(4)}, SymbolExpression("x")), + PolynomialRing({Integer(1)}, SymbolExpression("x")) + }, + SymbolExpression("y")), + PolynomialRing({ + PolynomialRing({Integer(1)}, SymbolExpression("x")) + }, + SymbolExpression("y")) + }, SymbolExpression("z")) +local h = PolynomialRing({ + PolynomialRing({ + PolynomialRing({Integer(-4), Integer(4)/Integer(5), Integer(1)}, SymbolExpression("z")), + PolynomialRing({Integer(0)}, SymbolExpression("z")), + PolynomialRing({Integer(8)}, SymbolExpression("z")) + }, + SymbolExpression("y")), + PolynomialRing({ + PolynomialRing({Integer(8), Integer(7), Integer(6), Integer(5)}, SymbolExpression("z")), + PolynomialRing({Integer(-1)}, SymbolExpression("z")), + }, + SymbolExpression("y")), + PolynomialRing({ + PolynomialRing({Integer(0)}, SymbolExpression("z")), + PolynomialRing({Integer(2), Integer(8), Integer(1)}, SymbolExpression("z")), + PolynomialRing({Integer(-16), Integer(1)/Integer(9)}, SymbolExpression("z")), + PolynomialRing({Integer(1)}, SymbolExpression("z")) + }, + SymbolExpression("y")), + PolynomialRing({ + PolynomialRing({Integer(1)}, SymbolExpression("z")) + }, + SymbolExpression("y")) + }, SymbolExpression("x")) +local i = Rational(PolynomialRing({-Integer(2), Integer(1)}, SymbolExpression("x")), + PolynomialRing({Integer(3), Integer(3), Integer(1)}, SymbolExpression("x"))) +local j = Rational(PolynomialRing({-Integer(2), Integer(1)}, SymbolExpression("x")), + PolynomialRing({Integer(3)/Integer(4), Integer(3)/Integer(8), Integer(1)}, SymbolExpression("x"))) +local k = PolynomialRing({IntegerModN(Integer(0), Integer(5)), + IntegerModN(Integer(1), Integer(5)), + IntegerModN(Integer(3), Integer(5)), + IntegerModN(Integer(1), Integer(5))}, SymbolExpression("x")) + +local l = PolynomialRing({Rational( + PolynomialRing({Integer(4), Integer(1)}, SymbolExpression("x")), + PolynomialRing({Integer(0), Integer(4)}, SymbolExpression("x")) + ), + Rational( + PolynomialRing({Integer(3)/Integer(2)}, SymbolExpression("x")), + PolynomialRing({Integer(6), Integer(1)/Integer(2), Integer(8), Integer(1)}, SymbolExpression("x")) + ), + Rational( + PolynomialRing({Integer(6), Integer(6), Integer(4)}, SymbolExpression("x")), + PolynomialRing({Integer(3), Integer(1)}, SymbolExpression("x")) + ), + Rational( + PolynomialRing({Integer(7)/Integer(6)}, SymbolExpression("x")), + PolynomialRing({Integer(2), Integer(1)}, SymbolExpression("x")) + ) + }, SymbolExpression("y")) + +local aring = a:getring() -- ZZ +local bring = b:getring() -- QQ +local cring = c:getring() -- ZZ_7 +local dring = d:getring() -- ZZ_14 +local ering = e:getring() -- ZZ[x] +local fring = f:getring() -- QQ[x] +local gring = g:getring() -- ZZ[x][y][z] +local hring = h:getring() -- QQ[z][y][x] +local iring = i:getring() -- ZZ(x) +local jring = j:getring() -- QQ(x) +local kring = k:getring() -- ZZ_5[x] +local lring = l:getring() -- QQ(x)[y] + +starttest("ring construction") +testeq(aring, "ZZ") +testeq(bring, "QQ") +testeq(cring, "Z/Z7") +testeq(dring, "Z/Z14") +testeq(ering, "ZZ[x]") +testeq(fring, "QQ[x]") +testeq(gring, "ZZ[x][y][z]") +testeq(hring, "QQ[z][y][x]") +testeq(iring, "ZZ(x)") +testeq(jring, "QQ(x)") +testeq(kring, "Z/Z5[x]") +testeq(lring, "QQ(x)[y]") +endtest() + +starttest("ring conversion") + +-- Commented-out tests denote elements whos rings are not subrings of the ring that is being converted to + +testringconvert(a, aring, "12", "ZZ") +testringconvert(a, bring, "12/1", "QQ") +testringconvert(a, cring, "5", "Z/Z7") +testringconvert(a, dring, "12", "Z/Z14") +testringconvert(a, ering, "12x^0", "ZZ[x]") +testringconvert(a, fring, "12/1x^0", "QQ[x]") +testringconvert(a, gring, "((12x^0)y^0)z^0", "ZZ[x][y][z]") +testringconvert(a, hring, "((12/1z^0)y^0)x^0", "QQ[z][y][x]") +testringconvert(a, iring, "(12x^0)/(1x^0)", "ZZ(x)") +testringconvert(a, jring, "(12x^0)/(1x^0)", "ZZ(x)") +testringconvert(a, kring, "2x^0", "Z/Z5[x]") +testringconvert(a, lring, "((12x^0)/(1x^0))y^0", "ZZ(x)[y]") + +-- testringconvert(b, aring, "3/2", "ZZ") +testringconvert(b, bring, "3/2", "QQ") +-- testringconvert(b, cring, "3/2", "Z/Z7") +-- testringconvert(b, dring, "3/2", "Z/Z14") +-- testringconvert(b, ering, "3/2", "ZZ[x]") +testringconvert(b, fring, "3/2x^0", "QQ[x]") +-- testringconvert(b, gring, "3/2", "ZZ[x][y][z]") +testringconvert(b, hring, "((3/2z^0)y^0)x^0", "QQ[z][y][x]") +-- testringconvert(b, iring, "3/2", "ZZ(x)") +testringconvert(b, jring, "(3/2x^0)/(1x^0)", "QQ(x)") +-- testringconvert(b, kring, "3/2", "Z/Z5[x]") +testringconvert(b, lring, "((3/2x^0)/(1x^0))y^0", "QQ(x)[y]") + +testringconvert(c, aring, "4", "ZZ") +-- testringconvert(c, bring, "4", "QQ") +testringconvert(c, cring, "4", "Z/Z7") +testringconvert(c, dring, "4", "Z/Z14") +testringconvert(c, ering, "4x^0", "ZZ[x]") +-- testringconvert(c, fring, "4x", "QQ[x]") +testringconvert(c, gring, "((4x^0)y^0)z^0", "ZZ[x][y][z]") +-- testringconvert(c, hring, "4", "QQ[z][y][x]") +testringconvert(c, iring, "(4x^0)/(1x^0)", "ZZ(x)") +-- testringconvert(c, jring, "12/1x^0/1/1x^0", "QQ(x)") +testringconvert(c, kring, "4x^0", "Z/Z5[x]") +-- testringconvert(c, lring, "4", "QQ(x)[y]") + +testringconvert(d, aring, "8", "ZZ") +-- testringconvert(d, bring, "8", "QQ") +testringconvert(d, cring, "1", "Z/Z7") +testringconvert(d, dring, "8", "Z/Z14") +testringconvert(d, ering, "8x^0", "ZZ[x]") +-- testringconvert(d, fring, "8", "QQ[x]") +testringconvert(d, gring, "((8x^0)y^0)z^0", "ZZ[x][y][z]") +-- testringconvert(d, hring, "8", "QQ[z][y][x]") +testringconvert(d, iring, "(8x^0)/(1x^0)", "ZZ(x)") +-- testringconvert(d, jring, "8", "QQ(x)") +testringconvert(d, kring, "3x^0", "Z/Z5[x]") +-- testringconvert(d, lring, "8", "QQ(x)[y]") + +-- testringconvert(e, aring, "3x^2+0x^1+6x^0", "ZZ") +-- testringconvert(e, bring, "3x^2+0x^1+6x^0", "QQ") +-- testringconvert(e, cring, "3x^2+0x^1+6x^0", "Z/Z7") +-- testringconvert(e, dring, "3x^2+0x^1+6x^0", "Z/Z14") +testringconvert(e, ering, "3x^2+0x^1+6x^0", "ZZ[x]") +testringconvert(e, fring, "3/1x^2+0/1x^1+6/1x^0", "QQ[x]") +testringconvert(e, gring, "((3x^2+0x^1+6x^0)y^0)z^0", "ZZ[x][y][z]") +testringconvert(e, hring, "((3/1z^0)y^0)x^2+((0/1z^0)y^0)x^1+((6/1z^0)y^0)x^0", "QQ[z][y][x]") +testringconvert(e, iring, "(3x^2+0x^1+6x^0)/(1x^0)", "ZZ(x)") +testringconvert(e, jring, "(3x^2+0x^1+6x^0)/(1x^0)", "ZZ(x)") +testringconvert(e, kring, "3x^2+0x^1+1x^0", "Z/Z5[x]") +testringconvert(e, lring, "((3x^2+0x^1+6x^0)/(1x^0))y^0", "ZZ(x)[y]") + +-- testringconvert(f, aring, "12x^1+4/5x^0", "ZZ") +-- testringconvert(f, bring, "12x^1+4/5x^0", "QQ") +-- testringconvert(f, cring, "12x^1+4/5x^0", "Z/Z7") +-- testringconvert(f, dring, "12x^1+4/5x^0", "Z/Z14") +-- testringconvert(f, ering, "12x^1+4/5x^0", "ZZ[x]") +testringconvert(f, fring, "12x^1+4/5x^0", "QQ[x]") +-- testringconvert(f, gring, "12x^1+4/5x^0", "ZZ[x][y][z]") +testringconvert(f, hring, "((12/1z^0)y^0)x^1+((4/5z^0)y^0)x^0", "QQ[z][y][x]") +-- testringconvert(f, iring, "12x^1+4/5x^0", "ZZ(x)") +testringconvert(f, jring, "(12x^1+4/5x^0)/(1x^0)", "QQ(x)") +-- testringconvert(f, kring, "12x^1+4/5x^0", "Z/Z5[x]") +testringconvert(f, lring, "((12x^1+4/5x^0)/(1x^0))y^0", "QQ(x)[y]") + +-- testringconvert(g, aring, "", "ZZ") +-- testringconvert(g, bring, "", "QQ") +-- testringconvert(g, cring, "", "Z/Z7") +-- testringconvert(g, dring, "", "Z/Z14") +-- testringconvert(g, ering, "", "ZZ[x]") +-- testringconvert(g, fring, "", "QQ[x]") +testringconvert(g, gring, "((1x^0)y^0)z^3+((1x^0)y^3+(4x^1+-16x^0)y^2+(1x^2+8x^1+2x^0)y^1+(0x^0)y^0)z^2+((-1x^0)y^1+(5x^3+6x^2+7x^1+8x^0)y^0)z^1+((8x^0)y^2+(0x^0)y^1+(1x^2+12x^1+-4x^0)y^0)z^0", "ZZ[x][y][z]") +-- testringconvert(g, hring, "", "QQ[z][y][x]") +-- testringconvert(g, iring, "", "ZZ(x)") +-- testringconvert(g, jring, "", "QQ(x)") +-- testringconvert(g, kring, "", "Z/Z5[x]") +-- testringconvert(g, lring, "", "QQ(x)[y]") + +-- testringconvert(h, aring, "", "ZZ") +-- testringconvert(h, bring, "", "QQ") +-- testringconvert(h, cring, "", "Z/Z7") +-- testringconvert(h, dring, "", "Z/Z14") +-- testringconvert(h, ering, "", "ZZ[x]") +-- testringconvert(h, fring, "", "QQ[x]") +-- testringconvert(h, gring, "", "ZZ[x][y][z]") +testringconvert(h, hring, "((1z^0)y^0)x^3+((1z^0)y^3+(1/9z^1+-16z^0)y^2+(1z^2+8z^1+2z^0)y^1+(0z^0)y^0)x^2+((-1z^0)y^1+(5z^3+6z^2+7z^1+8z^0)y^0)x^1+((8z^0)y^2+(0z^0)y^1+(1z^2+4/5z^1+-4z^0)y^0)x^0", "QQ[z][y][x]") +-- testringconvert(h, iring, "", "ZZ(x)") +-- testringconvert(h, jring, "", "QQ(x)") +-- testringconvert(h, kring, "", "Z/Z5[x]") +-- testringconvert(h, lring, "", "QQ(x)[y]") + +-- testringconvert(i, aring, "", "ZZ") +-- testringconvert(i, bring, "", "QQ") +-- testringconvert(i, cring, "", "Z/Z7") +-- testringconvert(i, dring, "", "Z/Z14") +-- testringconvert(i, ering, "", "ZZ[x]") +-- testringconvert(i, fring, "", "QQ[x]") +-- testringconvert(i, gring, "", "ZZ[x][y][z]") +-- testringconvert(i, hring, "", "QQ[z][y][x]") +testringconvert(i, iring, "(1x^1+-2x^0)/(1x^2+3x^1+3x^0)", "ZZ(x)") +testringconvert(i, jring, "(1x^1+-2x^0)/(1x^2+3x^1+3x^0)", "ZZ(x)") +-- testringconvert(i, kring, "", "Z/Z5[x]") +testringconvert(i, lring, "((1x^1+-2x^0)/(1x^2+3x^1+3x^0))y^0", "ZZ(x)[y]") + +-- testringconvert(j, aring, "", "ZZ") +-- testringconvert(j, bring, "", "QQ") +-- testringconvert(j, cring, "", "Z/Z7") +-- testringconvert(j, dring, "", "Z/Z14") +-- testringconvert(j, ering, "", "ZZ[x]") +-- testringconvert(j, fring, "", "QQ[x]") +-- testringconvert(j, gring, "", "ZZ[x][y][z]") +-- testringconvert(j, hring, "", "QQ[z][y][x]") +-- testringconvert(j, iring, "", "ZZ(x)") +testringconvert(j, jring, "(1x^1+-2x^0)/(1x^2+3/8x^1+3/4x^0)", "QQ(x)") +-- testringconvert(j, kring, "", "Z/Z5[x]") +testringconvert(j, lring, "((1x^1+-2x^0)/(1x^2+3/8x^1+3/4x^0))y^0", "QQ(x)[y]") + +-- testringconvert(k, aring, "", "ZZ") +-- testringconvert(k, bring, "", "QQ") +-- testringconvert(k, cring, "", "Z/Z7") +-- testringconvert(k, dring, "", "Z/Z14") +testringconvert(k, ering, "1x^3+3x^2+1x^1+0x^0", "ZZ[x]") +-- testringconvert(k, fring, "", "QQ[x]") +testringconvert(k, gring, "((1x^3+3x^2+1x^1+0x^0)y^0)z^0", "ZZ[x][y][z]") +-- testringconvert(k, hring, "", "QQ[z][y][x]") +testringconvert(k, iring, "(1x^3+3x^2+1x^1+0x^0)/(1x^0)", "ZZ(x)") +-- testringconvert(k, jring, "", "QQ(x)") +testringconvert(k, kring, "1x^3+3x^2+1x^1+0x^0", "Z/Z5[x]") +-- testringconvert(k, lring, "", "QQ(x)[y]") + +-- testringconvert(l, aring, "", "ZZ") +-- testringconvert(l, bring, "", "QQ") +-- testringconvert(l, cring, "", "Z/Z7") +-- testringconvert(l, dring, "", "Z/Z14") +-- testringconvert(l, ering, "", "ZZ[x]") +-- testringconvert(l, fring, "", "QQ[x]") +-- testringconvert(l, gring, "", "ZZ[x][y][z]") +-- testringconvert(l, hring, "", "QQ[z][y][x]") +-- testringconvert(l, iring, "", "ZZ(x)") +-- testringconvert(l, jring, "", "QQ(x)") +-- testringconvert(j, kring, "", "Z/Z5[x]") +testringconvert(l, lring, "((7/6x^0)/(1x^1+2x^0))y^3+((4x^2+6x^1+6x^0)/(1x^1+3x^0))y^2+((3/2x^0)/(1x^3+8x^2+1/2x^1+6x^0))y^1+((1/4x^1+1x^0)/(1x^1+0x^0))y^0", "QQ(x)[y]") + + + + +endtest()
\ No newline at end of file diff --git a/macros/luatex/latex/luacas/tex/test/rings/modulararithmetic.lua b/macros/luatex/latex/luacas/tex/test/rings/modulararithmetic.lua new file mode 100644 index 0000000000..1bd315595a --- /dev/null +++ b/macros/luatex/latex/luacas/tex/test/rings/modulararithmetic.lua @@ -0,0 +1,20 @@ +local a = IntegerModN(Integer(5), Integer(3)) +local b = IntegerModN(Integer(1), Integer(3)) +local c = IntegerModN(Integer(-12), Integer(3)) +local f = IntegerModN(Integer(100), Integer(62501)) +local d = IntegerModN(Integer(16), Integer(36)) +local e = IntegerModN(Integer(27), Integer(36)) + +starttest("modular arithmetic") +testeq(a, "2") +testeq(b, "1") +testeq(c, "0") +testeq(a + b, "0") +testeq(a - b, "1") +testeq(a * b, "2") +testeq(a:inv(), "2") +testeq(b:inv(), "1") +testeq(f:inv(), "61876") +testeq(d * e, "0") +testeq(a * d, "2") +endtest()
\ No newline at end of file diff --git a/macros/luatex/latex/luacas/tex/test/rings/number.lua b/macros/luatex/latex/luacas/tex/test/rings/number.lua new file mode 100644 index 0000000000..9afea0d364 --- /dev/null +++ b/macros/luatex/latex/luacas/tex/test/rings/number.lua @@ -0,0 +1,118 @@ +local a = Integer(5) +local b = Integer(3) +local c = Integer(-12) +local d = Integer("-54321") +local e = Integer("99989999999999999989999999999999999999999999999999999999989999999999999999999999999998999999999999999999999999989999999998") +local f = Integer("-1267650600228229401496703205376") +local g = Integer(16) +local h = Integer(8) +local x = Integer(8) / Integer(5) +local y = Integer(1) / Integer(12) +local z = Integer(-7) / Integer(10) + + +starttest("integer construction") +testeq(a, 5) +testeq(b, 3) +testeq(c, -12) +testeq(d, "-54321") +testeq(e, "99989999999999999989999999999999999999999999999999999999989999999999999999999999999998999999999999999999999999989999999998") +testeq(f, "-1267650600228229401496703205376") +endtest() + +starttest("integer operations") +testeq(-c, 12) +testeq(a + b, 8) +testeq(b - c, 15) +testeq(d - d, 0) +testeq(e + f, "99989999999999999989999999999999999999999999999999999999989999999999999999999999999998999998732349399771770598493296794622") +testeq(a * c, -60) +testeq(f * f, "1606938044258990275541962092341162602522202993782792835301376") +testeq(e * f, "-126752383516820657842978847503263945985032967946239999999987323493997717705985032967944972349399771770598503296781947493995182404784576509143246593589248") +testeq(a // b, 1) +testeq(a % b, 2) +testeq(f // d, "23336289836862896513258283") +testeq(f % d, "-14533") +testeq(e // -f, "78878201913048970415230130190415677050906625793723347950240237316957169209243093407705758276") +testeq(e % -f, "1011644662020502370048160308222") +testeq(c ^ a, -248832) +testeq(d ^ a, "-472975648731213834575601") +testeq(a == b, false) +testeq(b < a, true) +testeq(a <= a, true) +testeq(f < d, true) +testeq(e <= f, false) +endtest() + + + +starttest("integer conversions") +testeq(a / b, "5/3") +testeq(g / c, "-4/3") +testeq(c / b, -4) +endtest() + + +starttest("rational operations") +testeq(-x, "-8/5") +testeq(x + y, "101/60") +testeq(z - y, "-47/60") +testeq(x * z, "-28/25") +testeq(x / y, "96/5") +testeq(y<x, true) +testeq(z<z, false) +testeq(z<=z, true) +endtest() + +starttest("combined integer/rational operations") +testeq(a + x, "33/5") +testeq(x + a, "33/5") +testeq(b - y, "35/12") +testeq(y - b, "-35/12") +testeq(c * y, -1) +testeq(y * c, -1) +testeq(a / x, "25/8") +testeq(x / a, "8/25") +testeq(a/h == x, false) +testeq(h/a == x, true) +testeq(y < b , true) +testeq(b < y, false) +endtest() + +local f = Integer(3) +local g = Integer(216) +local h = Integer(945) +local i = Integer("7766999") +local j = Integer(4) +local k = Integer(8) +local m = Integer(16) +local n = Integer(100000000003) +local o = Integer(200250077) + +starttest("Miller-Rabin Primes") +testeq(f:isprime(), true, f) +testeq(g:isprime(), false, g) +testeq(h:isprime(), false, h) +testeq(i:isprime(), false, i) +testeq(n:isprime(), true, n) +testeq(o:isprime(), false, o) +endtest() + + +starttest("Pollard Rho algorithm") +testeq(f:findafactor(), 3, f) +testeq(g:findafactor(), 2, g) +testeq(h:findafactor(), 3, h) +testeq(i:findafactor(), 41, i) +testeq(j:findafactor(), 2, j) +testeq(k:findafactor(), 2, k) +testeq(m:findafactor(), 2, m) +endtest() + +starttest("prime factorization") +testeq(f:primefactorization(), "* (3 ^ 1)", f, true) +testeq(g:primefactorization(), "(2 ^ 3) * (3 ^ 3)", g, true) +testeq(h:primefactorization(), "(3 ^ 3) * (5 ^ 1) * (7 ^ 1)", h, true) +testeq(i:primefactorization(), "(41 ^ 1) * (189439 ^ 1)", i, true) +testeq(o:primefactorization(), "(10007 ^ 1) * (20011 ^ 1)", o, true) +endtest()
\ No newline at end of file |