\startenvironment MatrixLuacode

\startbuffer[luaMatrix]
\startluacode
matrixOP = matrixOP or {} -- recommended: use namespace

matrixOP.symMatrix = function(sym, x, y) -- symMatrix("a", "m", "n")
local entry
local mrow={}
local mm={}
   for i=1, 2 do							-- first two rows
   	mrow={}
	for j=1, 2 do
		entry=sym.."_{"..i..j.."}"
		table.insert(mrow, entry)
	end
	entry="\\cdots"
	table.insert(mrow, entry)	
	entry=sym.."_{"..i..y.."}"
	table.insert(mrow, entry)
	table.insert(mm,mrow)
   end
   entry = {"\\vdots","\\vdots","\\ddots","\\vdots"} 	--3rd row
   table.insert(mm,entry)
	mrow={}
	for j=1, 2 do						-- last row
		entry=sym.."_{"..x..j.."}"
		table.insert(mrow, entry)
	end
	entry="\\cdots"
	table.insert(mrow, entry)	
	entry=sym.."_{"..x..y.."}"
	table.insert(mrow, entry)
	table.insert(mm,mrow)
	return mm
end
 
matrixOP.write = function (t)
      context.startmatrix{left = "\\left(\\,", right = "\\,\\right)"}
        for _, r in ipairs(t) do
          for _, c in ipairs(r) do
            context.NC(c)
          end
          context.NR()
        end
      context.stopmatrix()
end


matrixOP.writeDet = function (t)
      context.startmatrix{left = "\\left|\\ ", right = "\\ \\right|"}
        for _, r in ipairs(t) do
          for _, c in ipairs(r) do
            context.NC(c)
          end
          context.NR()
        end
      context.stopmatrix()
end

matrixOP.rowChange = function(t, i, j) -- interchange two rows(i-th, j-th) 
	t[i] , t[j]= t[j], t[i]
end
  
matrixOP.rowMult = function(t, i, m) -- replace i-th row with m*(i-th row)
	local len
	len = #(t[i])
	for k = 1, len do t[i][k] =  m*t[i][k] end
end

matrixOP.rowMultSum = function(t, i, j, m) -- replace i-th row with i-th row + m*(j-th row)
	local len
	len = #(t[1])
	for k = 1, len do t[i][k] = t[i][k] + m*t[j][k] end
end

matrixOP.transpose = function(m) -- transpose of a matrix
  local temp
  local mT={}
  local mTrow

  for j = 1, #m[1] do
	mTrow={}
	for i=1, #m do
		temp = m[i][j]
		table.insert(mTrow, temp)
	end
	table.insert(mT, mTrow)
  end
  return mT
end

matrixOP.inner = function (u, v) -- inner product of two vectors
  temp=0
  if #u == #v then
	for i=1, #u do
		temp = temp + u[i]*v[i]
	end
  end
  return temp
end


matrixOP.product = function(m1, m2) -- product of two matrices
local temp
local m3={}
local mrow
	if #m1[1] == #m2 then
		for i = 1, #m1 do
			mrow={}
			for j=1, #m2[1] do
				temp = 0
				for k=1, #m1[1] do
					u = m1[i][k]*m2[k][j]
					temp = temp + u
				end
				table.insert(mrow, temp)
			end
			table.insert(m3, mrow)
		end
	end
	return m3
end

matrixOP.searchRow = function(m, i)
	local pv, pr
	pr = #m + 1

	for k=i+1, #m do
		pv=m[k][i]
		if pv == 0 then
			k = k+1
		else
			pr = k
			break
		end
	end

	if pr <= #m then 
		return pr
	else
		return 0
	end
end

matrixOP.upperTri = function(m)
  local pivot, pRow, multiple
  local temp
  temp = m
  sgn= 1
  for i=1, #temp-1 do
	pivot = temp[i][i]

	if pivot == 0 then
		pRow = matrixOP.searchRow(temp, i)
		if pRow==0 then
--			context("Singular Matrix")
			break
		end
		matrixOP.rowChange(temp, i, pRow)
		sgn=(-1)*sgn
	end

	for k=i+1, #temp do
		multiple = -temp[k][i]/temp[i][i]
		matrixOP.rowMultSum(temp, k, i,multiple)
	end
  end
  return temp
end

matrixOP.determinant = function(m)
	local det, sgn
	if #m ==#m[1]	then
		det=1
		sgn=1
		matrixOP.upperTri(m)
		for i = 1, #m do
			det = det*m[i][i]
		end
		det = sgn*det
	else
		det = 0
	end
--	context(det)
	return det
end

\stopluacode

\stopbuffer

\stopenvironment
