Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --todo
- --implement http://www.mathsisfun.com/algebra/matrix-inverse-minors-cofactors-adjugate.html in a matrix class
- --implement matrix multiplication in same class
- --implement points iterator
- --implement size function
- local function dot(v1,v2)
- print(#v1,#v2)
- local n=0
- for i,v in ipairs(v1) do
- n=n+v*v2[i]
- end
- return n
- end
- class "matrix"
- {
- __settings=
- {
- new=
- function(a,b,...)
- if type(a)=="number" and type(b)=="number" then
- local newmatrix={}
- local defaultval={...}
- defaultval=defaultval[1]
- for y=1,b do
- newmatrix[y]={}
- for x=1,a do
- newmatrix[y][x]=defaultval
- end
- end
- return {matrix=newmatrix}
- else
- local mat={}
- if not b then
- if type(a[1])=="table" then
- mat=a
- else
- mat={a}
- end
- else
- mat={a,b,...}
- end
- return {matrix=mat}
- end
- end,
- mt=
- {
- __call=
- function(self,x,y,v)
- if self.matrix[y] and self.matrix[y][x] then
- local val=self.matrix[y][x]
- if v then
- self.matrix[y][x]=v
- end
- return val
- end
- end,
- __tostring=
- function(self)
- local prevy=1
- local str="Matrix:\n"
- for x,y,v in self.points() do
- local attach=", "
- if x==1 and y==1 then attach="" end
- if y>prevy then
- prevy=y
- attach="\n"
- end
- str=str..attach..tostring(v)
- end
- return str
- end
- }
- },
- scalarmultiply=
- function(num)
- local result={}
- local X,Y=self.size()
- for y=1,Y do
- result[y]={}
- for x=1,X do
- result[y][x]=self(x,y)*num
- end
- end
- return matrix(result)
- end,
- matrixmultiply= --issue is here k
- function(other)
- local x1,y1=self.size()
- local x2,y2=other.size()
- if y1==x2 then --same inner dimensions
- local result=matrix(x1,y2,0) --outers
- for y=1,y2 do
- for x=1,x1 do
- local sum=0
- for i=1,x2 do
- local v=x
- if not other(v,i) then
- v=1
- end
- sum=sum+self(i,x)*(other(x,i) or other(1,i))
- end
- result(x,y,sum)
- end
- end
- return result
- else
- error("Inner dimensions must match in matrix multiplication!")
- end
- end,
- size=
- function()
- return #self.matrix,#self.matrix[1]
- end,
- points=
- function()
- local posY,posX=1,0
- return function()
- posX=posX+1
- if not self(posX,posY) then
- posY=posY+1
- if self.matrix[posY] then
- posX=1
- else
- return nil
- end
- end
- return posX,posY,self(posX,posY)
- end
- end,
- det=
- function()
- local sizex,sizey=self.size()
- if sizex==sizey and sizex==2 then
- return self(1,1)*self(2,2)-self(1,2)*self(2,1)
- end
- if sizex==sizey then
- local det=0
- for badX=1,sizex do
- local mat={}
- for y=1,sizey do
- if y~=1 then
- mat[y-1]={}
- for x=1,sizex do
- if x~=badX then
- mat[#mat][#mat[#mat]+1]=self(x,y)
- end
- end
- end
- end
- local newmat=matrix(mat)
- det=det+(badX%2==1 and -1 or 1)*newmat.det()*self(badX,1)
- end
- return det
- end
- end,
- inv=
- function()
- local SELFDET=self.det()
- local sizex,sizey=self.size()
- if SELFDET==0 then
- return "Cannot get inverse of this matrix - det 0"
- end
- if sizex==2 and sizey==2 then
- return matrix({self(2,2),-self(2,1)},{-self(1,2),self(1,1)})
- end
- if sizex==sizey then
- local minors={}
- for badY=1,sizey do
- minors[badY]={}
- for badX=1,sizex do
- local mat={}
- for y,row in pairs(self.matrix) do
- local clone={}
- for i,v in pairs(row) do
- clone[i]=v
- end
- table.remove(clone,badX)
- mat[#mat+1]=clone
- end
- table.remove(mat,badY)
- minors[badY][badX]=matrix(mat).det()
- end
- end
- for val=1,sizex do
- local odd=val%2==1
- local row=minors[val]
- for x,val in ipairs(row) do
- local odd2=x%2==1
- if odd and odd2 then
- row[x]=-val
- elseif not odd and not odd2 then
- row[x]=-val
- end
- end
- end
- local MINORSMAT=matrix(minors)
- for x,y,v in MINORSMAT.points() do
- if x>y then
- MINORSMAT(x,y,MINORSMAT(y,x,MINORSMAT(x,y)))
- end
- end
- return MINORSMAT.scalarmultiply(SELFDET^-1)
- end
- end
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement