This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
KingofGamesYami's profile picture

[Math] Matrices

Started by KingofGamesYami, 09 September 2014 - 03:17 AM
KingofGamesYami #1
Posted 09 September 2014 - 05:17 AM
So, I'm making a matrix function, complete with special metatables. The stuff I have so far works great, but I want to know, is there any way to divide a matrix? I have addition, subtraction, and multiplication, but I have no idea if this can be done, or how I should do it. If you can point me to a resource that explains this, I would be very greatful. If it doesn't exist, oh well… I guess I can just trigger an error. I already have matrix / number, I was just wondering about matrix / matrix.

I've posted this! http://www.computercraft.info/forums2/index.php?/topic/20299-10-matrix-api/

Highly confidential code
Spoiler

a = {
	len = function( self )
		return self.length
	end,
	wid = function( self )
		return self.width
	end,
	insert = function( self, x, y, value )
		if not self[ x ] then
			error( "x value out of bounds", 2 )
		end
		if not self[ x ][ y ] then
			error( "y value out of bounds", 2 )
		end
		self[ x ][ y ] = value
	end,
	getValue = function( self, x, y )
		return self[ x ] and self[ x ][ y ] or nil
	end,
}

mt = {
	__type = "array",
	__index = a,
	__add = function( lhs, rhs )
		if type( rhs ) ~= "table" then
			error( "attempt to add array and " .. type( rns ), 2 )
		elseif getmetatable( rhs ).__type ~= "array" then
			error( "attempt to add array and table", 2 )
		elseif lhs:len() ~= rhs:len() or lhs:wid() ~= rhs:wid() then
			error( "arrays' dimensions are not equal", 2 )
		end
		local array = create( lhs:len(), lhs:wid() )
		for x, tbl in ipairs( lhs ) do
			for y, value in ipairs( rhs ) do
				array:insert( x, y, rhs:getValue( x, y ) + lhs:getValue( x, y ) )
			end
		end
		return array
	end,
	__sub = function( lhs, rhs )
		if type( rhs ) ~= "table" and type( rhs ) ~= "number" then
			error( "attempt to subtract array and " .. type( rhs ), 2 )
		elseif getmetatable( rhs ).__type ~= "array" then
			error( "attempt to subtract array and table", 2 )
		elseif lhs:len() ~= rhs:len() or lhs:wid() ~= rhs:wid() then
			error( "arrays’ dimensions are not equal", 2 )
		end
		local array = create( lhs:len(), lhs:wid() )
		for x, tbl in ipairs( lhs ) do
			for y, value in ipairs( rhs ) do
				array:insert( x, y, rhs:getValue( x, y ) - lhs:getValue( x, y ) )
			end
		end
		return array
	end,
	__mul = function( lhs, rhs )
		if type( rhs ) ~= "table" and type( rhs ) ~= "number" then
			error( "attempt to multiply array and " .. type( rns ), 2 )
		elseif type( rhs ) == "table" and lhs:len() ~= rhs:wid() then
			error( 'attempt to multiply ' .. lhs:len() .. ", " .. lys:wid() .. " array with " .. rhs:len() .. ", " .. rhs:wid() .. " array", 2 )
		elseif type( rhs ) == "number" then
			local array = create( lhs:len(), lhs:wid() )
			for x = 1, lhs:len() do
				for y = 1, lhs:wid() do
					array:insert( x, y, lhs:getValue( x, y ) * rhs )
				end
			end
			return array
		elseif getmetatable( rhs ).__type ~= "array" then
			error( "attempt to multiply array and table", 2 )
		end
		local array = create( lhs:len(), rhs:wid() )
		for pos = 1, lhs:len() do
			for column = 1, rhs:len() do
				local value = 0
				for x = 1, lhs:wid() do
					value = value + lhs:getValue( pos, x ) * rhs:getValue( column, x )
				end
				array:insert( pos, column, value )
			end
		end
		return array
	end,
	__div = function( lhs, rhs )
		if type( rhs ) ~= "table" and type( rhs ) ~= "number" then
			error( "attempt to divide array and " .. type( rhs ), 2 )
		elseif type( rhs ) == "table" and getmetatable( rhs ).__type ~= "array" then
			error( "attempt to divide array and table", 2 )
		elseif type( rhs ) == "number" then
			local array = create( lhs:len(), lhs:wid() )
			for x = 1, lhs:len() do
				for y = 1, lhs:wid() do
					array:insert( x, y, lhs:getValue( x, y ) / rhs )
				end
			end
			return array
		end
		--#what to do here...
	end,
}

function create( length, width )
	if length and width then
		local array = { length = length, width = width }
		for x = 1, length do
			array[ x ] = {}
			for y = 1, width do
				array[ x ][ y ] = 0
			end
		end
		setmetatable( array, mt )
		return array
	end
	length.length = #length
	length.width = #length[ 1 ]
	setmetatable( length, mt )
	return length
end
Edited on 10 September 2014 - 05:46 PM
Lyqyd #2
Posted 09 September 2014 - 05:22 AM
You may be interested in the wikipedia article on matrices, specifically the linked subsection on matrix operations.
KingofGamesYami #3
Posted 09 September 2014 - 06:11 AM
You may be interested in the wikipedia article on matrices, specifically the linked subsection on matrix operations.
Well, I can't find anything on division, so I guess it isn't possible? I've added some of the stuff in as functions though, thanks for the information.
Bomb Bloke #4
Posted 09 September 2014 - 06:35 AM
It's not practical to divide a matrix, at least, not with another matrix. I mean, you can do it, but there are multiple (perhaps unlimited) possibilities as to the answer.
Lyqyd #5
Posted 09 September 2014 - 06:43 AM
I'm not a mathematician, as I may be about to make obvious, but if one were to perform a multiplication by an inverted matrix instead, would that be reasonable to describe as matrix division? I suspect not, but am not familiar enough with matrix operations myself to say either way.

Anyway, matrix division (if even a meaningful term) is obviously not something that occurs commonly enough (if at all) to be worthy of inclusion in an API.
hilburn #6
Posted 10 September 2014 - 05:21 PM
Matrices don't really have a direct equivalence to Division other than What Lyqyd suggested. However you have to remember the non-commutability of matrices. This means that unlike numbers where a*b=b*a, [A]*!=*[A]

So: on to division. The simple way to think about it is that any matrix can be represented as the product of 2 other matrices (even if one of those matrices is the index)

So [C]=[A]* where is defined as the matrix we want to "divide" by. We achieve this by post-multiplying (remember order is important) by the inverse of , ^(-1) to get

[C]*^(-1) = [A]**^(-1) = [A]

Where [A] is the matrix that when multiplied by , gives [C]. Which is pretty close, but not exactly, what the result of a division is.
Edited on 10 September 2014 - 03:21 PM