summaryrefslogtreecommitdiff
path: root/macros/luatex/latex/luacas/tex/core/binaryoperation/power.lua
diff options
context:
space:
mode:
Diffstat (limited to 'macros/luatex/latex/luacas/tex/core/binaryoperation/power.lua')
-rw-r--r--macros/luatex/latex/luacas/tex/core/binaryoperation/power.lua169
1 files changed, 169 insertions, 0 deletions
diff --git a/macros/luatex/latex/luacas/tex/core/binaryoperation/power.lua b/macros/luatex/latex/luacas/tex/core/binaryoperation/power.lua
new file mode 100644
index 0000000000..35df72c440
--- /dev/null
+++ b/macros/luatex/latex/luacas/tex/core/binaryoperation/power.lua
@@ -0,0 +1,169 @@
+-- Seperates the various binary operations into their own files for readability
+
+--- Automatic simplification of power expressions.
+--- @return BinaryOperation
+function BinaryOperation:simplifypower()
+ local base = self.expressions[1]
+ local exponent = self.expressions[2]
+
+ if base:isconstant() and exponent:isconstant() and exponent:getring() ~= Rational:getring() then
+ return self:evaluate()
+ end
+
+ -- Simplifies i^x for x integer.
+ if base == I and exponent:isconstant() and exponent:getring() == Integer:getring() then
+ if exponent % Integer(4) == Integer(0) then
+ return Integer(1)
+ end
+ if exponent % Integer(4) == Integer(1) then
+ return I
+ end
+ if exponent % Integer(4) == Integer(2) then
+ return Integer(-1)
+ end
+ if exponent % Integer(4) == Integer(3) then
+ return -I
+ end
+ end
+
+ -- Simplifies complex numbers raised to negative integer powers
+ if not base:isrealconstant() and base:iscomplexconstant() and exponent:isconstant() and exponent:getring() == Integer:getring() and exponent < Integer.zero() then
+ local a
+ local b
+ if base.operation == BinaryOperation.MUL then
+ a = Integer.zero()
+ b = base.expressions[1]
+ elseif base.operation == BinaryOperation.ADD and base.expressions[2] == I then
+ a = base.expressions[1]
+ b = Integer.one()
+ else
+ a = base.expressions[1]
+ b = base.expressions[2].expressions[1]
+ end
+ return (((a-b*I)/(a^Integer(2)+b^Integer(2)))^(-exponent)):expand():autosimplify()
+ end
+
+ -- Uses the property that 0^x = 0 if x does not equal 0
+ if base:isconstant() and base == base:zero() then
+ return Integer.zero()
+ end
+
+ -- Uses the property that 1^x = 1
+ if base:isconstant() and base == base:one() then
+ return base:one()
+ end
+
+ -- Uses the property that x^0 = 1
+ if exponent:isconstant() and exponent == exponent:zero() then
+ return exponent:one()
+ end
+
+ -- Uses the property that x^1 = x
+ if exponent:isconstant() and exponent == exponent:one() then
+ return base
+ end
+
+ -- Uses the property that b ^ (log(b, x)) == x
+ if exponent:type() == Logarithm and exponent.base == base then
+ return exponent.expression
+ end
+
+ -- Uses the property that b ^ (a * log(b, x)) == x ^ a
+ if exponent.operation == BinaryOperation.MUL then
+ local x
+ local rest = Integer.one()
+ for _, expression in ipairs(exponent.expressions) do
+ if expression:type() == Logarithm and expression.base == base and not log then
+ x = expression.expression
+ else
+ rest = rest * expression
+ end
+ end
+ if x then
+ return (x ^ rest):autosimplify()
+ end
+ end
+
+ -- Uses the property that (x^a)^b = x^(a*b)
+ if not base:isatomic() and base.operation == BinaryOperation.POW and exponent:isconstant() then
+ base, exponent = base.expressions[1], BinaryOperation(BinaryOperation.MUL, {exponent, base.expressions[2]}):autosimplify()
+ return BinaryOperation(BinaryOperation.POW, {base, exponent}):autosimplify()
+ end
+
+ -- Uses the property that (x_1*x_2*...*x_n)^a = x_1^a*x_2^a*..x_n^a if a is an integer
+ if base.operation == BinaryOperation.MUL and exponent:type() == Integer then
+ local results = {}
+ for index, expression in ipairs(base.expressions) do
+ results[index] = BinaryOperation(BinaryOperation.POW, {expression, exponent}):autosimplify()
+ end
+ return BinaryOperation(BinaryOperation.MUL, results):autosimplify()
+ end
+
+ -- Uses the property that sqrt(x,r)^d == sqrt(x,r/d)
+ if base:type() == SqrtExpression and exponent:type() == Integer and exponent > Integer.zero() then
+ local root = base.root
+ local expr = base.expression
+ local comm = Integer.gcd(root,exponent)
+ root = root / comm
+ local expo = exponent / comm
+ expr = expr ^ expo
+ return SqrtExpression(expr,root):autosimplify()
+ end
+
+ -- Rationalizing SqrtExpressions
+ if base:type() == SqrtExpression and exponent:type() == Integer and base.expression:type() == Integer and exponent < Integer.zero() then
+ local root = base.root
+ local expr = base.expression
+ local result = (SqrtExpression(expr ^ (root - Integer.one()),root) / expr) ^ exponent:neg()
+ return result:autosimplify()
+ end
+
+ if base:isconstant() and exponent:isconstant() and exponent:getring() == Rational.getring() then
+ return self --:simplifyrationalpower()
+ end
+
+ -- Our expression cannot be simplified
+ return self
+end
+
+-- Automatic simplification of rational power expressions
+function BinaryOperation:simplifyrationalpower()
+ local base = self.expressions[1]
+ local exponent = self.expressions[2]
+
+ if base:getring() == Rational.getring() then
+ return (BinaryOperation(BinaryOperation.POW, {base.numerator, exponent}):simplifyrationalpower()) /
+ (BinaryOperation(BinaryOperation.POW, {base.denominator, exponent}):simplifyrationalpower())
+ end
+
+ if base == Integer(-1) then
+ if exponent == Integer(1) / Integer(2) then
+ return I
+ end
+
+ return self
+ end
+
+ local primes = base:primefactorization()
+
+ if primes.expressions[1] and not primes.expressions[2] then
+ local primeexponent = primes.expressions[1].expressions[2]
+ local primebase = primes.expressions[1].expressions[1]
+ local newexponent = primeexponent * exponent
+ local integerpart
+ if newexponent.getring() == Rational.getring() then
+ integerpart = newexponent.numerator // newexponent.denominator
+ else
+ integerpart = newexponent
+ end
+
+ if integerpart == Integer.zero() then
+ return BinaryOperation(BinaryOperation.POW, {primebase, newexponent})
+ end
+ return BinaryOperation(BinaryOperation.MUL,
+ {BinaryOperation(BinaryOperation.POW, {primebase, integerpart}),
+ BinaryOperation(BinaryOperation.POW, {primebase, newexponent - integerpart})}):autosimplify()
+ end
+
+ return BinaryOperation(BinaryOperation.POW, {primes:autosimplify(), exponent})
+end \ No newline at end of file