m-matrix.mkiv /size: 22 Kb    last modification: 2020-07-01 14:35
 1%D \module 2%D [ file=m-matrix, 3%D version=2014.11.04, % already a year older 4%D title=\CONTEXT\ Extra Modules, 5%D subtitle=Matrices, 6%D author={Jeong Dalyoung \& Hans Hagen}, 7%D date=\currentdate, 8%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] 9%C 10%C This module is part of the \CONTEXT\ macro||package and is 11%C therefore copyrighted by \PRAGMA. See mreadme.pdf for 12%C details. 13 14%D This code is based on a post by Dalyoung on the context list. After that 15%D we turned it into a module and improved the code a bit. Feel free to ask 16%D us for more. Once we're satisfied, a more general helper l-matrix could 17%D be made. Dalyoung does the clever bits, and Hans only cleanes up and 18%D optimizes a bit. 19 20% \registerctxluafile{l-matrix}{} % not yet 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) -- symMatrix("a", "m", "n") 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-- todo: define a matrix at the tex end so that we have more control 74 75-- local fences = { 76-- parentheses = { left = "\\left(\\,", right = "\\,\\right)" }, 77-- brackets = { left = "\\left[\\,", right = "\\,\\right]" }, 78-- bars = { left = "\\left|\\,", right = "\\,\\right|" }, 79-- } 80 81local fences = { 82 parentheses = { "matrix:parentheses" }, 83 brackets = { "matrix:brackets" }, 84 bars = { "matrix:bars" }, 85} 86 87-- one can add more fences 88 89fences.bar = fences.bars 90fences.parenthesis = fences.parentheses 91fences.bracket = fences.brackets 92 93-- one can set the template 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 -- whatever = fences.brackets 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-- interchange two columns (i-th, j-th) 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-- replace i-th row with factor * (i-th row) 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-- scalar product "factor * m" 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-- replace i-th row with i-th row + factor * (j-th row) 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-- transpose of a matrix 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-- inner product of two vectors 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-- product of two matrices 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 -- if there is no nonzero number 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 -- no nonzero number in a column 325 pCol = pCol + 1 326 if pCol > #temp[pRow] then 327 -- there is no nonzero number in a row 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 -- make the "reduced row echelon form" 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 -- just make the row echelon form 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-- make matrices until its determinant is not 0 377 378local function make(m,n,low,high) -- m and n swapped 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-- extract submatrix by using 412 413local function submatrix(t,i,j) 414 local rows = #t 415 local columns = #t[1] 416 local sign = 1 -- not used 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-- calculating determinant using Laplace Expansion 433 434local function laplace(t) -- not sure if this is the most effient but 435 local factors = { 1 } -- it's not used for number crunching anyway 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-- solve the linear equation m X = c 475 476local function solve(m,c) 477 local n = #m 478 if n ~= #c then 479 -- return "error: size mismatch" 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 -- return "error: no unique solution" 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-- find the inverse matrix of m 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-- create zero and identity matrix 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-- append the rows of the second matrix to the bottom of the first matrix 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-- append the columns of the second matrix to the right of the first matrix 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{m-matrix.mkiv} 606 607\usemodule[m-matrix] 608\usemodule[art-01] 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 r_2$)}] 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($r_2 + 4 \times r_3$)}] 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