Author Topic: Matrix Library  (Read 15771 times)

0 Members and 2 Guests are viewing this topic.

Offline 3rik

  • LV3 Member (Next: 100)
  • ***
  • Posts: 92
  • Rating: +8/-0
  • My TI-84+ SE
    • View Profile
Matrix Library
« on: June 22, 2012, 06:28:21 pm »
As the title implies, I'm planning on making a matrix library for Lua. I want it to be usable in computer Lua, too, so I don't want to use math.eval or other calculator dependent functions in this library. The math related aspect of this project can be found here.

Spoiler For fixed (I think):
My first roadblock is with being able to make the matrix itself.

I want the matrix to be unable to be edited without using the matrix functions. This can be accomplished using up-values, __index, and __newindex but I cant seem to figure out a good way to do this. I also want all the matrix functions to be available from the matrix.

Basically, I want it to be tamper-proof. I imagine it functioning like like this: (don't worry about the functions them selves)

Code: [Select]
matrix1 = matrix.new({{2, 3, 4}, {3, 4, 5}})
matrix2 = matrix.new({{1, 0, 5}, {2, 5, 9}})

matrix1:add(matrix2) == matrix.add(matrix1, matrix2) --true

matrix1[1] = {2} --error

matrix1[1][1] = 2 --no error

matrix1[1][1] = "2" --converts to number

matrix1[1][1] = true --error

table.maxn(matrix1) == 0 --true matrix1 doesn't actually contain any values, it forwards them to a local table in the matrix.new function

matrix1[1][300] = 2 --error wrong dimensions

If anyone has any suggestions, it would be very helpful.

Edit: I've attached a copy to the first post so people don't have to search through the topic for a copy.



Lua Matrix Library
Last Update: July 16, 2012, 03:03:56 pm
Version: 0.9.2
New Features: added lu, trace, det, ref, rref, and rank

« Last Edit: July 16, 2012, 03:04:14 pm by 3rik »
Userbars

Offline Levak

  • LV9 Veteran (Next: 1337)
  • *********
  • Posts: 1002
  • Rating: +208/-39
    • View Profile
    • My website
Re: Matrix Library
« Reply #1 on: June 22, 2012, 08:43:16 pm »
In Nspire Lua, it is exactly the goal of the class() function. But as you want it to be also usuable in standard Lua, I guess you should look at this

But ... there is another problem.

In Lua, everything is tables .. and most likely I'm interested in the way someone will handle call errors on elements likes the one you describe. IMHO it is impossible the way you want the errors to be handled.

Also, Lua is multitype, so this :
Code: [Select]
matrix1[1][1] = "2" --converts to number

matrix1[1][1] = true --error
will be possible only with direct calls to functions. The way you want it to be is not possible in Lua, same in many languages.... but I can be wrong.

matrix1[1][1] will be possible with something like this :

matrix1 = {{1, 2, 3}, {4, 5, 6}, ["add"]=function(self, m2) end}
I do not get mad at people, I just want them to learn the way I learnt.
My website - TI-Planet - iNspired-Lua

Offline 3rik

  • LV3 Member (Next: 100)
  • ***
  • Posts: 92
  • Rating: +8/-0
  • My TI-84+ SE
    • View Profile
Re: Matrix Library
« Reply #2 on: June 22, 2012, 08:46:26 pm »
matrix1 = {{1, 2, 3}, {4, 5, 6}, ["add"]=function(self, m2) end}
what about
Code: [Select]
setmetatable(matrix1, {__index=matrix})?
I think it can be done but I'm just not sure how to organize it.
« Last Edit: June 22, 2012, 08:49:33 pm by 3rik »
Userbars

Offline Levak

  • LV9 Veteran (Next: 1337)
  • *********
  • Posts: 1002
  • Rating: +208/-39
    • View Profile
    • My website
Re: Matrix Library
« Reply #3 on: June 22, 2012, 09:10:44 pm »
getmetatable(matrix), but yes, it was just to show the content of matrix1.
matrix.new is the function described in the link I gave you.
I do not get mad at people, I just want them to learn the way I learnt.
My website - TI-Planet - iNspired-Lua

Offline 3rik

  • LV3 Member (Next: 100)
  • ***
  • Posts: 92
  • Rating: +8/-0
  • My TI-84+ SE
    • View Profile
Re: Matrix Library
« Reply #4 on: June 22, 2012, 09:30:40 pm »
here is an example of what I was trying to say:
Code: [Select]
matrix = {}
matrix.new = function(data)
local mat={}
setmetatable(mat, {__index = function(tbl, nobbc)
return data[nobbc]
end
})
return mat
end
matrix1 = matrix.new({{4}})
matrix2 = matrix.new({{7}})
print(matrix1[1][1], matrix2[1][1], mat, data) --prints 4 7 nil nil
nobbc was supposed to be key but I was having issues

This is an insecure example, but it works
« Last Edit: June 22, 2012, 09:53:30 pm by 3rik »
Userbars

Offline Jim Bauwens

  • Lua! Nspire! Linux!
  • Editor
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1881
  • Rating: +206/-7
  • Linux!
    • View Profile
    • nothing...
Re: Matrix Library
« Reply #5 on: June 23, 2012, 12:17:42 pm »
Here is the class function (although slightly modified):
Code: [Select]
class = function(prototype)
local derived={}

  if prototype then
derived.__proto = prototype
  function derived.__index(t,key)
  return rawget(derived,key) or prototype[nobbc]
  end
  else
  function derived.__index(t,key)
  return rawget(derived,key)
  end
  end
 
  function derived.__call(proto,...)
  local instance={}
  setmetatable(instance,proto)
  instance.__obj = true
  local init=instance.init
  if init then
  init(instance,...)
  end
  return instance
  end
 
  setmetatable(derived,derived)
  return derived
end

I think you want something like this:

Code: [Select]
Matrix = class()

function Matrix:init(mat)
    self.matrix = mat
end

function Matrix:set(x, y, n)
    self.matrix[y][x] = n
end


matrix1 = Matrix{{1,2,3},{1,2,3},{1,2,3}}
matrix2 = Matrix{{1,2,3},{1,2,3}}

matrix1:set(1,1,3)

matrix1 and matrix2 are not connected in anyway. You can expand the matrix class to your wishes.
Also, with metatables/-methods you could even make that matrix3=matrix1+matrix2 is possible :)
« Last Edit: June 23, 2012, 12:17:56 pm by jimbauwens »

