summaryrefslogtreecommitdiff
path: root/macros/luatex/latex/luacas/tex/algebra/factorialexpression.lua
diff options
context:
space:
mode:
Diffstat (limited to 'macros/luatex/latex/luacas/tex/algebra/factorialexpression.lua')
-rw-r--r--macros/luatex/latex/luacas/tex/algebra/factorialexpression.lua102
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