diff options
author | Karl Berry <karl@freefriends.org> | 2016-06-27 20:41:31 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2016-06-27 20:41:31 +0000 |
commit | f3714e22cf9b596abec6c42dc1dc9dd95ef82b61 (patch) | |
tree | 4aa08c0e81aa4e5b21e2cd909cabaa8dca30a889 /Master/texmf-dist/tex | |
parent | e9f2b559eb367b62e1b88e7e73dd32c3b7d253c1 (diff) |
diffcoeff (27jun16)
git-svn-id: svn://tug.org/texlive/trunk@41554 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex')
-rw-r--r-- | Master/texmf-dist/tex/latex/diffcoeff/diffcoeff.sty | 711 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/diffcoeff/diffcoeffx.sty | 972 |
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 |