Offline 3rik

  • LV3 Member (Next: 100)
  • ***
  • Posts: 92
  • Rating: +8/-0
  • My TI-84+ SE
    • View Profile
Re: Matrix Library
« Reply #6 on: June 23, 2012, 12:35:00 pm »
It's just that I don't want the data to be directly accessible to the programmer. I also want zeros to be stored as nils but when they're indexed, they return a 0. This is my version. It's still a work in progress.

I'm having issues with [ key ] turning into [nobbc] so I attached the file instead.
Userbars

Offline Jim Bauwens

  • Lua! Nspire! Linux!
  • Editor
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1881
  • Rating: +206/-7
  • Linux!
    • View Profile
    • nothing...
Re: Matrix Library
« Reply #7 on: June 23, 2012, 12:48:21 pm »
If you don't want users to have direct write access to the table, you can use something like this:

Code: [Select]

function createProxy(tbl)
local mt = {}
local proxy = {}
mt.__index = function (_, key)
return tbl[ key]
end

mt.__newindex = function ()
print("You are not allowed to write to this table!")
end
setmetatable(proxy, mt)
return proxy
end


a = createProxy{1,2,3,4,5}

print(a[2])
a[2] = 3

I'm taking a look at your code.

Edit: ouch, the forum is changing table keys to nobbc
Edit2: Okay, I think class you be something for you. You should be able to protect your variables enough.
« Last Edit: June 23, 2012, 12:55:32 pm by jimbauwens »

Offline 3rik

  • LV3 Member (Next: 100)
  • ***
  • Posts: 92
  • Rating: +8/-0
  • My TI-84+ SE
    • View Profile
