diff options
author | Karl Berry <karl@freefriends.org> | 2023-05-30 20:07:08 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2023-05-30 20:07:08 +0000 |
commit | 5c189e74d1e6286f801b7c6500d257fdbed0fba4 (patch) | |
tree | 9562bfaa3a038dca92f1c68c131ae00437fdb08f | |
parent | d522a13fb4b304e841880cd0aae1de7481c92b21 (diff) |
luacas (30may23)
git-svn-id: svn://tug.org/texlive/trunk@67247 c570f23f-e606-0410-a88d-b1316a301751
36 files changed, 426 insertions, 117 deletions
diff --git a/Master/texmf-dist/doc/lualatex/luacas/appendix/luacas.dat b/Master/texmf-dist/doc/lualatex/luacas/appendix/luacas.dat index 7f2efd0a10e..c0011e71b27 100644 --- a/Master/texmf-dist/doc/lualatex/luacas/appendix/luacas.dat +++ b/Master/texmf-dist/doc/lualatex/luacas/appendix/luacas.dat @@ -1,4 +1,4 @@ -% Copyright (c) ??? +% Copyright (c) % % Permission is granted to copy, distribute and/or modify this % software under the terms of the LaTeX Project Public License @@ -11,7 +11,7 @@ \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{luacas} - [2022/11/15 v1.0.1 CAS written in Lua for LaTeX] + [2023/05/26 v1.0.2 CAS written in Lua for LaTeX] \RequirePackage{iftex} \ifluatex diff --git a/Master/texmf-dist/doc/lualatex/luacas/appendix/versionhistory.tex b/Master/texmf-dist/doc/lualatex/luacas/appendix/versionhistory.tex index 26754b3c7d3..ad7e4f53fef 100644 --- a/Master/texmf-dist/doc/lualatex/luacas/appendix/versionhistory.tex +++ b/Master/texmf-dist/doc/lualatex/luacas/appendix/versionhistory.tex @@ -7,6 +7,15 @@ \section{Version History} +\subsection*{v1.0.2} + +\begin{itemize} + \item Fix Polynomial Rings displaying redundant ones in \LaTeX{} + \item Fix rational forced non-simplification not working + \item Added ability to load LuaCAS modules as local variables + \item Fix arithmetic with decimal expressions +\end{itemize} + \subsection*{v1.0.1} \begin{itemize} diff --git a/Master/texmf-dist/doc/lualatex/luacas/luacas.dat b/Master/texmf-dist/doc/lualatex/luacas/luacas.dat index 7f2efd0a10e..c0011e71b27 100644 --- a/Master/texmf-dist/doc/lualatex/luacas/luacas.dat +++ b/Master/texmf-dist/doc/lualatex/luacas/luacas.dat @@ -1,4 +1,4 @@ -% Copyright (c) ??? +% Copyright (c) % % Permission is granted to copy, distribute and/or modify this % software under the terms of the LaTeX Project Public License @@ -11,7 +11,7 @@ \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{luacas} - [2022/11/15 v1.0.1 CAS written in Lua for LaTeX] + [2023/05/26 v1.0.2 CAS written in Lua for LaTeX] \RequirePackage{iftex} \ifluatex diff --git a/Master/texmf-dist/doc/lualatex/luacas/luacas.pdf b/Master/texmf-dist/doc/lualatex/luacas/luacas.pdf Binary files differindex 667791efb60..13f358c5e87 100644 --- a/Master/texmf-dist/doc/lualatex/luacas/luacas.pdf +++ b/Master/texmf-dist/doc/lualatex/luacas/luacas.pdf diff --git a/Master/texmf-dist/doc/lualatex/luacas/luacas.tex b/Master/texmf-dist/doc/lualatex/luacas/luacas.tex index 3d0c51a343f..7c49b9eef57 100644 --- a/Master/texmf-dist/doc/lualatex/luacas/luacas.tex +++ b/Master/texmf-dist/doc/lualatex/luacas/luacas.tex @@ -160,7 +160,7 @@ style=numeric, \begin{document} \title{The {\ttfamily luacas} package} \author{Evan Cochrane\thanks{\href{mailto:cochraef@rose-hulman.edu}{\ttfamily cochraef@rose-hulman.edu}} , Timothy All\thanks{\href{mailto:timothy.all@rose-hulman.edu}{\ttfamily timothy.all@rose-hulman.edu}}} -\date{v1.0.1 \\ \today} +\date{v1.0.2\\ \today} \maketitle diff --git a/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-absexpression.lua b/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-absexpression.lua index 2bf0b6a7efc..264730cbbee 100644 --- a/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-absexpression.lua +++ b/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-absexpression.lua @@ -2,7 +2,7 @@ --- The absolute value of an expression. --- @field expression Expression AbsExpression = {} -__AbsExpression = {} +local __AbsExpression = {} ---------------------------- -- Instance functionality -- diff --git a/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-algebra_init.lua b/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-algebra_init.lua deleted file mode 100644 index ac37c56a5b5..00000000000 --- a/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-algebra_init.lua +++ /dev/null @@ -1,24 +0,0 @@ --- Loads algebra files in the correct order. -require("_lib.luacas-table") - -require("core.luacas-core_init") - -require("algebra.luacas-ring") -require("algebra.luacas-euclideandomain") -require("algebra.luacas-field") -require("algebra.luacas-polynomialring") -require("algebra.luacas-integer") -require("algebra.luacas-rational") -require("algebra.luacas-integerquotientring") -require("algebra.luacas-sqrtexpression") - -require("algebra.luacas-absexpression") -require("algebra.luacas-equation") -require("algebra.luacas-factorialexpression") -require("algebra.luacas-logarithm") -require("algebra.luacas-rootexpression") -require("algebra.luacas-trigexpression") - -require("algebra.polynomialring.luacas-berlekampfactoring") -require("algebra.polynomialring.luacas-zassenhausfactoring") -require("algebra.polynomialring.luacas-decomposition")
\ No newline at end of file diff --git a/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-equation.lua b/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-equation.lua index 4e81d5ca95d..18d6a9c0913 100644 --- a/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-equation.lua +++ b/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-equation.lua @@ -3,7 +3,7 @@ --- @field lhs Expression --- @field rhs Expression Equation = {} -__Equation = {} +local __Equation = {} -------------------------- -- Static functionality -- diff --git a/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-euclideandomain.lua b/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-euclideandomain.lua index fab2c5c7c26..fec52d5d810 100644 --- a/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-euclideandomain.lua +++ b/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-euclideandomain.lua @@ -1,7 +1,7 @@ --- @class EuclideanDomain --- Interface for an element of a euclidean domain. EuclideanDomain = {} -__EuclideanDomain = {} +local __EuclideanDomain = {} ---------------------- -- Required methods -- diff --git a/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-factorialexpression.lua b/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-factorialexpression.lua index 1c5b824ff7e..5920d22733b 100644 --- a/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-factorialexpression.lua +++ b/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-factorialexpression.lua @@ -2,7 +2,7 @@ --- The factorial of an expression. --- @field expression Expression FactorialExpression = {} -__FactorialExpression = {} +local __FactorialExpression = {} ---------------------------- -- Instance functionality -- diff --git a/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-field.lua b/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-field.lua index c845e94c55e..0846a90ec90 100644 --- a/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-field.lua +++ b/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-field.lua @@ -1,7 +1,7 @@ --- @class Field --- Interface for an element of a field. Field = {} -__Field = {} +local __Field = {} ---------------------- -- Required methods -- diff --git a/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-integer.lua b/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-integer.lua index a3c54f498cc..6a81be295bf 100644 --- a/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-integer.lua +++ b/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-integer.lua @@ -3,7 +3,7 @@ --- @field self table<number, number> --- @field sign number Integer = {} -__Integer = {} +local __Integer = {} -------------------------- -- Static functionality -- @@ -90,6 +90,9 @@ end --- @return Integer function Integer.ceillog(a, base) base = base or Integer(10) + if a == Integer.one() then + return Integer.one() + end local k = Integer.zero() while (base ^ k) < a do @@ -138,9 +141,9 @@ end ---------------------------- -- So we don't have to copy the Euclidean operations each time we create an integer. -local __o = Copy(__EuclideanOperations) -__o.__index = Integer -__o.__tostring = function(a) -- Only works if the digit size is a power of 10 +__IntegerOperations = Copy(__EuclideanOperations) +__IntegerOperations.__index = Integer +__IntegerOperations.__tostring = function(a) -- Only works if the digit size is a power of 10 local out = "" for i, digit in ipairs(a) do local pre = tostring(math.floor(digit)) @@ -156,7 +159,7 @@ __o.__tostring = function(a) -- Only works if the digit size is a power of 10 end return out end -__o.__div = function(a, b) -- Constructor for a rational number disguised as division +__IntegerOperations.__div = function(a, b) -- Constructor for a rational number disguised as division if not b.getring then return BinaryOperation.DIVEXP({a, b}) end @@ -165,7 +168,7 @@ __o.__div = function(a, b) -- Constructor for a rational number disguised as d end return __FieldOperations.__div(a, b) end -__o.__concat = function(a, b) -- Like a decimal, but fancier. Used mainly for the parser with decimal numbers. +__IntegerOperations.__concat = function(a, b) -- Like a decimal, but fancier. Used mainly for the parser with decimal numbers. return a + b / (Integer(10) ^ Integer.ceillog(b)) end @@ -174,7 +177,7 @@ end --- @return Integer function Integer:new(n) local o = {} - o = setmetatable(o, __o) + o = setmetatable(o, __IntegerOperations) if not n then o[1] = 0 diff --git a/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-integerquotientring.lua b/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-integerquotientring.lua index 4c2188c9e53..6fe0ce1cdf4 100644 --- a/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-integerquotientring.lua +++ b/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-integerquotientring.lua @@ -4,7 +4,7 @@ --- @field modulus Integer IntegerModN = {} -__IntegerModN = {} +local __IntegerModN = {} -- Metatable for ring objects. local __obj = {__index = IntegerModN, __eq = function(a, b) @@ -37,11 +37,10 @@ end ---------------------------- -- So we don't have to copy the field operations each time -local __o -__o = Copy(__FieldOperations) +__IntegerModNOperations = Copy(__FieldOperations) -__o.__index = IntegerModN -__o.__tostring = function(a) +__IntegerModNOperations.__index = IntegerModN +__IntegerModNOperations.__tostring = function(a) return tostring(a.element) end @@ -56,7 +55,7 @@ function IntegerModN:new(i, n) error("Argument error: modulus must be an integer greater than 0.") end - o = setmetatable(o, __o) + o = setmetatable(o, __IntegerModNOperations) if i < Integer.zero() or i >= n then i = i % n diff --git a/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-logarithm.lua b/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-logarithm.lua index 07a9db84d12..135a74f3267 100644 --- a/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-logarithm.lua +++ b/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-logarithm.lua @@ -4,7 +4,7 @@ --- @field base Expression --- @field expression Expression Logarithm = {} -__Logarithm = {} +local __Logarithm = {} ---------------------------- -- Instance functionality -- diff --git a/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-polynomialring.lua b/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-polynomialring.lua index 568c21c921a..2a76bda2650 100644 --- a/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-polynomialring.lua +++ b/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-polynomialring.lua @@ -4,7 +4,7 @@ --- @field symbol SymbolExpression --- @field ring RingIdentifier PolynomialRing = {} -__PolynomialRing = {} +local __PolynomialRing = {} -- Metatable for ring objects. local __obj = {__index = PolynomialRing, __eq = function(a, b) @@ -214,9 +214,9 @@ end ---------------------------- -- So we don't have to copy the Euclidean operations each time -local __o = Copy(__EuclideanOperations) -__o.__index = PolynomialRing -__o.__tostring = function(a) +__PolynomialOperations = Copy(__EuclideanOperations) +__PolynomialOperations.__index = PolynomialRing +__PolynomialOperations.__tostring = function(a) local out = "" local loc = a.degree:asnumber() while loc >= 0 do @@ -229,7 +229,7 @@ __o.__tostring = function(a) end return string.sub(out, 1, string.len(out) - 1) end -__o.__div = function(a, b) +__PolynomialOperations.__div = function(a, b) if not b.getring then return BinaryOperation.DIVEXP({a, b}) end @@ -258,13 +258,20 @@ function PolynomialRing:tolatex() end if self.ring == Rational.getring() or self.ring == Integer.getring() or self.ring == IntegerModN.getring() then if self.coefficients[loc] ~= Integer.one() then - out = out .. self.coefficients[loc]:tolatex() .. self.symbol + if self.coefficients[loc] == Integer(-1) then + out = out .. "-" .. self.symbol + elseif self.coefficients[loc] == Integer.zero() then + goto lead + else + out = out .. self.coefficients[loc]:tolatex() .. self.symbol + end else out = out .. self.symbol end if loc ~=1 then out = out .. "^{" .. loc .. "}" end + ::lead:: loc = loc -1 while loc >=0 do local coeff = self.coefficients[loc] @@ -330,7 +337,7 @@ end -- Creates a new polynomial ring given an array of coefficients and a symbol function PolynomialRing:new(coefficients, symbol, degree) local o = {} - o = setmetatable(o, __o) + o = setmetatable(o, __PolynomialOperations) if type(coefficients) ~= "table" then error("Sent parameter of wrong type: Coefficients must be in an array") diff --git a/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-rational.lua b/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-rational.lua index 811909a948f..0802eb51721 100644 --- a/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-rational.lua +++ b/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-rational.lua @@ -4,7 +4,7 @@ --- @field denominator Ring --- @field ring RingIdentifier Rational = {} -__Rational = {} +local __Rational = {} -------------------------- @@ -54,9 +54,9 @@ end ---------------------------- -- So we don't have to copy the field operations each time. -local __o = Copy(__FieldOperations) -__o.__index = Rational -__o.__tostring = function(a) +__RationalOperations = Copy(__FieldOperations) +__RationalOperations.__index = Rational +__RationalOperations.__tostring = function(a) if a.ring.symbol then return "(" .. tostring(a.numerator)..")/("..tostring(a.denominator) .. ")" end @@ -70,7 +70,7 @@ end --- @param keep boolean function Rational:new(n, d, keep) local o = {} - o = setmetatable(o, __o) + o = setmetatable(o, __RationalOperations) if n:getring() == PolynomialRing.getring() then o.symbol = n.symbol @@ -88,7 +88,15 @@ function Rational:new(n, d, keep) d = d or Integer.one() o.numerator = n o.denominator = d - o:reduce() + if not keep then + o:reduce() + end + + if o.numerator:getring() == Integer.getring() then + o.ring = Integer.getring() + elseif o.numerator:getring() == PolynomialRing.getring() then + o.ring = Ring.resultantring(o.numerator:getring(), o.denominator:getring()) + end if (not keep) and o.denominator == Integer.one() or (not keep) and o.numerator == Integer.zero() then return o.numerator @@ -107,7 +115,6 @@ function Rational:reduce() local gcd = Integer.gcd(self.numerator, self.denominator) self.numerator = self.numerator//gcd self.denominator = self.denominator//gcd - self.ring = Integer.getring() elseif self.numerator:getring() == PolynomialRing.getring() then local lc = self.denominator:lc() self.denominator = self.denominator/lc @@ -115,7 +122,6 @@ function Rational:reduce() local gcd = PolynomialRing.gcd(self.numerator, self.denominator) self.numerator = self.numerator//gcd self.denominator = self.denominator//gcd - self.ring = Ring.resultantring(self.numerator:getring(), self.denominator:getring()) end end diff --git a/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-ring.lua b/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-ring.lua index 4903b9c9127..81df15d18c7 100644 --- a/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-ring.lua +++ b/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-ring.lua @@ -1,7 +1,7 @@ --- @class Ring --- Interface for an element of a ring with unity. Ring = {} -__Ring = {} +local __Ring = {} -------------------------- -- Static functionality -- diff --git a/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-rootexpression.lua b/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-rootexpression.lua index a66182579a4..6f9a4925915 100644 --- a/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-rootexpression.lua +++ b/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-rootexpression.lua @@ -2,7 +2,7 @@ --- An expression that represents the solutions to expression = 0. --- @field expression Expression RootExpression = {} -__RootExpression = {} +local __RootExpression = {} ---------------------------- -- Instance functionality -- diff --git a/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-sqrtexpression.lua b/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-sqrtexpression.lua index bc96f4e1d8b..641198fd65f 100644 --- a/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-sqrtexpression.lua +++ b/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-sqrtexpression.lua @@ -2,7 +2,7 @@ --- An expression that represents the positive real solution to x^n = a where n is a positive integer and a is constant. --- @field expression Expression SqrtExpression = {} -__SqrtExpression = {} +local __SqrtExpression = {} ---------------------------- -- Instance functionality -- diff --git a/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-trigexpression.lua b/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-trigexpression.lua index 307bfe17379..6f09e39f573 100644 --- a/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-trigexpression.lua +++ b/Master/texmf-dist/tex/lualatex/luacas/algebra/luacas-trigexpression.lua @@ -3,7 +3,7 @@ --- @field name string --- @field expression Expression TrigExpression = {} -__TrigExpression = {} +local __TrigExpression = {} ---------------------------- -- Instance functionality -- diff --git a/Master/texmf-dist/tex/lualatex/luacas/calculus/luacas-calculus_init.lua b/Master/texmf-dist/tex/lualatex/luacas/calculus/luacas-calculus_init.lua deleted file mode 100644 index 89b38b650e3..00000000000 --- a/Master/texmf-dist/tex/lualatex/luacas/calculus/luacas-calculus_init.lua +++ /dev/null @@ -1,6 +0,0 @@ --- Loads calculus files in the correct order. -require("algebra.luacas-algebra_init") - -require("calculus.luacas-derivativeexpression") -require("calculus.luacas-integralexpression") -require("calculus.luacas-diffexpression") diff --git a/Master/texmf-dist/tex/lualatex/luacas/calculus/luacas-derivativeexpression.lua b/Master/texmf-dist/tex/lualatex/luacas/calculus/luacas-derivativeexpression.lua index b757759c4c9..2ef4c431258 100644 --- a/Master/texmf-dist/tex/lualatex/luacas/calculus/luacas-derivativeexpression.lua +++ b/Master/texmf-dist/tex/lualatex/luacas/calculus/luacas-derivativeexpression.lua @@ -3,7 +3,7 @@ --- @field symbol SymbolExpression --- @field expression Expression DerivativeExpression = {} -__DerivativeExpression = {} +local __DerivativeExpression = {} ---------------------------- -- Instance functionality -- diff --git a/Master/texmf-dist/tex/lualatex/luacas/calculus/luacas-diffexpression.lua b/Master/texmf-dist/tex/lualatex/luacas/calculus/luacas-diffexpression.lua index df1dc90f334..bf15c56b6f0 100644 --- a/Master/texmf-dist/tex/lualatex/luacas/calculus/luacas-diffexpression.lua +++ b/Master/texmf-dist/tex/lualatex/luacas/calculus/luacas-diffexpression.lua @@ -4,7 +4,7 @@ --- @field expression Expression DiffExpression = {} -__DiffExpression = {} +local __DiffExpression = {} ---------------------------- -- Instance functionality -- diff --git a/Master/texmf-dist/tex/lualatex/luacas/calculus/luacas-integralexpression.lua b/Master/texmf-dist/tex/lualatex/luacas/calculus/luacas-integralexpression.lua index 5267127264c..bddc179fa49 100644 --- a/Master/texmf-dist/tex/lualatex/luacas/calculus/luacas-integralexpression.lua +++ b/Master/texmf-dist/tex/lualatex/luacas/calculus/luacas-integralexpression.lua @@ -10,7 +10,7 @@ --- @field recursive boolean IntegralExpression = {} -__IntegralExpression = {} +local __IntegralExpression = {} -------------------------- diff --git a/Master/texmf-dist/tex/lualatex/luacas/core/luacas-atomicexpression.lua b/Master/texmf-dist/tex/lualatex/luacas/core/luacas-atomicexpression.lua index 6cc6e4f58e2..4eed1592f47 100644 --- a/Master/texmf-dist/tex/lualatex/luacas/core/luacas-atomicexpression.lua +++ b/Master/texmf-dist/tex/lualatex/luacas/core/luacas-atomicexpression.lua @@ -1,7 +1,7 @@ --- @class AtomicExpression --- Interface for an atomic mathematical expression that has no sub-expressions. AtomicExpression = {} -__AtomicExpression = {} +local __AtomicExpression = {} ---------------------- diff --git a/Master/texmf-dist/tex/lualatex/luacas/core/luacas-binaryoperation.lua b/Master/texmf-dist/tex/lualatex/luacas/core/luacas-binaryoperation.lua index 708a6c15402..f2998436eb1 100644 --- a/Master/texmf-dist/tex/lualatex/luacas/core/luacas-binaryoperation.lua +++ b/Master/texmf-dist/tex/lualatex/luacas/core/luacas-binaryoperation.lua @@ -5,7 +5,7 @@ --- @field operation function --- @field expressions table<number, Expression> BinaryOperation = {} -__BinaryOperation = {} +local __BinaryOperation = {} ---------------------------- -- Instance functionality -- @@ -621,6 +621,8 @@ function BinaryOperation:tolatex() for index, expression in ipairs(self.expressions) do if index == 1 then out = out .. expression:tolatex() + elseif expression:isconstant() and expression < Integer.zero() then + out = out .. "\\cdot (" .. expression:tolatex() .. ")" else out = out .. "\\cdot " .. expression:tolatex() end diff --git a/Master/texmf-dist/tex/lualatex/luacas/core/luacas-compoundexpression.lua b/Master/texmf-dist/tex/lualatex/luacas/core/luacas-compoundexpression.lua index 792c36cfc27..cae82719acd 100644 --- a/Master/texmf-dist/tex/lualatex/luacas/core/luacas-compoundexpression.lua +++ b/Master/texmf-dist/tex/lualatex/luacas/core/luacas-compoundexpression.lua @@ -1,7 +1,7 @@ --- @class CompoundExpression --- Interface for an expression consisting of one or more subexpressions. CompoundExpression = {} -__CompoundExpression = {} +local __CompoundExpression = {} ---------------------- -- Instance methods -- diff --git a/Master/texmf-dist/tex/lualatex/luacas/core/luacas-constantexpression.lua b/Master/texmf-dist/tex/lualatex/luacas/core/luacas-constantexpression.lua index 0f91a037a95..6d9f8e96d22 100644 --- a/Master/texmf-dist/tex/lualatex/luacas/core/luacas-constantexpression.lua +++ b/Master/texmf-dist/tex/lualatex/luacas/core/luacas-constantexpression.lua @@ -3,7 +3,7 @@ --- Interface for a mathematical expression without any symbols. --- ConstantExpressions are AtomicExpressions by default, but individual classes may overwrite that inheritance. ConstantExpression = {} -__ConstantExpression = {} +local __ConstantExpression = {} ---------------------- -- Instance methods -- diff --git a/Master/texmf-dist/tex/lualatex/luacas/core/luacas-core_init.lua b/Master/texmf-dist/tex/lualatex/luacas/core/luacas-core_init.lua deleted file mode 100644 index c9c3b891264..00000000000 --- a/Master/texmf-dist/tex/lualatex/luacas/core/luacas-core_init.lua +++ /dev/null @@ -1,16 +0,0 @@ --- Loads core files in the correct order. - -require("core.luacas-expression") -require("core.luacas-atomicexpression") -require("core.luacas-compoundexpression") -require("core.luacas-constantexpression") -require("core.luacas-symbolexpression") -require("core.luacas-binaryoperation") -require("core.luacas-functionexpression") - - -require("core.binaryoperation.luacas-power") -require("core.binaryoperation.luacas-product") -require("core.binaryoperation.luacas-sum") -require("core.binaryoperation.luacas-quotient") -require("core.binaryoperation.luacas-difference")
\ No newline at end of file diff --git a/Master/texmf-dist/tex/lualatex/luacas/core/luacas-functionexpression.lua b/Master/texmf-dist/tex/lualatex/luacas/core/luacas-functionexpression.lua index dc94790b816..f6f3a997208 100644 --- a/Master/texmf-dist/tex/lualatex/luacas/core/luacas-functionexpression.lua +++ b/Master/texmf-dist/tex/lualatex/luacas/core/luacas-functionexpression.lua @@ -6,7 +6,7 @@ --- @field variables table<number,SymbolExpression> --- @alias Function FunctionExpression FunctionExpression = {} -__FunctionExpression = {} +local __FunctionExpression = {} ---------------------------- -- Instance functionality -- diff --git a/Master/texmf-dist/tex/lualatex/luacas/core/luacas-symbolexpression.lua b/Master/texmf-dist/tex/lualatex/luacas/core/luacas-symbolexpression.lua index 0d9192c084e..068ab71dccd 100644 --- a/Master/texmf-dist/tex/lualatex/luacas/core/luacas-symbolexpression.lua +++ b/Master/texmf-dist/tex/lualatex/luacas/core/luacas-symbolexpression.lua @@ -3,7 +3,7 @@ --- @field symbol string --- @alias Symbol SymbolExpression SymbolExpression = {} -__SymbolExpression = {} +local __SymbolExpression = {} ---------------------- -- Instance methods -- diff --git a/Master/texmf-dist/tex/lualatex/luacas/luacas.sty b/Master/texmf-dist/tex/lualatex/luacas/luacas.sty index d46ee847fc3..939bd9d3928 100644 --- a/Master/texmf-dist/tex/lualatex/luacas/luacas.sty +++ b/Master/texmf-dist/tex/lualatex/luacas/luacas.sty @@ -9,7 +9,7 @@ \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{luacas} - [2022/11/15 v1.0.1 CAS written in Lua for LaTeX] + [2023/05/26 v1.0.2 CAS written in Lua for LaTeX] \RequirePackage{iftex} \ifluatex diff --git a/Master/texmf-dist/tex/lualatex/luacas/luacas_init.lua b/Master/texmf-dist/tex/lualatex/luacas/luacas_init.lua new file mode 100644 index 00000000000..8d58e259e72 --- /dev/null +++ b/Master/texmf-dist/tex/lualatex/luacas/luacas_init.lua @@ -0,0 +1,304 @@ +--- @class LuaCAS +--- @class Module +--- A table that initalizes and stores luacas modules. +--- @field moduleinfo table<string, table> +--- @field core Module +--- @field algebra Module +--- @field calculus Module +local luacas = {} + + +-- a table containing a list of module names, descriptions, class names, variables, required files, and dependent modules +luacas.moduleinfo = { + ["core"]= + { + "Classes needed for creating basic expressions such as symbols, binary operations, and functions.", + { + "Expression", + "AtomicExpression", + "CompoundExpression", + "ConstantExpression", + "SymbolExpression", + "BinaryOperation", + "FunctionExpression", + + "__ExpressionOperations" + }, + {"E", "I", "PI"}, + { + "_lib.luacas-table", + "core.luacas-expression", + "core.luacas-atomicexpression", + "core.luacas-compoundexpression", + "core.luacas-constantexpression", + "core.luacas-symbolexpression", + "core.luacas-binaryoperation", + "core.luacas-functionexpression", + "core.binaryoperation.luacas-power", + "core.binaryoperation.luacas-product", + "core.binaryoperation.luacas-sum", + "core.binaryoperation.luacas-quotient", + "core.binaryoperation.luacas-difference", + }, + {} + }, + + ["algebra"]= + { + "Classes for elements of rings (integers, rationals, polynomials, etc., and operations on those elements (polynomial factoring). Also includes some elementary functions like logs and trig functions.", + { + "Ring", + "EuclideanDomain", + "Field", + "PolynomialRing", + "Integer", + "Rational", + "IntegerModN", + "SqrtExpression", + "AbsExpression", + "Equation", + "FactorialExpression", + "Logarithm", + "RootExpression", + "TrigExpression", + + "__RingOperations", -- Not classes, but we need to set the environment for this + "__EuclideanOperations", + "__FieldOperations", + "__PolynomialOperations", + "__IntegerOperations", + "__IntegerModNOperations", + "__RationalOperations" + }, + {"ABS", "ARCCOS", "ARCCOT", "ARCCSC", "ARCSEC", "ARCSIN", "ARCTAN", "COS", "COT", "CSC", "FACT", "LN", "LOG", "SEC", "SIN", "TAN"}, + { + "algebra.luacas-ring", + "algebra.luacas-euclideandomain", + "algebra.luacas-field", + "algebra.luacas-polynomialring", + "algebra.luacas-integer", + "algebra.luacas-rational", + "algebra.luacas-integerquotientring", + "algebra.luacas-sqrtexpression", + "algebra.luacas-absexpression", + "algebra.luacas-equation", + "algebra.luacas-factorialexpression", + "algebra.luacas-logarithm", + "algebra.luacas-rootexpression", + "algebra.luacas-trigexpression", + "algebra.polynomialring.luacas-berlekampfactoring", + "algebra.polynomialring.luacas-zassenhausfactoring", + "algebra.polynomialring.luacas-decomposition" + }, + {"core"} + }, + + ["calculus"]= + { + "Classes for symbolic differentation and integration.", + { + "DerivativeExpression", + "IntegralExpression", + "DiffExpression" + }, + {"DD", "INT"}, + { + "calculus.luacas-derivativeexpression", + "calculus.luacas-integralexpression", + "calculus.luacas-diffexpression" + }, + {"algebra"} + } +} + +--- Retrieves a short description for a module. +--- @param mod string +--- @return string +function luacas:moduledesc(mod) + if self.moduleinfo[mod] then + return self.moduleinfo[mod][1] + end + return "Module not found." +end + +--- Retrieves a list of class names included in a module. +--- @param mod string +--- @return table<number,string> +function luacas:moduleclasses(mod) + if self.moduleinfo[mod] then + return self.moduleinfo[mod][2] + end + return {} +end + +--- Retrieves a list of fields included in a module. +--- @param mod string +--- @return table<number,string> +function luacas:modulefields(mod) + if self.moduleinfo[mod] then + return self.moduleinfo[mod][3] + end + return {} +end + +--- Retrieves a list of files included in a module. +--- @param mod string +--- @return table<number,string> +function luacas:modulefiles(mod) + if self.moduleinfo[mod] then + return self.moduleinfo[mod][4] + end + return {} +end + +--- Retrieves a list of a module's immediate dependencies. +--- @param mod string +--- @return table<number,string> +function luacas:moduledependencies(mod) + if self.moduleinfo[mod] then + return self.moduleinfo[mod][5] + end + return {} +end + +--- Initalizes a LuaCAS module and returns it. +--- Since this creates temporary global variables, it should be treated as atomic to avoid collisions. +--- @param mod string +--- @return Module|nil +function luacas:initmodule(mod) + if not self.moduleinfo[mod] then + return nil + end + + -- TODO: This is a special case, since the algebra module is dependent on the core module and vice versa, + -- but our initialization scheme does not allow for circular dependencies. + if mod == "core" then + self:initmodule("algebra") + end + + -- Since other modules require globals from their dependencies, we only remove global variables after all modules have been initalized + local G = self:saveglobalstate() + self:_initmodulerec(mod) + self:restoreglobalstate(G) + + return self[mod] +end + +--- Recursive part of initalizing modules. +--- @param mod string +function luacas:_initmodulerec(mod) + + for _, dep in ipairs(self:moduledependencies(mod)) do + self:_initmodulerec(dep) + end + + if self[mod] then + -- Since globals from a dependency might be needed to initialize a module, we create globals even if a module has already been initalized. + for class, _ in self[mod] do + _G[class] = self[mod][class] + end + else + -- Creates globals needed for modules dependent on this one. + self:initglobalmodule(mod) + + -- Adds classes to module table. + self[mod] = {} + for _, class in ipairs(self:moduleclasses(mod)) do + self[mod][class] = _G[class] + end + + -- Sets the environment for each method of each class to include all dependent classes of this class. + self:setmoduleenvironment(mod) + -- TODO: This is a special case, since the algebra module is dependent on the core module and vice versa, + -- but our initialization scheme does not allow for circular dependencies. + if mod == "algebra" then + self:setmoduleenvironment("core") + end + + -- Adds fields to module tables + for _, class in ipairs(self:modulefields(mod)) do + self[mod][class] = _G[class] + end + end +end + +--- Sets the environment for each method of each class in a module to the current global environment, so it can keep using global variables when reset. +--- @param mod string +function luacas:setmoduleenvironment(mod) + local realenv = self:saveglobalstate() + for _, class in pairs(self[mod]) do + -- print(_) + for _, func in pairs(class) do + -- print(" ", _) + if type(func) == "function" then + --- Functions only have an _ENV upvalue if they have a global variable, so this should work + local _envloc = debug.findupvalue(func, "_ENV") + if _envloc then + debug.upvaluejoin(func, debug.findupvalue(func, "_ENV"), function () return realenv end, 1) + end + end + end + + -- local meta = getmetatable(class) + -- if meta then + -- for _, func in pairs(meta) do + -- print(" ", _) + -- if type(func) == "function" then + -- --- Functions only have an _ENV upvalue if they have a global variable, so this should work + -- local _envloc = debug.findupvalue(func, "_ENV") + -- if _envloc then + -- debug.upvaluejoin(func, debug.findupvalue(func, "_ENV"), function () return realenv end, 1) + -- end + -- end + -- end + -- end + end +end + +--- Saves the current global state as a table and returns it. +--- @return table +function luacas:saveglobalstate() + local G = {} + for key, value in pairs(_G) do + G[key] = value + end + return G +end + +--- Saves the current global state as a table and returns it. +--- @param G table +function luacas:restoreglobalstate(G) + for key, _ in pairs(_G) do + if key ~= "_G" and key ~= "pairs" then + _G[key] = nil + end + end + for key, value in pairs(G) do + _G[key] = value + end +end + +--- Initalizes a LuaCAS module and creates global variables for all classes in that module. +--- DOES NOT HANDLE DEPENDENCIES, so dependent modules must be globally initalized first. +--- @param mod string +--- @return Module|nil +function luacas:initglobalmodule(mod) + for _, filename in ipairs(self:modulefiles(mod)) do + require(filename) + end +end + +--- Why is Lua like this? +function debug.findupvalue(fn, search_name) + local i = 1 + while true do + local name, val = debug.getupvalue(fn, i) + if not name then break end + if name == search_name then + return i, val + end + i = i + 1 + end +end + +return luacas
\ No newline at end of file diff --git a/Master/texmf-dist/tex/lualatex/luacas/test/luacas-main.lua b/Master/texmf-dist/tex/lualatex/luacas/test/luacas-main.lua index 95f77885e44..78b25aa5871 100644 --- a/Master/texmf-dist/tex/lualatex/luacas/test/luacas-main.lua +++ b/Master/texmf-dist/tex/lualatex/luacas/test/luacas-main.lua @@ -1,8 +1,23 @@ ---@diagnostic disable: lowercase-global -- Runs test code from test files. -require("calculus.luacas-calculus_init") require("_lib.luacas-pepperfish") +require("_lib.luacas-table") + +local luacas = require("luacas_init") +luacas:initmodule("calculus") + +for name, class in pairs(luacas.core) do + _G[name] = class +end + +for name, class in pairs(luacas.algebra) do + _G[name] = class +end + +for name, class in pairs(luacas.calculus) do + _G[name] = class +end -- 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"} diff --git a/Master/texmf-dist/tex/lualatex/luacas/test/luacas-parser.lua b/Master/texmf-dist/tex/lualatex/luacas/test/luacas-parser.lua index 33805496208..47f0640c3f2 100644 --- a/Master/texmf-dist/tex/lualatex/luacas/test/luacas-parser.lua +++ b/Master/texmf-dist/tex/lualatex/luacas/test/luacas-parser.lua @@ -1,8 +1,10 @@ -- Rudimentary parser for making the CAS easier to use. Essentially just wraps SymbolExpression() around symbols and Integer() around integers. - -require("calculus.luacas-calculus_init") +local luacas = require("luacas_init") +luacas:initglobalmodule("core") +luacas:initglobalmodule("algebra") +luacas:initglobalmodule("calculus") -- Splits a string on a seperator. function split(str, sep) @@ -284,8 +286,16 @@ end --- @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) + -- First, we replace any occurrence of a decimal with the appropriate fraction. + + local str = string.gsub(input,"%d+%.%d+", function(s) + local ints = split(s,"%.") + return "("..ints[1]..ints[2].." / 10^" .. tostring(string.len(ints[2])) .. ")" + end) + + -- Next, we replace any occurance of a number with an integer or rational version of itself. + + str = string.gsub(str, ".?[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 @@ -301,11 +311,11 @@ function CASparse(input) -------------------------- -- HERE COMES THE JANK. -- -------------------------- - + -- The JANK may not actually be doing anything now. But for the sake of posterity... -- 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] + return "("..ints[1] .. ".." .. ints[2] .. ")" end) str = string.gsub(str, ".?%.Integer%('[0-9]+'%)", function (s) if string.sub(s, 1, 2) == ".." then @@ -320,4 +330,4 @@ function CASparse(input) else print(err) end -end
\ No newline at end of file +end diff --git a/Master/texmf-dist/tex/lualatex/luacas/test/rings/luacas-conversion.lua b/Master/texmf-dist/tex/lualatex/luacas/test/rings/luacas-conversion.lua index b9eb523c7a5..6a53dacd179 100644 --- a/Master/texmf-dist/tex/lualatex/luacas/test/rings/luacas-conversion.lua +++ b/Master/texmf-dist/tex/lualatex/luacas/test/rings/luacas-conversion.lua @@ -120,9 +120,9 @@ 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, jring, "(12/1x^0)/(1/1x^0)", "QQ(x)") testringconvert(a, kring, "2x^0", "Z/Z5[x]") -testringconvert(a, lring, "((12x^0)/(1x^0))y^0", "ZZ(x)[y]") +testringconvert(a, lring, "((12/1x^0)/(1/1x^0))y^0", "QQ(x)[y]") -- testringconvert(b, aring, "3/2", "ZZ") testringconvert(b, bring, "3/2", "QQ") @@ -133,9 +133,9 @@ 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, jring, "(3/2x^0)/(1/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(b, lring, "((3/2x^0)/(1/1x^0))y^0", "QQ(x)[y]") testringconvert(c, aring, "4", "ZZ") -- testringconvert(c, bring, "4", "QQ") @@ -172,9 +172,9 @@ 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, jring, "(3/1x^2+0/1x^1+6/1x^0)/(1/1x^0)", "QQ(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(e, lring, "((3/1x^2+0/1x^1+6/1x^0)/(1/1x^0))y^0", "QQ(x)[y]") -- testringconvert(f, aring, "12x^1+4/5x^0", "ZZ") -- testringconvert(f, bring, "12x^1+4/5x^0", "QQ") @@ -185,9 +185,9 @@ 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, jring, "(12x^1+4/5x^0)/(1/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(f, lring, "((12x^1+4/5x^0)/(1/1x^0))y^0", "QQ(x)[y]") -- testringconvert(g, aring, "", "ZZ") -- testringconvert(g, bring, "", "QQ") @@ -224,9 +224,9 @@ testringconvert(h, hring, "((1z^0)y^0)x^3+((1z^0)y^3+(1/9z^1+-16z^0)y^2+(1z^2+8z -- 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, jring, "(1/1x^1+-2/1x^0)/(1/1x^2+3/1x^1+3/1x^0)", "QQ(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(i, lring, "((1/1x^1+-2/1x^0)/(1/1x^2+3/1x^1+3/1x^0))y^0", "QQ(x)[y]") -- testringconvert(j, aring, "", "ZZ") -- testringconvert(j, bring, "", "QQ") |