MineOS/lib/matrix.lua
2016-12-11 15:04:12 +03:00

223 lines
5.8 KiB
Lua

local matrixLibrary = {}
---------------------------------------------------- Matrix tables creation ----------------------------------------------------------------
function matrixLibrary.newIdentityMatrix(size)
local matrix = {}
for y = 1, size do
matrix[y] = {}
for x = 1, size do
matrix[y][x] = (x == y) and 1 or 0
end
end
return matrix
end
function matrixLibrary.newCofactorMatrix(matrix)
local cofactorMatrix = {}
for y = 1, #matrix do
cofactorMatrix[y] = {}
for x = 1, #matrix[y] do
cofactorMatrix[y][x] = matrixLibrary.getCofactor(matrix, y, x)
end
end
return cofactorMatrix
end
function matrixLibrary.newAdjugateMatrix(matrix)
return matrixLibrary.transpose(matrixLibrary.newCofactorMatrix(matrix))
end
function matrixLibrary.newFilledMatrix(width, height, value)
local matrix = {}
for y = 1, height do
matrix[y] = {}
for x = 1, width do
matrix[y][x] = value
end
end
return matrix
end
function matrixLibrary.copy(matrix)
local newMatrix = {}
for y = 1, #matrix do
newMatrix[y] = {}
for x = 1, #matrix[y] do
newMatrix[y][x] = matrix[y][x]
end
end
return newMatrix
end
function matrixLibrary.print(matrix)
print("Matrix size: " .. #matrix .. "x" .. #matrix[1])
for y = 1, #matrix do
for x = 1, #matrix[y] do
io.write(tostring((not matrix[y]) and "nil" or matrix[y][x]))
io.write(' ')
end
print("")
end
return matrix
end
---------------------------------------------------- Matrix arithmetic operations ----------------------------------------------------------------
function matrixLibrary.multiply(matrix, data)
local dataType = type(data)
if dataType == "table" then
if (#matrix[1] ~= #data) then error("Couldn't multiply matrixes AxB: A[columns] ~= B[rows]") end
local result = {}
for i = 1, #matrix do
result[i] = {}
for j = 1, #data[1] do
local resultElement = 0
for k = 1, #matrix[1] do
resultElement = resultElement + (matrix[i][k] * data[k][j])
end
result[i][j] = resultElement
end
end
return result
elseif dataType == "number" then
for y = 1, #matrix do
for x = 1, #matrix[y] do
matrix[y][x] = matrix[y][x] * data
end
end
return matrix
else
error("Unsupported operation data type: " .. tostring(dataType))
end
end
function matrixLibrary.divide(matrix, data)
local dataType = type(data)
if dataType == "table" then
error("Matrix by matrix division doesn't supported yet")
elseif dataType == "number" then
for y = 1, #matrix do
for x = 1, #matrix[y] do
matrix[y][x] = matrix[y][x] / data
end
end
return matrix
else
error("Unsupported operation data type: " .. tostring(dataType))
end
end
---------------------------------------------------- Matrix resizing methods ----------------------------------------------------------------
function matrixLibrary.addRow(matrix, row)
if (#matrix[1] ~= #row) then error("Insertion row size doesn't match matrix row size: " .. #row .. " vs " .. #matrix[1]) end
table.insert(matrix, row)
return matrix
end
function matrixLibrary.addColumn(matrix, column)
if (#matrix ~= #column ) then error("Insertion column size doesn't match matrix column size: " .. #column .. " vs " .. #matrix) end
for y = 1, #column do
table.insert(matrix[y], column[y])
end
return matrix
end
function matrixLibrary.removeRow(matrix, row)
if row > #matrix then error("Can't remove row that is bigger then matrix height") end
table.remove(matrix, row)
return matrix
end
function matrixLibrary.removeColumn(matrix, column)
if column > #matrix[1] then error("Can't remove column that is bigger then matrix width") end
for y = 1, #matrix do
table.remove(matrix[y], column)
end
return matrix
end
---------------------------------------------------- Matrix advanced manipulation methods ----------------------------------------------------------------
function matrixLibrary.transpose(matrix)
local transposedMatrix = {}
for x = 1, #matrix[1] do
transposedMatrix[x] = {}
for y = 1, #matrix do
transposedMatrix[x][y] = matrix[y][x]
end
end
return transposedMatrix
end
function matrixLibrary.getMinor(matrix, row, column)
return matrixLibrary.getDeterminant(matrixLibrary.removeColumn(matrixLibrary.removeRow(matrixLibrary.copy(matrix), row), column))
end
function matrixLibrary.getCofactor(matrix, row, column)
return (-1) ^ (row + column) * matrixLibrary.getMinor(matrix, row, column)
end
function matrixLibrary.getDeterminant(matrix)
local matrixSize = #matrix
if matrixSize ~= #matrix[1] then error("Can't find determinant for matrix, row count != column count: " .. #matrix .. "x" .. #matrix[1]) end
if matrixSize == 1 then
return matrix[1][1]
elseif matrixSize == 2 then
return matrix[1][1] * matrix[2][2] - matrix[1][2] * matrix[2][1]
else
local determinant = 0
for j = 1, matrixSize do
determinant = determinant + matrixLibrary.getCofactor(matrix, 1, j) * matrix[1][j]
end
return determinant
end
end
function matrixLibrary.invert(matrix)
local determinant = matrixLibrary.getDeterminant(matrix)
if determinant == 0 then error("Can't invert matrix with determinant equals 0") end
return matrixLibrary.divide(matrixLibrary.newAdjugateMatrix(matrix), determinant)
end
------------------------------------------------------------------------------------------------------------------------
-- local m = {
-- {2, 5, 4},
-- {-5, 5, 6},
-- {1, 3, 7},
-- }
-- matrixLibrary.print(m)
-- m = matrixLibrary.invert(m)
-- matrixLibrary.print(m)
------------------------------------------------------------------------------------------------------------------------
return matrixLibrary