summaryrefslogtreecommitdiff
path: root/macros/luatex/latex/luacas/tex/core/luacas-symbolexpression.lua
blob: 0d9192c084ea99c139cc5d05e44b4865377ff308 (plain)
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
--- @class SymbolExpression
--- An atomic expression corresponding to a symbol representing an arbitary value.
--- @field symbol string
--- @alias Symbol SymbolExpression
SymbolExpression = {}
__SymbolExpression = {}

----------------------
-- Instance methods --
----------------------

--- Given the name of the symbol as a string, creates a new symbol.
--- @param symbol string
--- @return SymbolExpression
function SymbolExpression:new(symbol)
    local o = {}
    local __o = Copy(__ExpressionOperations)
    __o.__index = SymbolExpression
    __o.__tostring = function(a)
        return a.symbol
    end
    __o.__eq = function(a, b)
        return a.symbol == b.symbol
    end

    if type(symbol) ~= "string" then
        error("Sent parameter of wrong type: symbol must be a string")
    end

    o.symbol = symbol
    o = setmetatable(o, __o)

    return o
end

--- @return boolean
function SymbolExpression:freeof(symbol)
    return symbol~=self
end

--- @return boolean
function SymbolExpression:isconstant()
    return false
end

--- @param other Expression
--- @return boolean
function SymbolExpression:order(other)

    -- Symbol Expressions come after constant expressions.
    if other:isconstant() then
        return false
    end

    -- Lexographic order on symbols.
    if other:type() == SymbolExpression then
        for i = 1, math.min(#self.symbol, #other.symbol) do
            if string.byte(self.symbol, i) ~= string.byte(other.symbol, i) then
                return string.byte(self.symbol, i) < string.byte(other.symbol, i)
            end
        end

        return #self.symbol < #other.symbol
    end

    if other.operation == BinaryOperation.POW then
        return BinaryOperation(BinaryOperation.POW, {self, Integer.one()}):order(other)
    end

    if other.operation == BinaryOperation.MUL then
        return BinaryOperation(BinaryOperation.MUL, {self}):order(other)
    end

    if other.operation == BinaryOperation.ADD then
        return BinaryOperation(BinaryOperation.ADD, {self}):order(other)
    end

    -- CASC Autosimplfication has some symbols appearing before functions, but that looks bad to me, so all symbols appear before products now.
    if other:type() == FunctionExpression or other:type() == TrigExpression or other:type() == Logarithm then
        return true
    end

    return false
end

--- Converts this symbol to an element of a polynomial ring.
--- @return PolynomialRing, boolean
function SymbolExpression:topolynomial()
    return PolynomialRing({Integer.zero(), Integer.one()}, self.symbol), true
end

-----------------
-- Inheritance --
-----------------

__SymbolExpression.__index = AtomicExpression
__SymbolExpression.__call = SymbolExpression.new
SymbolExpression = setmetatable(SymbolExpression, __SymbolExpression)


----------------------
-- Static Constants --
----------------------

-- The constant pi.
PI = SymbolExpression("pi")
function PI:tolatex()
    return "\\pi "
end

-- Approximates pi as a rational number. Uses continued fraction expansion.
function PI:approximate()
    return Integer(313383936) / Integer(99753205)
end

--function PI:isconstant()
--    return true
--end

-- The constant e.
E = SymbolExpression("e")

-- Approximates pi as a rational number. Uses continued fraction expansion.
function E:approximate()
    return Integer(517656) / Integer(190435)
end

-- The imaginary constant i.
I = SymbolExpression("i")
function I:tolatex()
    return "i"
end