PtokaX forum

Development Section => HOW-TO's => Topic started by: chill on 23 December, 2004, 00:06:14

Title: Metatables
Post by: chill on 23 December, 2004, 00:06:14
here we go a exsample of how to use
metatables,
to get your objetcts to do what you want them to do
on * - + and so on

written in LUA 5.0

--////////////////--
-- MATRIX HANDLER --
--////////////////--


function Main()

print( "Creating a Matrix ( 6, 3 ) and draw it")

print( "m1 = Matrix:Create( 6, 3 )")
m1 = Matrix:Create( 6, 3 )

print( "m1:draw()" )
m1:draw()

print( "Fill it random with numbers" )
print( "m1:fillrandom(1,5)" )
m1:fillrandom(1,5)

m1:draw()

print( "Set a ceratain value" )
print( "m1:setValue( 1, 1, 50 )" )

m1:setValue( 1, 1, 50 )
m1:draw()

print( "Transpose the matrix" )
print( "m1:transpose()" )
m1:transpose()
m1:draw()

print( "create a transposed matrix with values of m1" )
print( "Remeber to we transposed the matrix so now it 3 to 6 ")
print( "m2 = Matrix:Create( 3, 6, m1:getM() )")
m2 = Matrix:Create( 3, 6, m1:getM() )

print( "m3 = m2^T or even m2^-1")
m3 = m2^T

print("m2:draw()")
m2:draw()
print("m3:draw()")
m3:draw()

print("Create 2 4 x 4 matrixes,  m5 and m6 ")

m5 = Matrix:Create( 4, 4 )
m6 = Matrix:Create( 4, 4 )

m5:fillrandom(1,5)
m6:fillrandom(1,5)

print("m5:draw()")
m5:draw()
print("m6:draw()")
m6:draw()

print(" m7 = m5 + m6 ")
m7 = m5 + m6
m7:draw()

print(" m7 = m5 * m6 ")
m7 = m5 * m6
m7:draw()

print(" m7 = 5 * m6" )
m7 = 5 * m6
m7:draw()
end


-- Handler
Matrix = {}

function Matrix:Create( lines, columns, tvalues )

lines = lines or 2
columns = columns or 2

local mt = {}

-- create fields
mt._val = {}
for i = 1,lines do
mt._val[i] = {}
for i2 = 1,columns do
if tvalues then
mt._val[i][i2] = tvalues[i][i2]
else
mt._val[i][i2] = 0
end
end
end

-- geometrie
mt._lines = lines
mt._columns = columns


-- functions
function mt:setValue( line, column, value )
value = tonumber(value) or 0
if self._val[line][column] then
self._val[line][column] = value
end
end

function mt:getValue( line, column )
if self._val[line][column] then
return self._val[line][column]
end
end

function mt:getM()
return mt._val
end

function mt:set( mt1 )
for i = 1,self._lines do
for i2 = 1,self._columns do
mt._val[i][i2] =  mt1._val[i][i2]
end
end
end

function mt:draw()
local mstr = "\n"
for i = 1,self._lines do
for i2 = 1,self._columns do
mstr = mstr.."\t"..self._val[i][i2]
end
mstr = mstr.."\n"
end
print(mstr)
end

function mt:fillrandom( num1, num2 )
num1 = num1 or 0
num2 = num2 or 100
for i = 1,self._lines do
for i2 = 1,self._columns do
local ran = math.random( num1, num2 )
mt._val[i][i2] =  ran
end
end
end

function mt:mulskalar( num )
local num = tonumber(num) or 1
for i = 1,self._lines do
for i2 = 1,self._columns do
mt._val[i][i2] = mt._val[i][i2] * num
end
end
end

function mt:transpose()
local mtrans = {}
local columns = self._columns
local lines = self._lines
for i2 = 1,self._columns do
mtrans[i2] = {}
for i = 1,self._lines do
mtrans[i2][i] = mt._val[i][i2]
end
end
mt._val = mtrans
self._lines = columns
self._columns = lines
end

setmetatable( mt, Matrix_mt )

return mt
end




Matrix_mt = {

-- add ( + )
__add = function( a, b )

if (a._lines ~= b._lines) then
error("Cannot add ( 'M1' lines: "..a._lines.." ~= 'M2' lines: "..b._lines..")", 2)
return
end
if (a._columns ~= b._columns) then
error("Cannot add ( 'M1' columns: "..a._columns.." ~= 'M2' columns: "..b._columns..")", 2)
return
end

local lines = a._lines
local columns = a._columns

-- create new matrix of same size
mt = Matrix:Create( lines, columns )

-- add a + b
for i = 1,lines do
for i2 = 1,columns do
mt._val[i][i2] = a._val[i][i2] + b._val[i][i2]
end
end

return mt
end,

-- sub ( - )
__sub = function( a, b )


if (a._lines ~= b._lines) then
error("Cannot substitue ( 'M1' lines: "..a._lines.." ~= 'M2' lines: "..b._lines..")", 2)
return
end
if (a._columns ~= b._columns) then
error("Cannot substitue ( 'M1' columns: "..a._columns.." ~= 'M2' columns: "..b._columns..")", 2)
return
end

local lines = a._lines
local columns = a._columns

-- create new matrix of same size
mt = Matrix:Create( lines, columns )

-- add a + b
for i = 1,lines do
for i2 = 1,columns do
mt._val[i][i2] = a._val[i][i2] - b._val[i][i2]
end
end

return mt
end,

-- mul ( * )
__mul = function( a, b )

if (type(a) == "number") then

local lines = b._lines
local columns = b._columns

-- create new matrix of same size
mt = Matrix:Create( lines, columns, b:getM() )

mt:mulskalar( a )

return mt

elseif (type(b) == "number") then

local lines = a._lines
local columns = a._columns

-- create new matrix of same size
mt = Matrix:Create( lines, columns, a:getM() )

mt:mulskalar( b )

return mt
end


if (a._columns ~= b._lines) then
error("Cannot multiply ( 'M1' columns: "..a._columns.." ~= 'M2' lines: "..b._lines..")", 2)
return
end

if (a._columns ~= b._columns) then
error("Cannot multiply ( 'M1' columns: "..a._columns.." ~= 'M2' columns: "..b._columns..")", 2)
return
end


local lines = a._lines
local columns = a._columns

-- create new matrix of same size
mt = Matrix:Create( lines, columns )

-- mul a * b
for col = 1,columns do
for lin = 1,lines do
local v = 0
for i3 = 1,columns do
v = v + ( a._val[lin][i3] *  b._val[i3][col] )
end
mt._val[lin][col] = v
end
end

return mt
end,

-- pow  will only Transponse the Matrix

__pow = function( m , sp )

local lines = m._lines
local columns = m._columns

-- create new matrix of same size
mt = Matrix:Create( lines, columns, m:getM() )

mt:transpose()

return mt
end,

}

Main()