diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/modules/mkiv/m-matrix.mkiv')
-rw-r--r-- | Master/texmf-dist/tex/context/modules/mkiv/m-matrix.mkiv | 250 |
1 files changed, 222 insertions, 28 deletions
diff --git a/Master/texmf-dist/tex/context/modules/mkiv/m-matrix.mkiv b/Master/texmf-dist/tex/context/modules/mkiv/m-matrix.mkiv index ccb376e39c7..f59363e94b0 100644 --- a/Master/texmf-dist/tex/context/modules/mkiv/m-matrix.mkiv +++ b/Master/texmf-dist/tex/context/modules/mkiv/m-matrix.mkiv @@ -28,6 +28,9 @@ local formatters = string.formatters local copy = table.copy local insert = table.insert local remove = table.remove +local random = math.random + +local context = context local matrix = { } moduledata.matrix = matrix @@ -67,35 +70,120 @@ end -- todo: define a matrix at the tex end so that we have more control -local fences_p = { - left = "\\left(\\,", - right = "\\,\\right)", +local fences = { + parentheses = { left = "\\left(\\,", right = "\\,\\right)" }, + brackets = { left = "\\left[\\,", right = "\\,\\right]" }, + bars = { left = "\\left|\\,", right = "\\,\\right|" }, } -local fences_b = { - left = "\\left[\\,", - right = "\\,\\right]", -} +-- one can add more fences + +fences.bar = fences.bars +fences.parenthesis = fences.parentheses +fences.bracket = fences.brackets + +-- one can set the template + +matrix.template = "%0.3F" function matrix.typeset(m,options) - local options = settings_to_hash(options or "") - context.startmatrix(options.determinant and fences_b or fences_p) - for i=1, #m do - local mi = m[i] - for j=1,#mi do - context.NC(mi[j]) - end - context.NR() + if type(m) == "table" then + local options = settings_to_hash(options or "") + local whatever = options.determinant == "yes" and fences.bars or fences.parentheses + if options.fences then + whatever = fences[options.fences] or whatever + elseif options.determinant then + -- whatever = fences.brackets + whatever = fences.bars end - context.stopmatrix() + local template = options.template or matrix.template + if template == "yes" then + template = matrix.template + elseif template == "no" then + template = false + elseif tonumber(template) then + template = "%0." .. template .. "F" + end + context.startmatrix(whatever) + for i=1, #m do + local mi = m[i] + for j=1,#mi do + context.NC() + local n = mi[j] + if template and tonumber(n) then + context(template,n) + else + context(mi[j]) + end + end + context.NR() + end + context.stopmatrix() + elseif m then + context(m) + end end -- interchange two rows (i-th, j-th) -function matrix.swap(t,i,j) - t[i], t[j] = t[j], t[i] +-- function matrix.swaprows(t,i,j) +-- if i <= #t and j <= #t then +-- t[i], t[j] = t[j], t[i] +-- return t +-- else +-- return "error: out of bound" +-- end +-- end + +function matrix.swaprows(t,i,j) + local ti = t[i] + if not ti then + return "error: no row i" + end + local tj = t[j] + if not tj then + return "error: no row j" + end + t[i], t[j] = tj, ti + return t +end + +-- interchange two columns (i-th, j-th) + +-- function matrix.swapcolumns(t, i, j) +-- if i <= #t[1] and j <= #t[1] then +-- for k = 1, #t do +-- t[k][i], t[k][j] = t[k][j], t[k][i] +-- end +-- return t +-- else +-- return "error: out of bound" +-- end +-- end + +function matrix.swapcolumns(t, i, j) + local t1 = t[1] + if not t1 then + return "error: no rows" + end + local n = #t1 + if i <= n then + return "error: no row i" + end + if j <= n then + return "error: no row j" + end + for k = 1, #t do + local tk = t[k] + tk[i], tk[j] = tk[j], tk[i] + end + return t end +matrix.swapC = matrix.swapcolumns +matrix.swapR = matrix.swaprows +matrix.swap = matrix.swaprows + -- replace i-th row with factor * (i-th row) function matrix.multiply(m,i,factor) @@ -151,7 +239,7 @@ function matrix.inner(u,v) end local nv = #v if nv ~= nu then - return 0 + return "error: size mismatch" end local result = 0 for i=1,nu do @@ -163,8 +251,8 @@ end -- product of two matrices function matrix.product(m1,m2) - local product = { } if #m1[1] == #m2 then + local product = { } for i=1,#m1 do local m1i = m1[i] local mrow = { } @@ -177,8 +265,10 @@ function matrix.product(m1,m2) end product[i] = mrow end + return product + else + return "error: size mismatch" end - return product end local function uppertri(m,sign) @@ -216,7 +306,7 @@ end matrix.uppertri = uppertri -function matrix.determinant(m) +local function determinant(m) if #m == #m[1] then local d = 1 local t, s = uppertri(m,1) @@ -225,10 +315,12 @@ function matrix.determinant(m) end return s*d else - return 0 + return "error: not a square matrix" end end +matrix.determinant = determinant + local function rowechelon(m,r) local temp = copy(m) local pRow = 1 @@ -293,9 +385,102 @@ end matrix.rowechelon = rowechelon matrix.rowEchelon = rowechelon +-- make matrices until its determinant is not 0 + +function matrix.make(n,m,low,high) + if not n then + n = 10 + end + if not m then + m = 10 + end + if not low then + low = 0 + end + if not high then + high = 100 + end + local t = { } -- make an empty n1 x n2 array + local again = true + for i=1,n do + t[i] = { } + end + while true do + for i=1,n do + local ti = t[i] + for j=1,m do + ti[j] = random(low,high) + end + end + if n ~= m or determinant(t,1) ~= 0 then + return t + end + end +end + +-- extract submatrix by using + +local function submatrix(t,i,j) + local rows = #t + local columns = #t[1] + local sign = 1 -- not used + if i <= rows and j <= columns then + local c = copy(t) + remove(c,i) + for k=1,rows-1 do + remove(c[k],j) + end + return c + else + return "error: out of bound" + end +end + +matrix.submatrix = submatrix + +-- calculating determinant using Laplace Expansion + +function matrix.laplace(t) -- not sure if this is the most effient but + local factors = { 1 } -- it's not used for number crunching anyway + local data = copy(t) + local det = 0 + while #data > 0 do + local mat = { } + local siz = #data[1] + if siz == 0 then + return "error: no determinant" + elseif siz == 1 then + det = data[1][1] + return det + end + for i=1,siz do + mat[i] = data[1] + remove(data,1) + end + local factor = remove(factors,1) + local m1 = mat[1] + if siz == 2 then + local m2 = mat[2] + det = det + factor * (m1[1]*m2[2] - m1[2]*m2[1]) + else + for j=1,#m1 do + local m1j = m1[j] + if m1j ~= 0 then + insert(factors, (-1)^(j+1) * factor * m1j) + local m = submatrix(mat,1,j) + for k, v in next, m do + insert(data,v) + end + end + end + end + end + return det +end + -- solve the linear equation m X = c -local function solve(m,c) +local function solve(m,c) local n = #m if n ~= #c then return copy(m) @@ -393,14 +578,14 @@ moduledata.matrix.typeset(moduledata.matrix.multiply(document.DemoMatrixA, 2, 3) \stopsubject -\startsubject[title={Row 2 + $3 \times r_4$}] +\startsubject[title={Row 2 + $4 \times r_3$}] \startluacode moduledata.matrix.typeset(document.DemoMatrixA) context.blank() moduledata.matrix.sumrow(document.DemoMatrixA, 2, 3, 4) context.blank() -moduledata.matrix.typeset(document.DemoMatrixA) +moduledata.matrix.typeset(document.DemoMatrixA,{ fences = "bars" } ) \stopluacode \stopsubject @@ -445,7 +630,7 @@ local m = { { 0, 0, 2 }, { 2, 2, -6 }, } -context(moduledata.matrix.determinant(m)) +context(moduledata.matrix.determinant(m, "determinant=yes" )) \stopluacode \stopsubject @@ -461,7 +646,8 @@ local m = { } moduledata.matrix.typeset(m) -moduledata.matrix.typeset(moduledata.matrix.rowechelon(m,1)) +context.blank() +moduledata.matrix.typeset(moduledata.matrix.rowechelon(m,1), { determinant = "yes" }) \stopluacode \stopsubject @@ -479,6 +665,14 @@ local m = { local c = { 5, 2, 6, 8 } moduledata.matrix.typeset(moduledata.matrix.solve(m,c)) +context.blank() +moduledata.matrix.typeset(moduledata.matrix.solve(m,c), { template = 6 }) +context.blank() +moduledata.matrix.typeset(moduledata.matrix.solve(m,c), { template = "no" }) +context.blank() +moduledata.matrix.typeset(moduledata.matrix.solve(m,c), { template = "%0.3f" }) +context.blank() +moduledata.matrix.typeset(moduledata.matrix.solve(m,c), { template = "%0.4F" }) \stopluacode \stopsubject |