我对 LaTeX 还比较陌生,在使用这个出色的代码时遇到了语法问题这里,它允许在 LaTeX 中进行任意矩阵运算。
我编写了一个宏来生成某些矩阵。例如:
\def\GetRotationMatrixZ#1{
cos(#1),-sin(#1),0,
sin(#1), cos(#1),0,
0, 0,1
}
现在我想将它与链接代码的 \matnew、\matset 命令一起使用。然而,我尝试过的所有方法都失败了。我尝试了宏语法的许多变体,但还是卡住了。
编辑:主要用例看起来像:
\matnew \transformMatrixA
\matset \transformMatrixA {\GetRotationMatrixY\whatever}
% . . .
\matmul \transformMatrix \transformMatrixA \transformMatrixB
我尝试过类似的事情;我不记得具体是哪一个。这个特定示例给出:
Unexpected comma: extra arguments ignored.
答案1
LaTeX3
人们会给出更权威的答案(特别是他们知道如何生成变体来\matset
扩展其论点)。与此同时,也许这会有所帮助(似乎问题在于您没有使用分号来结束行,并且存在扩展问题)。
TeX
是一种宏语言,其中的关键词是扩展。即使你使用更高的抽象级别,例如LaTeX2
(它尽力向用户 \emph{hide} 编程可能性)或LaTeX3
(相反,它有一个非常深思熟虑和复杂的方案来使编码更容易,同时将程序员的任务与最终用户工具明确分开),你也无法逃避这一点。\matset
你链接的代码中的宏似乎没有扩展它的参数。如果你尝试将它用作\matset\MatrixA {\macro{3}}
,它将收到 \macro{3}
,而不是它似乎期望的以分号分隔的行。您首先需要告诉TeX
扩展\macro{3}
到该列表或行。程序员可以立即\LaTeX3
生成\matset
首先扩展其参数的变体,作为一种解决方法,\expandafter\matset\expandafter\MatrixA \expandafter{\macro{3}}
就可以了。请注意,括号{
是输入流的一部分,必须通过 跳过\expandafter
。
%% (to be embedded in the code from [there](https://tex.stackexchange.com/a/112683/34359))
\def\GetRotationMatrix #1{%
cos(#1), -sin(#1), 0;
sin(#1), cos(#1), 0;
0, 0, 1 }
\expandafter\matset\expandafter\transformMatrixA \expandafter
{\GetRotationMatrix {3.141592653}}
\begin{equation}
\mattypeset \transformMatrixA
\end{equation}
此处嵌入在布鲁诺·勒·弗洛克法典
% Programming-level functions: \fpm_new:N, \fpm_set:Nn, \fpm_gset:Nn,
% \fpm_add:NNN, \fpm_sub:NNN, \fp_neg:NN, \fp_transpose:NN, \fp_mul:NNN.
%
% Expandable programming-level functions: \fpm_lines:N, \fpm_columns:N,
% \fpm_get:Nnn.
%
% Document-level functions: \matnew, \matset, \matgset, \matadd,
% \matsub, \matmul, \mattypeset.
%
\RequirePackage{expl3}
{
\ExplSyntaxOn
%
% Programming-level code, for adding, multiplying, matrices. A matrix
% of size |MxN| is stored as a token list of the form
%
% \s__fpm { M } { N } { {a11} ... {a1N} } ... { {aM1} ... {aMN} } ;
%
% where |\s__fpm| is a marker used to recognize matrices, |M| and |N|
% are non-negative integers, and |aij| are floating point numbers.
%
% (1) Variables.
%
\cs_new_eq:NN \s__fpm \scan_stop: % A marker.
\tl_const:Nn \c_empty_fpm { \s__fpm { 0 } { 0 } ; }
\cs_new_eq:NN \l__fpm_tmpa_fpm \c_empty_fpm
\seq_new:N \l__fpm_lines_seq
\int_new:N \l__fpm_lines_A_int
\int_new:N \l__fpm_lines_B_int
\int_new:N \l__fpm_columns_A_int
\int_new:N \l__fpm_columns_B_int
\tl_new:N \l__fpm_matrix_A_tl
\tl_new:N \l__fpm_matrix_B_tl
\tl_new:N \l__fpm_matrix_C_tl
\seq_new:N \l__fpm_matrix_A_seq
\seq_new:N \l__fpm_matrix_B_seq
\seq_new:N \l__fpm_one_line_A_seq
\seq_new:N \l__fpm_one_line_B_seq
\tl_new:N \l__fpm_one_line_A_tl
\int_new:N \l__fpm_tmpa_int
%
% (2) Variants and generic helpers.
%
%
% (3) Storing matrices.
%
\cs_new_protected:Npn \fpm_new:N #1
{ \cs_new_eq:NN #1 \c_empty_fpm }
\cs_new_protected_nopar:Npn \fpm_set:Nn
{ \__fpm_set:NNn \tl_set:Nx }
\cs_new_protected_nopar:Npn \fpm_gset:Nn
{ \__fpm_set:NNn \tl_gset:Nx }
\cs_new_protected:Npn \__fpm_set:NNn #1#2#3
{
\seq_set_split:Nnn \l__fpm_lines_seq { ; } {#3}
\seq_set_filter:NNn \l__fpm_lines_seq \l__fpm_lines_seq
{ ! \tl_if_empty_p:n {##1} }
%
% Now all lines are non-empty.
%
\tl_clear:N \l__fpm_matrix_A_tl
\int_zero:N \l__fpm_lines_A_int
\int_zero:N \l__fpm_columns_A_int
\seq_map_inline:Nn \l__fpm_lines_seq
{
\int_incr:N \l__fpm_lines_A_int
\seq_set_from_clist:Nn \l__fpm_one_line_A_seq {##1}
\int_set:Nn \l__fpm_tmpa_int { \seq_count:N \l__fpm_one_line_A_seq }
\int_compare:nNnT \l__fpm_columns_A_int = \c_zero
{ \int_set_eq:NN \l__fpm_columns_A_int \l__fpm_tmpa_int }
\int_compare:nNnF \l__fpm_tmpa_int = \l__fpm_columns_A_int
{ \seq_map_break:n { \msg_error:nn { fpm } { invalid-size } } }
\tl_put_right:Nx \l__fpm_matrix_A_tl
{ { \seq_map_function:NN \l__fpm_one_line_A_seq \__fpm_set_aux:n } }
}
#1 #2
{
\s__fpm
{ \int_use:N \l__fpm_lines_A_int }
{ \int_use:N \l__fpm_columns_A_int }
\l__fpm_matrix_A_tl
;
}
}
\cs_new:Npn \__fpm_set_aux:n #1 { { \fp_to_tl:n {#1} } }
%
% (4) Extracting the size of a matrix, and its contents.
% |#1| is the matrix, |#2|, |#3| integer variables receiving the
% number of lines and of columns, and |#4| a token list receiving the
% contents of the matrix.
%
\cs_new_protected:Npn \__fpm_get_parts:NNNN #1#2#3#4
{ \exp_after:wN \__fpm_get_parts:NnnwNNN #1 #2 #3 #4 }
\cs_new_protected:Npn \__fpm_get_parts:NnnwNNN \s__fpm #1#2#3 ; #4#5#6
{
\int_set:Nn #4 {#1}
\int_set:Nn #5 {#2}
\tl_set:Nn #6 {#3}
}
%
% (5) Some expandable functions: getting one entry, getting the size.
%
\cs_new:Npn \fpm_lines:N #1
{ \exp_after:wN \__fpm_lines:NnnwN #1 \use_i:nn }
\cs_new:Npn \fpm_columns:N #1
{ \exp_after:wN \__fpm_lines:NnnwN #1 \use_ii:nn }
\cs_new:Npn \__fpm_lines:NnnwN \s__fpm #1#2#3 ; #4 { #4 {#1} {#2} }
\cs_new:Npn \fpm_get:Nnn #1#2#3
{ \exp_after:wN \__fpm_get:Nnnwnn #1 #2 #3 }
\cs_new:Npn \__fpm_get:Nnnwnn \s__fpm #1#2#3 ; #4#5
{ \exp_args:Nf \tl_item:nn { \tl_item:nn {#3} {#4} } {#5} }
%
% (6) Summing matrices
%
\cs_new_protected_nopar:Npn \fpm_add:NNN { \__fpm_add:NNNN + }
\cs_new_protected_nopar:Npn \fpm_sub:NNN { \__fpm_add:NNNN - }
\cs_new_protected:Npn \__fpm_add:NNNN #1#2#3#4
{
\tl_set:Nn \l__fpm_sign_tl {#1}
\__fpm_get_parts:NNNN #3
\l__fpm_lines_A_int \l__fpm_columns_A_int \l__fpm_matrix_A_tl
\__fpm_get_parts:NNNN #4
\l__fpm_lines_B_int \l__fpm_columns_B_int \l__fpm_matrix_B_tl
\int_compare:nNnTF \l__fpm_lines_A_int = \l__fpm_lines_B_int
{
\int_compare:nNnTF \l__fpm_columns_A_int = \l__fpm_columns_B_int
{ \__fpm_add:N #2 }
{ \msg_error:nn { fpm } { invalid-size } }
}
{ \msg_error:nn { fpm } { invalid-size } }
}
\cs_new_protected:Npn \__fpm_add:N #1
{
\seq_set_split:NnV \l__fpm_matrix_A_seq { } \l__fpm_matrix_A_tl
\seq_set_split:NnV \l__fpm_matrix_B_seq { } \l__fpm_matrix_B_tl
\tl_clear:N \l__fpm_matrix_C_tl
\seq_mapthread_function:NNN
\l__fpm_matrix_A_seq
\l__fpm_matrix_B_seq
\__fpm_add_lines:nn
\tl_set:Nx #1
{
\s__fpm
{ \int_use:N \l__fpm_lines_A_int }
{ \int_use:N \l__fpm_columns_A_int }
\l__fpm_matrix_C_tl
;
}
}
\cs_new_protected:Npn \__fpm_add_lines:nn #1#2
{
\seq_set_split:Nnn \l__fpm_one_line_A_seq { } {#1}
\seq_set_split:Nnn \l__fpm_one_line_B_seq { } {#2}
\tl_put_right:Nx \l__fpm_matrix_C_tl
{
{
\seq_mapthread_function:NNN
\l__fpm_one_line_A_seq
\l__fpm_one_line_B_seq
\__fpm_add_entries:nn
}
}
}
\cs_new:Npn \__fpm_add_entries:nn #1#2
{ { \fp_to_tl:n { #1 \l__fpm_sign_tl #2 } } }
%
% (7) Negating all entries.
%
\cs_new_protected:Npn \fpm_neg:NN #1#2
{ \tl_set:Nx #1 { \exp_after:wN \__fpm_neg:Nnnw #2 } }
\cs_new:Npn \__fpm_neg:Nnnw \s__fpm #1#2#3 ;
{ \s__fpm {#1} {#2} \tl_map_function:nN {#3} \__fpm_neg_aux:n ; }
\cs_new:Npn \__fpm_neg_aux:n #1
{ { \tl_map_function:nN {#1} \__fpm_neg_auxii:n } }
\cs_new:Npn \__fpm_neg_auxii:n #1
{ { \fp_to_tl:n { - #1 } } }
%
% (8) Transposing a matrix.
%
\cs_new_protected:Npn \fpm_transpose:NN #1#2
{
\__fpm_get_parts:NNNN #2
\l__fpm_lines_A_int \l__fpm_columns_A_int \l__fpm_matrix_A_tl
\seq_set_split:NnV \l__fpm_matrix_A_seq { } \l__fpm_matrix_A_tl
\tl_clear:N \l__fpm_matrix_B_tl
\prg_replicate:nn { \l__fpm_columns_A_int }
{
\tl_put_right:Nx \l__fpm_matrix_B_tl
{ { \seq_map_function:NN \l__fpm_matrix_A_seq \__fpm_wrap_head:n } }
\seq_set_map:NNn \l__fpm_matrix_A_seq \l__fpm_matrix_A_seq
{ \tl_tail:n {##1} }
}
\tl_set:Nx #1
{
\s__fpm
{ \int_use:N \l__fpm_columns_A_int }
{ \int_use:N \l__fpm_lines_A_int }
\l__fpm_matrix_B_tl
;
}
}
\cs_new:Npn \__fpm_wrap_head:n #1 { { \tl_head:n {#1} } }
%
% (9) Multiplying matrices.
%
\cs_new_protected:Npn \fpm_mul:NNN #1#2#3
{
\int_compare:nNnTF { \fpm_columns:N #2 } = { \fpm_lines:N #3 }
{
\fpm_transpose:NN \l__fpm_tmpa_fpm #3
\__fpm_get_parts:NNNN #2
\l__fpm_lines_A_int \l__fpm_columns_A_int \l__fpm_matrix_A_tl
\__fpm_get_parts:NNNN #3
\l__fpm_lines_B_int \l__fpm_columns_B_int \l__fpm_matrix_B_tl
\tl_set:Nx #1
{
\s__fpm
{ \int_use:N \l__fpm_lines_A_int }
{ \int_use:N \l__fpm_columns_B_int }
\tl_map_function:NN \l__fpm_matrix_A_tl \__fpm_mul_line:n
;
}
}
{ \msg_error:nn { fpm } { invalid-size } }
}
\cs_new:Npn \__fpm_mul_line:n #1
{ { \exp_after:wN \__fpm_mul_line:Nnnwn \l__fpm_tmpa_fpm {#1} } }
\cs_new:Npn \__fpm_mul_line:Nnnwn \s__fpm #1#2#3 ; #4
{ \__fpm_mul_line:nn {#4} #3 \q_recursion_tail \q_recursion_stop }
\cs_new:Npn \__fpm_mul_line:nn #1#2
{
\quark_if_recursion_tail_stop:n {#2}
{
\fp_to_tl:n
{
\__fpm_mul_one:nwn #1 \use_none_delimit_by_q_stop:w
\q_mark #2 \q_nil \q_stop
0
}
}
\__fpm_mul_line:nn {#1}
}
\cs_new:Npn \__fpm_mul_one:nwn #1#2 \q_mark #3
{ #1 * #3 + \__fpm_mul_one:nwn #2 \q_mark }
%
%
% Messages.
%
\msg_new:nnn { fpm } { invalid-size }
{ Sizes~of~matrices~or~lines~don't~match. }
}
\RequirePackage{amsmath, siunitx}
{
\ExplSyntaxOn
%
% Turning matrices into arrays for display.
%
\cs_new_protected:Npn \fpm_to_array:N #1
{
\begin{pmatrix}
\exp_after:wN \__fpm_to_array:Nnnw #1
\end{pmatrix}
}
\cs_new_eq:NN \__fpm_newline: ? % Dummy def.
\cs_new_protected:Npn \__fpm_to_array:Nnnw \s__fpm #1#2#3 ;
{
\cs_gset_nopar:Npn \__fpm_newline:
{ \cs_gset_nopar:Npn \__fpm_newline: { \\ } }
\tl_map_inline:nn {#3}
{
\__fpm_newline:
\seq_set_split:Nnn \l__fpm_one_line_A_seq { } {##1}
\seq_set_map:NNn \l__fpm_one_line_A_seq \l__fpm_one_line_A_seq
{ \__fpm_to_array_entry:n {####1} }
\seq_use:Nnnn \l__fpm_one_line_A_seq { & } { & } { & }
}
}
\cs_new_protected:Npn \__fpm_to_array_entry:n #1
{
\str_case:nnn {#1}
{
{ nan } { \text{nan} }
{ inf } { \infty }
{ -inf } { -\infty }
}
{ \num{#1} }
}
}
\RequirePackage{xparse}
\ExplSyntaxOn
%
% Document-level functions.
%
\NewDocumentCommand { \matnew } { m } { \fpm_new:N #1 }
\NewDocumentCommand { \matset } { mm } { \fpm_set:Nn #1 {#2} }
\NewDocumentCommand { \matgset } { mm } { \fpm_gset:Nn #1 {#2} }
\NewDocumentCommand { \matadd } { mmm } { \fpm_add:NNN #1 #2 #3 }
\NewDocumentCommand { \matsub } { mmm } { \fpm_sub:NNN #1 #2 #3 }
\NewDocumentCommand { \matneg } { mm } { \fpm_neg:NN #1 #2 }
\NewDocumentCommand { \mattranspose } { mm } { \fpm_transpose:NN #1 #2 }
\NewDocumentCommand { \matmul } { mmm } { \fpm_mul:NNN #1 #2 #3 }
\NewDocumentCommand { \mattypeset } { m }
{ \fpm_to_array:N #1 }
\ExplSyntaxOff
\documentclass{article}
\begin{document}
\matnew \X
\matnew \Y
\matnew \Z
\matset \X { 1 , 2 + 3 ; 4 , 3.4e22 }
\matset \Y { 3 , 4 ; -5 , 6 }
\begin{align}
\matadd \Z \X \Y
\mattypeset \Z & = \mattypeset \X + \mattypeset \Y \\
\matsub \Z \X \Y
\mattypeset \Z & = \mattypeset \X - \mattypeset \Y \\
\matmul \Z \X \Y
\mattypeset \Z & = \mattypeset \X \times \mattypeset \Y \\
\matmul \Z \Y \X
\mattypeset \Z & = \mattypeset \Y \times \mattypeset \X
\end{align}
\def\GetRotationMatrix #1{%
cos(#1), -sin(#1), 0;
sin(#1), cos(#1), 0;
0, 0, 1 }
\expandafter\matset\expandafter\transformMatrixA \expandafter
{\GetRotationMatrix {3.141592653}}
\begin{equation}
\mattypeset \transformMatrixA
\end{equation}
\end{document}
前四个方程来自原始代码