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