import version 0.2.9, 2008-08-26
- decoupled symbol class from matrix class: - matrix.replace has new semantics, applying a function to each element. For old behavior: mtx = mtx:replace(matrix.symbol.makereplacer(...)) - replaced mtx:gsub(a,b) with mtx = mtx:replace(symbol.gsub,a,b) - replaced matrix.tosymbol(mtx) with mtx = mtx:replace(symbol) - eliminated dependency on complex: - replaced matrix.tocomplex(mtx) with mtx = mtx:replace(complex) - replaced matrix.conjugate(mtx) with mtx = mtx:replace(complex.conjugate) - mulnum and divnum no longer can take num of type string - complex table no longer returned on module load - renamed remcomplex to elementstostrings and changed it to return new matrix rather than doing in-place modification - fixed matrix.numround (numround variable mispelled). Reported by Goeff Richards.master
parent
67f724300f
commit
fe6837f6dc
|
@ -0,0 +1,35 @@
|
|||
LuaMatrix License
|
||||
-----------
|
||||
|
||||
LuaMatrix ( http://luamatrix.luaforge.net/ ) is licensed under the
|
||||
same terms as Lua (MIT license) reproduced below. This means that
|
||||
LuaMatrix is free software and can be used for both academic and
|
||||
commercial purposes at absolutely no cost.
|
||||
|
||||
For details and rationale, see http://www.lua.org/license.html .
|
||||
|
||||
===============================================================================
|
||||
|
||||
Copyright (C) 2007-2010 Michael Lutz.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
===============================================================================
|
||||
|
||||
(end of COPYRIGHT)
|
|
@ -0,0 +1,22 @@
|
|||
== Description ==
|
||||
|
||||
LuaMatrix - Matrices and matrix operations implemented in pure Lua.
|
||||
|
||||
This supports operations on matrices and vectors whose elements are
|
||||
real, complex, or symbolic. Implemented entirely in Lua as tables.
|
||||
Includes a complex number data type too.
|
||||
|
||||
For details on use, see the comments in matrix.lua and complex.lua,
|
||||
as well as the test suite.
|
||||
|
||||
To install, copy matrix.lua and complex.lua into your LUA_PATH. The
|
||||
modules can alternately be installed via LuaRocks ("luarocks install
|
||||
luamatrix").
|
||||
|
||||
== Project Page ==
|
||||
|
||||
http://lua-users.org/wiki/LuaMatrix
|
||||
|
||||
== License ==
|
||||
|
||||
See the LICENSE.txt file for licensing details.
|
|
@ -1,5 +1,8 @@
|
|||
complex changelog
|
||||
|
||||
complex changelog:
|
||||
v 0.3.1: 2007-11-12
|
||||
[ David Manura ]
|
||||
rename mulconjugate to norm2
|
||||
|
||||
v 0.3.0: 2007-08-26
|
||||
- fixed print function
|
|
@ -1,49 +1,21 @@
|
|||
matrix function list:
|
||||
matrix changelog
|
||||
|
||||
matrix.add
|
||||
matrix.columns
|
||||
matrix.concath
|
||||
matrix.concatv
|
||||
matrix.conjugate
|
||||
matrix.copy
|
||||
matrix.cross
|
||||
matrix.det
|
||||
matrix.div
|
||||
matrix.divnum
|
||||
matrix.dogauss
|
||||
matrix.getelement
|
||||
matrix.gsub
|
||||
matrix.invert
|
||||
matrix.ipairs
|
||||
matrix.latex
|
||||
matrix.len
|
||||
matrix.mul
|
||||
matrix.mulnum
|
||||
matrix:new
|
||||
matrix.normf
|
||||
matrix.normmax
|
||||
matrix.pow
|
||||
matrix.print
|
||||
matrix.random
|
||||
matrix.remcomplex
|
||||
matrix.replace
|
||||
matrix.root
|
||||
matrix.rotl
|
||||
matrix.rotr
|
||||
matrix.round
|
||||
matrix.rows
|
||||
matrix.scalar
|
||||
matrix.setelement
|
||||
matrix.size
|
||||
matrix.solve
|
||||
matrix.sqrt
|
||||
matrix.sub
|
||||
matrix.subm
|
||||
matrix.tocomplex
|
||||
matrix.tostring
|
||||
matrix.tosymbol
|
||||
matrix.transpose
|
||||
matrix.type
|
||||
v 0.2.9: 2008-08-26
|
||||
[ David Manura ]
|
||||
- decoupled symbol class from matrix class:
|
||||
- matrix.replace has new semantics, applying a function to each element.
|
||||
For old behavior: mtx = mtx:replace(matrix.symbol.makereplacer(...))
|
||||
- replaced mtx:gsub(a,b) with mtx = mtx:replace(symbol.gsub,a,b)
|
||||
- replaced matrix.tosymbol(mtx) with mtx = mtx:replace(symbol)
|
||||
- eliminated dependency on complex:
|
||||
- replaced matrix.tocomplex(mtx) with mtx = mtx:replace(complex)
|
||||
- replaced matrix.conjugate(mtx) with mtx = mtx:replace(complex.conjugate)
|
||||
- mulnum and divnum no longer can take num of type string
|
||||
- complex table no longer returned on module load
|
||||
- renamed remcomplex to elementstostrings and changed it to return new
|
||||
matrix rather than doing in-place modification
|
||||
- Fixed matrix.numround (numround variable mispelled).
|
||||
Reported by Goeff Richards.
|
||||
|
||||
v 0.2.8: 2007-08-26
|
||||
[ Michael Lutz ]
|
|
@ -1,4 +1,4 @@
|
|||
-- complex 0.3.0
|
||||
-- complex 0.3.1
|
||||
-- Lua 5.1
|
||||
|
||||
-- 'complex' provides common tasks with complex numbers
|
||||
|
@ -15,8 +15,7 @@
|
|||
-- the access is faster than in a hash table
|
||||
-- the metatable is just a add on, when it comes to speed, one is faster using a direct function call
|
||||
|
||||
-- http://luaforge.net/projects/LuaMatrix
|
||||
-- http://lua-users.org/wiki/ComplexNumbers
|
||||
-- http://luamatrix.luaforge.net
|
||||
|
||||
-- Licensed under the same terms as Lua itself.
|
||||
|
||||
|
@ -191,9 +190,10 @@ function complex.polardeg( cx )
|
|||
return math.sqrt( cx[1]^2 + cx[2]^2 ), math.atan2( cx[2], cx[1] ) / math.pi * 180
|
||||
end
|
||||
|
||||
-- complex.mulconjugate( cx )
|
||||
-- multiply with conjugate, function returning a number
|
||||
function complex.mulconjugate( cx )
|
||||
-- complex.norm2( cx )
|
||||
-- multiply with conjugate, function returning a scalar number
|
||||
-- norm2(x + i*y) returns x^2 + y^2
|
||||
function complex.norm2( cx )
|
||||
return cx[1]^2 + cx[2]^2
|
||||
end
|
||||
|
||||
|
@ -330,6 +330,10 @@ function complex.round( cx,idp )
|
|||
math.floor( cx[2] * mult + 0.5 ) / mult }, complex_meta )
|
||||
end
|
||||
|
||||
--// variables
|
||||
complex.zero = complex.new(0, 0)
|
||||
complex.one = complex.new(1, 0)
|
||||
|
||||
--// metatable functions
|
||||
|
||||
complex_meta.__add = function( cx1,cx2 )
|
|
@ -1,5 +1,5 @@
|
|||
--[[
|
||||
matrix v 0.2.8
|
||||
matrix v 0.2.9
|
||||
|
||||
Lua 5.1 compatible
|
||||
|
||||
|
@ -30,10 +30,53 @@
|
|||
where num will be a matrix with the result in mtx[1][1],
|
||||
or use num = vec1:scalar( vec2 ), where num is a number
|
||||
|
||||
Sites:
|
||||
http://luaforge.net/projects/LuaMatrix
|
||||
http://lua-users.org/wiki/SimpleMatrix
|
||||
|
||||
Site: http://luamatrix.luaforge.net
|
||||
|
||||
matrix function list:
|
||||
|
||||
matrix.add
|
||||
matrix.columns
|
||||
matrix.concath
|
||||
matrix.concatv
|
||||
matrix.copy
|
||||
matrix.cross
|
||||
matrix.det
|
||||
matrix.div
|
||||
matrix.divnum
|
||||
matrix.dogauss
|
||||
matrix.elementstostring
|
||||
matrix.getelement
|
||||
matrix.gsub
|
||||
matrix.invert
|
||||
matrix.ipairs
|
||||
matrix.latex
|
||||
matrix.len
|
||||
matrix.mul
|
||||
matrix.mulnum
|
||||
matrix:new
|
||||
matrix.normf
|
||||
matrix.normmax
|
||||
matrix.pow
|
||||
matrix.print
|
||||
matrix.random
|
||||
matrix.replace
|
||||
matrix.root
|
||||
matrix.rotl
|
||||
matrix.rotr
|
||||
matrix.round
|
||||
matrix.rows
|
||||
matrix.scalar
|
||||
matrix.setelement
|
||||
matrix.size
|
||||
matrix.solve
|
||||
matrix.sqrt
|
||||
matrix.sub
|
||||
matrix.subm
|
||||
matrix.tostring
|
||||
matrix.transpose
|
||||
matrix.type
|
||||
|
||||
|
||||
Licensed under the same terms as Lua itself.
|
||||
|
||||
Developers:
|
||||
|
@ -41,10 +84,6 @@
|
|||
David Manura http://lua-users.org/wiki/DavidManura
|
||||
]]--
|
||||
|
||||
-- for speed and clearer code load the complex function table
|
||||
-- in there we define the complex number
|
||||
local complex = require "complex"
|
||||
|
||||
--////////////
|
||||
--// matrix //
|
||||
--////////////
|
||||
|
@ -54,13 +93,6 @@ local matrix = {}
|
|||
-- access to the metatable we set at the end of the file
|
||||
local matrix_meta = {}
|
||||
|
||||
-- access to the symbolic metatable
|
||||
local symbol_meta = {}; symbol_meta.__index = symbol_meta
|
||||
-- set up a symbol type
|
||||
local function newsymbol(o)
|
||||
return setmetatable({tostring(o)}, symbol_meta)
|
||||
end
|
||||
|
||||
--/////////////////////////////
|
||||
--// Get 'new' matrix object //
|
||||
--/////////////////////////////
|
||||
|
@ -124,7 +156,7 @@ setmetatable( matrix, { __call = function( ... ) return matrix.new( ... ) end }
|
|||
--// matrix 'matrix' functions //
|
||||
--///////////////////////////////
|
||||
|
||||
--// for real, complx and symbolic matrices //--
|
||||
--// for real, complex and symbolic matrices //--
|
||||
|
||||
-- note: real and complex matrices may be added, subtracted, etc.
|
||||
-- real and symbolic matrices may also be added, subtracted, etc.
|
||||
|
@ -132,33 +164,35 @@ setmetatable( matrix, { __call = function( ... ) return matrix.new( ... ) end }
|
|||
-- since it is not clear which metatable then is used
|
||||
|
||||
--// matrix.add ( m1, m2 )
|
||||
-- Add 2 matrices; m2 may be of bigger size than m1
|
||||
-- Add two matrices; m2 may be of bigger size than m1
|
||||
function matrix.add( m1, m2 )
|
||||
local mtx = {}
|
||||
for i = 1,#m1 do
|
||||
mtx[i] = {}
|
||||
local m3i = {}
|
||||
mtx[i] = m3i
|
||||
for j = 1,#m1[1] do
|
||||
mtx[i][j] = m1[i][j] + m2[i][j]
|
||||
m3i[j] = m1[i][j] + m2[i][j]
|
||||
end
|
||||
end
|
||||
return setmetatable( mtx, matrix_meta )
|
||||
end
|
||||
|
||||
--// matrix.sub ( m1 ,m2 )
|
||||
-- Subtract 2 matrices; m2 may be of bigger size than m1
|
||||
-- Subtract two matrices; m2 may be of bigger size than m1
|
||||
function matrix.sub( m1, m2 )
|
||||
local mtx = {}
|
||||
for i = 1,#m1 do
|
||||
mtx[i] = {}
|
||||
local m3i = {}
|
||||
mtx[i] = m3i
|
||||
for j = 1,#m1[1] do
|
||||
mtx[i][j] = m1[i][j] - m2[i][j]
|
||||
m3i[j] = m1[i][j] - m2[i][j]
|
||||
end
|
||||
end
|
||||
return setmetatable( mtx, matrix_meta )
|
||||
end
|
||||
|
||||
--// matrix.mul ( m1, m2 )
|
||||
-- Multiply 2 matrices; m1 columns must be equal to m2 rows
|
||||
-- Multiply two matrices; m1 columns must be equal to m2 rows
|
||||
-- e.g. #m1[1] == #m2
|
||||
function matrix.mul( m1, m2 )
|
||||
-- multiply rows with columns
|
||||
|
@ -177,7 +211,7 @@ function matrix.mul( m1, m2 )
|
|||
end
|
||||
|
||||
--// matrix.div ( m1, m2 )
|
||||
-- Divide 2 matrices; m1 columns must be equal to m2 rows
|
||||
-- Divide two matrices; m1 columns must be equal to m2 rows
|
||||
-- m2 must be square, to be inverted,
|
||||
-- if that fails returns the rank of m2 as second argument
|
||||
-- e.g. #m1[1] == #m2; #m2 == #m2[1]
|
||||
|
@ -189,12 +223,9 @@ end
|
|||
|
||||
--// matrix.mulnum ( m1, num )
|
||||
-- Multiply matrix with a number
|
||||
-- num may be of type 'number','complex number' or 'string'
|
||||
-- num may be of type 'number' or 'complex number'
|
||||
-- strings get converted to complex number, if that fails then to symbol
|
||||
function matrix.mulnum( m1, num )
|
||||
if type(num) == "string" then
|
||||
num = complex.to(num) or newsymbol(num)
|
||||
end
|
||||
local mtx = {}
|
||||
-- multiply elements with number
|
||||
for i = 1,#m1 do
|
||||
|
@ -208,18 +239,16 @@ end
|
|||
|
||||
--// matrix.divnum ( m1, num )
|
||||
-- Divide matrix by a number
|
||||
-- num may be of type 'number','complex number' or 'string'
|
||||
-- num may be of type 'number' or 'complex number'
|
||||
-- strings get converted to complex number, if that fails then to symbol
|
||||
function matrix.divnum( m1, num )
|
||||
if type(num) == "string" then
|
||||
num = complex.to(num) or newsymbol(num)
|
||||
end
|
||||
local mtx = {}
|
||||
-- divide elements by number
|
||||
for i = 1,#m1 do
|
||||
mtx[i] = {}
|
||||
local mtxi = {}
|
||||
mtx[i] = mtxi
|
||||
for j = 1,#m1[1] do
|
||||
mtx[i][j] = m1[i][j] / num
|
||||
mtxi[j] = m1[i][j] / num
|
||||
end
|
||||
end
|
||||
return setmetatable( mtx, matrix_meta )
|
||||
|
@ -251,6 +280,10 @@ function matrix.pow( m1, num )
|
|||
return mtx
|
||||
end
|
||||
|
||||
local function number_norm2(x)
|
||||
return x * x
|
||||
end
|
||||
|
||||
--// matrix.det ( m1 )
|
||||
-- Calculate the determinant of a matrix
|
||||
-- m1 needs to be square
|
||||
|
@ -261,8 +294,6 @@ end
|
|||
-- here we try to get the nearest element to |1|, (smallest pivot element)
|
||||
-- os that usually we have |mtx[i][j]/subdet| > 1 or mtx[i][j];
|
||||
-- with complex matrices we use the complex.abs function to check if it is bigger or smaller
|
||||
local fiszerocomplex = function( cx ) return complex.is(cx,0,0) end
|
||||
local fiszeronumber = function( num ) return num == 0 end
|
||||
function matrix.det( m1 )
|
||||
|
||||
-- check if matrix is quadratic
|
||||
|
@ -284,16 +315,10 @@ function matrix.det( m1 )
|
|||
end
|
||||
|
||||
--// no symbolic matrix supported below here
|
||||
|
||||
local fiszero, abs
|
||||
if matrix.type( m1 ) == "complex" then
|
||||
fiszero = fiszerocomplex
|
||||
abs = complex.mulconjugate
|
||||
else
|
||||
fiszero = fiszeronumber
|
||||
abs = math.abs
|
||||
end
|
||||
|
||||
local e = m1[1][1]
|
||||
local zero = type(e) == "table" and e.zero or 0
|
||||
local norm2 = type(e) == "table" and e.norm2 or number_norm2
|
||||
|
||||
--// matrix is bigger than 3x3
|
||||
-- get determinant
|
||||
-- using Gauss elimination and Laplace
|
||||
|
@ -313,12 +338,12 @@ function matrix.det( m1 )
|
|||
-- if no subdet has been found
|
||||
if not subdet then
|
||||
-- check if element it is not zero
|
||||
if not fiszero(e) then
|
||||
if e ~= zero then
|
||||
-- use element as new subdet
|
||||
subdet,xrow = e,i
|
||||
end
|
||||
-- check for elements nearest to 1 or -1
|
||||
elseif (not fiszero(e)) and math.abs(abs(e)-1) < math.abs(abs(subdet)-1) then
|
||||
elseif e ~= zero and math.abs(norm2(e)-1) < math.abs(norm2(subdet)-1) then
|
||||
subdet,xrow = e,i
|
||||
end
|
||||
end
|
||||
|
@ -335,7 +360,7 @@ function matrix.det( m1 )
|
|||
for i = 1,rows-1 do
|
||||
-- factor is the dividor of the first element
|
||||
-- if element is not already zero
|
||||
if not fiszero( mtx[i][j] ) then
|
||||
if mtx[i][j] ~= zero then
|
||||
local factor = mtx[i][j]/subdet
|
||||
-- update all remaining fields of the matrix, with value from xrow
|
||||
for n = j+1,#mtx[1] do
|
||||
|
@ -366,23 +391,23 @@ end
|
|||
|
||||
-- locals
|
||||
-- checking here for the nearest element to 1 or -1; (smallest pivot element)
|
||||
-- this way the factor of the evolving number division should be > 1 or the divided number itself,
|
||||
-- what gives better results
|
||||
local setelementtosmallest = function( mtx,i,j,fiszero,fisone,abs )
|
||||
-- this way the factor of the evolving number division should be > 1 or the
|
||||
-- divided number itself, what gives better results
|
||||
local setelementtosmallest = function( mtx,i,j,zero,one,norm2 )
|
||||
-- check if element is one
|
||||
if fisone(mtx[i][j]) then return true end
|
||||
if mtx[i][j] == one then return true end
|
||||
-- check for lowest value
|
||||
local _ilow
|
||||
for _i = i,#mtx do
|
||||
local e = mtx[_i][j]
|
||||
if fisone(e) then
|
||||
if e == one then
|
||||
break
|
||||
end
|
||||
if not _ilow then
|
||||
if not fiszero(e) then
|
||||
if e ~= zero then
|
||||
_ilow = _i
|
||||
end
|
||||
elseif (not fiszero(e)) and math.abs(abs(e)-1) < math.abs(abs(mtx[_ilow][j])-1) then
|
||||
elseif (e ~= zero) and math.abs(norm2(e)-1) < math.abs(norm2(mtx[_ilow][j])-1) then
|
||||
_ilow = _i
|
||||
end
|
||||
end
|
||||
|
@ -395,40 +420,28 @@ local setelementtosmallest = function( mtx,i,j,fiszero,fisone,abs )
|
|||
return true
|
||||
end
|
||||
end
|
||||
local cxfiszero = function( cx ) return complex.is(cx,0,0) end
|
||||
local cxfsetzero = function( mtx,i,j ) complex.set(mtx[i][j],0,0) end
|
||||
local cxfisone = function( cx ) return complex.abs(cx) == 1 end
|
||||
local cxfsetone = function( mtx,i,j ) complex.set(mtx[i][j],1,0) end
|
||||
local numfiszero = function( num ) return num == 0 end
|
||||
local numfsetzero = function( mtx,i,j ) mtx[i][j] = 0 end
|
||||
local numfisone = function( num ) return math.abs(num) == 1 end
|
||||
local numfsetone = function( mtx,i,j ) mtx[i][j] = 1 end
|
||||
|
||||
local function copy(x)
|
||||
return type(x) == "table" and x.copy(x) or x
|
||||
end
|
||||
|
||||
-- note: in --// ... //-- we have a way that does no divison,
|
||||
-- however with big number and matrices we get problems since we do no reducing
|
||||
function matrix.dogauss( mtx )
|
||||
local fiszero,fsetzero,fisone,fsetone,abs
|
||||
if matrix.type( mtx ) == "complex" then
|
||||
fiszero = cxfiszero
|
||||
fsetzero = cxfsetzero
|
||||
fisone = cxfisone
|
||||
fsetone = cxfsetone
|
||||
abs = complex.mulconjugate
|
||||
else
|
||||
fiszero = numfiszero
|
||||
fsetzero = numfsetzero
|
||||
fisone = numfisone
|
||||
fsetone = numfsetone
|
||||
abs = math.abs
|
||||
end
|
||||
local e = mtx[1][1]
|
||||
local zero = type(e) == "table" and e.zero or 0
|
||||
local one = type(e) == "table" and e.one or 1
|
||||
local norm2 = type(e) == "table" and e.norm2 or number_norm2
|
||||
|
||||
local rows,columns = #mtx,#mtx[1]
|
||||
-- stairs left -> right
|
||||
for j = 1,rows do
|
||||
-- check if element can be setted to one
|
||||
if setelementtosmallest( mtx,j,j,fiszero,fisone,abs ) then
|
||||
if setelementtosmallest( mtx,j,j,zero,one,norm2 ) then
|
||||
-- start parsing rows
|
||||
for i = j+1,rows do
|
||||
-- check if element is not already zero
|
||||
if not fiszero(mtx[i][j]) then
|
||||
if mtx[i][j] ~= zero then
|
||||
-- we may add x*otherline row, to set element to zero
|
||||
-- tozero - x*mtx[j][j] = 0; x = tozero/mtx[j][j]
|
||||
local factor = mtx[i][j]/mtx[j][j]
|
||||
|
@ -436,7 +449,7 @@ function matrix.dogauss( mtx )
|
|||
-- yet with big matrices (since we do no reducing and other things)
|
||||
-- we get too big numbers
|
||||
--local factor1,factor2 = mtx[i][j],mtx[j][j] //--
|
||||
fsetzero(mtx,i,j)
|
||||
mtx[i][j] = copy(zero)
|
||||
for _j = j+1,columns do
|
||||
--// mtx[i][_j] = mtx[i][_j] * factor2 - factor1 * mtx[j][_j] //--
|
||||
mtx[i][_j] = mtx[i][_j] - factor * mtx[j][_j]
|
||||
|
@ -459,15 +472,15 @@ function matrix.dogauss( mtx )
|
|||
-- start parsing rows
|
||||
for i = j-1,1,-1 do
|
||||
-- check if element is not already zero
|
||||
if not fiszero(mtx[i][j]) then
|
||||
if mtx[i][j] ~= zero then
|
||||
local factor = mtx[i][j]
|
||||
for _j = j+1,columns do
|
||||
mtx[i][_j] = mtx[i][_j] - factor * mtx[j][_j]
|
||||
end
|
||||
fsetzero(mtx,i,j)
|
||||
mtx[i][j] = copy(zero)
|
||||
end
|
||||
end
|
||||
fsetone(mtx,j,j)
|
||||
mtx[j][j] = copy(one)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
@ -481,27 +494,14 @@ function matrix.invert( m1 )
|
|||
assert(#m1 == #m1[1], "matrix not square")
|
||||
local mtx = matrix.copy( m1 )
|
||||
local ident = setmetatable( {},matrix_meta )
|
||||
if matrix.type( mtx ) == "complex" then
|
||||
for i = 1,#m1 do
|
||||
ident[i] = {}
|
||||
for j = 1,#m1 do
|
||||
if i == j then
|
||||
ident[i][j] = complex.new( 1,0 )
|
||||
else
|
||||
ident[i][j] = complex.new( 0,0 )
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
for i = 1,#m1 do
|
||||
ident[i] = {}
|
||||
for j = 1,#m1 do
|
||||
if i == j then
|
||||
ident[i][j] = 1
|
||||
else
|
||||
ident[i][j] = 0
|
||||
end
|
||||
end
|
||||
local e = m1[1][1]
|
||||
local zero = type(e) == "table" and e.zero or 0
|
||||
local one = type(e) == "table" and e.one or 1
|
||||
for i = 1,#m1 do
|
||||
local identi = {}
|
||||
ident[i] = identi
|
||||
for j = 1,#m1 do
|
||||
identi[j] = copy((i == j) and one or zero)
|
||||
end
|
||||
end
|
||||
mtx = matrix.concath( mtx,ident )
|
||||
|
@ -527,7 +527,8 @@ end
|
|||
-- local average error
|
||||
local function get_abs_avg( m1, m2 )
|
||||
local dist = 0
|
||||
local abs = matrix.type(m1) == "complex" and complex.abs or math.abs
|
||||
local e = m1[1][1]
|
||||
local abs = type(e) == "table" and e.abs or math.abs
|
||||
for i=1,#m1 do
|
||||
for j=1,#m1[1] do
|
||||
dist = dist + abs(m1[i][j]-m2[i][j])
|
||||
|
@ -650,7 +651,7 @@ local tround = function( t,mult )
|
|||
end
|
||||
function matrix.round( mtx, idp )
|
||||
local mult = 10^( idp or 0 )
|
||||
local fround = matrix.type( mtx ) == "number" and numound or tround
|
||||
local fround = matrix.type( mtx ) == "number" and numround or tround
|
||||
for i = 1,#mtx do
|
||||
for j = 1,#mtx[1] do
|
||||
mtx[i][j] = fround(mtx[i][j],mult)
|
||||
|
@ -691,12 +692,10 @@ end
|
|||
--// matrix.type ( mtx )
|
||||
-- get type of matrix, normal/complex/symbol or tensor
|
||||
function matrix.type( mtx )
|
||||
if type(mtx[1][1]) == "table" then
|
||||
if complex.type(mtx[1][1]) then
|
||||
return "complex"
|
||||
end
|
||||
if getmetatable(mtx[1][1]) == symbol_meta then
|
||||
return "symbol"
|
||||
local e = mtx[1][1]
|
||||
if type(e) == "table" then
|
||||
if e.type then
|
||||
return e:type()
|
||||
end
|
||||
return "tensor"
|
||||
end
|
||||
|
@ -766,7 +765,7 @@ function matrix.subm( m1,i1,j1,i2,j2 )
|
|||
end
|
||||
|
||||
--// matrix.concath( m1, m2 )
|
||||
-- Concatenate 2 matrices, horizontal
|
||||
-- Concatenate two matrices, horizontal
|
||||
-- will return m1m2; rows have to be the same
|
||||
-- e.g.: #m1 == #m2
|
||||
function matrix.concath( m1,m2 )
|
||||
|
@ -787,7 +786,7 @@ function matrix.concath( m1,m2 )
|
|||
end
|
||||
|
||||
--// matrix.concatv ( m1, m2 )
|
||||
-- Concatenate 2 matrices, vertical
|
||||
-- Concatenate two matrices, vertical
|
||||
-- will return m1
|
||||
-- m2
|
||||
-- columns have to be the same; e.g.: #m1[1] == #m2[1]
|
||||
|
@ -838,59 +837,32 @@ function matrix.rotr( m1 )
|
|||
return mtx
|
||||
end
|
||||
|
||||
-- local get_elemnts in string
|
||||
local get_tstr = function( t )
|
||||
return "["..table.concat(t,",").."]"
|
||||
end
|
||||
local get_str = function( e )
|
||||
return tostring(e)
|
||||
end
|
||||
-- local get_elemnts in string and formated
|
||||
local getf_tstr = function( t,fstr )
|
||||
local function tensor_tostring( t,fstr )
|
||||
if not fstr then return "["..table.concat(t,",").."]" end
|
||||
local tval = {}
|
||||
for i,v in ipairs( t ) do
|
||||
tval[i] = string.format( fstr,v )
|
||||
end
|
||||
return "["..table.concat(tval,",").."]"
|
||||
end
|
||||
local getf_cxstr = function( e,fstr )
|
||||
return complex.tostring( e,fstr )
|
||||
end
|
||||
local getf_symstr = function( e,fstr )
|
||||
return string.format( fstr,e[1] )
|
||||
end
|
||||
local getf_str = function( e,fstr )
|
||||
return string.format( fstr,e )
|
||||
local function number_tostring( e,fstr )
|
||||
return fstr and string.format( fstr,e ) or e
|
||||
end
|
||||
|
||||
--// matrix.tostring ( mtx, formatstr )
|
||||
-- tostring function
|
||||
function matrix.tostring( mtx, formatstr )
|
||||
local ts = {}
|
||||
local getstr
|
||||
if formatstr then -- get str formatted
|
||||
local mtype = matrix.type( mtx )
|
||||
if mtype == "tensor" then getstr = getf_tstr
|
||||
elseif mtype == "complex" then getstr = getf_cxstr
|
||||
elseif mtype == "symbol" then getstr = getf_symstr
|
||||
else getstr = getf_str end
|
||||
-- iteratr
|
||||
for i = 1,#mtx do
|
||||
local tstr = {}
|
||||
for j = 1,#mtx[1] do
|
||||
tstr[j] = getstr(mtx[i][j],formatstr)
|
||||
end
|
||||
ts[i] = table.concat(tstr, "\t")
|
||||
end
|
||||
else
|
||||
getstr = matrix.type( mtx ) == "tensor" and get_tstr or get_str
|
||||
for i = 1,#mtx do
|
||||
local tstr = {}
|
||||
for j = 1,#mtx[1] do
|
||||
tstr[j] = getstr(mtx[i][j])
|
||||
end
|
||||
ts[i] = table.concat(tstr, "\t")
|
||||
local mtype = matrix.type( mtx )
|
||||
local e = mtx[1][1]
|
||||
local tostring = mtype == "tensor" and tensor_tostring or
|
||||
type(e) == "table" and e.tostring or number_tostring
|
||||
for i = 1,#mtx do
|
||||
local tstr = {}
|
||||
for j = 1,#mtx[1] do
|
||||
tstr[j] = tostring(mtx[i][j],formatstr)
|
||||
end
|
||||
ts[i] = table.concat(tstr, "\t")
|
||||
end
|
||||
return table.concat(ts, "\n")
|
||||
end
|
||||
|
@ -909,7 +881,7 @@ function matrix.latex( mtx, align )
|
|||
-- \usepackage{dcolumn}; D{.}{,}{-1}; aligns number by . replaces it with ,
|
||||
local align = align or "c"
|
||||
local str = "$\\left( \\begin{array}{"..string.rep( align, #mtx[1] ).."}\n"
|
||||
local getstr = matrix.type( mtx ) == "tensor" and get_tstr or get_str
|
||||
local getstr = matrix.type( mtx ) == "tensor" and tensor_tostring or number_tostring
|
||||
for i = 1,#mtx do
|
||||
str = str.."\t"..getstr(mtx[i][1])
|
||||
for j = 2,#mtx[1] do
|
||||
|
@ -1014,96 +986,29 @@ function matrix.len( m1 )
|
|||
return math.sqrt( m1[1][1]^2 + m1[2][1]^2 + m1[3][1]^2 )
|
||||
end
|
||||
|
||||
--////////////////////////////////
|
||||
--// matrix 'complex' functions //
|
||||
--////////////////////////////////
|
||||
|
||||
--// matrix.tocomplex ( mtx )
|
||||
-- we set now all elements to a complex number
|
||||
-- also set the metatable
|
||||
function matrix.tocomplex( mtx )
|
||||
assert( matrix.type(mtx) == "number", "matrix not of type 'number'" )
|
||||
for i = 1,#mtx do
|
||||
for j = 1,#mtx[1] do
|
||||
mtx[i][j] = complex.to( mtx[i][j] )
|
||||
--// matrix.replace (mtx, func, ...)
|
||||
-- for each element e in the matrix mtx, replace it with func(mtx, ...).
|
||||
function matrix.replace( m1, func, ... )
|
||||
local mtx = {}
|
||||
for i = 1,#m1 do
|
||||
local m1i = m1[i]
|
||||
local mtxi = {}
|
||||
for j = 1,#m1i do
|
||||
mtxi[j] = func( m1i[j], ... )
|
||||
end
|
||||
mtx[i] = mtxi
|
||||
end
|
||||
return setmetatable( mtx, matrix_meta )
|
||||
end
|
||||
|
||||
--// matrix.remcomplex ( mtx )
|
||||
-- set the matrix elements to a number or complex number string
|
||||
function matrix.remcomplex( mtx )
|
||||
assert( matrix.type(mtx) == "complex", "matrix not of type 'complex'" )
|
||||
for i = 1,#mtx do
|
||||
for j = 1,#mtx[1] do
|
||||
mtx[i][j] = complex.tostring( mtx[i][j] )
|
||||
end
|
||||
end
|
||||
return setmetatable( mtx, matrix_meta )
|
||||
end
|
||||
|
||||
--// matrix.conjugate ( m1 )
|
||||
-- get the conjugate complex matrix
|
||||
function matrix.conjugate( m1 )
|
||||
assert( matrix.type(m1) == "complex", "matrix not of type 'complex'" )
|
||||
local mtx = {}
|
||||
for i = 1,#m1 do
|
||||
mtx[i] = {}
|
||||
for j = 1,#m1[1] do
|
||||
mtx[i][j] = complex.conjugate( m1[i][j] )
|
||||
end
|
||||
end
|
||||
return setmetatable( mtx, matrix_meta )
|
||||
end
|
||||
|
||||
--/////////////////////////////////
|
||||
--// matrix 'symbol' functions //
|
||||
--/////////////////////////////////
|
||||
|
||||
--// matrix.tosymbol ( mtx )
|
||||
-- set the matrix elements to symbolic values
|
||||
function matrix.tosymbol( mtx )
|
||||
assert( matrix.type( mtx ) ~= "tensor", "cannot convert type 'tensor' to 'symbol'" )
|
||||
for i = 1,#mtx do
|
||||
for j = 1,#mtx[1] do
|
||||
mtx[i][j] = newsymbol( mtx[i][j] )
|
||||
end
|
||||
end
|
||||
return setmetatable( mtx, matrix_meta )
|
||||
end
|
||||
|
||||
--// matrix.gsub( m1, from, to )
|
||||
-- perform gsub on all elements
|
||||
function matrix.gsub( m1,from,to )
|
||||
assert( matrix.type( m1 ) == "symbol", "matrix not of type 'symbol'" )
|
||||
local mtx = {}
|
||||
for i = 1,#m1 do
|
||||
mtx[i] = {}
|
||||
for j = 1,#m1[1] do
|
||||
mtx[i][j] = newsymbol( string.gsub( m1[i][j][1],from,to ) )
|
||||
end
|
||||
end
|
||||
return setmetatable( mtx, matrix_meta )
|
||||
end
|
||||
|
||||
--// matrix.replace ( m1, ... )
|
||||
-- replace one letter by something else
|
||||
-- replace( "a",4,"b",7, ... ) will replace a with 4 and b with 7
|
||||
function matrix.replace( m1,... )
|
||||
assert( matrix.type( m1 ) == "symbol", "matrix not of type 'symbol'" )
|
||||
local tosub,args = {},{...}
|
||||
for i = 1,#args,2 do
|
||||
tosub[args[i]] = args[i+1]
|
||||
end
|
||||
local mtx = {}
|
||||
for i = 1,#m1 do
|
||||
mtx[i] = {}
|
||||
for j = 1,#m1[1] do
|
||||
mtx[i][j] = newsymbol( string.gsub( m1[i][j][1], "%a", function( a ) return tosub[a] or a end ) )
|
||||
end
|
||||
end
|
||||
return setmetatable( mtx, matrix_meta )
|
||||
-- set the matrix elements to strings
|
||||
-- IMPROVE: tostring v.s. tostringelements confusing
|
||||
function matrix.elementstostrings( mtx )
|
||||
local e = mtx[1][1]
|
||||
local tostring = type(e) == "table" and e.tostring or tostring
|
||||
return matrix.replace(mtx, tostring)
|
||||
end
|
||||
|
||||
--// matrix.solve ( m1 )
|
||||
|
@ -1120,46 +1025,6 @@ function matrix.solve( m1 )
|
|||
return setmetatable( mtx, matrix_meta )
|
||||
end
|
||||
|
||||
function symbol_meta.__add(a,b)
|
||||
return newsymbol(a .. "+" .. b)
|
||||
end
|
||||
|
||||
function symbol_meta.__sub(a,b)
|
||||
return newsymbol(a .. "-" .. b)
|
||||
end
|
||||
|
||||
function symbol_meta.__mul(a,b)
|
||||
return newsymbol("(" .. a .. ")*(" .. b .. ")")
|
||||
end
|
||||
|
||||
function symbol_meta.__div(a,b)
|
||||
return newsymbol("(" .. a .. ")/(" .. b .. ")")
|
||||
end
|
||||
|
||||
function symbol_meta.__pow(a,b)
|
||||
return newsymbol("(" .. a .. ")^(" .. b .. ")")
|
||||
end
|
||||
|
||||
function symbol_meta.__eq(a,b)
|
||||
return a[1] == b[1]
|
||||
end
|
||||
|
||||
function symbol_meta.__tostring(a)
|
||||
return a[1]
|
||||
end
|
||||
|
||||
function symbol_meta.__concat(a,b)
|
||||
return tostring(a) .. tostring(b)
|
||||
end
|
||||
|
||||
function symbol_meta.abs(a)
|
||||
return newsymbol("(" .. a[1] .. "):abs()")
|
||||
end
|
||||
|
||||
function symbol_meta.sqrt(a)
|
||||
return newsymbol("(" .. a[1] .. "):sqrt()")
|
||||
end
|
||||
|
||||
--////////////////////////--
|
||||
--// METATABLE HANDLING //--
|
||||
--////////////////////////--
|
||||
|
@ -1232,7 +1097,7 @@ matrix_meta.__eq = function( m1, m2 )
|
|||
if #m1 ~= #m2 or #m1[1] ~= #m2[1] then
|
||||
return false
|
||||
end
|
||||
-- check normal,complex and symbolic
|
||||
-- check elements equal
|
||||
for i = 1,#m1 do
|
||||
for j = 1,#m1[1] do
|
||||
if m1[i][j] ~= m2[i][j] then
|
||||
|
@ -1259,8 +1124,107 @@ for k,v in pairs( matrix ) do
|
|||
matrix_meta.__index[k] = v
|
||||
end
|
||||
|
||||
-- return the matrix and complex
|
||||
return matrix, complex
|
||||
|
||||
--/////////////////////////////////
|
||||
--// symbol class implementation
|
||||
--/////////////////////////////////
|
||||
|
||||
-- access to the symbolic metatable
|
||||
local symbol_meta = {}; symbol_meta.__index = symbol_meta
|
||||
local symbol = symbol_meta
|
||||
|
||||
function symbol_meta.new(o)
|
||||
return setmetatable({tostring(o)}, symbol_meta)
|
||||
end
|
||||
symbol_meta.to = symbol_meta.new
|
||||
|
||||
-- symbol( arg )
|
||||
-- same as symbol.to( arg )
|
||||
-- set __call behaviour of symbol
|
||||
setmetatable( symbol_meta, { __call = function( _,s ) return symbol_meta.to( s ) end } )
|
||||
|
||||
|
||||
-- Converts object to string, optionally with formatting.
|
||||
function symbol_meta.tostring( e,fstr )
|
||||
return string.format( fstr,e[1] )
|
||||
end
|
||||
|
||||
-- Returns "symbol" if object is a symbol type, else nothing.
|
||||
function symbol_meta:type()
|
||||
if getmetatable(self) == symbol_meta then
|
||||
return "symbol"
|
||||
end
|
||||
end
|
||||
|
||||
-- Performs string.gsub on symbol.
|
||||
-- for use in matrix.replace
|
||||
function symbol_meta:gsub(from, to)
|
||||
return symbol.to( string.gsub( self[1],from,to ) )
|
||||
end
|
||||
|
||||
-- creates function that replaces one letter by something else
|
||||
-- makereplacer( "a",4,"b",7, ... )(x)
|
||||
-- will replace a with 4 and b with 7 in symbol x.
|
||||
-- for use in matrix.replace
|
||||
function symbol_meta.makereplacer( ... )
|
||||
local tosub = {}
|
||||
local args = {...}
|
||||
for i = 1,#args,2 do
|
||||
tosub[args[i]] = args[i+1]
|
||||
end
|
||||
local function func( a ) return tosub[a] or a end
|
||||
return function(sym)
|
||||
return symbol.to( string.gsub( sym[1], "%a", func ) )
|
||||
end
|
||||
end
|
||||
|
||||
-- applies abs function to symbol
|
||||
function symbol_meta.abs(a)
|
||||
return symbol.to("(" .. a[1] .. "):abs()")
|
||||
end
|
||||
|
||||
-- applies sqrt function to symbol
|
||||
function symbol_meta.sqrt(a)
|
||||
return symbol.to("(" .. a[1] .. "):sqrt()")
|
||||
end
|
||||
|
||||
function symbol_meta.__add(a,b)
|
||||
return symbol.to(a .. "+" .. b)
|
||||
end
|
||||
|
||||
function symbol_meta.__sub(a,b)
|
||||
return symbol.to(a .. "-" .. b)
|
||||
end
|
||||
|
||||
function symbol_meta.__mul(a,b)
|
||||
return symbol.to("(" .. a .. ")*(" .. b .. ")")
|
||||
end
|
||||
|
||||
function symbol_meta.__div(a,b)
|
||||
return symbol.to("(" .. a .. ")/(" .. b .. ")")
|
||||
end
|
||||
|
||||
function symbol_meta.__pow(a,b)
|
||||
return symbol.to("(" .. a .. ")^(" .. b .. ")")
|
||||
end
|
||||
|
||||
function symbol_meta.__eq(a,b)
|
||||
return a[1] == b[1]
|
||||
end
|
||||
|
||||
function symbol_meta.__tostring(a)
|
||||
return a[1]
|
||||
end
|
||||
|
||||
function symbol_meta.__concat(a,b)
|
||||
return tostring(a) .. tostring(b)
|
||||
end
|
||||
|
||||
matrix.symbol = symbol
|
||||
|
||||
|
||||
-- return matrix
|
||||
return matrix
|
||||
|
||||
--///////////////--
|
||||
--// chillcode //--
|
|
@ -0,0 +1,31 @@
|
|||
package = "LuaMatrix"
|
||||
version = "[VERSION]"
|
||||
source = {
|
||||
url = "[URL]",
|
||||
}
|
||||
description = {
|
||||
summary = "Matrices and matrix operations implemented in pure Lua.",
|
||||
detailed = [[
|
||||
This supports operations on matrices and vectors whose elements are
|
||||
real, complex, or symbolic. Implemented entirely in Lua as tables.
|
||||
Includes a complex number data type too.
|
||||
]],
|
||||
license = "MIT/X11",
|
||||
homepage = "http://luamatrix.luaforge.net/",
|
||||
maintainer = "David Manura <http://lua-users.org/wiki/DavidManura>",
|
||||
}
|
||||
dependencies = {
|
||||
"lua >= 5.1",
|
||||
}
|
||||
build = {
|
||||
type = "none",
|
||||
install = {
|
||||
lua = {
|
||||
["complex"] = "lua/complex.lua",
|
||||
["matrix"] = "lua/matrix.lua",
|
||||
}
|
||||
},
|
||||
copy_directories = {"doc", "samples", "tests"},
|
||||
}
|
||||
-- test: tests/test.lua
|
||||
|
|
@ -8,8 +8,7 @@
|
|||
|
||||
-- little add-on to the matrix module, to show some curve fitting
|
||||
|
||||
-- http://luaforge.net/projects/LuaMatrix
|
||||
-- http://lua-users.org/wiki/SimpleFit
|
||||
-- http://luamatrix.luaforge.net
|
||||
|
||||
-- Licensed under the same terms as Lua itself.
|
||||
|
22
test_fit.lua
22
test_fit.lua
|
@ -1,22 +0,0 @@
|
|||
-- require fit
|
||||
local fit = require "fit"
|
||||
|
||||
print( "Fit a straight line " )
|
||||
-- x(i) = 2 | 3 | 4 | 5
|
||||
-- y(i) = 5 | 9 | 15 | 21
|
||||
-- model = y = a + b * x
|
||||
-- r(i) = y(i) - ( a + b * x(i) )
|
||||
local a,b = fit.linear( { 2,3, 4, 5 },
|
||||
{ 5,9,15,21 } )
|
||||
print( "=> y = ( "..a.." ) + ( "..b.." ) * x")
|
||||
|
||||
print( "Fit a parabola " )
|
||||
local a, b, c = fit.parabola( { 0,1,2,4,6 },
|
||||
{ 3,1,0,1,4 } )
|
||||
print( "=> y = ( "..a.." ) + ( "..b.." ) * x + ( "..c.." ) * x²")
|
||||
|
||||
print( "Fit exponential" )
|
||||
local a, b = fit.exponential( {1, 2, 3, 4, 5},
|
||||
{1,3.1,5.6,9.1,12.9} )
|
||||
print( "=> y = ( "..a.." ) * x^( "..b.." )")
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
-- test suite (run from parent directory).
|
||||
|
||||
package.path = './lua/?.lua;' .. package.path
|
||||
|
||||
dofile 'tests/test_complex.lua'
|
||||
dofile 'tests/test_matrix.lua'
|
||||
dofile 'tests/test_fit.lua'
|
||||
print 'ALL PASSED'
|
|
@ -82,9 +82,9 @@ local r,phi = complex.polardeg( {0,-3} )
|
|||
assert( r == 3 )
|
||||
assert( phi == -90 )
|
||||
|
||||
-- complex.mulconjugate( cx )
|
||||
-- complex.norm2( cx )
|
||||
cx = complex "2+3i"
|
||||
assert( complex.mulconjugate( cx ) == 13 )
|
||||
assert( complex.norm2( cx ) == 13 )
|
||||
|
||||
-- complex.abs( cx )
|
||||
cx = complex "3+4i"
|
||||
|
@ -168,7 +168,7 @@ assert( cx:ln():round( 4 ) == complex "1.6094+0.9273i" )
|
|||
|
||||
-- complex.exp( cx )
|
||||
cx = complex "2+3i"
|
||||
assert( cx:ln():exp() == complex "2+3i" )
|
||||
assert( cx.abs( cx:ln():exp() - complex "2+3i" ) < 1e-7 )
|
||||
|
||||
-- complex.conjugate( cx )
|
||||
cx = complex "2+3i"
|
||||
|
@ -182,4 +182,6 @@ assert( cx+2 == complex "4+3i" )
|
|||
|
||||
-- __unm
|
||||
cx = complex "2+3i"
|
||||
assert( -cx == complex "-2-3i" )
|
||||
assert( -cx == complex "-2-3i" )
|
||||
|
||||
print 'PASSED'
|
|
@ -0,0 +1,25 @@
|
|||
-- require fit
|
||||
package.path = "samples/?.lua;" .. package.path
|
||||
local fit = require "fit"
|
||||
|
||||
-- Fit a straight line
|
||||
-- x(i) = 2 | 3 | 4 | 5
|
||||
-- y(i) = 5 | 9 | 15 | 21
|
||||
-- model = y = a + b * x
|
||||
-- r(i) = y(i) - ( a + b * x(i) )
|
||||
local a,b = fit.linear( { 2,3, 4, 5 }, { 5,9,15,21 } )
|
||||
assert(math.abs(a - -6.4) < 0.001)
|
||||
assert(math.abs(b - 5.4) < 0.001)
|
||||
|
||||
-- Fit a parabola
|
||||
local a, b, c = fit.parabola( { 0,1,2,4,6 }, { 3,1,0,1,4 } )
|
||||
assert(math.abs(a - 2.8251599147122) < 0.001)
|
||||
assert(math.abs(b - -2.0490405117271) < 0.001)
|
||||
assert(math.abs(c - 0.3773987206823) < 0.001)
|
||||
|
||||
-- Fit exponential
|
||||
local a, b = fit.exponential( {1, 2, 3, 4, 5}, {1,3.1,5.6,9.1,12.9} )
|
||||
assert(math.abs(a - 1.0077958966968) < 0.001)
|
||||
assert(math.abs(b - 1.5834684450364) < 0.001)
|
||||
|
||||
print 'PASSED'
|
|
@ -1,4 +1,6 @@
|
|||
local matrix, complex = require "matrix"
|
||||
local matrix = require "matrix"
|
||||
local complex = require "complex"
|
||||
local symbol = matrix.symbol
|
||||
|
||||
local mtx, m1,m2,m3,m4,m5, ms,ms1,ms2,ms3,ms4
|
||||
|
||||
|
@ -24,42 +26,42 @@ m1 = matrix{{8,4,1},{6,8,3}}
|
|||
m2 = matrix{{-8,1,3},{5,2,1}}
|
||||
assert(m1 + m2 == matrix{{0,5,4},{11,10,4}})
|
||||
-- matrix.add; complex
|
||||
m1 = matrix{{10,"2+6i",1},{5,1,"4-2i"}}:tocomplex()
|
||||
m2 = matrix{{3,4,5},{"2+3i",4,"6i"}}:tocomplex()
|
||||
assert(m1 + m2 == matrix{{13,"6+6i",6},{"7+3i",5,"4+4i"}}:tocomplex())
|
||||
m1 = matrix{{10,"2+6i",1},{5,1,"4-2i"}}:replace(complex)
|
||||
m2 = matrix{{3,4,5},{"2+3i",4,"6i"}}:replace(complex)
|
||||
assert(m1 + m2 == matrix{{13,"6+6i",6},{"7+3i",5,"4+4i"}}:replace(complex))
|
||||
-- matrix.add; symbol
|
||||
m1 = matrix{{8,4,1},{6,8,3}}:tosymbol()
|
||||
m2 = matrix{{-8,1,3},{5,2,1}}:tosymbol()
|
||||
assert(m1 + m2 == matrix{{"8+-8","4+1","1+3"},{"6+5","8+2","3+1"}}:tosymbol())
|
||||
m1 = matrix{{8,4,1},{6,8,3}}:replace(symbol)
|
||||
m2 = matrix{{-8,1,3},{5,2,1}}:replace(symbol)
|
||||
assert(m1 + m2 == matrix{{"8+-8","4+1","1+3"},{"6+5","8+2","3+1"}}:replace(symbol))
|
||||
|
||||
-- matrix.sub; number
|
||||
m1 = matrix{{8,4,1},{6,8,3}}
|
||||
m2 = matrix{{-8,1,3},{5,2,1}}
|
||||
assert(m1 - m2 == matrix{{16,3,-2},{1,6,2}})
|
||||
-- matrix.sub; complex
|
||||
m1 = matrix{{10,"2+6i",1},{5,1,"4-2i"}}:tocomplex()
|
||||
m2 = matrix{{3,4,5},{"2+3i",4,"6i"}}:tocomplex()
|
||||
assert(m1 - m2 == matrix{{7,"-2+6i",-4},{"3-3i",-3,"4-8i"}}:tocomplex())
|
||||
m1 = matrix{{10,"2+6i",1},{5,1,"4-2i"}}:replace(complex)
|
||||
m2 = matrix{{3,4,5},{"2+3i",4,"6i"}}:replace(complex)
|
||||
assert(m1 - m2 == matrix{{7,"-2+6i",-4},{"3-3i",-3,"4-8i"}}:replace(complex))
|
||||
-- matrix.sub; symbol
|
||||
m1 = matrix{{8,4,1},{6,8,3}}:tosymbol()
|
||||
m2 = matrix{{-8,1,3},{5,2,1}}:tosymbol()
|
||||
assert(m1 - m2 == matrix{{"8--8","4-1","1-3"},{"6-5","8-2","3-1"}}:tosymbol())
|
||||
m1 = matrix{{8,4,1},{6,8,3}}:replace(symbol)
|
||||
m2 = matrix{{-8,1,3},{5,2,1}}:replace(symbol)
|
||||
assert(m1 - m2 == matrix{{"8--8","4-1","1-3"},{"6-5","8-2","3-1"}}:replace(symbol))
|
||||
|
||||
-- matrix.mul; number
|
||||
m1 = matrix{{8,4,1},{6,8,3}}
|
||||
m2 = matrix{{3,1},{2,5},{7,4}}
|
||||
assert(m1 * m2 == matrix{{39,32},{55,58}})
|
||||
-- matrix.mul; complex
|
||||
m1 = matrix{{"1+2i","3-i"},{"2-2i","1+i"}}:tocomplex()
|
||||
m2 = matrix{{"i","5-i"},{2,"1-i"}}:tocomplex()
|
||||
assert( m1*m2 == matrix{{"4-i","9+5i"},{"4+4i","10-12i"}}:tocomplex() )
|
||||
m1 = matrix{{"1+2i","3-i"},{"2-2i","1+i"}}:replace(complex)
|
||||
m2 = matrix{{"i","5-i"},{2,"1-i"}}:replace(complex)
|
||||
assert( m1*m2 == matrix{{"4-i","9+5i"},{"4+4i","10-12i"}}:replace(complex) )
|
||||
-- matrix.mul; symbol
|
||||
m1 = matrix{{8,4,1},{6,8,3}}:tosymbol()
|
||||
m2 = matrix{{3,1},{2,5},{7,4}}:tosymbol()
|
||||
m1 = matrix{{8,4,1},{6,8,3}}:replace(symbol)
|
||||
m2 = matrix{{3,1},{2,5},{7,4}}:replace(symbol)
|
||||
assert(m1 * m2 == matrix{
|
||||
{"(8)*(3)+(4)*(2)+(1)*(7)", "(8)*(1)+(4)*(5)+(1)*(4)"},
|
||||
{"(6)*(3)+(8)*(2)+(3)*(7)", "(6)*(1)+(8)*(5)+(3)*(4)"}
|
||||
}:tosymbol())
|
||||
}:replace(symbol))
|
||||
|
||||
-- matrix.div; number, same for complex, not for symbol
|
||||
m1 = matrix {{1,2},{3,4}}
|
||||
|
@ -72,9 +74,9 @@ assert( m2/2 == matrix{{2,2.5},{3,3.5}} )
|
|||
mtx = matrix {{3,5,1},{2,4,5},{1,2,2}}
|
||||
assert( 2 / mtx == matrix{{4,16,-42},{-2,-10,26},{0,2,-4}} )
|
||||
-- matrix.mulnum; symbol
|
||||
m1 = m1:tosymbol()
|
||||
assert( m1*2 == matrix{{"(1)*(2)","(2)*(2)"},{"(3)*(2)","(4)*(2)"}}:tosymbol() )
|
||||
assert( m1/2 == matrix{{"(1)/(2)","(2)/(2)"},{"(3)/(2)","(4)/(2)"}}:tosymbol() )
|
||||
m1 = m1:replace(symbol)
|
||||
assert( m1*2 == matrix{{"(1)*(2)","(2)*(2)"},{"(3)*(2)","(4)*(2)"}}:replace(symbol) )
|
||||
assert( m1/2 == matrix{{"(1)/(2)","(2)/(2)"},{"(3)/(2)","(4)/(2)"}}:replace(symbol) )
|
||||
|
||||
-- matrix.pow; number, same complex
|
||||
mtx = matrix{{3,5,1},{2,4,5},{1,2,2}}
|
||||
|
@ -94,8 +96,8 @@ assert(select(2, pcall(function() return mtx^-1 end))
|
|||
mtx = matrix {{1,4,3,2},{2,1,-1,-1},{-3,2,2,-2},{-1,-5,-4,1}}
|
||||
assert( mtx:det() == 78 )
|
||||
-- matrix.det; complex
|
||||
m1 = matrix{{"1+2i","3-i"},{"2-2i","1+i"}}:tocomplex()
|
||||
m2 = matrix{{"i","5-i"},{2,"1-i"}}:tocomplex()
|
||||
m1 = matrix{{"1+2i","3-i"},{"2-2i","1+i"}}:replace(complex)
|
||||
m2 = matrix{{"i","5-i"},{2,"1-i"}}:replace(complex)
|
||||
m3 = m1*m2
|
||||
-- (checked in maple)
|
||||
assert( m3:det() == complex "12-114i" )
|
||||
|
@ -104,7 +106,7 @@ mtx = {{"2+3i","1+4i","-2i",3,2},
|
|||
{3,"-2i",6,"4+5i",0},
|
||||
{1,"1+2i",3,5,7},
|
||||
{"-3+3i","3+3i",3,-8,2}}
|
||||
matrix(mtx):tocomplex()
|
||||
mtx = matrix(mtx):replace(complex)
|
||||
-- (checked in maple)
|
||||
assert( mtx:det():round(10) == complex "5527+2687i" )
|
||||
|
||||
|
@ -123,7 +125,7 @@ mtx = {
|
|||
{3,"-1+5i",-3},
|
||||
{4,0,7},
|
||||
}
|
||||
matrix.tocomplex( mtx )
|
||||
mtx = matrix.replace( mtx, complex )
|
||||
local mtxinv = mtx^-1
|
||||
local mtxinvcomp = {
|
||||
{"0.13349-0.07005i","0.14335+0.03609i","0.04237+0.02547i"},
|
||||
|
@ -131,7 +133,7 @@ local mtxinvcomp = {
|
|||
{"-0.07628+0.04003i","-0.08192-0.02062i","0.11865-0.01456i"},}
|
||||
mtxinvcomp = matrix( mtxinvcomp )
|
||||
mtxinv:round( 5 )
|
||||
mtxinv:remcomplex()
|
||||
mtxinv = mtxinv:elementstostrings()
|
||||
assert( mtxinvcomp == mtxinv )
|
||||
|
||||
-- matrix.sqrt; number
|
||||
|
@ -140,7 +142,7 @@ local m2 = m1*m1
|
|||
local msqrt = m2:sqrt()
|
||||
assert((m2 - msqrt^2):normmax() < 1E-12)
|
||||
-- matrix.sqrt; complex
|
||||
local m1 = matrix{{4,"2+i",1},{1,5,"4-2i"},{1,"5+3i",2}}:tocomplex()
|
||||
local m1 = matrix{{4,"2+i",1},{1,5,"4-2i"},{1,"5+3i",2}}:replace(complex)
|
||||
local m2 = m1*m1
|
||||
local msqrt = m2:sqrt()
|
||||
assert((m2 - msqrt^2):normmax() < 1E-12)
|
||||
|
@ -152,7 +154,7 @@ local m2 = m1^p
|
|||
local mroot = m2:root(p)
|
||||
assert((m2 - mroot^p):normmax() < 1E-7)
|
||||
-- matrix.root; complex
|
||||
local m1 = matrix{{4,"2+i",1},{1,5,"4-2i"},{1,"5+3i",2}}:tocomplex()
|
||||
local m1 = matrix{{4,"2+i",1},{1,5,"4-2i"},{1,"5+3i",2}}:replace(complex)
|
||||
local m2 = m1^p
|
||||
local mroot = m2:root(p)
|
||||
assert((m2 - mroot^p):normmax() < 1E-7)
|
||||
|
@ -160,16 +162,16 @@ assert((m2 - mroot^p):normmax() < 1E-7)
|
|||
-- matrix.normf
|
||||
mtx = matrix{{2,3},{-2,-3}}
|
||||
assert(mtx:normf() == math.sqrt(2^2+3^2+2^2+3^2))
|
||||
mtx = matrix{{'2i','3'},{'-2i','-3'}}:tocomplex()
|
||||
mtx = matrix{{'2i','3'},{'-2i','-3'}}:replace(complex)
|
||||
assert(mtx:normf() == math.sqrt(2^2+3^2+2^2+3^2))
|
||||
mtx = matrix{{'a','b'},{'c','d'}}:tosymbol()
|
||||
mtx = matrix{{'a','b'},{'c','d'}}:replace(symbol)
|
||||
assert(tostring(mtx:normf()) == "(0+((a):abs())^(2)+((b):abs())^(2)+((c):abs())^(2)+((d):abs())^(2)):sqrt()")
|
||||
|
||||
-- matrix.normmax
|
||||
-- note: symbolic matrices not supported
|
||||
mtx = matrix{{2,3},{-2,-4}}
|
||||
assert(mtx:normmax() == 4)
|
||||
mtx = matrix{{'2i','3'},{'-2i','-4i'}}:tocomplex()
|
||||
mtx = matrix{{'2i','3'},{'-2i','-4i'}}:replace(complex)
|
||||
assert(mtx:normmax() == 4)
|
||||
|
||||
-- matrix.transpose
|
||||
|
@ -187,7 +189,7 @@ assert( m1:rotr() == matrix{{6,4,2},{7,5,3}} )
|
|||
mtx = matrix{{4,2,-3},{3,-5,2}}
|
||||
assert(tostring(mtx) == "4\t2\t-3\n3\t-5\t2" )
|
||||
-- matrix.tostring; complex
|
||||
mtx = matrix{{4,"2+i"},{"3-4i",5}}:tocomplex()
|
||||
mtx = matrix{{4,"2+i"},{"3-4i",5}}:replace(complex)
|
||||
assert(tostring(mtx) == "4\t2+i\n3-4i\t5" )
|
||||
-- matrix.tostring; tensor
|
||||
local mt = matrix {{{1,2},{3,4}},{{5,6},{7,8}}}
|
||||
|
@ -216,14 +218,14 @@ assert( vx:scalar( v2 ) == 0 )
|
|||
assert( v2:len() == math.sqrt( 3^2+4^2 ) )
|
||||
|
||||
--// test symbolic
|
||||
ms = matrix {{ "a",1 },{2,"b"}}:tosymbol()
|
||||
ms2 = matrix {{ "a",2 },{"b",3}}:tosymbol()
|
||||
ms = matrix {{ "a",1 },{2,"b"}}:replace(symbol)
|
||||
ms2 = matrix {{ "a",2 },{"b",3}}:replace(symbol)
|
||||
ms3 = ms2+ms
|
||||
ms3 = ms3:replace( "a",4,"b",2 )
|
||||
ms3 = ms3:replace( symbol.makereplacer( "a",4,"b",2 ) )
|
||||
ms3 = ms3:solve()
|
||||
assert( ms3 == matrix {{8,3},{4,5}} )
|
||||
ms4 = ms2*ms
|
||||
ms4 = ms4:replace( "a",4,"b",2 )
|
||||
ms4 = ms4:replace( symbol.makereplacer( "a",4,"b",2 ) )
|
||||
ms4 = ms4:solve()
|
||||
assert( ms4 == matrix {{20,8},{14,8}} )
|
||||
|
||||
|
@ -255,4 +257,6 @@ end
|
|||
table.sort( t )
|
||||
for i,v in ipairs( t ) do
|
||||
--print( "matrix."..v )
|
||||
end
|
||||
end
|
||||
|
||||
print 'PASSED'
|
Loading…
Reference in New Issue