使用 lua 模块的矩阵乘法(和其他运算)宏

使用 lua 模块的矩阵乘法(和其他运算)宏

我希望能够创建一个宏来使用 lua 模块乘以矩阵。模块在这里:

https://raw.github.com/davidm/lua-matrix/master/lua/matrix.lua

正如我所建议的那样上一个问题 我把我的 lua 代码放在一个单独的 lua 文件中,dofiled如下所示:

\documentclass{article}
\usepackage{xparse}
\usepackage{luacode}
\usepackage{fontspec}

\directlua{dofile("matrix.lua")}
\directlua{dofile("lua2.lua")}
\ExplSyntaxOn

\NewDocumentCommand{\matrixop}{ m m }
{
    \luaexec{
        matrop(#1,#2)
    }
}
\ExplSyntaxOff

\begin{document}
\matrixop{{1,2,3},{4,5,6}}{{7,8,9},{10,11,12}}
\end{document}

该文件lua2.lua包含以下内容:

function matrop (mat1, mat2)
local matrix = require 'matrix'
m1 = matrix {mat1}
m2 = matrix {mat2}
m3 = matrix.add(m1,m2)
a  = matrix.latex(m3,c)
tex.print(a)
end

由此产生的问题是,在matrix.lua矩阵中定义为例如

m = matrix{{1,2,3},{4,5,6}}

因此,我必须将其传递为mat1类似于的内容{1,2,3},{4,5,6}。但是,就目前情况而言,上面的代码matrop(#1,#2)相当于

matrop({1,2,3},{4,5,6},{7,8,9},{10,11,12})

其中,分隔行的逗号mat1对宏是可见的,因此matrop可以看到 4 个逗号分隔的参数,而不是 2 个逗号分隔的参数。Lua 理解我在删除“额外”的两个参数后传递了一对单行矩阵(这花了很长时间才弄清楚)。在每个参数周围添加额外的括号来隐藏逗号是行不通的,因为它会搞乱matrix预期的表。我的想法是用 替换分隔行的逗号*,将其传递给matrop,使用字符串在 lua 中将 恢复*为逗号,将字符串转换回表,然后将其传递给矩阵命令(这需要大量阅读和摆弄,我根本不了解 lua)。结果如下:

\documentclass{article}
\usepackage{xparse}
\usepackage{luacode}
\usepackage{fontspec}

\directlua{dofile("matrix.lua")}
\directlua{dofile("lua2.lua")}
\ExplSyntaxOn

\NewDocumentCommand{\matrixop}{ m m }
{
    % quotes are so that matrop sees args as strings
    \luaexec{
        matrop("{#1}","{#2}")
    }
}
\ExplSyntaxOff

\begin{document}
% row separator now a *
\matrixop{{1,2,3}*{4,5,6}}{{7,8,9}*{10,11,12}}
\end{document}

其中lua2.lua如下:

function matrop (mat1, mat2)
    -- replace *'s with ,'s
    s1 = string.gsub(mat1,"*",",")
    s2 = string.gsub(mat2,"*",",")

    -- functions that load resulting strings
    f1 = assert(loadstring("return"..s1))
    f2 = assert(loadstring("return"..s2))

    -- t1 and t2 are now tables (as I understand it)
    t1 = f1()
    t2 = f2()

    local matrix = require 'matrix'
    -- pass table entries (rows) to matrix definers
    m1 = matrix {t1[1],t1[2]}
    m2 = matrix {t2[1],t2[2]}
    m3 = matrix.add(m1,m2)
    a  = matrix.latex(m3,c)
    tex.print(a)
end

我确信我上面做了很多不好/不恰当/可怕的事情。我的问题是:我到底应该怎么做?有没有一种简单的方法可以将定义矩阵所需的信息传递给 lua?欢迎提出任何建议、评论、提示、解决方案等。

答案1

如果您使用(IMHO)更用户友好的输入,类似于(a,b,c)(d,e,f),那么使用基本 lua 命令创建矩阵很容易,而无需知道矩阵的大小。

\documentclass{article}
\usepackage{xparse}
\usepackage{fontspec}
\usepackage{filecontents}

\begin{filecontents*}{luaFunctions.lua}
function matrop (mat1, mat2)
    local matrix = require 'matrix'

    m1 = matrix{unpack(CreateMatrix(mat1))}
    m2 = matrix{unpack(CreateMatrix(mat2))}
    m3 = matrix.add(m1,m2)

    --tex.print("\\\\")
    tex.sprint( matrix.latex(m1,c).."+")
    tex.sprint( matrix.latex(m2,c).."=")
    tex.sprint( matrix.latex(m3,c))
end

function CreateMatrix(str)
    rows={}

    -- get the elements between the braces 
    -- and execute the following function
    string.gsub(str, "%((.-)%)",
        function(sub)
            -- for debugging
            --tex.print("Row: "..sub.."\\\\")
            -- split the string at ','
            elements = string.explode(sub,",")
            row={}
            for i,e in ipairs(elements) do
                -- remove spaces (not really necessary)
                e = string.gsub(e," ","")
                -- insert the element to the row-table
                table.insert(row,e)
                -- for debugging
                --tex.print("Element :"..e.."\\\\")            
            end
            -- insert the row-table to the rows-table
            table.insert(rows,row)
        end 
    )

    return rows
end
\end{filecontents*}

\directlua{dofile("luaFunctions.lua")}
\ExplSyntaxOn

\NewDocumentCommand{\matrixop}{mm}{
    \directlua{matrop("#1","#2")}}

\ExplSyntaxOff

\begin{document}\noindent
\matrixop{(-1)} {( 10)}\\[2ex]
%
\matrixop{(-1, -2, -3)} {( 10, 11, 12)}\\[2ex]
%
\matrixop{(-1, -2, -3)(4, 5, -6)}{(7, -98, 9) (10, 11, 12)}\\[2ex]
%
\matrixop{(-1, -2, -3, 4, 5, -6)(8, 4, 1, 6, 8, 3)} {(7, -98, 9, 10, 11, 12)(8, 4, 1, 6, 8, 3)}\\[2ex]
%
\matrixop{(-1, -2, -3)(4, 5, -6)(8, 4, 1)(6, 8, 3)} {(7, -98, 9) (10, 11, 12)(8, 4, 1)(6, 8, 3)}\\[2ex]
%
\matrixop{(-1, -2)( -3, 4)( 5, -6)(8, 4)( 1, 6)( 8, 3)} {(7, -98)( 9, 10)( 11, 12)(8, 4)( 1, 6)( 8, 3)}\\[2ex]
%
\matrixop{(-1)( -3)( 5)} {(7)( 9)( 11)}\\[2ex]
\end{document}

在此处输入图片描述

编辑 Matlab 样式: 如果您想使用类似于 Matlab 的矩阵输入,则可以使用以下函数。这里不需要使用包xparse,也不需要知道用户为函数提供了多少个矩阵(及其维度)。

\documentclass{article}
\usepackage{fontspec}
\usepackage{filecontents}

\begin{filecontents*}{luaFunctions.lua}
function matropMatlab (mat)
    local matrix = require 'matrix'

    matrices = CreateMatrixMatlab(mat)
    m1 = matrix{unpack(matrices[1])}
    m2 = matrix{unpack(matrices[2])}
    m3 = matrix.add(m1,m2)

    tex.sprint( matrix.latex(m1,c).."+")
    tex.sprint( matrix.latex(m2,c).."=")
    tex.sprint( matrix.latex(m3,c))
end

function CreateMatrixMatlab(str)    
    matrices={}
    string.gsub(str, "%[(.-)%]",
        function(sub)
            splitedRows = string.explode(sub,";")
            rows={}
            for i,sr in ipairs(splitedRows) do
               elements = string.explode(sr)
               row={}
               for k,e in ipairs(elements) do
                  table.insert(row,e)
               end       
               table.insert(rows,row)
            end
            table.insert(matrices,rows)
        end 
    )    
    return matrices
end
\end{filecontents*}

\directlua{dofile("luaFunctions.lua")}

\def\matrixopMatlab#1{%
    \directlua{matropMatlab("#1")}}

\begin{document}
\matrixopMatlab{
[16 3 2 13; 5 -10 11 8; 19 65 7 12; 41 15 -14 1] 
[4 3 21 17; 5 14 11 23; 18 1 71 12; 24 15 44 14]}\\[2ex]
\matrixopMatlab{
[16 3 2 13 1; 5 -10 11 8 2; 19 65 7 12 3] 
[4 3 21 17 1; 5 14 11 23 2; 18 1 71 12 3]}
\end{document}

答案2

这不是一个真正的答案(因为你已经分析了这个问题),而只是我的想法:

我认为你做得很好!如果你将宏扩展视为文本替换,问题可能会更加明显:

\NewDocumentCommand{\matrixop}{ m m }
{
    \luaexec{
        matrop(#1,#2)
    }
}

本质上等同于

\def\matrixop#1#2{\luaexec{matrop(#1,#2)}

对吧?所以当你调用 时\matrixop{{1,2,3},{4,5,6}}{{7,8,9},{10,11,12}}#1会得到{1,2,3},{4,5,6}#2 {7,8,9},{10,11,12}(这就是你写的)。所以上面的替换文本\def是:\luaexec{matrop(#1,#2)-> ,一个带有四个参数的函数调用。如果你知道你总是用逗号分隔宏,那么你可以定义带有四个参数的\luaexec{matrop({1,2,3},{4,5,6},{7,8,9},{10,11,12})函数:matrop()

function matrop (_1, _2, _3, _4)
  m1 = matrix {_1,_2}
  m2 = matrix {_3,_4}
  m3 = matrix.add(m1,m2)
  a  = matrix.latex(m3,c)
  tex.print(a)
end

我认为事实就是如此。

我不会选择你的第二种解决方案,因为它可能不安全(loadstring("return"..s1)。如果它不能解析,你的代码就会崩溃。而且仅仅用一个分隔符替换另一个分隔符是不值得的(IMHO)。

答案3

感谢 Holle 和 Gundla 先生,这就是最终的结果。我想在这里分享它,因为我认为人们会发现它很有用:


以下是一个经过修改的 LaTeX 接口,用于 lua 矩阵计算模块。结果是可以在“文档中”执行矩阵计算。Matrixop.sty 提供了两个宏:\matrixop<args>\formatmatrix{matrix}。其基本形式之一:

\matrixop{operation}{matrix1}{matrix2}

执行计算并排版操作和结果。例如,左侧的输入产生右侧的输出:

在此处输入图片描述

该模块提供的大多数操作matrix都支持数字和符号形式:加法、减法、乘法、求逆、“除法”、行列式、向量标量和交叉积。有关详细信息,请将文件matrixop.stymatrix.luamatrixop.lua放在matrixop-test.tex同一目录中(或安装.sty并将 lua 文件放在同一目录中)并matrixop-test.tex使用进行编译lualatex

文件:matrixop.sty

\NeedsTeXFormat{LaTeX2e}

\ProvidesPackage{matrixop}[2012/09/26 ver 1.0]


\RequirePackage{xparse}
\RequirePackage{fontspec}
\RequirePackage{mathtools}
\RequirePackage{geometry}

\DeclareMathOperator{\rref}{rref}

\directlua{dofile(kpse.find_file("matrixop.lua"))}
\directlua{dofile(kpse.find_file("matrix.lua"))}

\ExplSyntaxOn

\seq_new:N \g__matrop_symbops_seq
\seq_gset_split:Nnn \g__matrop_symbops_seq {,}{add,sub,mul,det,transpose,scalar,cross,add*,sub*,mul*,transpose*,cross*}

% Main Document Command: \matrixop
% - starred gives symbolic output
% - operation is first mandatory argument
% - operations are: add, sub, mul, div, invert, pow, root, det, dogauss, scalar and cross
% - starring the operation name, e.g \matrixop{mul*}... doesn't typeset operation but returns
% - the resulting matrix (not in useable form) in the macro \mout
% - root and pow require a numeric argument after the operation name giving the power/root, e.g. \matrixop{pow}[3]{matrix}
% - the final, optional, argument is the number of digits to round the output to

\NewDocumentCommand{\matrixop}{ s m o m g o }
    {
        \IfBooleanTF{#1}
        { % if star
            \seq_if_in:NnTF \g__matrop_symbops_seq {#2}
            {
            \IfNoValueTF{#5}
                { % if unary
                    \directlua{matropsymb("#2","#4")}
                }
                { % if binary
                    \directlua{matropsymb("#2","#4","#5")}
                }
            }
            {
                \msg_error:nnx {matrop} {Operation~not~compatible~with~symbolic} {#2}
            }
        }
        { % if no star
                % if not root or pow
            \IfNoValueTF{#3}
                { % if not binary
                    \IfNoValueTF{#5}
                        { % if unary
                            % if not round
                            \IfNoValueTF{#6}
                                % then unary op, no round
                                {\directlua{matrop("#2","#4")}}
                                % then unary op, with round
                                {\directlua{matrop("#2","#4","#6")}}
                        }
                        { % if binary
                            % if not round
                            \IfNoValueTF{#6}
                                % then binary, no round
                                {\directlua{matrop("#2","#4","#5")}}
                                % then binary, with round
                                {\directlua{matrop("#2","#4","#5","#6")}}
                        }
                }
                { % root or pow
                    % if not round
                    \IfNoValueTF{#6}
                        % then root or pow, no round
                        {\directlua{matrop("#2","#3","#4")}}
                        % then root or pow, with round
                        {\directlua{matrop("#2","#3","#4","#6")}}
                }
        }
    }

% This takes a macro that contains a matrix, and typesets the result.
% - first arg is optional to specify column justification

\NewDocumentCommand{\formatmatrix}{ O{r} m}
    {
        \matrixop_format:nn {#1}{#2}
    }

% helper macro for the above

\cs_new:Npn \matrixop_format:nn #1#2
    {
        \tl_set:NV \l_tmpa_tl {#2}
        \tl_replace_all:Nnn \l_tmpa_tl {)(}{\\}
        \tl_replace_all:Nnn \l_tmpa_tl {,}{&}
        \tl_set:Nx \l_tmpa_tl {\tl_tail:N \l_tmpa_tl}
        \tl_replace_all:Nnn \l_tmpa_tl {)}{}
        \begin{bmatrix*}[#1]
            \tl_use:N \l_tmpa_tl
        \end{bmatrix*}
    }

\ExplSyntaxOff

文件:matrixop.lua

function matropsymb (...)
        -- desired operation is passed as first arg
        local op = arg[1]
    local matrix = require 'matrix'
        local symbol = matrix.symbol
        local m1, m2, mout

        -- determine whether starred
        local test = op
        if string.match(test,"*") then
            -- if so, then set flag and drop star
            op = string.sub(op,1,-2)
            star = true
        else
            star = false
        end -- if string

        -- if 2 args, must be unary
        if #arg == 2 then
            m1   = matrix{unpack(CreateMatrix(arg[2]))}:replace(symbol)
            mout = matrix[op](m1)
        -- if 3 args, must be binary
        elseif #arg == 3 then
                m1   = matrix{unpack(CreateMatrix(arg[2]))}:replace(symbol)
                m2   = matrix{unpack(CreateMatrix(arg[3]))}:replace(symbol)
                mout = matrix[op](m1,m2)--:replace(symbol)
        end

-- if no star, then typeset operation and result    
if not star then
  if op == "mul" then
    tex.sprint( matrix.latex(m1,"r").."\\cdot")
    tex.sprint( matrix.latex(m2,"r").."=")
    tex.sprint( matrix.latex(mout,"r"))

  elseif op == "add" then 
    tex.sprint( matrix.latex(m1,"r").."+")
    tex.sprint( matrix.latex(m2,"r").."=")
    tex.sprint( matrix.latex(mout,"r"))

  elseif op == "sub" then
    tex.sprint( matrix.latex(m1,"r").."-")
    tex.sprint( matrix.latex(m2,"r").."=")
    tex.sprint( matrix.latex(mout,"r"))

    elseif op == "det" then
        tex.sprint( "\\det"..matrix.latex(m1,"r").."=")
        tex.sprint(mout)

    elseif op == "transpose" then
        tex.sprint(matrix.latex(m1,"r").."^{T}".."\\mkern -8mu=")
        tex.sprint(matrix.latex(mout,"r"))

    elseif op == "scalar" then
        m1 = matrix.transpose(m1)
        m2 = matrix.transpose(m2)
        tex.sprint(matrix.latex(m1,"r").."\\cdot"..matrix.latex(m2,"r").."=")
        tex.sprint(mout)

    elseif op == "cross" then
        tex.sprint(matrix.latex(m1,"r").."\\times"..matrix.latex(m2,"r").."=")
        tex.sprint(matrix.latex(mout,"r"))

  end -- if
end -- if not star

-- store output matrix in macro.
-- tex.print("\\gdef\\matout{"..ReturnMatrix(mout).."}")
    if op ~= "det" then
        if op ~="scalar" then
        tex.print("\\gdef\\matout{"..ReturnMatrix(mout).."}")
        end
    end

end -- function

function matrop (...)
        -- desired operation is passed as first arg
        local op = arg[1]
    local matrix = require 'matrix'
        local m1, m2, m3, mout

        -- determine whether starred
        local test = op
        if string.match(test,"*") then
            op = string.sub(op,1,-2)
            star = true
        else
            star = false
        end

        -- to test whether args are numbers or matrices
        local test2 = tonumber(arg[2])
        local test3 = tonumber(arg[3])

        if #arg == 2 then
        -- if 2 args, then unary
        -- dogauss, alters original matrix so handled differently
            m1   = matrix{unpack(CreateMatrix(arg[2]))}
            if op == "dogauss" then
                mout = matrix.copy(m1)
                matrix[op](mout)
            else
                mout = matrix[op](m1)
            end -- if gauss
        -- several cases for 3 args
        elseif #arg == 3 then
            -- if second arg is a number-> root or pow
            if test2 then
                m1   = matrix{unpack(CreateMatrix(arg[3]))}
                mout = matrix[op](m1,tonumber(arg[2]))
            else
                -- if not then if arg 3 is a number-> unary with round
                -- as above, dogauss handled differently
                if test3 then
                m1   = matrix{unpack(CreateMatrix(arg[2]))}
                    if op == "dogauss" then
                        mout = matrix.copy(m1)
                        matrix[op](mout)
                        mout = matrix.round(mout,arg[3])
                    else
                        m2   = matrix[op](m1)
                        mout = matrix.round(m2,arg[3])
                    end -- if dogauss
                -- if arg 3 is nan-> binary no round
                else
                    m1   = matrix{unpack(CreateMatrix(arg[2]))}
                    m2   = matrix{unpack(CreateMatrix(arg[3]))}
                    mout = matrix[op](m1,m2)
                end -- if test3
            end -- if test2
        else -- pow or root with round or binary with round
            if test2 then
                m1   = matrix{unpack(CreateMatrix(arg[3]))}
                m2   = matrix[op](m1,tonumber(arg[2]))
                mout = matrix.round(m2,arg[4])
            else
                m1   = matrix{unpack(CreateMatrix(arg[2]))}
                m2   = matrix{unpack(CreateMatrix(arg[3]))}
                m3   = matrix[op](m1,m2)
                mout = matrix.round(m3,arg[4])
            end -- if test2
        end -- if #arg

-- no star-> typeset operation and result   
if not star then
  if op == "mul" then
    tex.sprint( matrix.latex(m1,"r").."\\cdot")
    tex.sprint( matrix.latex(m2,"r").."=")
    tex.sprint( matrix.latex(mout,"r"))

  elseif op == "add" then 
    tex.sprint( matrix.latex(m1,"r").."+")
    tex.sprint( matrix.latex(m2,"r").."=")
    tex.sprint( matrix.latex(mout,"r"))

  elseif op == "div" then
    tex.sprint( matrix.latex(m1,"r").."\\cdot")
    tex.sprint( matrix.latex(m2,"r").."^{-1}".."\\mkern -8mu=")
    tex.sprint( matrix.latex(mout,"r"))

  elseif op == "sub" then
    tex.sprint( matrix.latex(m1,"r").."-")
    tex.sprint( matrix.latex(m2,"r").."=")
    tex.sprint( matrix.latex(mout,"r"))

    elseif op == "invert" then
        tex.sprint( matrix.latex(m1,"r").."^{-1}".."\\mkern -8mu=")
        tex.sprint( matrix.latex(mout,"r"))

    elseif op == "det" then
        tex.sprint( "\\det"..matrix.latex(m1,"r").."=")
        tex.sprint(mout)

    elseif op == "dogauss" then
        tex.sprint("\\rref"..matrix.latex(m1,"r").."=")
        tex.sprint( matrix.latex(mout,"r"))

    elseif op == "root" then
        tex.sprint(matrix.latex(m1,"r").."^{\\frac{1}{"..arg[2].."}}".."\\mkern -8mu=")
        tex.sprint(matrix.latex(mout,"r"))

    elseif op == "transpose" then
        tex.sprint(matrix.latex(m1,"r").."^{T}".."\\mkern -8mu=")
        tex.sprint(matrix.latex(mout,"r"))

    elseif op == "pow" then
        tex.sprint(matrix.latex(m1,"r").."^{"..arg[2].."}".."\\mkern -8mu=")
        tex.sprint(matrix.latex(mout,"r"))

    elseif op == "scalar" then
        m1 = matrix.transpose(m1)
        m2 = matrix.transpose(m2)
        tex.sprint(matrix.latex(m1,"r").."\\cdot"..matrix.latex(m2,"r").."=")
        tex.sprint(mout)

    elseif op == "cross" then
        tex.sprint(matrix.latex(m1,"r").."\\times"..matrix.latex(m2,"r").."=")
        tex.sprint(matrix.latex(mout,"r"))
  end -- if op
end -- if not star

tex.print("\\gdef\\matout{"..ReturnMatrix(mout).."}")

end -- function

-- builds matrix table from input passed by tex
function CreateMatrix(str)
    rows={}

    -- get the elements between the braces
    -- and execute the following function
    string.gsub(str, "%((.-)%)",
        function(sub)
            -- for debugging
            -- tex.print("Row: "..sub.."\\\\")
            -- split the string at ','
            elements = string.explode(sub,",")
            row={}
            for i,e in ipairs(elements) do
                -- remove spaces (not really necessary)
                e = string.gsub(e," ","")
                -- insert the element to the row-table
                table.insert(row,e)
                -- for debugging
                -- tex.print("Element :"..e.."\\\\")
            end
            -- insert the row-table to the rows-table
            table.insert(rows,row)
        end
    )

    return rows
end

-- returns output matrix in format that can be passed back
function ReturnMatrix(t)
    if not (type(t)=="table") then
        return t
    else
    local str = ""
        for i=1,#t do
            str=str.."("..t[i][1]
                for j=2,#t[1] do
                    str=str..","..t[i][j]
                end
            str=str..")"
        end
    return str
    end
end

文件:matrix.lua 该文件可以在这里找到:https://github.com/davidm/lua-matrix 我稍微修改了文件matrix.lua。特别是,我改变了matrix.latex函数。 为了使宏正常工作,您需要在源代码中将该函数编辑为以下内容(第 898-918 行)

--// matrix.latex ( mtx [, align] )
-- LaTeX output
function matrix.latex( mtx, align )
    -- align : option to align the elements
    --      c = center; l = left; r = right
    --      \usepackage{dcolumn}; D{.}{,}{-1}; aligns number by . replaces it with ,
    local align = align or "c"
    local str = "\\begin{bmatrix*}[r]"
    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
            str = str.." & "..getstr(mtx[i][j])
        end
        -- close line
        if i == #mtx then
            str = str.."\n"
        else
            str = str.." \\\\\n"
        end
    end
    return str.."\\end{bmatrix*}"
end

文件:matrixop-test.tex

\documentclass{article}
\usepackage{matrixop}
\usepackage{showexpl}

\setlength{\parindent}{0pt}

\begin{document}

\begin{center}{\Huge Matrix operations in \TeX}\end{center}

\textbf{matrixop.sty} provides two commands: \verb=\matrixop= and \verb=\formatmatrix=.  The package requires that the document be compiled with Lua\LaTeX.  Matrices are passed to the macro either directly or in macros.  A matrix is passed as bracket delimited rows with comma separated entries, e.g. $(1,2,3)(4,5,6)$ would represent a $2\times 3$ matrix.  The \verb=\matrixop= macro itself takes a variety of forms.
\begin{enumerate}
    \item \verb=\matrixop<args>= Performs the operation and typesets the operation and result.
    \item \verb=\matrixop*<args>= Produces symbolic rather than calculated results.
    \item \verb=\matrixop<args>[n]= Rounds the entries of the resulting matrix to $n$ decimal places.
    \item \verb=\matrixop{op*}<args>= Performs the operation, but does not typeset the operation or result.
\end{enumerate}
In all cases, excluding symbolic determinant or symbolic dot product, the resulting matrix is stored in the macro \verb=\matout= in the same format as input.  Thus, \verb=\matout= can be reused as input.  Since \verb=\matout= is overwritten after each operation, it may be necessary to save it via, e.g. \verb=\let\mymat\matout=, so that it can be used later.  The supported operations are
\begin{itemize}
    \item Binary:
        \begin{itemize}
            \item add
            \item sub
            \item mul
            \item div
            \item scalar (dot product)
            \item cross (cross product)
        \end{itemize}
    \item Unary:
        \begin{itemize}
            \item det
            \item invert
            \item dogauss (returns $\rref$)
            \item root
            \item pow
            \item transpose
        \end{itemize}
\end{itemize}

The operations that support symbolic output are: add, mul, sub, det, transpose, scalar, and cross.

\section{Usage}

\def\matA{(1,2,3)(4,5,6)(7,0,9)}
\def\matB{(1,2,-1)(2,2,4)(1,3,-3)}
\def\matC{(1,1,2)(2,3,4)(5,6,7)}
\def\vA{(1)(2)(3)}
\def\vB{(4)(5)(6)}
\def\vC{(a)(b)(c)}
\def\matD{(a,b,c)(d,e,f)(g,h,i)}
\def\matE{(r,s,t)(u,v,w)(x,y,z)}

\begin{LTXexample}[pos=r]
\def\matA{(1,2,3)(4,5,6)(7,0,9)}
\def\matB{(1,2,-1)(2,2,4)(1,3,-3)}
\[\matrixop{mul}{\matA}{\matB}\]
\end{LTXexample}

For symbolic output, we may use (symbolic can be used with numeric input as well)

\begin{LTXexample}[pos=b, wide=true]
\def\matD{(a,b,c)(d,e,f)(g,h,i)}
\def\matE{(r,s,t)(u,v,w)(x,y,z)}
\[\matrixop*{mul}{\matD}{\matE}\]
\end{LTXexample}

If we prefer that the output is not typeset, then a star can be appended to the operation name within the first argument.  In this case the matrix (or number) resulting from the operation is stored in the \verb=\matout= macro and can be invoked as such before the next operation is executed, or stored for later use.  With the following code:

\begin{LTXexample}[pos=r,rframe=]
\matrixop{invert*}{\matA} % output stored in \matout
\let\ainv\matout % save for later
\matrixop{invert*}{\matB} % etc.
\let\binv\matout
\matrixop{mul*}{\binv}{\ainv}[5]
\let\bainv\matout
\matrixop{mul*}{\matA}{\matB}
\let\abprod\matout
\matrixop{mul*}{\abprod}{\bainv}[3]
\end{LTXexample}

% this is just here because of grouping introduced by showexpl, ie. the definitions
% above don't leave the scope of the environment
\matrixop{invert*}{\matA}
\let\ainv\matout
\matrixop{invert*}{\matB}
\let\binv\matout
\matrixop{mul*}{\binv}{\ainv}[5]
\let\bainv\matout
\matrixop{mul*}{\matA}{\matB}
\let\abprod\matout
\matrixop{mul*}{\abprod}{\bainv}[3]

We could then type,
\begin{LTXexample}[pos=b]
If $A$ and $B$ are as given below, 
\[
        A=\formatmatrix{\matA}\qquad B=\formatmatrix{\matB}
\]
Then the product $AB$
\[
    AB=\formatmatrix{\abprod}
\]
when multiplied (on the right) by the matrix $B^{-1}A^{-1}$
\[
    B^{-1}A^{-1}=\formatmatrix{\bainv}
\]
should produce the identity matrix,
\[
    AB(B^{-1}A^{-1})=\formatmatrix{\abprod}\cdot\formatmatrix{\bainv}=\formatmatrix{\matout}
\]
\end{LTXexample}

Some more examples below

\begin{LTXexample}[pos=b]
$\matrixop*{add}{\matD}{\matE}$
\end{LTXexample}
\begin{LTXexample}[pos=r]
$\matrixop{mul}{\matA}{\matB}$
\end{LTXexample}
\begin{LTXexample}[pos=b,wide=true]
$\matrixop*{mul}{\matD}{\matE}$
\end{LTXexample}
\begin{LTXexample}[pos=r]
$\matrixop{div}{\matA}{\matB}$
\end{LTXexample}
\begin{LTXexample}[pos=r]
$\matrixop{sub}{\matA}{\matB}$
\end{LTXexample}
\begin{LTXexample}[pos=b]
$\matrixop*{sub}{\matD}{\matE}$
\end{LTXexample}
\begin{LTXexample}[pos=b]
$\matrixop{invert}{\matA}$
\end{LTXexample}
\begin{LTXexample}[pos=r]
$\matrixop{invert}{\matA}[4]$
\end{LTXexample}
\begin{LTXexample}[pos=r]
$\matrixop{det}{\matA}$
\end{LTXexample}
\begin{LTXexample}[pos=b]
$\matrixop*{det}{\matE}$
\end{LTXexample}
\begin{LTXexample}[pos=r]
$\matrixop{dogauss}{\matA}$
\end{LTXexample}
\begin{LTXexample}[pos=b]
$\matrixop{root}[5]{\matA}$
\end{LTXexample}
\begin{LTXexample}[pos=r]
$\matrixop{root}[5]{\matA}[4]$
\end{LTXexample}
\begin{LTXexample}[pos=r]
$\matrixop{transpose}{\matA}$
\end{LTXexample}
\begin{LTXexample}[pos=r]
$\matrixop{pow}[3]{\matA}$
\end{LTXexample}
\begin{LTXexample}[pos=r]
$\matrixop{scalar}{\vA}{\vB}$
\end{LTXexample}
\begin{LTXexample}[pos=r]
$\matrixop*{scalar}{\vA}{\vC}$
\end{LTXexample}
\begin{LTXexample}[pos=r]
$\matrixop{cross}{\vA}{\vB}$
\end{LTXexample}
\begin{LTXexample}[pos=r]
$\matrixop*{cross}{\vA}{\vC}$
\end{LTXexample}

\end{document}

相关内容