summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/latex/diffcoeff
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2016-06-27 20:41:31 +0000
committerKarl Berry <karl@freefriends.org>2016-06-27 20:41:31 +0000
commitf3714e22cf9b596abec6c42dc1dc9dd95ef82b61 (patch)
tree4aa08c0e81aa4e5b21e2cd909cabaa8dca30a889 /Master/texmf-dist/tex/latex/diffcoeff
parente9f2b559eb367b62e1b88e7e73dd32c3b7d253c1 (diff)
diffcoeff (27jun16)
git-svn-id: svn://tug.org/texlive/trunk@41554 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/latex/diffcoeff')
-rw-r--r--Master/texmf-dist/tex/latex/diffcoeff/diffcoeff.sty711
-rw-r--r--Master/texmf-dist/tex/latex/diffcoeff/diffcoeffx.sty972
2 files changed, 1683 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/latex/diffcoeff/diffcoeff.sty b/Master/texmf-dist/tex/latex/diffcoeff/diffcoeff.sty
new file mode 100644
index 00000000000..bb18b85d6fa
--- /dev/null
+++ b/Master/texmf-dist/tex/latex/diffcoeff/diffcoeff.sty
@@ -0,0 +1,711 @@
+% This is file `diffcoeff.sty'.
+%
+% This program is free software; you can redistribute it and/or modify it
+% under the terms of the GNU General Public License as published by the
+% Free Software Foundation; either version 2 of the License, or (at your
+% option) any later version.
+%
+% Andrew Parsloe aparsloe@clear.net.nz
+%
+\RequirePackage{expl3}
+\RequirePackage{xparse}
+\ProvidesExplPackage{diffcoeff} {2016/06/27} {1.0}
+ {Write differential coefficients easily.}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\cs_generate_variant:Nn \tl_if_eq:nnF { no }
+\cs_generate_variant:Nn \tl_if_eq:nnT { no }
+\cs_generate_variant:Nn \tl_if_in:NnTF { NV }
+\cs_generate_variant:Nn \prop_pop:NnNT { NV }
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% variables
+\tl_new:N \g_diffco_d_ldelim_tl
+\tl_new:N \g_diffco_d_rdelim_tl
+\tl_new:N \g_diffco_p_ldelim_tl
+\tl_new:N \g_diffco_p_rdelim_tl
+
+\tl_new:N \l__diffco_entiand_tl
+\tl_new:N \l__diffco_phantom_tl
+\tl_new:N \g_diffco_dop_tl
+\tl_new:N \l__diffco_denom_tl
+\tl_new:N \l__diffco_coeff_tl
+
+\clist_new:N \l__diffco_order_clist
+\tl_new:N \l__diffco_order_spec_tl
+
+\bool_new:N \g__diffco_erent_shape_bool
+\bool_new:N \l__diffco_no_parens_bool
+\bool_new:N \l__diffco_override_bool
+\bool_new:N \l__diffco_vars_noted_bool
+
+\tl_new:N \l__diffco_orders_in_tl
+\tl_new:N \l__diffco_order_tl
+
+\tl_new:N \l__diffco_curr_tok_tl
+\tl_new:N \l__diffco_curr_term_tl
+
+\int_new:N \l__diffco_curr_tok_int
+\int_new:N \l__diffco_curr_state_int
+
+\prop_new:N \l__diffco_vars_prop
+\tl_new:N \l__diffco_vars_tl
+\clist_new:N \l__diffco_vars_clist
+
+\tl_new:N \l__diffco_curr_var_tl
+\tl_new:N \l__diffco_nos_tl
+\tl_new:N \l__diffco_nos_aux_tl
+
+\tl_new:N \l__diffco_alg_tl
+\tl_new:N \l__diffco_alg_aux_tl
+\tl_new:N \l__diffco_alg_expr_tl
+
+\tl_const:Nn \c__diffco_digits_tl { 1234567890 }
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\keys_define:nn { diffcoeff }
+ {
+ roman .bool_gset:N = \g_diffco_roman_bool,
+ roman .default:n = { false },
+ d-delims .code:n = {
+ \tl_gset:Nx \g_diffco_d_ldelim_tl { \left \use_i:nn #1 }
+ \tl_gset:Nx \g_diffco_d_rdelim_tl
+ { \right \use_ii:nn #1 }
+ },
+ d-delims .default:n = { .| },
+ p-delims .code:n = {
+ \tl_gset:Nx \g_diffco_p_ldelim_tl { \left \use_i:nn #1 }
+ \tl_gset:Nx \g_diffco_p_rdelim_tl
+ { \right \use_ii:nn #1 }
+ },
+ p-delims .default:n = { () },
+ d-nudge .code:n = { \tl_gset:Nn \g_diffco_d_nudge_tl { \mskip #1 mu } },
+ d-nudge .default:n = { 0 },
+ p-nudge .code:n = { \tl_gset:Nn \g_diffco_p_nudge_tl { \mskip #1 mu } },
+ p-nudge .default:n = { -6 },
+ sep .code:n = { \tl_gset:Nn \g_diffco_sep_tl { \mskip #1 mu } },
+ sep .default:n = { 2 },
+ d-sep .code:n = { \tl_gset:Nn \g_diffco_d_sep_tl { \mskip #1 mu } },
+ d-sep .default:n = { 1 },
+ p-sep .code:n = { \tl_gset:Nn \g_diffco_p_sep_tl { \mskip #1 mu } },
+ p-sep .default:n = { 1 },
+ }
+
+\DeclareDocumentCommand \diffset { o }
+ {
+ \IfValueTF { #1 }
+ {
+ \clist_if_empty:nTF { #1 }
+ { \keys_set:nn { diffcoeff } { roman,d-delims,p-delims,
+ d-nudge,p-nudge,sep,d-sep,p-sep } }
+ { \keys_set:nn { diffcoeff } { #1 } }
+ }
+ {
+ \keys_set:nn { diffcoeff } { roman,d-delims,p-delims,
+ d-nudge,p-nudge,sep,d-sep,p-sep }
+ }
+ }
+
+% now set the defaults
+\diffset
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Derivatives
+% Ordinary differential coefficient. #1 is the order; #2 the
+% differentiand; #3 the variable of differentiation; #4 the
+% point of evaluation.
+\NewDocumentCommand \diff{ s o m t/ m g }
+ {
+ \group_begin:
+ % roman or italic?
+ \bool_if:NF \g__diffco_erent_shape_bool
+ { \__diffco_shape:N d }
+
+ \IfValueTF { #2 }
+ {
+ \tl_set:Nn \l__diffco_order_tl { ^{ \g_diffco_d_sep_tl #2 } }
+ \int_compare:nNnTF { \tl_count:n { #5 } } > { \c_one }
+ { \tl_set:Nn \l__diffco_denom_tl { (#5)^{ #2 } } }
+ { \tl_set:Nn \l__diffco_denom_tl { #5^{ #2 } } }
+ }
+ {
+ \tl_set:Nn \l__diffco_order_tl { }
+ \tl_if_in:nnTF { #5 } { ^ }
+ { \tl_set:Nn \l__diffco_denom_tl { (#5) } }
+ { \tl_set:Nn \l__diffco_denom_tl { #5 } }
+ }
+
+% position of differentiand: appended (star) or numerator (no star);
+% slash or fraction?
+ \IfBooleanTF { #1 }
+ { % differentiand follows diff coeff
+ \__diffco_phantom:n { #3 }
+ \tl_set:Nn \l__diffco_coeff_tl
+ {
+ \IfBooleanTF { #4 }
+ { % slash (therefore no phantom)
+ (\g_diffco_dop_tl \l__diffco_order_tl
+ /
+ \g_diffco_dop_tl \l__diffco_denom_tl )
+ \l__diffco_entiand_tl
+ }
+ { % frac
+ \frac { \g_diffco_dop_tl \l__diffco_order_tl \l__diffco_phantom_tl }
+ { \g_diffco_dop_tl \l__diffco_denom_tl } \l__diffco_entiand_tl
+ }
+ }
+ }
+ { % differentiand in numerator
+ \tl_set:Nn \l__diffco_coeff_tl
+ {
+ \IfBooleanTF { #4 }
+ { % slash
+ \g_diffco_dop_tl \l__diffco_order_tl #3
+ /
+ \g_diffco_dop_tl \l__diffco_denom_tl
+ }
+ { % frac
+ \frac { \g_diffco_dop_tl \l__diffco_order_tl #3 }
+ { \g_diffco_dop_tl \l__diffco_denom_tl }
+ }
+ }
+ }
+ % pt of eval
+ \IfNoValueTF { #6 }
+ {
+ \l__diffco_coeff_tl
+ }
+ { % trailing arg: pt of eval.
+ \tl_if_empty:nTF { #6 }
+ {
+ \l__diffco_coeff_tl
+ }
+ {
+ \g_diffco_d_ldelim_tl \l__diffco_coeff_tl \g_diffco_d_rdelim_tl
+ \c_math_subscript_token { \g_diffco_d_nudge_tl #6 }
+ }
+ }
+ \group_end:
+ }
+
+\NewDocumentCommand \Diff { o m m g }
+ {
+ \group_begin:
+ \__diffco_shape:N D
+ \bool_gset_true:N \g__diffco_erent_shape_bool
+ \diff[#1]{#2}{#3}{#4}
+ \bool_gset_false:N \g__diffco_erent_shape_bool
+ \group_end:
+ }
+
+\NewDocumentCommand \diffd { o m m g }
+ {
+ \group_begin:
+ \__diffco_shape:N \delta
+ \bool_gset_true:N \g__diffco_erent_shape_bool
+ \diff[#1]{#2}{#3}{#4}
+ \bool_gset_false:N \g__diffco_erent_shape_bool
+ \group_end:
+ }
+
+\NewDocumentCommand \Diffd { o m m g }
+ {
+ \group_begin:
+ \__diffco_shape:N \Delta
+ \bool_gset_true:N \g__diffco_erent_shape_bool
+ \diff[#1]{#2}{#3}{#4}
+ \bool_gset_false:N \g__diffco_erent_shape_bool
+ \group_end:
+ }
+
+\cs_new_nopar:Npn \__diffco_shape:N #1
+ {
+ \bool_if:NTF \g_diffco_roman_bool
+ { \tl_gset:Nn \g_diffco_dop_tl { \mathrm{ #1} } }
+ { \tl_gset:Nn \g_diffco_dop_tl { #1 } }
+ }
+%%%%%
+\cs_new:Npn \__diffco_append:nn #1#2
+ {
+ \g_diffco_d_ldelim_tl \l__diffco_coeff_tl \g_diffco_d_rdelim_tl
+ \c_math_subscript_token { \mskip #1 mu #2 }
+ }
+
+\cs_new:Npn \__diffco_phantom:n #1
+ {
+ \bool_if:nTF
+ {
+ \tl_if_head_eq_meaning_p:nN { #1 } \hfill ||
+ \tl_if_head_eq_meaning_p:nN { #1 } \hfil
+ }
+ {
+ \l__diffco_phantom_aux:nn #1\q_stop
+ }
+ {
+ \bool_if:nTF
+ {
+ \tl_if_head_eq_meaning_p:nN { #1 } \hspace ||
+ \tl_if_head_eq_meaning_p:nN { #1 } \hphantom
+ }
+ {
+ \l__diffco_phantom_aux:nnn #1\q_stop
+ }
+ {
+ \tl_set:Nn \l__diffco_entiand_tl { #1 }
+ }
+ }
+ }
+
+\cs_new:Npn \l__diffco_phantom_aux:nn #1#2\q_stop
+ {
+ \tl_set:Nn \l__diffco_phantom_tl { #1 }
+ \tl_set:Nn \l__diffco_entiand_tl { #2 }
+ }
+
+\cs_new:Npn \l__diffco_phantom_aux:nnn #1#2#3\q_stop
+ {
+ \tl_set:Nn \l__diffco_phantom_tl { #1 { #2 } }
+ \tl_set:Nn \l__diffco_entiand_tl { #3 }
+ }
+%%%%%%%%%%%%%%%%%%%%
+% Partial differential coefficient.
+% #1 (star) = append differentiand boolean
+% #2 = comma list of the orders of diff. in each var.;
+% #3 = order override for the numerator; #4 = differentiand;
+% #5 slash / boolean; #6 = comma list of vars of diff.;
+% #7 = list of vars held const.
+\NewDocumentCommand \diffp{ s o o m t/ m g }
+ {
+ \group_begin:
+
+ % diff. order list
+ \tl_clear:N \l__diffco_order_clist
+ \IfValueT { #2 }
+ {
+ \clist_set:Nn \l__diffco_order_clist { #2 }
+ \tl_set:Nx \l__diffco_order_spec_tl
+ { [\clist_use:Nn \l__diffco_order_clist { , }]}
+ }
+
+ % order list override
+ \IfValueT { #3 }
+ {
+ \bool_set_true:N \l__diffco_override_bool
+ \tl_set:Nn \l__diffco_order_tl { #3 }
+ }
+
+ \__diffco_orders:Nn \l__diffco_order_clist { #6 }
+
+ % position of differentiand
+ \IfBooleanTF { #1 }
+ { % appended
+ \__diffco_phantom:n { #4 }
+ \tl_set:Nn \l__diffco_coeff_tl
+ {
+ \IfBooleanTF { #5 }
+ { % slash (therefore no phantom)
+ ( \partial \__diffco_omit_order_if_i:N
+ \l__diffco_order_tl
+ /
+ \l__diffco_denom_tl ) \l__diffco_entiand_tl
+ }
+ { % frac
+ \frac { \partial \__diffco_omit_order_if_i:N
+ \l__diffco_order_tl \l__diffco_phantom_tl }
+ { \l__diffco_denom_tl } \l__diffco_entiand_tl
+ }
+ }
+ }
+ { % in numerator
+ \tl_set:Nn \l__diffco_coeff_tl
+ {
+ \IfBooleanTF { #5 }
+ {
+ \partial \__diffco_omit_order_if_i:N \l__diffco_order_tl #4
+ / \l__diffco_denom_tl
+ }
+ {
+ \frac { \partial
+ \__diffco_omit_order_if_i:N \l__diffco_order_tl
+ #4 } { \l__diffco_denom_tl }
+ }
+ }
+ }
+
+ \IfNoValueTF { #7 }
+ {
+ \l__diffco_coeff_tl
+ }
+ {
+ \tl_if_empty:nTF { #7 }
+ {
+ \l__diffco_coeff_tl
+ }
+ {
+ \g_diffco_p_ldelim_tl \l__diffco_coeff_tl \g_diffco_p_rdelim_tl
+ \c_math_subscript_token { \g_diffco_p_nudge_tl #7 }
+ }
+ }
+ \group_end:
+ } % end of \diffp
+
+\NewDocumentCommand \jacob { m m }
+ { % need extra braces in denom for clist manipulations
+ \diffp{ (#1) }{ { {{(#2)}} } }
+ }
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% #1 is the clist of diff. orders
+% #2 is the tl of variables (if commas present treat as clist)
+\cs_new:Npn \__diffco_orders:Nn #1#2
+ {
+ \int_zero:N \l_tmpa_int
+ \tl_clear:N \l_tmpb_tl
+ \clist_clear:N \l_tmpa_clist
+ \clist_clear:N \l_tmpb_clist
+ \clist_clear:N \l__diffco_vars_clist
+
+ \clist_set:Nn \l__diffco_vars_clist { #2 }
+ \clist_map_inline:Nn \l__diffco_vars_clist
+ {
+ \bool_set_false:N \l__diffco_no_parens_bool
+
+ % get order of each variable
+ \clist_pop:NNF #1 \l_tmpa_tl
+ { \tl_set:Nn \l_tmpa_tl { 1 } }
+
+ \tl_if_eq:noT { 1 } \l_tmpa_tl
+ { \bool_set_true:N \l__diffco_no_parens_bool }
+
+ \clist_put_right:NV \l_tmpa_clist \l_tmpa_tl
+
+ % create the denominator
+ \tl_clear:N \l_tmpb_tl
+ \bool_if:nTF
+ {
+ \int_compare_p:nNn { \tl_count:n { ##1 } } = { \c_one }
+ ||
+ \l__diffco_no_parens_bool
+ }
+ { \tl_put_right:Nn \l_tmpb_tl { \partial ##1 } }
+ { \tl_put_right:Nn \l_tmpb_tl { \partial (##1) } }
+
+ \tl_if_eq:noF { 1 } \l_tmpa_tl
+ {
+ \tl_put_right:Nn \l_tmpb_tl { ^ }
+ \tl_put_right:Nx \l_tmpb_tl { { \l_tmpa_tl } }
+ }
+
+ \clist_put_right:No \l_tmpb_clist \l_tmpb_tl
+ } % end of inline map
+
+ % numerator order
+ \bool_if:NF \l__diffco_override_bool
+ {
+ \tl_set:Nx \l__diffco_orders_in_tl { \clist_use:Nn \l_tmpa_clist {+} }
+ \diff_simplify_orders:NN \l__diffco_orders_in_tl \l__diffco_order_tl
+ }
+
+ % denominator
+ \tl_set:Nx \l__diffco_denom_tl { \clist_use:Nn
+ \l_tmpb_clist { \g_diffco_sep_tl } }
+ }
+
+% don't display order 1 superscript
+\cs_new:Npn \__diffco_omit_order_if_i:N #1
+ {
+ \tl_if_eq:noF { 1 } #1
+ { ^{ \g_diffco_p_sep_tl \l__diffco_order_tl } }
+ }
+%%%%%%%%%%%%%%%%%%%%%%
+% #1 is expr. in; #2 is expr. out
+\cs_new:Npn \diff_simplify_orders:NN #1 #2
+ {
+ \tl_clear:N \l__diffco_nos_tl
+
+ \__diffco_digest_expr:NNNN \l__diffco_orders_in_tl \l__diffco_nos_tl
+ \l__diffco_alg_tl \l__diffco_vars_prop
+
+ \__diffco_eval_nos:N \l__diffco_nos_tl
+
+ \tl_if_empty:NF \l__diffco_alg_tl
+ { \__diffco_eval_vars:NN \l__diffco_alg_tl \l__diffco_vars_prop }
+
+ \__diffco_manicure_result:NNN \l__diffco_nos_tl \l__diffco_alg_tl #2
+ }
+
+% #1 is the expression; #2 (tl) receives the numerical part;
+% #3 (tl) receives the algebraic part; #4 (prop) receives the vars
+\cs_new:Npn \__diffco_digest_expr:NNNN #1#2#3#4
+ {
+ \tl_put_right:Nn #1 { + }
+ \tl_set:Nn \l__diffco_curr_term_tl { + }
+ \int_set:Nn \l__diffco_curr_state_int { \c_zero }
+ \int_set:Nn \l__diffco_curr_tok_int { \c_zero }
+ \tl_clear:N #3
+ \prop_clear:N #4
+
+ \tl_map_inline:Nn #1
+ {
+ \tl_set:Nn \l__diffco_curr_tok_tl { ##1 }
+ \__diffco_get_curr_index:NN ##1 \l__diffco_curr_tok_int
+ \__diffco_compare_states:NNNNN \l__diffco_curr_state_int
+ \l__diffco_curr_tok_int #2#3#4
+ }
+ \tl_if_empty:NT #2 { \tl_set:Nn #2 { 0 } }
+ }
+
+% #1 contains current token (tl); #2 receives current state (int)
+\cs_new:Npn \__diffco_get_curr_index:NN #1#2
+ {
+ \tl_if_in:NnTF \c__diffco_digits_tl { #1 }
+ { % digit
+ \int_set:Nn #2 { \c_one }
+ }
+ {
+ \tl_case:NnF #1
+ {
+ + { \int_set_eq:NN #2 \c_zero }
+ - { \int_set_eq:NN #2 \c_zero }
+ ( {
+ \msg_error:nnxx { diffcoeff } { unknown_token }
+ { \l__diffco_order_spec_tl } { parentheses }
+ }
+ ^ {
+ \msg_error:nnxx { diffcoeff } { unknown_token }
+ { \l__diffco_order_spec_tl } { superscript }
+ }
+ }
+ {
+ \token_if_math_subscript:NTF #1
+ {
+ \msg_error:nnxx { diffcoeff } { unknown_token }
+ { \l__diffco_order_spec_tl } { subscript }
+ }
+ { % var
+ \int_set_eq:NN #2 \c_two
+ }
+ }
+ }
+ }
+
+% #1 (int) is curr. state; #2 (int) is curr token index;
+% #3 (tl) receives the numerical part;
+% #4 (tl) receives the algebraic part;
+% #5 (prop) receives the vars
+\cs_new:Npn \__diffco_compare_states:NNNNN #1#2#3#4#5
+ {
+ \int_case:nn { #1 }
+ {
+ { \c_zero } % sgn
+ {
+ \int_case:nn { #2 }
+ {
+ { \c_zero } % tok = s
+ {
+ \tl_if_eq:NNTF \l__diffco_curr_term_tl \l__diffco_curr_tok_tl
+ { \tl_set:Nn \l__diffco_curr_term_tl { + } }
+ { \tl_set:Nn \l__diffco_curr_term_tl { - } }
+ % \int_set:Nn #1 { \c_zero }
+ }
+ { \c_one } % tok = d
+ { \__diffco_term_append:NN #1#2 }
+ { \c_two } % tok = v
+ {
+ \tl_put_right:Nn \l__diffco_curr_term_tl { 1 }
+ \__diffco_term_var_append:NN #1#2
+ }
+ }
+ }
+ { \c_one } % num
+ {
+ \int_case:nn { #2 }
+ {
+ { \c_zero } % tok = s
+ {
+ \tl_put_right:NV #3 \l__diffco_curr_term_tl
+ \tl_clear:N \l__diffco_curr_term_tl
+ \__diffco_term_append:NN #1#2
+ }
+ { \c_one } % tok = d
+ { \__diffco_term_append:NN #1 \c_one }
+ { \c_two } % tok = v
+ { \__diffco_term_var_append:NN #1#2 }
+ }
+ }
+ { \c_two } % alg
+ {
+ \int_case:nn { #2 }
+ {
+ { \c_zero } % tok = s
+ {
+ \tl_put_right:NV #4 \l__diffco_curr_term_tl
+ \tl_clear:N \l__diffco_curr_term_tl
+ \bool_if:NF \l__diffco_vars_noted_bool
+ { \__diffco_store_var:NN #5 \l__diffco_curr_var_tl }
+ \tl_clear:N \l__diffco_curr_var_tl
+ \__diffco_term_append:NN #1#2
+ }
+ { \c_one } % tok = d
+ {
+ \msg_error:nnx { diffcoeff } { variable_digit_sequence }
+ { \l__diffco_order_spec_tl }
+ }
+ { \c_two } % tok = v
+ { \__diffco_term_var_append:NN #1 \c_two }
+ }
+ }
+ }
+ }
+
+% #1 current state; #2 current token index
+\cs_new:Npn \__diffco_term_var_append:NN #1#2
+ {
+ \tl_put_right:NV \l__diffco_curr_term_tl \l__diffco_curr_tok_tl
+ \tl_put_right:NV \l__diffco_curr_var_tl \l__diffco_curr_tok_tl
+ \int_set_eq:NN #1 #2
+ }
+
+% #1 current state; #2 current token index
+\cs_new:Npn \__diffco_term_append:NN #1#2
+ {
+ \tl_put_right:NV \l__diffco_curr_term_tl \l__diffco_curr_tok_tl
+ \int_set_eq:NN #1 #2
+ }
+
+% #1 is prop list; #2 is tl containing var
+\cs_new:Npn \__diffco_store_var:NN #1 #2
+ {
+ \int_set:Nn \l_tmpa_int { \exp_args:NV \tl_count_tokens:n #2 }
+ \prop_get:NVNTF #1 \l_tmpa_int \l_tmpa_tl
+ {
+ \tl_put_right:Nn \l_tmpa_tl { , }
+ \tl_put_right:NV \l_tmpa_tl #2
+ \prop_put:NVV #1 \l_tmpa_int \l_tmpa_tl
+ }
+ {
+ \prop_put:NVV #1 \l_tmpa_int #2
+ }
+ }
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% evals numerical expr. in #1, which receives the
+% evaluated expr.
+\cs_new:Npn \__diffco_eval_nos:N #1
+ {
+ \int_set:Nn \l_tmpa_int { #1 }
+ \tl_set:Nx #1 { \int_use:N \l_tmpa_int }
+ \int_compare:nNnT { \l_tmpa_int } > { \c_zero }
+ { \tl_put_left:Nn #1 { + } }
+ }
+
+% #1 (tl) has algebraic part & receives eval. expression
+% #2 (prop) contains the variables
+% The idea is to remove each var but leave coeffs, split into
+% num & alg parts, eval. the num part for the net coeff of var
+\cs_new:Npn \__diffco_eval_vars:NN #1#2
+ {
+ \bool_set_true:N \l__diffco_vars_noted_bool
+ \prop_set_eq:NN \l_tmpa_prop #2
+ \int_set_eq:NN \l_tmpa_int \c_one
+ \bool_until_do:nn { \prop_if_empty_p:N #2 }
+ {
+ \prop_pop:NVNT #2 \l_tmpa_int \l_tmpa_tl
+ {
+ \tl_put_left:Nn \l_tmpa_tl { , }
+ \tl_put_left:NV \l__diffco_vars_tl \l_tmpa_tl
+ }
+ \int_incr:N \l_tmpa_int
+ }
+
+ \clist_set:NV \l__diffco_vars_clist \l__diffco_vars_tl
+ \clist_remove_duplicates:N \l__diffco_vars_clist
+
+ \clist_map_inline:Nn \l__diffco_vars_clist
+ {
+ \tl_replace_all:Nnn #1 { ##1 } { }
+ \__diffco_digest_expr:NNNN #1 \l__diffco_nos_aux_tl \l__diffco_alg_aux_tl
+ \l_tmpa_prop
+
+ \__diffco_eval_nos:N \l__diffco_nos_aux_tl
+
+ \__diffco_cumulate_expr:NnN \l__diffco_nos_aux_tl { ##1 }
+ \l__diffco_alg_expr_tl
+
+ \tl_set_eq:NN #1 \l__diffco_alg_aux_tl
+ \tl_clear:N \l__diffco_nos_aux_tl
+ \tl_clear:N \l__diffco_alg_aux_tl
+ }
+
+ \tl_set_eq:NN #1 \l__diffco_alg_expr_tl
+ }
+
+% #1 is num coeff; #2 is var; #3 is cumulating expr. (All tl.)
+\cs_new:Npn \__diffco_cumulate_expr:NnN #1#2#3
+ {
+ \int_case:nnF { #1 }
+ {
+ { 0 } { \prg_do_nothing: }
+ { +1 } { \tl_put_right:Nn #3 { + #2 } }
+ { -1 } { \tl_put_right:Nn #3 { - #2 } }
+ }
+ {
+ \tl_put_right:NV #3 { #1 }
+ \tl_put_right:Nn #3 { #2 }
+ }
+ }
+
+% alg. part precedes num. part unless alg. starts
+% with - and nums > 0. #1 nums, #2 alg, #3 output
+\cs_new:Npn \__diffco_manicure_result:NNN #1#2#3
+ { % alg < 0 ?
+ \exp_args:NV \tl_if_head_eq_charcode:nNTF #2 -
+ {
+ \int_compare:nNnTF { #1 } > { \c_zero }
+ { % nums > 0
+ \tl_concat:NNN #3 #1 #2
+ }
+ { % nums =< 0
+ \seq_set_split:NnV \l_tmpa_seq { + } #2
+ \seq_pop:NN \l_tmpa_seq \l_tmpa_tl
+ \tl_set:Nx \l_tmpb_tl { \seq_use:Nn \l_tmpa_seq { + } }
+ \int_compare:nNnF { #1 } = { \c_zero }
+ { \tl_concat:NNN \l_tmpa_tl \l_tmpa_tl #1 }
+ \tl_concat:NNN #3 \l_tmpb_tl \l_tmpa_tl
+ }
+ }
+ { % alg >= 0
+ \int_compare:nNnTF { #1 } = { \c_zero }
+ { \tl_set_eq:NN #3 #2 }
+ { \tl_concat:NNN #3 #2 #1 }
+ }
+
+ % if everything cancels, output 0
+ \tl_if_empty:NTF #3 { \tl_set:Nn #3 { 0 } }
+ {
+ % trim initial + sign
+ \exp_args:NV \tl_if_head_eq_charcode:nNT #3 +
+ { \tl_set:Nx #3 { \tl_tail:N #3 } }
+ }
+ }
+%%%%%%%%%%%
+% messages
+\cs_gset:Npn \msg_error_text:n #1
+ { Unimplemented~in~#1.sty: }
+\cs_gset:Npn \msg_info_text:n #1
+ { Use~the~order-override~option~to~specify~the~overall~order~of~
+ differentiation~(or~use~diffcoeffx.sty). }
+
+\msg_new:nnnn { diffcoeff } { unknown_token }
+ { \msg_error_text:n { diffcoeff }~#2~in~the~order~specification~#1~
+ \msg_line_context:. }
+ { \msg_info_text:n { diffcoeff } }
+
+\msg_new:nnnn { diffcoeff } { variable_digit_sequence }
+ { \msg_error_text:n { diffcoeff }~a~digit~follows~a~variable~in~the~order~
+ specification~#1~\msg_line_context:. }
+ { \msg_info_text:n { diffcoeff } }
+
+ \ No newline at end of file
diff --git a/Master/texmf-dist/tex/latex/diffcoeff/diffcoeffx.sty b/Master/texmf-dist/tex/latex/diffcoeff/diffcoeffx.sty
new file mode 100644
index 00000000000..727175176bc
--- /dev/null
+++ b/Master/texmf-dist/tex/latex/diffcoeff/diffcoeffx.sty
@@ -0,0 +1,972 @@
+% This is file `diffcoeffx.sty'.
+%
+% This program is free software; you can redistribute it and/or modify it
+% under the terms of the GNU General Public License as published by the
+% Free Software Foundation; either version 2 of the License, or (at your
+% option) any later version.
+%
+% Andrew Parsloe aparsloe@clear.net.nz
+%
+\RequirePackage{expl3}
+\RequirePackage{xparse}
+\ProvidesExplPackage{diffcoeffx} {2015/06/27} {1.0}
+ {Write differential coefficients easily.}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\cs_generate_variant:Nn \tl_if_eq:nnF { no }
+\cs_generate_variant:Nn \tl_if_eq:nnT { no }
+\cs_generate_variant:Nn \tl_if_in:NnTF { NV }
+\cs_generate_variant:Nn \prop_pop:NnNT { NV }
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% variables
+\tl_new:N \g_diffco_d_ldelim_tl
+\tl_new:N \g_diffco_d_rdelim_tl
+\tl_new:N \g_diffco_p_ldelim_tl
+\tl_new:N \g_diffco_p_rdelim_tl
+
+\tl_new:N \l__diffco_entiand_tl
+\tl_new:N \l__diffco_phantom_tl
+\tl_new:N \g_diffco_dop_tl
+\tl_new:N \l__diffco_denom_tl
+\tl_new:N \l__diffco_coeff_tl
+
+\clist_new:N \l__diffco_order_clist
+\tl_new:N \l__diffco_order_spec_tl
+\tl_new:N \l__diffco_nudge_tl
+
+\bool_new:N \g__diffco_erent_shape_bool
+\bool_new:N \l__diffco_no_parens_bool
+\bool_new:N \l__diffco_override_bool
+\bool_new:N \l__diffco_ordinary_bool
+\bool_new:N \l__diffco_fp_bool
+\bool_new:N \l__diffco_vars_noted_bool
+
+\tl_new:N \l__diffco_orders_in_tl
+\tl_new:N \l__diffco_order_tl
+
+\tl_new:N \l__diffco_curr_tok_tl
+\tl_new:N \l__diffco_curr_term_tl
+
+\int_new:N \l__diffco_curr_tok_int
+\int_new:N \l__diffco_curr_state_int
+\int_new:N \l__diffco_prev_state_int
+
+\prop_new:N \l__diffco_vars_prop
+\tl_new:N \l__diffco_vars_tl
+\clist_new:N \l__diffco_vars_clist
+
+\tl_new:N \l__diffco_curr_var_tl
+\tl_new:N \l__diffco_curr_qvar_tl
+\tl_new:N \l__diffco_nos_tl
+\tl_new:N \l__diffco_nos_aux_tl
+
+\tl_new:N \l__diffco_alg_tl
+\tl_new:N \l__diffco_alg_aux_tl
+\tl_new:N \l__diffco_alg_expr_tl
+
+\tl_const:Nn \c__diffco_digits_tl { 1234567890 }
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\keys_define:nn { diffcoeffx }
+ {
+ roman .bool_gset:N = \g_diffco_roman_bool,
+ roman .default:n = { false },
+ d-delims .code:n = {
+ \tl_gset:Nx \g_diffco_d_ldelim_tl { \left \use_i:nn #1 }
+ \tl_gset:Nx \g_diffco_d_rdelim_tl
+ { \right \use_ii:nn #1 }
+ },
+ d-delims .default:n = { .| },
+ p-delims .code:n = {
+ \tl_gset:Nx \g_diffco_p_ldelim_tl { \left \use_i:nn #1 }
+ \tl_gset:Nx \g_diffco_p_rdelim_tl
+ { \right \use_ii:nn #1 }
+ },
+ p-delims .default:n = { () },
+ d-nudge .code:n = { \tl_gset:Nn \g_diffco_d_nudge_tl { \mskip #1 mu } },
+ d-nudge .default:n = { 0 },
+ p-nudge .code:n = { \tl_gset:Nn \g_diffco_p_nudge_tl { \mskip #1 mu } },
+ p-nudge .default:n = { -6 },
+ sep .code:n = { \tl_gset:Nn \g_diffco_sep_tl { \mskip #1 mu } },
+ sep .default:n = { 2 },
+ d-sep .code:n = { \tl_gset:Nn \g_diffco_d_sep_tl { \mskip #1 mu } },
+ d-sep .default:n = { 1 },
+ p-sep .code:n = { \tl_gset:Nn \g_diffco_p_sep_tl { \mskip #1 mu } },
+ p-sep .default:n = { 1 }
+ }
+
+\DeclareDocumentCommand \diffset { o }
+ {
+ \IfValueTF { #1 }
+ {
+ \clist_if_empty:nTF { #1 }
+ {
+ \keys_set:nn { diffcoeffx } { roman,d-delims,p-delims,
+ d-nudge,p-nudge,sep,d-sep,p-sep }
+ }
+ {
+ \keys_set:nn { diffcoeffx } { #1 }
+ }
+ }
+ {
+ \keys_set:nn { diffcoeffx } { roman,d-delims,p-delims,
+ d-nudge,p-nudge,sep,d-sep,p-sep }
+ }
+ }
+
+% now set the defaults
+\diffset
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Derivatives
+% Ordinary differential coefficient. #1 (star) is the append boolean;
+% #2 is the order; #3 the differentiand; #4 slash / boolean;
+% #5 the variable of differentiation; #6 the point of evaluation.
+
+\NewDocumentCommand \diff{ s o m t/ m g }
+ {
+ \group_begin:
+ % roman or italic?
+ \bool_if:NF \g__diffco_erent_shape_bool
+ { \__diffco_shape:N d }
+
+ \IfValueTF { #2 }
+ {
+ \tl_set:Nn \l__diffco_order_tl { \g_diffco_d_sep_tl ^{ #2 } }
+ \int_compare:nNnTF { \tl_count:n { #5 } } > { \c_one }
+ { \tl_set:Nn \l__diffco_denom_tl { (#5)^{ #2 } } }
+ { \tl_set:Nn \l__diffco_denom_tl { #5^{ #2 } } }
+ }
+ {
+ \tl_set:Nn \l__diffco_order_tl { }
+ \tl_if_in:nnTF { #5 } { ^ }
+ { \tl_set:Nn \l__diffco_denom_tl { (#5) } }
+ { \tl_set:Nn \l__diffco_denom_tl { #5 } }
+ }
+
+ % differentiand appended (star) or numerator (no star);
+ % slash or fraction?
+ \IfBooleanTF { #1 }
+ { % differentiand follows diff coeff
+ \__diffco_phantom:n { #3 }
+ \tl_set:Nn \l__diffco_coeff_tl
+ {
+ \IfBooleanTF { #4 }
+ { % slash (therefore no phantom)
+ (\g_diffco_dop_tl \l__diffco_order_tl
+ /
+ \g_diffco_dop_tl \l__diffco_denom_tl )
+ \l__diffco_entiand_tl
+ }
+ { % frac
+ \frac { \g_diffco_dop_tl \l__diffco_order_tl \l__diffco_phantom_tl }
+ { \g_diffco_dop_tl \l__diffco_denom_tl } \l__diffco_entiand_tl
+ }
+ }
+ }
+ { % differentiand in numerator
+ \tl_set:Nn \l__diffco_coeff_tl
+ {
+ \IfBooleanTF { #4 }
+ { % slash
+ \g_diffco_dop_tl \l__diffco_order_tl #3
+ /
+ \g_diffco_dop_tl \l__diffco_denom_tl
+ }
+ { % frac
+ \frac { \g_diffco_dop_tl \l__diffco_order_tl #3 }
+ { \g_diffco_dop_tl \l__diffco_denom_tl }
+ }
+ }
+ }
+
+ % point of eval?
+ \IfNoValueTF { #6 }
+ { % no
+ \l__diffco_coeff_tl
+ }
+ { % yes
+ \bool_set_true:N \l__diffco_ordinary_bool
+ \__diffco_delims:nnnnN #6;;;;\q_stop \l__diffco_ordinary_bool
+ }
+ \group_end:
+ }
+
+\NewDocumentCommand \Diff { o m m g }
+ {
+ \group_begin:
+ \__diffco_shape:N D
+ \bool_gset_true:N \g__diffco_erent_shape_bool
+ \diff[#1]{#2}{#3}{#4}
+ \bool_gset_false:N \g__diffco_erent_shape_bool
+ \group_end:
+ }
+
+\NewDocumentCommand \diffdelta { o m m g }
+ {
+ \group_begin:
+ \__diffco_shape:N \delta
+ \bool_gset_true:N \g__diffco_erent_shape_bool
+ \diff[#1]{#2}{#3}{#4}
+ \bool_gset_false:N \g__diffco_erent_shape_bool
+ \group_end:
+ }
+
+\NewDocumentCommand \Diffdelta { o m m g }
+ {
+ \group_begin:
+ \__diffco_shape:N \Delta
+ \bool_gset_true:N \g__diffco_erent_shape_bool
+ \diff[#1]{#2}{#3}{#4}
+ \bool_gset_false:N \g__diffco_erent_shape_bool
+ \group_end:
+ }
+
+\cs_new_nopar:Npn \__diffco_shape:N #1
+ {
+ \bool_if:NTF \g_diffco_roman_bool
+ { \tl_gset:Nn \g_diffco_dop_tl { \mathrm{ #1} } }
+ { \tl_gset:Nn \g_diffco_dop_tl { #1 } }
+ }
+%%%%%
+\cs_new:Npn \__diffco_phantom:n #1
+ {
+ \bool_if:nTF
+ {
+ \tl_if_head_eq_meaning_p:nN { #1 } \hfill ||
+ \tl_if_head_eq_meaning_p:nN { #1 } \hfil
+ }
+ {
+ \l__diffco_phantom_aux:nn #1\q_stop
+ }
+ {
+ \bool_if:nTF
+ {
+ \tl_if_head_eq_meaning_p:nN { #1 } \hspace ||
+ \tl_if_head_eq_meaning_p:nN { #1 } \hphantom
+ }
+ {
+ \l__diffco_phantom_aux:nnn #1\q_stop
+ }
+ {
+ \tl_set:Nn \l__diffco_entiand_tl { #1 }
+ }
+ }
+ }
+
+\cs_new:Npn \l__diffco_phantom_aux:nn #1#2\q_stop
+ {
+ \tl_set:Nn \l__diffco_phantom_tl { #1 }
+ \tl_set:Nn \l__diffco_entiand_tl { #2 }
+ }
+
+\cs_new:Npn \l__diffco_phantom_aux:nnn #1#2#3\q_stop
+ {
+ \tl_set:Nn \l__diffco_phantom_tl { #1 { #2 } }
+ \tl_set:Nn \l__diffco_entiand_tl { #3 }
+ }
+%%%%%%%%%%%%%%%%%%%%
+% Partial differential coefficient. #1 (star) = append differentiand
+% to diff. coeff.(displace from numerator); #2 = comma list of the
+% orders of diff. in each var.; #3 = order override for the
+% numerator; #4 = differentiand; #5 = clist of vars of diff. in
+% order; #6 = list of vars held constant
+\NewDocumentCommand \diffp{ s o o t/ m m g }
+ {
+ \group_begin:
+
+ % diff. order list
+ \tl_clear:N \l__diffco_order_clist
+ \IfValueT { #2 }
+ {
+ \clist_set:Nn \l__diffco_order_clist { #2 }
+ \tl_set:Nx \l__diffco_order_spec_tl
+ { [\clist_use:Nn \l__diffco_order_clist { , }]}
+ }
+
+ % order list override
+ \IfValueT { #3 }
+ {
+ \bool_set_true:N \l__diffco_override_bool
+ \tl_set:Nn \l__diffco_order_tl { #3 }
+ }
+
+ \__diffco_orders:Nn \l__diffco_order_clist { #6 }
+
+ % position of differentiand
+ \IfBooleanTF { #1 }
+ { % appended
+ \__diffco_phantom:n { #5 }
+ \tl_set:Nn \l__diffco_coeff_tl
+ {
+ \frac { \partial
+ \__diffco_omit_order_if_i:N \l__diffco_order_tl
+ \l__diffco_phantom_tl } { \l__diffco_denom_tl }
+ \l__diffco_entiand_tl
+ }
+ }
+ { % in numerator
+ \tl_set:Nn \l__diffco_coeff_tl
+ {
+ \frac { \partial
+ \__diffco_omit_order_if_i:N \l__diffco_order_tl
+ #5 } { \l__diffco_denom_tl }
+ }
+ }
+
+ \IfNoValueTF { #7 }
+ {
+ \l__diffco_coeff_tl
+ }
+ { % hold some vars const./ pt of eval.
+ \bool_set_false:N \l__diffco_ordinary_bool
+ \__diffco_delims:nnnnN #7;;;;\q_stop \l__diffco_ordinary_bool
+ }
+
+ \group_end:
+ } % end of \diffp
+
+
+\NewDocumentCommand \jacob { m m }
+ { % need extra braces in denom for clist manipulations
+ \diffp{ (#1) }{ { {{(#2)}} } }
+ }
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% #1 subscript; #2 superscript; #3 delims; #4 nudge override
+% #5 detritus; #6 boolean (true = ordinary deriv.; false = partial deriv.)
+\cs_new:Npn \__diffco_delims:nnnnN #1;#2;#3;#4;#5\q_stop#6
+ {
+ \tl_set:Nn \l__diffco_sub_tl { #1 }
+ \tl_set:Nn \l__diffco_super_tl { #2 }
+ \tl_if_empty:nTF { #3 }
+ { % default delims
+ \bool_if:NTF #6
+ { % ordinary
+ \tl_set_eq:NN \l__diffco_ldelim_tl \g_diffco_d_ldelim_tl
+ \tl_set_eq:NN \l__diffco_rdelim_tl \g_diffco_d_rdelim_tl
+ \tl_if_empty:nTF { #4 }
+ { \tl_set_eq:NN \l__diffco_nudge_tl \g_diffco_d_nudge_tl }
+ { \tl_set:Nn \l__diffco_nudge_tl { \mskip #4 mu } }
+ }
+ { % partial
+ \tl_set_eq:NN \l__diffco_ldelim_tl \g_diffco_p_ldelim_tl
+ \tl_set_eq:NN \l__diffco_rdelim_tl \g_diffco_p_rdelim_tl
+ \tl_if_empty:nTF { #4 }
+ { \tl_set_eq:NN \l__diffco_nudge_tl \g_diffco_p_nudge_tl }
+ { \tl_set:Nn \l__diffco_nudge_tl { \mskip #4 mu } }
+ }
+ }
+ { % delims specified
+ \tl_set:Nn \l__diffco_ldelim_tl { \left \use_i:nn #3 }
+ \tl_set:Nn \l__diffco_rdelim_tl { \right \use_ii:nn #3 }
+ \tl_if_empty:nTF { #4 }
+ {
+ \tl_set:NV \l_tmpa_tl { \use_ii:nn #3 }
+ \__diffco_get_nudge:N \l_tmpa_tl
+ }
+ {
+ \tl_set:Nx \l__diffco_nudge_tl { \mskip #4 mu }
+ }
+ }
+ \l__diffco_ldelim_tl \l__diffco_coeff_tl \l__diffco_rdelim_tl
+ \tl_if_empty:NF \l__diffco_sub_tl
+ { \c_math_subscript_token { \l__diffco_nudge_tl \l__diffco_sub_tl } }
+ \tl_if_empty:NF \l__diffco_super_tl
+ { \c_math_superscript_token { \l__diffco_nudge_tl \l__diffco_super_tl } }
+ }
+
+\cs_new:Npn \__diffco_get_nudge:N #1
+ {
+ \exp_args:NV\tl_case:NnF #1
+ {
+ ) { \tl_set:Nn \l__diffco_nudge_tl { \mskip -6mu } }
+ > { \tl_set:Nn \l__diffco_nudge_tl { \mskip -6mu } }
+ \} { \tl_set:Nn \l__diffco_nudge_tl { \mskip -4mu } }
+ \rangle { \tl_set:Nn \l__diffco_nudge_tl { \mskip -6mu } }
+ }
+ { \tl_set:Nn \l__diffco_nudge_tl { \mskip 0mu } }
+ }
+
+% #1 is the clist of diff. orders
+% #2 is the clist of variables
+\cs_new:Npn \__diffco_orders:Nn #1#2
+ {
+ \int_zero:N \l_tmpa_int
+ \tl_clear:N \l_tmpb_tl
+ \clist_clear:N \l_tmpa_clist
+ \clist_clear:N \l_tmpb_clist
+ \clist_clear:N \l__diffco_vars_clist
+
+ \clist_set:Nn \l__diffco_vars_clist { #2 }
+ \clist_map_inline:Nn \l__diffco_vars_clist
+ {
+ \bool_set_false:N \l__diffco_no_parens_bool
+
+ % get order of each variable
+ \clist_pop:NNF #1 \l_tmpa_tl
+ { \tl_set:Nn \l_tmpa_tl { 1 } }
+
+ \tl_if_eq:noT { 1 } \l_tmpa_tl
+ { \bool_set_true:N \l__diffco_no_parens_bool }
+
+ \clist_put_right:NV \l_tmpa_clist \l_tmpa_tl
+
+ % create the denominator
+ \tl_clear:N \l_tmpb_tl
+ \bool_if:nTF
+ {
+ \int_compare_p:nNn { \tl_count:n { ##1 } } = { \c_one }
+ ||
+ \l__diffco_no_parens_bool
+ }
+ { \tl_put_right:Nn \l_tmpb_tl { \partial ##1 } }
+ { \tl_put_right:Nn \l_tmpb_tl { \partial (##1) } }
+
+ \tl_if_eq:noF { 1 } \l_tmpa_tl
+ {
+ \tl_put_right:Nn \l_tmpb_tl { ^ }
+ \tl_put_right:Nx \l_tmpb_tl { { \l_tmpa_tl } }
+ }
+
+ \clist_put_right:No \l_tmpb_clist \l_tmpb_tl
+ } % end of inline map
+
+ % numerator order
+ \bool_if:NF \l__diffco_override_bool
+ {
+ \tl_set:Nx \l__diffco_orders_in_tl { \clist_use:Nn \l_tmpa_clist {+} }
+ \diff_simplify_orders:NN \l__diffco_orders_in_tl \l__diffco_order_tl
+ }
+
+ % denominator
+ \tl_set:Nx \l__diffco_denom_tl { \clist_use:Nn
+ \l_tmpb_clist { \g_diffco_sep_tl } }
+ }
+
+% don't display order 1 superscript
+\cs_new:Npn \__diffco_omit_order_if_i:N #1
+ {
+ \tl_if_eq:noF { 1 } #1
+ { ^{ \g_diffco_p_sep_tl \l__diffco_order_tl } }
+ }
+%%%%%%%%%%%%%%%%%%%%%%
+% #1 is expr. in; #2 is expr. out
+\cs_new:Npn \diff_simplify_orders:NN #1 #2
+ {
+ \tl_clear:N \l__diffco_nos_tl
+
+ \__diffco_digest_expr:NNNN #1 \l__diffco_nos_tl
+ \l__diffco_alg_tl \l__diffco_vars_prop
+
+ \__diffco_eval_nos:N \l__diffco_nos_tl
+
+ \tl_if_empty:NF \l__diffco_alg_tl
+ { \__diffco_eval_vars:NN \l__diffco_alg_tl \l__diffco_vars_prop }
+
+ \__diffco_manicure_result:NNN \l__diffco_nos_tl \l__diffco_alg_tl #2
+ }
+
+% #1 is the expression; #2 (tl) receives the numerical part;
+% #3 (tl) receives the algebraic part; #4 (prop) receives the vars
+\cs_new:Npn \__diffco_digest_expr:NNNN #1#2#3#4
+ {
+ \tl_put_right:Nn #1 { + }
+ \tl_set:Nn \l__diffco_curr_term_tl { + }
+ \int_set:Nn \l__diffco_curr_state_int { \c_zero }
+ \int_set:Nn \l__diffco_prev_state_int { \c_zero }
+ \int_set:Nn \l__diffco_curr_tok_int { \c_zero }
+ \tl_clear:N #3
+ \prop_clear:N #4
+
+ \tl_map_inline:Nn #1
+ {
+ \tl_set:Nn \l__diffco_curr_tok_tl { ##1 }
+ \__diffco_get_curr_index:NN ##1 \l__diffco_curr_tok_int
+ \__diffco_compare_states:NNNNN \l__diffco_curr_state_int
+ \l__diffco_curr_tok_int #2#3#4
+ }
+ \tl_if_empty:NT #2 { \tl_set:Nn #2 { 0 } }
+ }
+
+% #1 contains current token (tl); #2 receives current token index (int)
+\cs_new:Npn \__diffco_get_curr_index:NN #1#2
+ {
+ \tl_if_in:NnTF \c__diffco_digits_tl { #1 }
+ { % digit
+ \int_set:Nn #2 { \c_one }
+ }
+ {
+ \tl_case:NnF #1
+ {
+ + { \int_set_eq:NN #2 \c_zero }
+ - { \int_set_eq:NN #2 \c_zero }
+ ^ { \int_set_eq:NN #2 \c_three }
+ * { \int_set_eq:NN #2 \c_five }
+ \times
+ {
+ \int_set_eq:NN #2 \c_five
+ \tl_set:Nn \l__diffco_curr_tok_tl { * }
+ }
+ ( { \int_set_eq:NN #2 \c_six }
+ ) { \int_set_eq:NN #2 \c_seven }
+ }
+ {
+ \token_if_math_subscript:NTF #1
+ { \int_set_eq:NN #2 { \c_four } }
+ {
+ \int_set_eq:NN #2 \c_two } % var
+ }
+ }
+ }
+
+% #1 (int) is curr. state; #2 (int) is curr token index;
+% #3 (tl) receives the numerical part;
+% #4 (tl) receives the algebraic part;
+% #5 (prop) receives the vars
+\cs_new:Npn \__diffco_compare_states:NNNNN #1#2#3#4#5
+ {
+ \int_case:nn { #1 }
+ {
+ { \c_zero } % sgn
+ { \__diffco_sgn_transitions:NNNN #1#2#3#4 }
+ { \c_one } % num
+ { \__diffco_num_transitions:NNNN #1#2#3#4 }
+ { \c_two } % alg
+ { \__diffco_alg_transitions:NNNNN #1#2#3#4#5 }
+ { \c_three } % exp
+ { \__diffco_exp_transitions:NN #1#2 }
+ { \c_four } % sub (_)
+ { \__diffco_sub_transitions:NN #1#2 }
+ { \c_five } % mul (*,X)
+ { \__diffco_mul_transitions:NNNN #1#2#3#4 }
+ }
+ }
+
+% transitions from the signed state
+% #1 = 0, current state; #2 current token index
+% #3 store num. part; #4 store alg. part
+\cs_new:Npn \__diffco_sgn_transitions:NNNN #1#2#3#4
+ {
+ \int_case:nnF { #2 }
+ {
+ { \c_zero } % tok = s
+ {
+ \tl_if_eq:NNTF \l__diffco_curr_term_tl \l__diffco_curr_tok_tl
+ { \tl_set:Nn \l__diffco_curr_term_tl { + } }
+ { \tl_set:Nn \l__diffco_curr_term_tl { - } }
+ \int_set_eq:NN \l__diffco_prev_state_int #1
+ % \int_set:Nn #1 { \c_zero }
+ }
+ { \c_one } % tok = d
+ { \__diffco_term_qvar_append:NN #1 #2 }
+ { \c_two } % tok = v
+ {
+ \tl_put_right:Nn \l__diffco_curr_term_tl { 1 }
+ \__diffco_term_var_append:NN #1 #2
+ }
+ { \c_six } % tok = (
+ {
+ \tl_put_right:Nn \l__diffco_curr_term_tl { 1*( }
+ \tl_put_right:NV #3 \l__diffco_curr_term_tl
+ \tl_put_right:NV #4 \l__diffco_curr_term_tl
+ \tl_set:Nn \l__diffco_curr_term_tl { + }
+ \int_set_eq:NN \l__diffco_prev_state_int #1
+ \int_set:Nn #1 { \c_zero }
+ }
+ { \c_seven } % tok = )
+ {
+ \tl_put_right:Nn #3 { ) }
+ \tl_put_right:Nn #4 { ) }
+ \tl_set:Nn \l__diffco_curr_term_tl { + }
+ \int_set_eq:NN \l__diffco_prev_state_int #1
+ \int_set:Nn #1 { \c_zero }
+ }
+ }
+ {
+ \msg_error:nnxxx { diffcoeffx } { order_spec_construct }
+ { \l__diffco_order_spec_tl } { \l__diffco_curr_tok_tl } { sign }
+ }
+ }
+
+% transitions from the numeric state
+% #1 = 1, current state; #2 current token index
+% #3 store num. part; #4 store alg. part
+\cs_new:Npn \__diffco_num_transitions:NNNN #1#2#3#4
+ {
+ \int_case:nnF { #2 }
+ {
+ { \c_zero } % tok = s
+ {
+ \tl_put_right:NV #3 \l__diffco_curr_term_tl
+ \tl_clear:N \l__diffco_curr_qvar_tl
+ \tl_clear:N \l__diffco_curr_term_tl
+ \__diffco_term_append:NN #1#2
+ }
+ { \c_one } % tok = d
+ { \__diffco_term_qvar_append:NN #1 #2 }
+ { \c_two } % tok = v
+ {
+ \tl_clear:N \l__diffco_curr_qvar_tl
+ \__diffco_term_var_append:NN #1#2
+ }
+ { \c_three } % tok = ^
+ { \__diffco_term_qvar_append:NN #1#2 }
+ { \c_five } % tok = *
+ {
+ \tl_clear:N \l__diffco_curr_qvar_tl
+ \__diffco_term_append:NN #1#2
+ }
+ { \c_six } % tok = (
+ {
+ \tl_put_right:Nn \l__diffco_curr_term_tl { *( }
+ \tl_put_right:NV #3 \l__diffco_curr_term_tl
+ \tl_put_right:NV #4 \l__diffco_curr_term_tl
+ \tl_set:Nn \l__diffco_curr_term_tl { + }
+ \int_set_eq:NN \l__diffco_prev_state_int #1
+ \int_set:Nn #1 { \c_zero }
+ }
+ { \c_seven } % tok = )
+ {
+ \tl_put_right:Nn \l__diffco_curr_term_tl { ) }
+ \tl_put_right:NV #3 \l__diffco_curr_term_tl
+ \tl_put_right:Nn #4 { +0) }
+ \tl_set:Nn \l__diffco_curr_term_tl { + }
+ \int_set_eq:NN \l__diffco_prev_state_int #1
+ \int_set:Nn #1 { \c_zero }
+ }
+ }
+ {
+ \msg_error:nnxxx { diffcoeffx } { order_spec_construct }
+ { \l__diffco_order_spec_tl } { \l__diffco_curr_tok_tl } { number }
+ }
+ }
+
+% transitions from the algebraic state
+% #1 = 2, current state; #2 current token index
+% #3 store num. part; #4 store alg. part; #5 var store
+\cs_new:Npn \__diffco_alg_transitions:NNNNN #1#2#3#4#5
+ {
+ \int_case:nnF { #2 }
+ {
+ { \c_zero } % tok = s
+ {
+ \bool_if:NF \l__diffco_vars_noted_bool
+ { \__diffco_store_var:NN #5 \l__diffco_curr_var_tl }
+ \tl_clear:N \l__diffco_curr_var_tl
+ \tl_put_right:NV #4 \l__diffco_curr_term_tl
+ \tl_clear:N \l__diffco_curr_term_tl
+ \__diffco_term_append:NN #1 #2
+ }
+ { \c_one } % tok = d
+ {
+ \int_compare:nNnTF { \l__diffco_prev_state_int } = { \c_three }
+ { \__diffco_term_var_append:NN #1 \c_two }
+ {
+ \msg_error:nnxxx { diffcoeffx } { order_spec_construct }
+ { \l__diffco_order_spec_tl } { \l__diffco_curr_tok_tl }
+ { variable }
+ }
+ }
+ { \c_two } % tok = v
+ { \__diffco_term_var_append:NN #1 #2 }
+
+ { \c_three } % tok = ^
+ { \__diffco_term_var_append:NN #1#2 }
+ { \c_four } % tok = _
+ { \__diffco_term_var_append:NN #1#2 }
+ { \c_seven } % tok = )
+ {
+ \bool_if:NF \l__diffco_vars_noted_bool
+ { \__diffco_store_var:NN #5 \l__diffco_curr_var_tl }
+ \tl_clear:N \l__diffco_curr_var_tl
+ \tl_put_right:Nn \l__diffco_curr_term_tl { ) }
+ \tl_put_right:Nn #3 { +0) }
+ \tl_put_right:NV #4 \l__diffco_curr_term_tl
+ \tl_set:Nn \l__diffco_curr_term_tl { + }
+ \int_set_eq:NN \l__diffco_prev_state_int #1
+ \int_set:Nn #1 { \c_zero }
+ }
+ }
+ {
+ \msg_error:nnxxx { diffcoeffx } { order_spec_construct }
+ { \l__diffco_order_spec_tl } { \l__diffco_curr_tok_tl } { variable }
+ }
+ }
+
+% transitions from the exponent state
+% #1 = 3, current state; #2 current token index
+\cs_new:Npn \__diffco_exp_transitions:NN #1#2
+ {
+ \int_case:nn { \l__diffco_prev_state_int }
+ {
+ { \c_one } % prev = num
+ {
+ \int_case:nnF { #2 }
+ {
+ { \c_one } % tok = d
+ {
+ \tl_clear:N \l__diffco_curr_qvar_tl
+ \tl_put_right:Nn \l__diffco_curr_tok_tl { * }
+ \__diffco_term_append:NN #1 \c_five
+ \bool_set_true:N \l__diffco_fp_bool
+ }
+ { \c_two } % tok = v
+ {
+ \__diffco_term_qvar_append:NN #1 \c_two
+ \tl_set_eq:NN \l__diffco_curr_var_tl \l__diffco_curr_qvar_tl
+ \tl_clear:N \l__diffco_curr_qvar_tl
+ }
+ }
+ {
+ \msg_error:nnxxx { diffcoeffx } { order_spec_construct }
+ { \l__diffco_order_spec_tl } { \l__diffco_curr_tok_tl } { ^ }
+ }
+ }
+ { \c_two } % prev = alg
+ {
+ \int_compare:nNnTF { #2 } < { \c_three }
+ { \__diffco_term_var_append:NN #1 \c_two }
+ {
+ \msg_error:nnxxx { diffcoeffx } { order_spec_construct }
+ { \l__diffco_order_spec_tl } { \l__diffco_curr_tok_tl } { ^ }
+ }
+ }
+ }
+ }
+
+% transitions from the subscript state
+% #1 = 4, current state; #2 current token index
+\cs_new:Npn \__diffco_sub_transitions:NN #1#2
+ {
+ \bool_if:nTF
+ {(
+ \int_compare_p:nNn { \l__diffco_prev_state_int } = { \c_two } &&
+ \int_compare_p:nNn { #2 } < { \c_three }
+ )}
+ {
+ \__diffco_term_var_append:NN #1 \c_two
+ }
+ {
+ \msg_error:nnxxx { diffcoeffx } { order_spec_construct }
+ { \l__diffco_order_spec_tl } { \l__diffco_curr_tok_tl } { _ }
+ }
+ }
+
+% transitions from the multiplicative state
+% #1 = 5, current state; #2 current token index
+% #3 store num. part; #4 store alg. part
+\cs_new:Npn \__diffco_mul_transitions:NNNN #1#2#3#4
+ {
+ \int_case:nnF { #2 }
+ {
+ { \c_zero } % tok = s
+ {
+ \int_compare:nNnTF {\l__diffco_prev_state_int } = { \c_three }
+ {
+ \tl_put_right:Nn \l__diffco_curr_term_tl { 1 }
+ \tl_put_right:NV #3 \l__diffco_curr_term_tl
+ \tl_clear:N \l__diffco_curr_term_tl
+ \__diffco_term_append:NN #1 #2
+ }
+ {
+ \msg_error:nnxxx { diffcoeffx } { order_spec_construct }
+ { \l__diffco_order_spec_tl } { \l__diffco_curr_tok_tl }
+ { multiplicative~token }
+ }
+ }
+ { \c_one } % tok = d
+ { \__diffco_term_qvar_append:NN #1 #2 }
+ { \c_two } % tok = v
+ {
+ \tl_put_right:Nn \l__diffco_curr_term_tl {1 }
+ \__diffco_term_var_append:NN #1#2
+ }
+ { \c_five } % tok = *
+ { \prg_do_nothing: }
+ { \c_six } % tok = (
+ {
+ \tl_put_right:Nn \l__diffco_curr_term_tl { ( }
+ \tl_put_right:NV #3 \l__diffco_curr_term_tl
+ \tl_put_right:NV #4 \l__diffco_curr_term_tl
+ \tl_set:Nn \l__diffco_curr_term_tl { + }
+ \int_set_eq:NN \l__diffco_prev_state_int #1
+ \int_set:Nn #1 { \c_zero }
+ }
+ }
+ {
+ \msg_error:nnxxx { diffcoeffx } { order_spec_construct }
+ { \l__diffco_order_spec_tl } { \l__diffco_curr_tok_tl }
+ { multiplicative~token }
+ }
+ }
+
+%%%%%%%%%%%%%%%%%%%
+% term/var/qvar appending routines
+% #1 current state; #2 current token index
+\cs_new:Npn \__diffco_term_var_append:NN #1#2
+ {
+ \tl_put_right:NV \l__diffco_curr_term_tl \l__diffco_curr_tok_tl
+ \tl_put_right:NV \l__diffco_curr_var_tl \l__diffco_curr_tok_tl
+ \int_set_eq:NN \l__diffco_prev_state_int #1
+ \int_set_eq:NN #1 #2
+ }
+
+% #1 current state; #2 current token index
+\cs_new:Npn \__diffco_term_qvar_append:NN #1#2
+ {
+ \tl_put_right:NV \l__diffco_curr_term_tl \l__diffco_curr_tok_tl
+ \tl_put_right:NV \l__diffco_curr_qvar_tl \l__diffco_curr_tok_tl
+ \int_set_eq:NN \l__diffco_prev_state_int #1
+ \int_set_eq:NN #1 #2
+ }
+
+% #1 current state; #2 current token index
+\cs_new:Npn \__diffco_term_append:NN #1#2
+ {
+ \tl_put_right:NV \l__diffco_curr_term_tl \l__diffco_curr_tok_tl
+ \int_set_eq:NN \l__diffco_prev_state_int #1
+ \int_set_eq:NN #1 #2
+ }
+
+% #1 is prop list; #2 is tl containing var
+\cs_new:Npn \__diffco_store_var:NN #1 #2
+ {
+ \int_set:Nn \l_tmpa_int { \exp_args:NV \tl_count_tokens:n #2 }
+ \prop_get:NVNTF #1 \l_tmpa_int \l_tmpa_tl
+ {
+ \tl_put_right:Nn \l_tmpa_tl { , }
+ \tl_put_right:NV \l_tmpa_tl #2
+ \prop_put:NVV #1 \l_tmpa_int \l_tmpa_tl
+ }
+ {
+ \prop_put:NVV #1 \l_tmpa_int #2
+ }
+ }
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% evals numerical expr. in #1, which receives the
+% evaluated expr.
+\cs_new:Npn \__diffco_eval_nos:N #1
+ {
+ \bool_if:NTF \l__diffco_fp_bool
+ { % exponent; use l3fp
+ \fp_set:Nn \l_tmpa_fp { #1 }
+ \int_set:Nn \l_tmpa_int { \fp_use:N \l_tmpa_fp }
+ \bool_set_false:N \l__diffco_fp_bool
+ }
+ { % normal mode; use l3int
+ \int_set:Nn \l_tmpa_int { #1 }
+ }
+ \tl_set:Nx #1 { \int_use:N \l_tmpa_int }
+
+ \int_compare:nNnT { \l_tmpa_int } > { \c_zero }
+ { \tl_put_left:Nn #1 { + } }
+ }
+
+% #1 (tl) has algebraic part & receives eval. expression
+% #2 (prop) contains the variables
+% The idea is to remove each var but leave coeffs, split into
+% num & alg parts, eval. the num part for the net coeff of var
+\cs_new:Npn \__diffco_eval_vars:NN #1#2
+ {
+ \bool_set_true:N \l__diffco_vars_noted_bool
+ \prop_set_eq:NN \l_tmpa_prop #2
+ \int_set_eq:NN \l_tmpa_int \c_one
+ \bool_until_do:nn { \prop_if_empty_p:N #2 }
+ {
+ \prop_pop:NVNT #2 \l_tmpa_int \l_tmpa_tl
+ {
+ \tl_put_left:Nn \l_tmpa_tl { , }
+ \tl_put_left:NV \l__diffco_vars_tl \l_tmpa_tl
+ }
+ \int_incr:N \l_tmpa_int
+ }
+
+ \clist_set:NV \l__diffco_vars_clist \l__diffco_vars_tl
+ \clist_remove_duplicates:N \l__diffco_vars_clist
+ \bool_if:NF \l__diffco_override_bool
+ {
+ \clist_map_inline:Nn \l__diffco_vars_clist
+ {
+ \tl_replace_all:Nnn #1 { ##1 } { }
+ \__diffco_digest_expr:NNNN #1 \l__diffco_nos_aux_tl
+ \l__diffco_alg_aux_tl \l_tmpa_prop
+ \__diffco_eval_nos:N \l__diffco_nos_aux_tl
+
+ \__diffco_cumulate_expr:NnN \l__diffco_nos_aux_tl { ##1 }
+ \l__diffco_alg_expr_tl
+
+ \tl_set_eq:NN #1 \l__diffco_alg_aux_tl
+ \tl_clear:N \l__diffco_nos_aux_tl
+ \tl_clear:N \l__diffco_alg_aux_tl
+ }
+ }
+ \tl_set_eq:NN #1 \l__diffco_alg_expr_tl
+ }
+
+% #1 is num coeff; #2 is var; #3 is cumulating expr. (All tl.)
+\cs_new:Npn \__diffco_cumulate_expr:NnN #1#2#3
+ {
+ \int_case:nnF { #1 }
+ {
+ { 0 } { \prg_do_nothing: }
+ { +1 } { \tl_put_right:Nn #3 { + #2 } }
+ { -1 } { \tl_put_right:Nn #3 { - #2 } }
+ }
+ {
+ \tl_put_right:NV #3 { #1 }
+ \exp_args:NNx \tl_if_in:NnT \c__diffco_digits_tl { \tl_head:n { #2 } }
+ { \tl_put_right:Nn #3 { \times} }
+ \tl_put_right:Nn #3 { #2 }
+ }
+ }
+
+% alg. part precedes num. part unless alg. starts
+% with - and nums > 0. #1 nums, #2 alg, #3 output
+\cs_new:Npn \__diffco_manicure_result:NNN #1#2#3
+ { % alg < 0 ?
+ \exp_args:NV \tl_if_head_eq_charcode:nNTF #2 -
+ {
+ \int_compare:nNnTF { #1 } > { \c_zero }
+ { % nums > 0
+ \tl_concat:NNN #3 #1 #2
+ }
+ { % nums =< 0
+ \seq_set_split:NnV \l_tmpa_seq { + } #2
+ \seq_pop:NN \l_tmpa_seq \l_tmpa_tl
+ \tl_set:Nx \l_tmpb_tl { \seq_use:Nn \l_tmpa_seq { + } }
+ \int_compare:nNnF { #1 } = { \c_zero }
+ { \tl_concat:NNN \l_tmpa_tl \l_tmpa_tl #1 }
+ \tl_concat:NNN #3 \l_tmpb_tl \l_tmpa_tl
+ }
+ }
+ { % alg >= 0
+ \int_compare:nNnTF { #1 } = { \c_zero }
+ { \tl_set_eq:NN #3 #2 }
+ { \tl_concat:NNN #3 #2 #1 }
+ }
+
+ % if everything cancels, output 0
+ \tl_if_empty:NTF #3 { \tl_set:Nn #3 { 0 } }
+ {
+ % trim initial + sign
+ \exp_args:NV \tl_if_head_eq_charcode:nNT #3 +
+ { \tl_set:Nx #3 { \tl_tail:N #3 } }
+ }
+ }
+
+%%%%%%%%%%%%%%%%%%%%
+% messages
+\cs_gset:Npn \msg_error_text:n #1
+ { #1.sty.~Is~this~construction~intended }
+\cs_gset:Npn \msg_info_text:n #1
+ { If~intended~then~use~the~order-override~option~to~specify~the~overall~
+ order~of~differentiation. }
+
+\msg_new:nnnn { diffcoeffx } { order_spec_construct }
+ { \msg_error_text:n { diffcoeffx }:~#3~followed~by~#2~in~the~order~
+ specification~#1~\msg_line_context:? }
+ { \msg_info_text:n { diffcoeffx } } \ No newline at end of file