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
733\startbuffer
734\startluacode
735 moduledata.matrix.typeset(document.DemoMatrixA)
736 context("$\\qquad \\Rightarrow \\qquad$")
737 moduledata.matrix.typeset(moduledata.matrix.transpose(document.DemoMatrixA))
738\stopluacode
739\stopbuffer
740
741\getbuffer[demo]
742
743\stopsubject
744
745\startsubject[title={The inner product of two vectors}]
746
747\startbuffer
748\startluacode
749 context("$<1,2,3> \\cdot <3,1,2> \\ =\\ $ ")
750 context( moduledata.matrix.inner({ 1, 2, 3 }, { 3, 1, 2 }))
751\stopluacode
752\stopbuffer
753
754\getbuffer[demo]
755
756\startbuffer
757\startluacode
758context("$<1,2,3> \\cdot <3,1,2, 4> \\ =\\ $ ")
759context(moduledata.matrix.inner({ 1, 2, 3 }, { 3, 1, 2, 4 }))
760\stopluacode
761\stopbuffer
762
763\getbuffer[demo]
764
765\stopsubject
766
767\startsubject[title={The product of two matrices}]
768
769\startbuffer
770\startluacode
771 context("$\\ $")
772 moduledata.matrix.typeset(document.DemoMatrixB)
773 context("$\\cdot$")
774 moduledata.matrix.typeset(document.DemoMatrixA)
775 context("$ = $")
776 moduledata.matrix.typeset(moduledata.matrix.product
777 (document.DemoMatrixB,document.DemoMatrixB))
778\stopluacode
779\stopbuffer
780
781\getbuffer[demo]
782
783\stopsubject
784
785\startsubject[title={An Upper Triangular Matrix}]
786
787\startbuffer
788\startluacode
789 moduledata.matrix.typeset(document.DemoMatrixB)
790 context("$\\qquad \\Rightarrow \\qquad$")
791 moduledata.matrix.typeset(moduledata.matrix.uppertri(document.DemoMatrixB))
792\stopluacode
793\stopbuffer
794
795\getbuffer[demo]
796
797\stopsubject
798
799\startsubject[title={Determinant: using triangulation}]
800
801\startbuffer
802\startluacode
803 local m = {
804 { 1, 2, 4 },
805 { 0, 0, 2 },
806 { 2, 2, -6 },
807 { 2, 2, -6 },
808 }
809 moduledata.matrix.typeset(m, {fences="bars"})
810 context("$\\qquad = \\qquad$")
811 context(moduledata.matrix.determinant(m))
812\stopluacode
813\stopbuffer
814
815\getbuffer[demo]
816
817\startbuffer
818\startluacode
819 moduledata.matrix.typeset(document.DemoMatrixC, { fences = "bars" })
820 context("$\\qquad = \\qquad$")
821 context(moduledata.matrix.determinant(document.DemoMatrixC))
822\stopluacode
823\stopbuffer
824
825\getbuffer[demo]
826
827\stopsubject
828
829\startsubject[title={Determinant: using Laplace Expansion}]
830
831\startbuffer
832\startluacode
833 moduledata.matrix.typeset(document.DemoMatrixC, { fences = "bars" })
834 context("$\\qquad = \\qquad$")
835 context(moduledata.matrix.laplace(document.DemoMatrixC))
836\stopluacode
837\stopbuffer
838
839\getbuffer[demo]
840
841\stopsubject
842
843\startsubject[title={Example of Laplace Expansion using submatrix function}]
844
845\startbuffer
846\startluacode
847 local m = {
848 { 1, 5, 4, 2 },
849 { 5, 2, 0, 4 },
850 { 2, 2, 1, 1 },
851 { 1, 0, 0, 5 },
852 }
853 local options = {fences = "bars"}
854
855 moduledata.matrix.typeset(m,options)
856 context("\\par $=$")
857 for j = 1, #m[1] do
858 local mm = moduledata.matrix.submatrix(m, 1, j)
859 local factor = (-1)^(1+j) *(m[1][j])
860 context("\\ ($%d$) \\cdot ", factor)
861 moduledata.matrix.typeset(mm, options)
862 if j < #m[1] then
863 context("\\ $+$ ")
864 end
865 end
866\stopluacode
867\stopbuffer
868
869\getbuffer[demo]
870
871\stopsubject
872
873\startsubject[title={Row echelon form}]
874
875\startbuffer
876\startluacode
877 local m = {
878 { 1, 3, -2, 0, 2, 0, 0 },
879 { 2, 6, -5, -2, 4, -3, -1 },
880 { 0, 0, 5, 10, 0, 15, 5 },
881 { 2, 6, 0, 8, 4, 18, 6 },
882 }
883 moduledata.matrix.typeset(m)
884 context("$\\Rightarrow$")
885 moduledata.matrix.typeset(moduledata.matrix.rowechelon(m,1))
886\stopluacode
887\stopbuffer
888
889\getbuffer[demo]
890
891\stopsubject
892
893\startsubject[title={Solving linear equation}]
894
895\startbuffer
896\startluacode
897 local m = {
898 { 1, 3, -2, 0 },
899 { 2, 0, 1, 2 },
900 { 6, -5, -2, 4 },
901 { -3, -1, 5, 10 },
902 }
903
904 local c = { 5, 2, 6, 8 }
905
906 moduledata.matrix.typeset(moduledata.matrix.solve(m,c))
907 context.blank()
908 moduledata.matrix.typeset(moduledata.matrix.solve(m,c), { template = 6 })
909 context.blank()
910 moduledata.matrix.typeset(moduledata.matrix.solve(m,c), { template = "no" })
911 context.blank()
912 moduledata.matrix.typeset(moduledata.matrix.solve(m,c), { template = "%0.3f" })
913 context.blank()
914 moduledata.matrix.typeset(moduledata.matrix.solve(m,c), { template = "%0.4F" })
915\stopluacode
916\stopbuffer
917
918\getbuffer[demo]
919
920\stopsubject
921
922\startsubject[title={Inverse matrix}]
923
924\startbuffer
925\startluacode
926 local m = {
927 { 1, 1, 1 },
928 { 0, 2, 3 },
929 { 3, 2, 1 },
930 }
931 context("$A =\\quad$")
932 moduledata.matrix.typeset(m)
933 context("$\\qquad A^{-1} = \\quad$")
934 moduledata.matrix.typeset(moduledata.matrix.inverse(m))
935 context("\\blank\\ ")
936 moduledata.matrix.typeset(m)
937 context("$\\cdot$")
938 moduledata.matrix.typeset(moduledata.matrix.inverse(m))
939 context("$ = $")
940 moduledata.matrix.typeset(moduledata.matrix.product(m, moduledata.matrix.inverse(m)))
941\stopluacode
942\stopbuffer
943
944\getbuffer[demo]
945
946\stopsubject
947
948\startsubject[title={make matrices(zero, identiry, random}]
949
950\startbuffer
951\startluacode
952 moduledata.matrix.typeset(moduledata.matrix.makeM(3, 0))
953 context.qquad()
954 moduledata.matrix.typeset(moduledata.matrix.makeM(3, 1))
955 context.qquad()
956 moduledata.matrix.typeset(moduledata.matrix.makeR(4,3))
957\stopluacode
958\stopbuffer
959
960\getbuffer[demo]
961
962\stopsubject
963
964\startsubject[title={join rows, join columns}]
965
966\startbuffer
967\startluacode
968 local mat1 = moduledata.matrix.makeR(3, 4)
969 local mat2 = moduledata.matrix.makeR(4, 3)
970
971 context("Appending as columns: ")
972 context.blank()
973 moduledata.matrix.typeset(mat1)
974 context("$\\&$")
975 moduledata.matrix.typeset(mat1)
976 context("\\quad $\\Rightarrow$ \\quad")
977 moduledata.matrix.joinColumns(mat1, mat1)
978 moduledata.matrix.typeset(mat1)
979 context.blank()
980 context("Appending as rows: ")
981 context.blank()
982 moduledata.matrix.typeset(mat2)
983 context("$\\&$")
984 moduledata.matrix.typeset(mat2)
985 context("\\quad $\\Rightarrow$ \\quad")
986 moduledata.matrix.joinRows(mat2, mat2)
987 moduledata.matrix.typeset(mat2)
988\stopluacode
989\stopbuffer
990
991\getbuffer[demo]
992
993\stoptext
994 |