1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22\startmodule[matrix]
23
24\startluacode
25
26local tonumber, type = tonumber, type
27
28local settings_to_hash = utilities.parsers.settings_to_hash
29local formatters = string.formatters
30local copy = table.copy
31local insert = table.insert
32local remove = table.remove
33local random = math.random
34
35local context = context
36
37local matrix = { }
38moduledata.matrix = matrix
39
40local f_matrix_slot = formatters["%s_{%s%s}"]
41
42function matrix.symbolic(sym, x, y, nx ,ny)
43 local nx = nx or 2
44 local ny = ny or nx
45 local function filled(i,y)
46 local mrow = { }
47 for j=1,nx do
48 mrow[#mrow+1] = f_matrix_slot(sym,i,j)
49 end
50 mrow[#mrow+1] = "\\cdots"
51 mrow[#mrow+1] = f_matrix_slot(sym,i,y)
52 return mrow
53 end
54 local function dummy()
55 local mrow = { }
56 for j=1,nx do
57 mrow[#mrow+1] = "\\vdots"
58 end
59 mrow[#mrow+1] = "\\ddots"
60 mrow[#mrow+1] = "\\vdots"
61 return mrow
62 end
63
64 local mm = { }
65 for i=1,ny do
66 mm[i] = filled(i,y)
67 end
68 mm[#mm+1] = dummy()
69 mm[#mm+1] = filled(x,y)
70 return mm
71end
72
73
74
75
76
77
78
79
80
81local fences = {
82 parentheses = { "matrix:parentheses" },
83 brackets = { "matrix:brackets" },
84 bars = { "matrix:bars" },
85}
86
87
88
89fences.bar = fences.bars
90fences.parenthesis = fences.parentheses
91fences.bracket = fences.brackets
92
93
94
95matrix.template = "%0.3F"
96
97function matrix.typeset(m,options)
98 if type(m) == "table" then
99 local options = settings_to_hash(options or "")
100 local whatever = options.determinant == "yes" and fences.bars or fences.parentheses
101 if options.fences then
102 whatever = fences[options.fences] or whatever
103 elseif options.determinant then
104
105 whatever = fences.bars
106 end
107 local template = options.template or matrix.template
108 if template == "yes" then
109 template = matrix.template
110 elseif template == "no" then
111 template = false
112 elseif tonumber(template) then
113 template = "%0." .. template .. "F"
114 end
115 context.startnamedmatrix(whatever)
116 if type(m[1]) ~= "table" then
117 m = { copy(m) }
118 end
119 for i=1,#m do
120 local mi = m[i]
121 for j=1,#mi do
122 context.NC()
123 local n = mi[j]
124 if template and tonumber(n) then
125 context(template,n)
126 else
127 context(mi[j])
128 end
129 end
130 context.NR()
131 end
132 context.stopnamedmatrix()
133 elseif m then
134 context(m)
135 end
136end
137
138function matrix.swaprows(t,i,j)
139 local ti = t[i]
140 if not ti then
141 return "error: no row"
142 end
143 local tj = t[j]
144 if not tj then
145 return "error: no row"
146 end
147 t[i], t[j] = tj, ti
148 return t
149end
150
151
152
153function matrix.swapcolumns(t, i, j)
154 local t1 = t[1]
155 if not t1 then
156 return "error: no rows"
157 end
158 local n = #t1
159 if i > n or j > n then
160 return "error: no column"
161 end
162 for k = 1, #t do
163 local tk = t[k]
164 tk[i], tk[j] = tk[j], tk[i]
165 end
166 return t
167end
168
169matrix.swapC = matrix.swapcolumns
170matrix.swapR = matrix.swaprows
171matrix.swapcolumns = matrix.swapcolumns
172matrix.swaprows = matrix.swaprows
173matrix.swap = matrix.swaprows
174
175
176
177function matrix.multiply(m,i,factor)
178 local mi = m[i]
179 for k=1,#mi do
180 mi[k] = factor * mi[k]
181 end
182 return m
183end
184
185
186
187function matrix.scalar(m, factor)
188 for i=1,#m do
189 local mi = m[i]
190 for j=1,#mi do
191 mi[j] = factor * mi[j]
192 end
193 end
194 return m
195end
196
197
198
199function matrix.sumrow(m,i,j,factor)
200 local mi = m[i]
201 local mj = m[j]
202 for k=1,#mi do
203 mi[k] = mi[k] + factor * mj[k]
204 end
205end
206
207
208
209function matrix.transpose(m)
210 local t = { }
211 for j=1,#m[1] do
212 local r = { }
213 for i=1,#m do
214 r[i] = m[i][j]
215 end
216 t[j] = r
217 end
218 return t
219end
220
221
222
223function matrix.inner(u,v)
224 local nu = #u
225 if nu == 0 then
226 return 0
227 end
228 local nv = #v
229 if nv ~= nu then
230 return "error: size mismatch"
231 end
232 local result = 0
233 for i=1,nu do
234 result = result + u[i] * v[i]
235 end
236 return result
237end
238
239
240
241function matrix.product(m1,m2)
242 if #m1[1] == #m2 then
243 local product = { }
244 for i=1,#m1 do
245 local m1i = m1[i]
246 local mrow = { }
247 for j=1,#m2[1] do
248 local temp = 0
249 for k=1,#m1[1] do
250 temp = temp + m1i[k] * m2[k][j]
251 end
252 mrow[j] = temp
253 end
254 product[i] = mrow
255 end
256 return product
257 else
258 return "error: size mismatch"
259 end
260end
261
262local function uppertri(m,sign)
263 local temp = copy(m)
264 for i=1,#temp-1 do
265 local pivot = temp[i][i]
266 if pivot == 0 then
267 local pRow = i +1
268 while temp[pRow][i] == 0 do
269 pRow = pRow + 1
270 if pRow > #temp then
271 return temp
272 end
273 end
274 temp[i], temp[pRow] = temp[pRow], temp[i]
275 if sign then
276 sign = -sign
277 end
278 end
279 local mi = temp[i]
280 for k=i+1, #temp do
281 local factor = -temp[k][i]/mi[i]
282 local mk = temp[k]
283 for l=i,#mk do
284 mk[l] = mk[l] + factor * mi[l]
285 end
286 end
287 end
288 if sign then
289 return temp, sign
290 else
291 return temp
292 end
293end
294
295matrix.uppertri = uppertri
296
297local function determinant(m)
298 if #m == #m[1] then
299 local d = 1
300 local t, s = uppertri(m,1)
301 for i=1,#t do
302 d = d * t[i][i]
303 end
304 return s*d
305 else
306 return "error: not a square matrix"
307 end
308end
309
310matrix.determinant = determinant
311
312local function rowechelon(m,r)
313 local temp = copy(m)
314 local pRow = 1
315 local pCol = 1
316 while pRow <= #temp do
317 local pivot = temp[pRow][pCol]
318 if pivot == 0 then
319 local i = pRow
320 local n = #temp
321 while temp[i][pCol] == 0 do
322 i = i + 1
323 if i > n then
324
325 pCol = pCol + 1
326 if pCol > #temp[pRow] then
327
328 return temp
329 end
330 i = pRow
331 end
332 end
333 temp[pRow], temp[i] = temp[i], temp[pRow]
334 end
335 local row = temp[pRow]
336 pivot = row[pCol]
337 for l=pCol,#row do
338 row[l] = row[l]/pivot
339 end
340
341 if r == 1 then
342
343 local row = temp[pRow]
344 for k=1,pRow-1 do
345 local current = temp[k]
346 local factor = -current[pCol]
347 local mk = current
348 for l=pCol,#mk do
349 mk[l] = mk[l] + factor * row[l]
350 end
351 end
352 end
353
354 local row = temp[pRow]
355 for k=pRow+1, #temp do
356 local current = temp[k]
357 local factor = -current[pCol]
358 local mk = current
359 for l=pCol,#mk do
360 mk[l] = mk[l] + factor * row[l]
361 end
362 end
363 pRow = pRow + 1
364 pCol = pCol + 1
365
366 if pRow > #temp or pCol > #temp[1] then
367 pRow = #temp + 1
368 end
369 end
370 return temp
371end
372
373matrix.rowechelon = rowechelon
374matrix.rowEchelon = rowechelon
375
376
377
378local function make(m,n,low,high)
379 if not n then
380 n = 10
381 end
382 if not m then
383 m = 10
384 end
385 if not low then
386 low = 0
387 end
388 if not high then
389 high = 10
390 end
391 local t = { }
392 for i=1,m do
393 t[i] = { }
394 end
395 while true do
396 for i=1,m do
397 local ti = t[i]
398 for j=1,n do
399 ti[j] = random(low,high)
400 end
401 end
402 if n ~= m or determinant(t,1) ~= 0 then
403 return t
404 end
405 end
406end
407
408matrix.make = make
409matrix.makeR = matrix.make
410
411
412
413local function submatrix(t,i,j)
414 local rows = #t
415 local columns = #t[1]
416 local sign = 1
417 if i <= rows and j <= columns then
418 local c = copy(t)
419 remove(c,i)
420 for k=1,rows-1 do
421 remove(c[k],j)
422 end
423 return c
424 else
425 return "error: out of bound"
426 end
427end
428
429matrix.submatrix = submatrix
430matrix.subMatrix = submatrix
431
432
433
434local function laplace(t)
435 local factors = { 1 }
436 local data = copy(t)
437 local det = 0
438 while #data > 0 do
439 local mat = { }
440 local siz = #data[1]
441 if siz == 0 then
442 return "error: no determinant"
443 elseif siz == 1 then
444 det = data[1][1]
445 return det
446 end
447 for i=1,siz do
448 mat[i] = data[1]
449 remove(data,1)
450 end
451 local factor = remove(factors,1)
452 local m1 = mat[1]
453 if siz == 2 then
454 local m2 = mat[2]
455 det = det + factor * (m1[1]*m2[2] - m1[2]*m2[1])
456 else
457 for j=1,#m1 do
458 local m1j = m1[j]
459 if m1j ~= 0 then
460 insert(factors, (-1)^(j+1) * factor * m1j)
461 local m = submatrix(mat,1,j)
462 for k, v in next, m do
463 insert(data,v)
464 end
465 end
466 end
467 end
468 end
469 return det
470end
471
472matrix.laplace = laplace
473
474
475
476local function solve(m,c)
477 local n = #m
478 if n ~= #c then
479
480 return nil
481 end
482 local newm = copy(m)
483 local temp = copy(c)
484 local solution = copy(c)
485 for i=1,n do
486 insert(newm[i],temp[i])
487 end
488 newm = uppertri(newm, 0)
489 for k = n,1,-1 do
490 local val = 0
491 local new = newm[k]
492 for j = k+1, n do
493 val = val + new[j] * solution[j]
494 end
495 if new[k] == 0 then
496
497 return nil
498 else
499 solution[k] = (new[n+1] - val)/new[k]
500 end
501 end
502 return solution
503end
504
505matrix.solve = solve
506
507
508
509local function inverse(m)
510 local n = #m
511 local temp = copy(m)
512 if n ~= #m[1] then
513 return temp
514 end
515 for i=1,n do
516 for j=1,n do
517 insert(temp[i],j == i and 1 or 0)
518 end
519 end
520 temp = rowechelon(temp,1)
521 for i=1,n do
522 for j=1,n do
523 remove(temp[i], 1)
524 end
525 end
526 return temp
527end
528
529matrix.inverse = inverse
530
531
532
533local function makeM(k,v)
534 local tt = { }
535 for i=1,k do
536 local temp = { }
537 for j=1,k do
538 temp[j] = 0
539 end
540 tt[i] = temp
541 end
542 if v and v > 0 then
543 for i=1,k do
544 tt[i][i] = 1
545 end
546 end
547 return tt
548end
549
550matrix.makeM = makeM
551matrix.makeidentity = makeM
552matrix.makezero = makeM
553
554
555
556local function joinrows(t1, t2)
557 local nt1 = #t1
558 local nt2 = #t2
559 if (nt1*nt2 > 0) and (#t1[1] ~= #t2[1]) then
560 return "error: different number of columns"
561 else
562 for i=1,nt2 do
563 t1[nt1+i] = t2[i]
564 end
565 return t1
566 end
567end
568
569matrix.joinrows = joinrows
570matrix.joinRows = joinrows
571
572
573
574local function joincolumns(t1, t2)
575 local nt1 = #t1
576 local nt2 = #t2
577 if nt1 == 0 then
578 return t2
579 end
580 if nt2 == 0 then
581 return t1
582 end
583 if nt1 ~= nt2 then
584 return "error: different number of rows"
585 end
586 nt3 = #t2[1]
587 for i=1,nt1 do
588 local temp = t2[i]
589 for j= 1, nt3 do
590 insert(t1[i],temp[j])
591 end
592 end
593 return t1
594end
595
596matrix.joincolumns = joincolumns
597matrix.joinColumns = joincolumns
598
599\stopluacode
600
601\stopmodule
602
603\unexpanded\def\ctxmodulematrix#1{\ctxlua{moduledata.matrix.#1}}
604
605\continueifinputfile{mmatrix.mkiv}
606
607\usemodule[mmatrix]
608\usemodule[art01]
609
610\starttext
611
612\startluacode
613document.DemoMatrixA = {
614 { 0, 2, 4, -4, 1 },
615 { 0, 0, 2, 3, 4 },
616 { 2, 2, -6, 2, 4 },
617 { 2, 0, -6, 9, 7 },
618 { 2, 3, 4, 5, 6 },
619 { 6, 6, -6, 6, 6 },
620}
621
622document.DemoMatrixB = {
623 { 0, 2, 4, -4, 1 },
624 { 0, 0, 2, 3, 4 },
625 { 2, 2, -6, 3, 4 },
626 { 2, 0, -6, 9, 7 },
627 { 2, 2, -6, 2, 4 },
628}
629
630document.DemoMatrixC = {
631 { 3, 3, -1, 3 },
632 { -1, 4, 1, 3 },
633 { 5, 4, 0, 2 },
634 { 2, 4, 0, -1 },
635}
636\stopluacode
637
638\startbuffer[demo]
639\typebuffer
640\startalignment[middle]
641 \dontleavehmode\inlinebuffer
642\stopalignment
643\stopbuffer
644
645\setuphead[section][before={\testpage[5]\blank[2*big]}]
646
647\startsubject[title={A symbolic matrix}]
648
649\startbuffer
650\ctxmodulematrix{typeset(moduledata.matrix.symbolic("a", "m", "n"))}
651$\qquad\qquad$
652\ctxmodulematrix{typeset(moduledata.matrix.symbolic("a", "m", "n", 4, 8))}
653\stopbuffer
654
655\getbuffer[demo]
656
657\stopsubject
658
659\startsubject[title={Generate a new $m \times n$ matrix}]
660
661\startbuffer
662\startluacode
663 moduledata.matrix.typeset(moduledata.matrix.makeR(4,3, 0,5))
664 context.qquad()
665 context("\\qquad")
666 moduledata.matrix.typeset(moduledata.matrix.makeR(5,5,-1,5))
667\stopluacode
668\stopbuffer
669
670\getbuffer[demo]
671
672\stopsubject
673
674\startsubject[title={Swap two rows (ex: 2 and 4)}]
675
676\startbuffer
677\startluacode
678 moduledata.matrix.typeset(document.DemoMatrixA)
679 context("$\\qquad \\Rightarrow \\qquad$")
680 moduledata.matrix.typeset(moduledata.matrix.swaprows(document.DemoMatrixA,2,4))
681\stopluacode
682\stopbuffer
683
684\getbuffer[demo]
685
686\stopsubject
687
688\startsubject[title={Swap two columns (ex: 1 and 3)}]
689
690\startbuffer
691\startluacode
692 moduledata.matrix.typeset(document.DemoMatrixA)
693 context("$\\qquad \\Rightarrow \\qquad$")
694 moduledata.matrix.typeset(moduledata.matrix.swapcolumns(document.DemoMatrixA,1, 3))
695\stopluacode
696\stopbuffer
697
698\getbuffer[demo]
699
700\stopsubject
701
702\startsubject[title={Multiply 3 to row 2($3 \times r2$)}]
703
704\startbuffer
705\startluacode
706 moduledata.matrix.typeset(document.DemoMatrixA)
707 context("$\\qquad \\Rightarrow \\qquad$")
708 moduledata.matrix.typeset(moduledata.matrix.multiply(document.DemoMatrixA,2,3))
709\stopluacode
710\stopbuffer
711
712\getbuffer[demo]
713
714\stopsubject
715
716\startsubject[title={Add 4 times of row 3 to row 2($r2 4 \times r3$)}]
717
718\startbuffer
719\startluacode
720 moduledata.matrix.typeset(document.DemoMatrixA)
721 context("$\\qquad \\Rightarrow \\qquad$")
722 moduledata.matrix.sumrow(document.DemoMatrixA,2,3,4)
723 moduledata.matrix.typeset(document.DemoMatrixA)
724\stopluacode
725\stopbuffer
726
727\getbuffer[demo]
728
729\stopsubject
730
731\startsubject[title={Transpose a matrix}]
732\startbuffer
733\startluacode
734 moduledata.matrix.typeset(document.DemoMatrixA)
735 context("$\\qquad \\Rightarrow \\qquad$")
736 moduledata.matrix.typeset(moduledata.matrix.transpose(document.DemoMatrixA))
737\stopluacode
738\stopbuffer
739
740\getbuffer[demo]
741
742\stopsubject
743
744\startsubject[title={The inner product of two vectors}]
745
746\startbuffer
747\startluacode
748 context("$<1,2,3> \\cdot <3,1,2> \\ =\\ $ ")
749 context( moduledata.matrix.inner({ 1, 2, 3 }, { 3, 1, 2 }))
750\stopluacode
751\stopbuffer
752
753\getbuffer[demo]
754
755\startluacode
756context("$<1,2,3> \\cdot <3,1,2, 4> \\ =\\ $ ")
757context(moduledata.matrix.inner({ 1, 2, 3 }, { 3, 1, 2, 4 }))
758\stopluacode
759\stopbuffer
760
761\getbuffer[demo]
762
763\stopsubject
764
765\startsubject[title={The product of two matrices}]
766
767\startbuffer
768\startluacode
769 context("$\\ $")
770 moduledata.matrix.typeset(document.DemoMatrixB)
771 context("$\\cdot$")
772 moduledata.matrix.typeset(document.DemoMatrixA)
773 context("$ = $")
774 moduledata.matrix.typeset(moduledata.matrix.product
775 (document.DemoMatrixB,document.DemoMatrixB))
776\stopluacode
777\stopbuffer
778
779\getbuffer[demo]
780
781\stopsubject
782
783\startsubject[title={An Upper Triangular Matrix}]
784
785\startbuffer
786\startluacode
787 moduledata.matrix.typeset(document.DemoMatrixB)
788 context("$\\qquad \\Rightarrow \\qquad$")
789 moduledata.matrix.typeset(moduledata.matrix.uppertri(document.DemoMatrixB))
790\stopluacode
791\stopbuffer
792
793\getbuffer[demo]
794
795\stopsubject
796
797\startsubject[title={Determinant: using triangulation}]
798
799\startbuffer
800\startluacode
801 local m = {
802 { 1, 2, 4 },
803 { 0, 0, 2 },
804 { 2, 2, -6 },
805 { 2, 2, -6 },
806 }
807 moduledata.matrix.typeset(m, {fences="bars"})
808 context("$\\qquad = \\qquad$")
809 context(moduledata.matrix.determinant(m))
810\stopluacode
811\stopbuffer
812
813\getbuffer[demo]
814
815\startbuffer
816\startluacode
817 moduledata.matrix.typeset(document.DemoMatrixC, { fences = "bars" })
818 context("$\\qquad = \\qquad$")
819 context(moduledata.matrix.determinant(document.DemoMatrixC))
820\stopluacode
821\stopbuffer
822
823\getbuffer[demo]
824
825\stopsubject
826
827\startsubject[title={Determinant: using Laplace Expansion}]
828
829\startbuffer
830\startluacode
831 moduledata.matrix.typeset(document.DemoMatrixC, { fences = "bars" })
832 context("$\\qquad = \\qquad$")
833 context(moduledata.matrix.laplace(document.DemoMatrixC))
834\stopluacode
835\stopbuffer
836
837\getbuffer[demo]
838
839\stopsubject
840
841\startsubject[title={Example of Laplace Expansion using submatrix function}]
842
843\startbuffer
844\startluacode
845 local m = {
846 { 1, 5, 4, 2 },
847 { 5, 2, 0, 4 },
848 { 2, 2, 1, 1 },
849 { 1, 0, 0, 5 },
850 }
851 local options = {fences = "bars"}
852
853 moduledata.matrix.typeset(m,options)
854 context("\\par $=$")
855 for j = 1, #m[1] do
856 local mm = moduledata.matrix.submatrix(m, 1, j)
857 local factor = (-1)^(1+j) *(m[1][j])
858 context("\\ ($%d$) \\cdot ", factor)
859 moduledata.matrix.typeset(mm, options)
860 if j < #m[1] then
861 context("\\ $+$ ")
862 end
863 end
864\stopluacode
865\stopbuffer
866
867\getbuffer[demo]
868
869\stopsubject
870
871\startsubject[title={Row echelon form}]
872
873\startbuffer
874\startluacode
875 local m = {
876 { 1, 3, -2, 0, 2, 0, 0 },
877 { 2, 6, -5, -2, 4, -3, -1 },
878 { 0, 0, 5, 10, 0, 15, 5 },
879 { 2, 6, 0, 8, 4, 18, 6 },
880 }
881 moduledata.matrix.typeset(m)
882 context("$\\Rightarrow$")
883 moduledata.matrix.typeset(moduledata.matrix.rowechelon(m,1))
884\stopluacode
885
886\stopbuffer
887
888\getbuffer[demo]
889
890\stopsubject
891
892\startsubject[title={Solving linear equation}]
893
894\startbuffer
895\startluacode
896 local m = {
897 { 1, 3, -2, 0 },
898 { 2, 0, 1, 2 },
899 { 6, -5, -2, 4 },
900 { -3, -1, 5, 10 },
901 }
902
903 local c = { 5, 2, 6, 8 }
904
905 moduledata.matrix.typeset(moduledata.matrix.solve(m,c))
906 context.blank()
907 moduledata.matrix.typeset(moduledata.matrix.solve(m,c), { template = 6 })
908 context.blank()
909 moduledata.matrix.typeset(moduledata.matrix.solve(m,c), { template = "no" })
910 context.blank()
911 moduledata.matrix.typeset(moduledata.matrix.solve(m,c), { template = "%0.3f" })
912 context.blank()
913 moduledata.matrix.typeset(moduledata.matrix.solve(m,c), { template = "%0.4F" })
914\stopluacode
915\stopbuffer
916
917\getbuffer[demo]
918
919\stopsubject
920
921\startsubject[title={Inverse matrix}]
922
923\startbuffer
924\startluacode
925 local m = {
926 { 1, 1, 1 },
927 { 0, 2, 3 },
928 { 3, 2, 1 },
929 }
930 context("$A =\\quad$")
931 moduledata.matrix.typeset(m)
932 context("$\\qquad A^{-1} = \\quad$")
933 moduledata.matrix.typeset(moduledata.matrix.inverse(m))
934 context("\\blank\\ ")
935 moduledata.matrix.typeset(m)
936 context("$\\cdot$")
937 moduledata.matrix.typeset(moduledata.matrix.inverse(m))
938 context("$ = $")
939 moduledata.matrix.typeset(moduledata.matrix.product(m, moduledata.matrix.inverse(m)))
940\stopluacode
941\stopbuffer
942
943\getbuffer[demo]
944
945\stopsubject
946
947\startsubject[title={make matrices(zero, identiry, random}]
948
949\startbuffer
950\startluacode
951 moduledata.matrix.typeset(moduledata.matrix.makeM(3, 0))
952 context.qquad()
953 moduledata.matrix.typeset(moduledata.matrix.makeM(3, 1))
954 context.qquad()
955 moduledata.matrix.typeset(moduledata.matrix.makeR(4,3))
956\stopluacode
957\stopbuffer
958
959\getbuffer[demo]
960
961\stopsubject
962
963\startsubject[title={join rows, join columns}]
964
965\startbuffer
966\startluacode
967 local mat1 = moduledata.matrix.makeR(3, 4)
968 local mat2 = moduledata.matrix.makeR(4, 3)
969
970 context("Appending as columns: ")
971 context.blank()
972 moduledata.matrix.typeset(mat1)
973 context("$\\&$")
974 moduledata.matrix.typeset(mat1)
975 context("\\quad $\\Rightarrow$ \\quad")
976 moduledata.matrix.joinColumns(mat1, mat1)
977 moduledata.matrix.typeset(mat1)
978 context.blank()
979 context("Appending as rows: ")
980 context.blank()
981 moduledata.matrix.typeset(mat2)
982 context("$\\&$")
983 moduledata.matrix.typeset(mat2)
984 context("\\quad $\\Rightarrow$ \\quad")
985 moduledata.matrix.joinRows(mat2, mat2)
986 moduledata.matrix.typeset(mat2)
987\stopluacode
988\stopbuffer
989
990\getbuffer[demo]
991
992\stopsubject
993
994\stoptext
995 |