1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
--- @class RootExpression
--- An expression that represents the solutions to expression = 0.
--- @field expression Expression
RootExpression = {}
__RootExpression = {}
----------------------------
-- Instance functionality --
----------------------------
--- Creates a new root expression with the given expression.
--- @param expression Expression
--- @return RootExpression
function RootExpression:new(expression)
local o = {}
local __o = Copy(__ExpressionOperations)
o.expression = Copy(expression)
__o.__index = RootExpression
__o.__tostring = function(a)
return 'Root Of: (' .. tostring(a.expression) .. ')'
end
__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() == RootExpression then
return false
end
return a.expression == b.expression
end
o = setmetatable(o, __o)
return o
end
--- @return Expression
function RootExpression:autosimplify(subpart)
local simplified = self.expression:autosimplify()
local simplified, ispoly = simplified:topolynomial()
if simplified:isconstant() then
-- 0 = 0 is always true (obviously).
return simplified == simplified:zero()
end
if ispoly then
if simplified.degree == Integer.zero() then
return simplified == simplified:zero()
end
if simplified.degree == Integer.one() then
return {-simplified.coefficients[0] / simplified.coefficients[1]}
end
if simplified.degree == Integer(2) then
local a = simplified.coefficients[2]
local b = simplified.coefficients[1]
local c = simplified.coefficients[0]
-- This is a hack until we can get more expression manipulation working, but that's okay.
if subpart then
c = (c - subpart):autosimplify()
end
return {((-b + sqrt(b^Integer(2) - Integer(4) * a * c)) / (Integer(2) * a)):autosimplify(),
((-b - sqrt(b^Integer(2) - Integer(4) * a * c)) / (Integer(2) * a)):autosimplify()}
end
if simplified.degree == Integer(3) then
local a = simplified.coefficients[3]
local b = simplified.coefficients[2]
local c = simplified.coefficients[1]
local d = simplified.coefficients[0]
-- This is a hack until we can get more expression manipulation working, but that's okay.
if subpart then
d = (d - subpart):autosimplify()
end
local delta0 = (b^Integer(2) - Integer(3)*a*c):autosimplify()
local delta1 = (Integer(2) * b^Integer(3) - Integer(9)*a*b*c+Integer(27)*a^Integer(2)*d):autosimplify()
local C = sqrt((delta1 + sqrt(delta1 ^ Integer(2) - Integer(4) * delta0 ^ Integer(3))) / Integer(2), Integer(3)):autosimplify()
if C == Integer.zero() then
C = sqrt((delta1 - sqrt(delta1 ^ Integer(2) - Integer(4) * delta0 ^ Integer(3))) / Integer(2), Integer(3)):autosimplify()
end
if C == Integer.zero() then
C = (-b/(Integer(3)*a)):autosimplify()
end
local eta = ((Integer(-1) + sqrt(Integer(-3))) / Integer(2)):autosimplify()
return {((-Integer.one() / (Integer(3) * a)) * (b + C + delta0 / C)):autosimplify(),
((-Integer.one() / (Integer(3) * a)) * (b + C*eta + delta0 / (C*eta))):autosimplify(),
((-Integer.one() / (Integer(3) * a)) * (b + C*eta^Integer(2) + delta0 / (C*eta^Integer(2)))):autosimplify()}
end
end
if ispoly then
simplified = simplified:autosimplify()
end
if subpart then
simplified = (simplified - subpart):autosimplify()
end
return {RootExpression(simplified)}
end
--- @return table<number, Expression>
function RootExpression:subexpressions()
return {self.expression}
end
--- @param subexpressions table<number, Expression>
--- @return RootExpression
function RootExpression:setsubexpressions(subexpressions)
return RootExpression(subexpressions[1])
end
--- @param other Expression
--- @return boolean
function RootExpression:order(other)
--- TODO: Fix ordering on new expression types
if other:type() ~= RootExpression then
return false
end
return self.expression:order(other.expression)
end
--- @return string
function RootExpression:tolatex()
return '\\operatorname{RootOf}\\left(' .. self.expression:tolatex() .. '\\right)'
end
-----------------
-- Inheritance --
-----------------
__RootExpression.__index = CompoundExpression
__RootExpression.__call = RootExpression.new
RootExpression = setmetatable(RootExpression, __RootExpression)
|