1if not modules then modules = { } end modules ['math-ali'] = {
2 version = 1.001,
3 comment = "companion to math-ali.mkiv",
4 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5 copyright = "PRAGMA ADE / ConTeXt Development Team",
6 license = "see context related readme files"
7}
8
9local unpack = unpack
10local gsub = string.gsub
11local sort, keys = table.sort, table.keys
12local settings_to_array = utilities.parsers.settings_to_array
13local P, R, S, C, Cc, Ct, Cs = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cc, lpeg.Ct, lpeg.Cs
14local lpegmatch = lpeg.match
15
16local context = context
17
18do
19
20 local rows = utilities.parsers.groupedsplitat(";")
21 local cols = utilities.parsers.groupedsplitat(",")
22
23 local actions = {
24 transpose = function(m)
25 local t = { }
26 for j=1,#m[1] do
27 local r = { }
28 for i=1,#m do
29 r[i] = m[i][j]
30 end
31 t[j] = r
32 end
33 return t
34 end,
35 negate = function(m)
36 for i=1,#m do
37 local mi = m[i]
38 for j=1,#mi do
39 mi[j] = - mi[j]
40 end
41 end
42 return m
43 end,
44 scale = function(m,s)
45 s = tonumber(s)
46 if s then
47 for i=1,#m do
48 local mi = m[i]
49 for j=1,#mi do
50 mi[j] = s*mi[j]
51 end
52 end
53 end
54 return m
55 end,
56 }
57
58 local useractions = {
59 }
60
61 interfaces.implement {
62 name = "simplematrix",
63 arguments = "2 strings",
64 actions = function(method,data)
65 local m = lpegmatch(rows,(gsub(data,"%s+"," ")))
66 for i=1,#m do
67 m[i] = lpegmatch(cols,m[i])
68 end
69 local methods = settings_to_array(method)
70 for i=1,#methods do
71 local detail = settings_to_array(methods[i])
72 local method = detail[1]
73 local action = actions[method] or useractions[method]
74 if action then
75 m = action(m,unpack(detail,2)) or m
76 end
77 end
78 for i=1,#m do
79 context("\\NC %{ \\NC }t \\NR",m[i])
80 end
81 end
82 }
83
84 function mathematics.registersimplematrix(name,action)
85 if type(action) == "function" then
86 useractions[name] = action
87 end
88 end
89
90
91
92 interfaces.implement {
93 name = "simplecases",
94 arguments = "2 strings",
95 actions = function(method,data)
96
97 local m = lpegmatch(rows,(gsub(data,"%s+"," ")))
98 for i=1,#m do
99 m[i] = lpegmatch(cols,m[i])
100 end
101 for i=1,#m do
102 context("\\NC %{ \\NC }t \\NR",m[i])
103 end
104 end
105 }
106
107end
108
109do
110
111 local relations = {
112 ["<"] = "<", [">"] = ">",
113 ["!<"] = "≮", ["!>"] = "≯",
114 ["<<"] = "≪", [">>"] = "≫",
115 ["="] = "=", ["=="] = "=",
116 ["<>"] = "≠", ["!="] = "≠",
117 ["<="] = "≤", [">="] = "≥",
118 ["=<"] = "≦", ["=>"] = "≧",
119 ["!=<"] = "≰", ["!=>"] = "≱",
120 ["~"] = "≈", ["~~"] = "≈",
121 }
122
123 for k, v in next, table.copy(relations) do relations[v] = v end
124
125
126
127
128
129
130
131
132 local separators = {
133 [","] = true,
134 [";"] = true,
135 }
136
137 local alternatives = {
138
139 }
140
141 local p_sign = S("-+")
142 local p_script = S("^")^1
143 local p_number = R("09","..")^1 + lpeg.patterns.nestedbraces
144 local p_alpha = R("az","AZ")^1
145 local p_variable = p_alpha * (P("_") * (p_number + p_alpha))^-1
146
147 local spacing = P(" ")^0
148 local script = Cs(p_script * Cc("{") * p_sign^0 * (p_number + p_variable) * Cc("}"))
149 local sign = C(p_sign) + Cc("+")
150 local number = C(p_number)
151 local variable = C(p_variable)
152
153 local relation = lpeg.utfchartabletopattern(relations) / relations
154 local separator = lpeg.utfchartabletopattern(separators)
155
156 local snippet = Ct (
157 (
158 spacing * sign * spacing * number * spacing * variable
159 + spacing * sign * spacing * number * spacing * Cc(false)
160 + spacing * sign * spacing * Cc(false) * spacing * variable
161 ) * (script + Cc(false))
162 )
163
164 local parser = Ct ( Ct (
165 ( Ct ( snippet^1 ) * spacing * relation )^1
166 * ( Ct ( snippet^1 ) * spacing * separator^0 )
167 )^1 )
168
169 local num = "!"
170
171 local ctx_NC, ctx_NR = context.NC, context.NR
172 local ctx_typ = context.typ
173 local ctx_ord, ctx_rel = context.mathord, context.mathrel
174
175 local clean = table.setmetatableindex(function(t,k)
176 local v = gsub(k,"[{}]","")
177 t[k] = v
178 return v
179 end)
180
181 alternatives.equationsystem = function(action,str)
182 local rows = lpegmatch(parser,str)
183 if not rows then
184 ctx_typ("bad system, case 1: %s",1,str)
185 return
186 end
187 local nrow = #rows
188 local all = table.setmetatableindex("table")
189 for r=1,nrow do
190 local row = rows[r]
191 for s=1,#row,2 do
192 local set = row[s]
193 for v=1,#set do
194 local vvv = set[v]
195 local var = vvv[3]
196 if not var then
197 var = num
198 end
199 if set[var] then
200 print("bad system, two constants")
201 end
202 set[var] = set[v]
203 all[s][var] = true
204 set[v] = nil
205 end
206 end
207 end
208
209 local cnt = #rows[1]
210 for r=1,nrow do
211 if #rows[r] ~= cnt then
212 ctx_typ("bad system, case %i: %s",2,str)
213 return
214 end
215 end
216 for r=1,#rows[1] do
217 local a = keys(all[r])
218 sort(a,function(a,b)
219 return clean[a] < clean[b]
220 end)
221 all[r] = a
222 end
223
224 for r=1,nrow do
225 local row = rows[r]
226 for r=1,#row do
227 local set = row[r]
228 local how = all[r]
229 if #how > 0 then
230
231 for i=1,#how do
232 local k = how[i]
233 local e = set[k]
234 if e then
235 ctx_NC()
236
237 if i == 1 and e[1] == "+" then
238
239
240
241 else
242 ctx_ord("")
243 context(e[1])
244 ctx_ord("")
245
246 end
247 ctx_NC()
248 if e[2] then
249 context(e[2])
250
251 end
252 if e[3] then
253 context(e[3])
254
255 end
256 if e[4] then
257 context(e[4])
258
259 end
260 else
261 ctx_NC()
262
263 ctx_NC()
264 end
265 end
266 else
267 ctx_NC()
268 ctx_ord("")
269 context(set)
270 ctx_ord("")
271 end
272 end
273 ctx_NR()
274 end
275 end
276
277 interfaces.implement {
278 name = "simplealign",
279
280 protected = true,
281 arguments = "3 strings",
282 actions = function(alternative,action,str)
283 local a = alternatives[alternative]
284 if a then
285 a(action,str)
286 else
287 context(str)
288 end
289 end
290 }
291
292end
293 |