summaryrefslogtreecommitdiff
path: root/tex/context/modules/mkiv/m-matrix.mkiv
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/modules/mkiv/m-matrix.mkiv')
-rw-r--r--tex/context/modules/mkiv/m-matrix.mkiv250
1 files changed, 222 insertions, 28 deletions
diff --git a/tex/context/modules/mkiv/m-matrix.mkiv b/tex/context/modules/mkiv/m-matrix.mkiv
index ccb376e39..f59363e94 100644
--- a/tex/context/modules/mkiv/m-matrix.mkiv
+++ b/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