diff options
Diffstat (limited to 'macros/luatex/latex/luacas/tex/calculus/diffexpression.lua')
-rw-r--r-- | macros/luatex/latex/luacas/tex/calculus/diffexpression.lua | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/macros/luatex/latex/luacas/tex/calculus/diffexpression.lua b/macros/luatex/latex/luacas/tex/calculus/diffexpression.lua new file mode 100644 index 0000000000..df1dc90f33 --- /dev/null +++ b/macros/luatex/latex/luacas/tex/calculus/diffexpression.lua @@ -0,0 +1,190 @@ +--- @class DiffExpression +--- An expression for a multi-variable higher-order derivatives of an expression. +--- @field symbols SymbolExpression +--- @field expression Expression + +DiffExpression = {} +__DiffExpression = {} + +---------------------------- +-- Instance functionality -- +---------------------------- + +-- Creates a new derivative operation with the given symbols and expression. +--- @param expression Expression +--- @param symbols table<number, Symbol> +--- @return DiffExpression +function DiffExpression:new(expression,symbols) + local o = {} + local __o = Copy(__ExpressionOperations) + + o.symbols = Copy(symbols) + o.degree = #o.symbols + o.expression = Copy(expression) + + __o.__tostring = function(a) + local varlist = '(d' + if a.degree == 1 then + varlist = varlist .. '/d' .. tostring(a.symbols[1]) .. " " .. tostring(a.expression) .. ')' + end + if a.degree > 1 then + varlist = varlist .. '^' .. tostring(a.degree) .. '/' + local varnum = 1 + for index = 1, #a.symbols do + local var = a.symbols[#a.symbols-index+1] + if a.symbols[#a.symbols-index] == var then + varnum = varnum + 1 + goto nextvar + end + if a.symbols[#a.symbols-index] ~=var then + if varnum == 1 then + varlist = varlist .. 'd' .. tostring(var) + else + varlist = varlist .. 'd' .. tostring(var) .. '^' .. tostring(varnum) + end + varnum = 1 + end + ::nextvar:: + end + varlist = varlist .. " " .. tostring(a.expression) .. ')' + end + return varlist + end + + __o.__index = DiffExpression + __o.__eq = function(a, b) + -- This shouldn't be needed, since __eq should only fire if both metamethods have the same function, but for some reason Lua always rungs this anyway + if not b:type() == DiffExpression then + return false + end + if a.expression ~= b.expression then + return false + end + local loc = 1 + while a.symbols[loc] or b.symbols[loc] do + if not a.symbols[loc] or not b.symbols[loc] or + (a.symbols[loc] ~= b.symbols[loc]) then + return false + end + loc = loc + 1 + end + return true + end + o = setmetatable(o, __o) + + return o +end + +--- @return Expression +function DiffExpression:evaluate() + local exp = self.expression + + for _,var in ipairs(self.symbols) do + exp = DerivativeExpression(exp,var):evaluate() + end + return exp +end + +--- @return Expression +function DiffExpression:autosimplify() + return DiffExpression(self.expression:autosimplify(), self.symbols):evaluate() +end + + +--- @return table<number, Expression> +function DiffExpression:subexpressions() + return {self.expression} +end + +--- @param subexpressions table<number, Expression> +--- @return DiffExpression +function DiffExpression:setsubexpressions(subexpressions) + return DiffExpression(subexpressions[1], self.symbols) +end + +--- @param other Expression +--- @return boolean +function DiffExpression:order(other) + if other:type() == IntegralExpression then + return true + end + + if other:type() ~= DiffExpression then + return false + end + + if self.degree > other.degree then + return false + end + + if self.degree < other.degree then + return true + end + + return self.expression:order(other.expression) +end + +--- @return string +function DiffExpression:tolatex() + local varlist = '\\frac{' + if self.degree == 1 then + varlist = varlist .. 'd}{d' .. self.symbols[1]:tolatex() .. '}\\left(' .. self.expression:tolatex() .. '\\right)' + end + if self.degree > 1 then + local cvarlist = {} + local count = 1 + for index, var in ipairs(self.symbols) do + if var == self.symbols[index+1] then + count = count + 1 + else + table.insert(cvarlist,{var,count}) + count = 1 + end + end + if #cvarlist == 1 then + varlist = varlist .. 'd^{' .. self.degree .. '}}{' .. 'd' .. cvarlist[1][1]:tolatex() .. '^{' .. self.degree .. '}' + end + if #cvarlist > 1 then + varlist = varlist .. '\\partial^{' .. self.degree .. '}}{' + for index, varnum in ipairs(cvarlist) do + var = cvarlist[#cvarlist - index+1][1] + num = cvarlist[#cvarlist - index+1][2] + if num == 1 then + varlist = varlist .. '\\partial ' .. var:tolatex() + else + varlist = varlist .. '\\partial ' .. var:tolatex() .. '^{' .. num .. '}' + end + end + end + varlist = varlist .. '} \\left(' .. self.expression:tolatex() .. '\\right)' + end + return varlist +end + +----------------- +-- Inheritance -- +----------------- + +__DiffExpression.__index = CompoundExpression +__DiffExpression.__call = DiffExpression.new +DiffExpression = setmetatable(DiffExpression, __DiffExpression) + +---------------------- +-- Static constants -- +---------------------- + +diff = function(expression,...) + local symbols = {} + for i = 1, select("#",...) do + local var = select(i,...) + if #var == 0 then + table.insert(symbols,var) + end + if #var > 0 then + for index=1, RR(var[2]) do + table.insert(symbols,var[1]) + end + end + end + return DiffExpression(expression,symbols) +end
\ No newline at end of file |