Advertisement
LuaWeaver

Slightly buggy Matrix class for wOOP

May 4th, 2013
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 4.16 KB | None | 0 0
  1. --todo
  2. --implement http://www.mathsisfun.com/algebra/matrix-inverse-minors-cofactors-adjugate.html in a matrix class
  3. --implement matrix multiplication in same class
  4. --implement points iterator
  5. --implement size function
  6.  
  7. local function dot(v1,v2)
  8.     print(#v1,#v2)
  9.     local n=0
  10.     for i,v in ipairs(v1) do
  11.         n=n+v*v2[i]
  12.     end
  13.     return n
  14. end
  15.  
  16. class "matrix"
  17. {
  18.     __settings=
  19.     {
  20.         new=
  21.         function(a,b,...)
  22.             if type(a)=="number" and type(b)=="number" then
  23.                 local newmatrix={}
  24.                 local defaultval={...}
  25.                 defaultval=defaultval[1]
  26.                 for y=1,b do
  27.                     newmatrix[y]={}
  28.                     for x=1,a do
  29.                         newmatrix[y][x]=defaultval
  30.                     end
  31.                 end
  32.                 return {matrix=newmatrix}
  33.             else
  34.                 local mat={}
  35.                 if not b then
  36.                     if type(a[1])=="table" then
  37.                         mat=a
  38.                     else
  39.                         mat={a}
  40.                     end
  41.                 else
  42.                     mat={a,b,...}
  43.                 end
  44.                 return {matrix=mat}
  45.             end
  46.         end,
  47.         mt=
  48.         {
  49.             __call=
  50.             function(self,x,y,v)
  51.                 if self.matrix[y] and self.matrix[y][x] then
  52.                     local val=self.matrix[y][x]
  53.                     if v then
  54.                         self.matrix[y][x]=v
  55.                     end
  56.                     return val
  57.                 end
  58.             end,
  59.  
  60.             __tostring=
  61.             function(self)
  62.                 local prevy=1
  63.                 local str="Matrix:\n"
  64.                 for x,y,v in self.points() do
  65.                     local attach=", "
  66.                     if x==1 and y==1 then attach="" end
  67.                     if y>prevy then
  68.                         prevy=y
  69.                         attach="\n"
  70.                     end
  71.                     str=str..attach..tostring(v)
  72.                 end
  73.                 return str
  74.             end
  75.         }
  76.     },
  77.     scalarmultiply=
  78.     function(num)
  79.         local result={}
  80.         local X,Y=self.size()
  81.         for y=1,Y do
  82.             result[y]={}
  83.             for x=1,X do
  84.                 result[y][x]=self(x,y)*num
  85.             end
  86.         end
  87.         return matrix(result)
  88.     end,
  89.     matrixmultiply= --issue is here k
  90.     function(other)
  91.         local x1,y1=self.size()
  92.         local x2,y2=other.size()
  93.         if y1==x2 then --same inner dimensions
  94.             local result=matrix(x1,y2,0) --outers
  95.             for y=1,y2 do
  96.                 for x=1,x1 do
  97.                     local sum=0
  98.                     for i=1,x2 do
  99.                         local v=x
  100.                         if not other(v,i) then
  101.                             v=1
  102.                         end
  103.                         sum=sum+self(i,x)*(other(x,i) or other(1,i))
  104.                     end
  105.                     result(x,y,sum)
  106.                 end
  107.             end
  108.             return result
  109.         else
  110.             error("Inner dimensions must match in matrix multiplication!")
  111.         end
  112.     end,
  113.     size=
  114.     function()
  115.         return #self.matrix,#self.matrix[1]
  116.     end,
  117.     points=
  118.     function()
  119.         local posY,posX=1,0
  120.         return function()
  121.             posX=posX+1
  122.             if not self(posX,posY) then
  123.                 posY=posY+1
  124.                 if self.matrix[posY] then
  125.                     posX=1
  126.                 else
  127.                     return nil
  128.                 end
  129.             end
  130.             return posX,posY,self(posX,posY)
  131.         end
  132.     end,
  133.     det=
  134.     function()
  135.         local sizex,sizey=self.size()
  136.         if sizex==sizey and sizex==2 then
  137.             return self(1,1)*self(2,2)-self(1,2)*self(2,1)
  138.         end
  139.         if sizex==sizey then
  140.             local det=0
  141.  
  142.             for badX=1,sizex do
  143.                 local mat={}
  144.                 for y=1,sizey do
  145.                     if y~=1 then
  146.                         mat[y-1]={}
  147.                         for x=1,sizex do
  148.                             if x~=badX then
  149.                                 mat[#mat][#mat[#mat]+1]=self(x,y)
  150.                             end
  151.                         end
  152.                     end
  153.                 end
  154.                 local newmat=matrix(mat)
  155.                 det=det+(badX%2==1 and -1 or 1)*newmat.det()*self(badX,1)
  156.             end
  157.             return det
  158.         end
  159.     end,
  160.     inv=
  161.     function()
  162.         local SELFDET=self.det()
  163.         local sizex,sizey=self.size()
  164.         if SELFDET==0 then
  165.             return "Cannot get inverse of this matrix - det 0"
  166.         end
  167.         if sizex==2 and sizey==2 then
  168.             return matrix({self(2,2),-self(2,1)},{-self(1,2),self(1,1)})
  169.         end
  170.         if sizex==sizey then
  171.             local minors={}
  172.             for badY=1,sizey do
  173.                 minors[badY]={}
  174.                 for badX=1,sizex do
  175.                     local mat={}
  176.                     for y,row in pairs(self.matrix) do
  177.                         local clone={}
  178.                         for i,v in pairs(row) do
  179.                             clone[i]=v
  180.                         end
  181.                         table.remove(clone,badX)
  182.                         mat[#mat+1]=clone
  183.                     end
  184.                     table.remove(mat,badY)
  185.                     minors[badY][badX]=matrix(mat).det()
  186.                 end
  187.             end
  188.             for val=1,sizex do
  189.                 local odd=val%2==1
  190.                 local row=minors[val]
  191.                 for x,val in ipairs(row) do
  192.                     local odd2=x%2==1
  193.                     if odd and odd2 then
  194.                         row[x]=-val
  195.                     elseif not odd and not odd2 then
  196.                         row[x]=-val
  197.                     end
  198.                 end
  199.             end
  200.             local MINORSMAT=matrix(minors)
  201.             for x,y,v in MINORSMAT.points() do
  202.                 if x>y then
  203.                     MINORSMAT(x,y,MINORSMAT(y,x,MINORSMAT(x,y)))
  204.                 end
  205.             end
  206.             return MINORSMAT.scalarmultiply(SELFDET^-1)
  207.         end
  208.     end
  209. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement