diff options
Diffstat (limited to 'macros/luatex/latex/luacas/tex/algebra/factorialexpression.lua')
-rw-r--r-- | macros/luatex/latex/luacas/tex/algebra/factorialexpression.lua | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/macros/luatex/latex/luacas/tex/algebra/factorialexpression.lua b/macros/luatex/latex/luacas/tex/algebra/factorialexpression.lua new file mode 100644 index 0000000000..1c5b824ff7 --- /dev/null +++ b/macros/luatex/latex/luacas/tex/algebra/factorialexpression.lua @@ -0,0 +1,102 @@ +--- @class FactorialExpression +--- The factorial of an expression. +--- @field expression Expression +FactorialExpression = {} +__FactorialExpression = {} + +---------------------------- +-- Instance functionality -- +---------------------------- + +--- Creates a new factorial expression with the given expression. +--- @param expression Expression +--- @return FactorialExpression +function FactorialExpression:new(expression) + local o = {} + local __o = Copy(__ExpressionOperations) + + o.expression = expression + + __o.__index = FactorialExpression + __o.__tostring = function(a) + return '(' .. tostring(a.expression) .. ')!' + end + + o = setmetatable(o, __o) + return o +end + +--- @return Expression +function FactorialExpression:evaluate() + if self.expression:type() == Integer then + if self.expression < Integer.zero() then + error("Aritmetic Error: Factorials of negative integers are not defined.") + end + + if not FactorialExpression.LIMIT then + FactorialExpression.LIMIT = Integer(5000) + end + + if self.expression > FactorialExpression.LIMIT then + return self + end + -- TODO: More efficient factorial computations. + local out = Integer.one() + local i = Integer.zero() + while i < self.expression do + i = i + Integer.one() + out = out * i + end + return out + end + return self +end + +--- @return Expression +function FactorialExpression:autosimplify() + return FactorialExpression(self.expression:autosimplify()):evaluate() +end + +--- @return table<number, Expression> +function FactorialExpression:subexpressions() + return {self.expression} +end + +--- @param subexpressions table<number, Expression> +--- @return AbsExpression +function FactorialExpression:setsubexpressions(subexpressions) + return FactorialExpression(subexpressions[1]) +end + +--- @param other Expression +--- @return boolean +function FactorialExpression:order(other) + return FunctionExpression("fact", self.expression):order(other) +end + +--- @return string +function FactorialExpression:tolatex() + if self.expression:isatomic() then + return self.expression:tolatex() .. "!" + end + return "(" .. self.expression:tolatex() .. ")!" +end + +----------------- +-- Inheritance -- +----------------- + +__FactorialExpression.__index = CompoundExpression +__FactorialExpression.__call = FactorialExpression.new +FactorialExpression = setmetatable(FactorialExpression, __FactorialExpression) + +---------------------- +-- Static constants -- +---------------------- + +-- Do not attempt to compute factorials larger than this. +FactorialExpression.LIMIT = Integer(5000) + +FACT = function (a) + return FactorialExpression(a) +end
\ No newline at end of file |