Re: Matrix Library
« Reply #8 on: June 23, 2012, 01:15:00 pm »
It's just that the matrix is a bunch of tables inside a table. Since the tables are passed by reference they could be altered using class(). Another tricky part is that when assigning to a spot in the matrix like
Code: [Select]
A[1][2] = 6
the A[1] is found by __index not __newindex so it is like
Code: [Select]
B = A[1]
B[2] = 6
--or
(A[1])[2] = 6
the reference to A[1] is assigned to B and then B[2] is assigned 6. This means __index and __newindex have to work together to allow assignment but control what can be assigned where while protecting the reference to the actual data.
« Last Edit: June 23, 2012, 01:16:29 pm by 3rik »
Userbars

Offline Jim Bauwens

  • Lua! Nspire! Linux!
  • Editor
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1881
  • Rating: +206/-7
  • Linux!
    • View Profile
    • nothing...
Re: Matrix Library
« Reply #9 on: June 23, 2012, 04:06:12 pm »
Well, here is almost the same for a matrix:

Code: [Select]
function createProxy(tbl)


local mt = {}
local proxy = {}
mt.__index = function (t, key)
local rownumber = rawget(t, "rownumber")
if rownumber then
return tbl[ rownumber][ key]
else
return tbl[ key]
end
end

mt.__newindex = function ()
print("You are not allowed to write to this table!")
end

for key, row in ipairs(tbl) do
proxy[ key] = {}
proxy[ key].rownumber = key
setmetatable(proxy[ key], mt)
end

setmetatable(proxy, mt)

return proxy
end


a = createProxy{{5,4,3,2,1},{3,6,9,1}}

print(a[ 2][ 3])
a[ 2][ 3] = 3
print(a[ 2][ 3])
« Last Edit: June 23, 2012, 04:07:00 pm by jimbauwens »

Offline 3rik

  • LV3 Member (Next: 100)
  • ***
  • Posts: 92
  • Rating: +8/-0
  • My TI-84+ SE
    • View Profile
Re: Matrix Library
« Reply #10 on: June 23, 2012, 04:20:29 pm »
One issue with this kind of matrix is that it allows a whole row to be assigned at one time without being checked if all the values are numbers or nils. I also want to still be able to assign to the matrix, just not directly. Also I would like to make all zeros be nils in the matrix. It allows large spaece matrices to be stored without taking up a massive amount of space.
Code: [Select]
a = matrix.new({[10000] = { [100000] = 8}})
a[2][3] = 6
print(a[2][3]+a[250][44]+a[10000][100000]) --prints 14
« Last Edit: June 23, 2012, 04:23:58 pm by 3rik »
Userbars

Offline Jim Bauwens

  • Lua! Nspire! Linux!
  • Editor
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1881
  • Rating: +206/-7
  • Linux!
    • View Profile
    • nothing...
Re: Matrix Library
« Reply #11 on: June 23, 2012, 04:24:08 pm »
It should not allow it. You can modify __newindex so to parse the input and possible modify it.
The above code is just the concept, you can build on it and make it do what you want.

Edit: wait, it does. Let me fix it
« Last Edit: June 23, 2012, 04:25:18 pm by jimbauwens »

Offline 3rik

  • LV3 Member (Next: 100)
  • ***
  • Posts: 92
  • Rating: +8/-0
  • My TI-84+ SE
    • View Profile
Re: Matrix Library
« Reply #12 on: June 23, 2012, 04:30:20 pm »
I think this is getting closer to what I came up with. It's just that my code is so inflated.
btw thanks for all the help you're offering.  :)
Userbars

Offline Jim Bauwens

  • Lua! Nspire! Linux!
  • Editor
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1881
  • Rating: +206/-7
  • Linux!
    • View Profile
    • nothing...
Re: Matrix Library
« Reply #13 on: June 23, 2012, 04:35:56 pm »
Okay, I guess you just need to modify some things to get it working.
However, why don't you just make the matrix local to your functions, so only your functions can access it ?
That way you could have matrix.getValue and matrix.setValue. Matrix[ y][ x] would not work. That way you don't need to deal with lot's of stuff.
« Last Edit: June 23, 2012, 04:36:05 pm by jimbauwens »

Offline 3rik

  • LV3 Member (Next: 100)
  • ***
  • Posts: 92
  • Rating: +8/-0
  • My TI-84+ SE
    • View Profile
Re: Matrix Library
« Reply #14 on: June 23, 2012, 04:39:01 pm »
I was considering that. If this is too much to manage, I'll probably just switch to that plan.
Userbars