summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/diffcoeff/diffcoeff.sty
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/diffcoeff/diffcoeff.sty
Initial commit
Diffstat (limited to 'macros/latex/contrib/diffcoeff/diffcoeff.sty')
-rw-r--r--macros/latex/contrib/diffcoeff/diffcoeff.sty686
1 files changed, 686 insertions, 0 deletions
diff --git a/macros/latex/contrib/diffcoeff/diffcoeff.sty b/macros/latex/contrib/diffcoeff/diffcoeff.sty
new file mode 100644
index 0000000000..71689c911e
--- /dev/null
+++ b/macros/latex/contrib/diffcoeff/diffcoeff.sty
@@ -0,0 +1,686 @@
+% This is file `diffcoeff.sty'.
+%
+% This work may be distributed and/or modified under the conditions
+% of the LaTeX Project Public License, either version 1.3c
+% (2008-05-04) of this license or any later version; see
+% http://www.latex-project.org/lppl.txt
+%
+% Andrew Parsloe ajparsloe@gmail.com
+%
+\RequirePackage{expl3}
+\RequirePackage{xparse,l3keys2e,xtemplate}
+\ProvidesExplPackage {diffcoeff} {2019/03/10} {3.1}
+ {Write differential coefficients consistently and easily.}
+%
+\keys_define:nn { diffcoeff }
+ {
+ ISO .bool_gset:N = \g__diffcoeff_ISO_bool,
+ def-file .tl_gset:N = \g__diffcoeff_def_tl ,
+ def-file .initial:n = diffcoeff ,
+ def-file .default:n = diffcoeff
+ }
+\ProcessKeysPackageOptions { diffcoeff }
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\cs_generate_variant:Nn \tl_if_eq:nnTF { nV }
+
+\tl_new:N \l__diffcoeff_oporder_tl
+\tl_new:N \l__diffcoeff_differentiand_tl
+\tl_new:N \l__diffcoeff_type_tl
+\tl_new:N \l__diffcoeff_tot_order_tl
+\tl_new:N \l__diffcoeff_curr_num_tl
+\tl_new:N \l__diffcoeff_curr_var_tl
+\tl_new:N \l__diffcoeff_paren_tl
+\tl_new:N \l__diffcoeff_trailing_tl
+
+\tl_const:Nn \c__diffcoeff_digits_tl { 1234567890 }
+
+\seq_new:N \l__diffcoeff_orders_seq
+\seq_new:N \l__diffcoeff_vars_seq
+\seq_new:N \l__diffcoeff_denom_seq
+\seq_new:N \l__diffcoeff_paren_seq
+
+\prop_new:N \l__diffcoeff_vars_prop
+
+\bool_new:N \l__diffcoeff_op_left_bool
+\bool_new:N \l__diffcoeff_single_var_bool
+\bool_new:N \l__diffcoeff_opwrap_bool
+\bool_new:N \l__diffcoeff_integ_bool
+
+\int_new:N \l__diffcoeff_vars_int
+\int_new:N \l__diffcoeff_format_int
+\int_new:N \l__diffcoeff_curr_tok_int
+\int_new:N \l__diffcoeff_curr_state_int
+\int_new:N \l__diffcoeff_nos_int
+\int_new:N \l__diffcoeff_parenvar_int
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DeclareObjectType { derivative } { 5 }
+
+% defaults: ordinary deriv. values
+\DeclareTemplateInterface { derivative } { DERIV } { 5 }
+ {
+ op-symbol : tokenlist = d ,
+ op-symbol-alt : tokenlist = \KeyValue { op-symbol },
+ op-order-sep : muskip = 1 mu ,
+ /-op-order-sep : muskip = 1 mu ,
+ *-op-left : boolean = false ,
+ *-italic-nudge : muskip = 3 mu ,
+ */-op-wrap : boolean = true ,
+ long-var-wrap : choice { dv, d(v), (dv) }
+ = d(v) ,
+ denom-term-sep : muskip = 2 mu ,
+ /-denom-term-sep : muskip = 1 mu ,
+ term-sep-adjust : muskip = -1 mu ,
+ left-delim : tokenlist = \left . ,
+ right-delim : tokenlist = \right |,
+ elbowroom : muskip = 0 mu ,
+ subscr-nudge : muskip = 0 mu ,
+ /-left-delim : tokenlist = ( ,
+ /-right-delim : tokenlist = ) ,
+ /-elbowroom : muskip = 0 mu ,
+ /-subscr-nudge : muskip = 0 mu
+ }
+% #1 order spec(seqvar); #2 order override(tlvar)
+% #3 differentiand(tlvar); #4 denominator(seqvar)
+% #5 subscript(tlvar)
+\DeclareTemplateCode { derivative } { DERIV } { 5 }
+ {
+ op-symbol = \l__diffcoeff_op_tl ,
+ op-symbol-alt = \l__diffcoeff_op_alt_tl ,
+ op-order-sep = \l__diffcoeff_oporder_muskip ,
+ /-op-order-sep = \l_tmpa_muskip ,
+ *-op-left = \l__diffcoeff_op_left_bool ,
+ *-italic-nudge = \l__diffcoeff_opnudge_muskip ,
+ */-op-wrap = \l__diffcoeff_opwrap_bool ,
+ long-var-wrap = {
+ dv = \cs_set:Npn \__diffcoeff_wrap_longvars:nn #1#2
+ { \l__diffcoeff_op_alt_tl {#2}^{#1} },
+ d(v) = \cs_set:Npn \__diffcoeff_wrap_longvars:nn #1#2
+ { \l__diffcoeff_op_alt_tl {(#2)}^{#1} },
+ (dv) = \cs_set:Npn \__diffcoeff_wrap_longvars:nn #1#2
+ { (\l__diffcoeff_op_alt_tl {#2)}^{#1} },
+ unknown = \cs_set:Npn \__diffcoeff_wrap_longvars:nn #1#2
+ { \l__diffcoeff_op_alt_tl {(#2)}^{#1} }
+ } ,
+ denom-term-sep = \l__diffcoeff_varsep_muskip ,
+ /-denom-term-sep = \l_tmpb_muskip ,
+ term-sep-adjust = \l__diffcoeff_sep_adj_muskip ,
+ left-delim = \l__diffcoeff_ldelim_tl ,
+ right-delim = \l__diffcoeff_rdelim_tl ,
+ elbowroom = \l__diffcoeff_elbowrm_muskip ,
+ subscr-nudge = \l__diffcoeff_subnudge_muskip,
+ /-left-delim = \l_tmpa_tl ,
+ /-right-delim = \l_tmpb_tl ,
+ /-elbowroom = \l_tmpc_muskip ,
+ /-subscr-nudge = \l_tmpd_muskip
+ }
+ {
+ \AssignTemplateKeys
+
+ \bool_if:NF\l__diffcoeff_integ_bool
+ {
+ \int_compare:nNnT { \l__diffcoeff_format_int } > { 1 }
+ { \__diffcoeff_slash_vals: }
+ \__diffcoeff_build:NNNNN #1#2#3#4#5
+ }
+ }
+%%%%%%%%%%
+\cs_new:Npn \__diffcoeff_slash_vals:
+ {
+ \muskip_set:Nn \l__diffcoeff_oporder_muskip \l_tmpa_muskip
+ \muskip_set:Nn \l__diffcoeff_varsep_muskip \l_tmpb_muskip
+ \muskip_set:Nn \l__diffcoeff_elbowrm_muskip \l_tmpc_muskip
+ \muskip_set:Nn \l__diffcoeff_subnudge_muskip \l_tmpd_muskip
+ \tl_set:NV \l__diffcoeff_ldelim_tl \l_tmpa_tl
+ \tl_set:NV \l__diffcoeff_rdelim_tl \l_tmpb_tl
+ }
+\cs_new:Npn \__diffcoeff_build:NNNNN #1#2#3#4#5
+ {
+ \bool_if:NF \l__diffcoeff_opwrap_bool
+ { \int_set:Nn \l__diffcoeff_format_int { 4 } }
+ \exp_args:NV\tl_if_novalue:nF #5
+ { \l__diffcoeff_ldelim_tl \mkern \l__diffcoeff_elbowrm_muskip }
+ \bool_if:NTF \l__diffcoeff_single_var_bool
+ {
+ \tl_set:Nx \l_tmpa_tl { \seq_use:Nn #4 { , } }
+ \__diffcoeff_single:NNN #2 #3 \l_tmpa_tl
+ }
+ {
+ \int_zero:N \l_tmpa_int
+ \seq_mapthread_function:NNN #1 #4 \__diffcoeff_map_orders:nn
+ \__diffcoeff_mixed:NNN #2 #3 \l__diffcoeff_denom_seq
+ }
+ \exp_args:NV\tl_if_novalue:nF #5
+ {
+ \mkern \l__diffcoeff_elbowrm_muskip \l__diffcoeff_rdelim_tl
+ \exp_args:NV\tl_if_empty:nF #5
+ {
+ \c_math_subscript_token
+ { \mskip \l__diffcoeff_subnudge_muskip #5 }
+ }
+ }
+ }
+%%%%%%%%%%%%%%%%%%%%
+% (ptl) form denom from #1 orders seq & #2 vars seq
+\cs_new_protected:Npn \__diffcoeff_map_orders:nn #1#2
+ {
+ \tl_if_eq:nnTF { #1 } { 1 }
+ { \seq_put_right:Nn \l__diffcoeff_denom_seq { \l__diffcoeff_op_alt_tl #2 } }
+ {
+ \int_compare:nNnTF { \tl_count:n { #2 } } = { 1 }
+ {
+ \seq_put_right:Nn \l__diffcoeff_denom_seq
+ { \l__diffcoeff_op_alt_tl #2^{ #1 } }
+ }
+ {
+ \seq_put_right:Nn \l__diffcoeff_denom_seq
+ { \__diffcoeff_wrap_longvars:nn { #1\vphantom{)} } { #2 } }
+ }
+ }
+ }
+% #1 order(tlvar) ; #2 diff'iand(tlvar); #3 denom(tlvar)
+\cs_new:Npn \__diffcoeff_single:NNN #1#2#3
+ {
+ \__diffcoeff_numer:N { #1 }
+ \__diffcoeff_form_deriv:NNn
+ \l__diffcoeff_oporder_tl
+ \l__diffcoeff_differentiand_tl
+ { \__diffcoeff_denom_single:NN #1 #3 }
+ }
+% #1 total order; #2 differentiand; #3 denom seq
+\cs_new_protected:Npn \__diffcoeff_mixed:NNN #1#2#3
+ {
+ \__diffcoeff_numer:N #1
+ \__diffcoeff_form_deriv:NNn
+ \l__diffcoeff_oporder_tl
+ \l__diffcoeff_differentiand_tl
+ { \__diffcoeff_denom_sep:N #3 }
+ }
+\cs_new:Npn \__diffcoeff_denom_sep:N #1
+ {
+ \int_zero:N \l_tmpa_int
+ \seq_map_inline:Nn #1
+ {
+ \int_incr:N \l_tmpa_int ##1
+ \int_compare:nNnT { \l_tmpa_int } < { \l__diffcoeff_vars_int }
+ {
+ \seq_pop:NN \l__diffcoeff_orders_seq \l_tmpa_tl
+ \str_if_eq:VnTF \l_tmpa_tl { 1 }
+ { \mkern \l__diffcoeff_varsep_muskip }
+ {
+ \mkern \muskip_eval:n { \l__diffcoeff_varsep_muskip +
+ \l__diffcoeff_sep_adj_muskip }
+ }
+ }
+ }
+ }
+% #1(tl) total order
+\cs_new_protected:Npn \__diffcoeff_numer:N #1
+ {
+ \bool_if:NTF \l__diffcoeff_op_left_bool
+ {
+ \tl_set:Nn \l__diffcoeff_oporder_tl
+ { \mskip \l__diffcoeff_opnudge_muskip }
+ }
+ { \tl_clear:N \l__diffcoeff_oporder_tl }
+ \tl_put_right:No \l__diffcoeff_oporder_tl \l__diffcoeff_op_tl
+ \exp_args:NnV \tl_if_eq:nnF { 1 } #1
+ {
+ \tl_put_right:Nn \l__diffcoeff_oporder_tl
+ { \mskip \l__diffcoeff_oporder_muskip ^ { #1 } }
+ }
+ \bool_if:NT \l__diffcoeff_op_left_bool
+ { \tl_put_right:Nn \l__diffcoeff_oporder_tl { \hfill } }
+ }
+% #1 order; #2 var
+\cs_new_protected:Npn \__diffcoeff_denom_single:NN #1#2
+ {
+ \tl_if_eq:nVTF { 1 } #1
+ { \l__diffcoeff_op_alt_tl #2 }
+ {
+ \int_compare:nNnTF { \tl_count:N #2 } = { 1 }
+ { \l__diffcoeff_op_alt_tl #2^{ #1 } }
+ { \__diffcoeff_wrap_longvars:nn { #1\vphantom) } { #2 } }
+ }
+ }
+% #1 op+order; #2 diff'iand; #3 denom
+% 0 frac; 1 frac append; 2 slash ; 3 slash append
+\cs_new:Npn \__diffcoeff_form_deriv:NNn #1#2#3
+ {
+ \int_case:nn { \l__diffcoeff_format_int }
+ {
+ { 0 } { \frac { #1 #2 } { #3 } }
+ { 1 } { \frac { #1 } { #3 } { #2 } }
+ { 2 } { #1 #2 / #3 }
+ { 3 } { ( #1 / #3 ) { #2 } }
+ { 4 } { #1 / #3 { #2 } }
+ }
+ }
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% differential
+% #1 variant; #2 = space in mu before d (0--9)
+% note \group_end placement for \vec{x} etc
+\NewDocumentCommand \dl { d.. m }
+ {
+ \group_begin:
+ \bool_set_true:N \l__diffcoeff_integ_bool
+ \bool_set_true:N \l__diffcoeff_single_var_bool
+ \seq_set_from_clist:Nn \l__diffcoeff_orders_seq { 1 }
+ \tl_set:Nn \l__diffcoeff_tot_order_tl { 1 }
+ \IfValueT { #1 } { \tl_set:Nn \l__diffcoeff_type_tl { .#1 } }
+ \UseInstance { derivative } { ord\l__diffcoeff_type_tl }
+ \l__diffcoeff_orders_seq \l__diffcoeff_tot_order_tl
+ \c_empty_tl \c_empty_seq \c_empty_tl
+ \tl_if_in:NnTF \c__diffcoeff_digits_tl { #2 }
+ { \mkern #2 mu \l__diffcoeff_op_tl \group_end: }
+ { \l__diffcoeff_op_tl \group_end: #2 }
+ }
+\NewDocumentCommand \negmu {} { \mkern -1 mu }
+\NewDocumentCommand \nilmu {} { \mkern 0 mu }
+\NewDocumentCommand \onemu {} { \mkern 1 mu }
+\NewDocumentCommand \twomu {} { \mkern 2 mu }
+% derivative
+% #1(tl) = name of variant; #2(*)= append diff'iand boolean
+% #3(clist) = orders of diff. in each var.; #4(tl) = order override
+% #5(tl) = diff'iand; #6( / ) = slash boolean
+% #7(clist) = vars of diff.; #8(tl) = pt of eval./vars held const
+% #9(tl) = as #8 (for backwards compat)
+\NewDocumentCommand \diff{ d.. s O{1} o m t/ m !O{#9} g }
+ {
+ \group_begin:
+ \tl_set:Nn \l__diffcoeff_differentiand_tl { #5 }
+ \tl_set:Nn \l__diffcoeff_trailing_tl { #8 }
+ \seq_set_from_clist:Nn \l__diffcoeff_vars_seq { #7 }
+ \seq_set_from_clist:Nn \l__diffcoeff_orders_seq { #3 }
+ \int_set:Nn \l__diffcoeff_vars_int
+ { \seq_count:N \l__diffcoeff_vars_seq }
+ \int_set:Nn \l_tmpb_int { \seq_count:N \l__diffcoeff_orders_seq }
+ \int_compare:nNnTF { \l__diffcoeff_vars_int } = { 1 }
+ { \bool_set_true:N \l__diffcoeff_single_var_bool }
+ {
+ \int_compare:nNnTF { \l__diffcoeff_vars_int } < { \l_tmpb_int }
+ {
+ \msg_error:nnxxxx { diffcoeff } { numbers-conflict }
+ { \int_use:N \l__diffcoeff_vars_int } { \int_use:N \l_tmpb_int }
+ { \seq_use:Nn \l__diffcoeff_orders_seq { , } }
+ { \seq_use:Nn \l__diffcoeff_vars_seq { , } }
+ }
+ { % pad orders seq if nec.
+ \int_step_inline:nnnn
+ { 1 + \l_tmpb_int } { 1 } { \l__diffcoeff_vars_int }
+ { \seq_put_right:Nn \l__diffcoeff_orders_seq { 1 } }
+ }
+ }
+ % override/calc total order
+ \IfValueTF { #4 }
+ { \tl_set:Nn \l__diffcoeff_tot_order_tl { #4 } }
+ {
+ \bool_if:NTF \l__diffcoeff_single_var_bool
+ { \tl_set:Nn \l__diffcoeff_tot_order_tl { #3 } }
+ {
+ \__diffcoeff_calc_tot_order:NN \l__diffcoeff_orders_seq
+ \l__diffcoeff_tot_order_tl
+ }
+ }
+ \IfValueT { #1 } { \tl_set:Nn \l__diffcoeff_type_tl { .#1 } }
+ \int_zero:N \l__diffcoeff_format_int
+ % append? slash?
+ \IfBooleanT #2 { \int_incr:N \l__diffcoeff_format_int }
+ \IfBooleanT #6 { \int_add:Nn \l__diffcoeff_format_int { 2 } }
+
+ \UseInstance { derivative } { ord\l__diffcoeff_type_tl }
+ \l__diffcoeff_orders_seq
+ \l__diffcoeff_tot_order_tl
+ \l__diffcoeff_differentiand_tl
+ \l__diffcoeff_vars_seq
+ \l__diffcoeff_trailing_tl
+ \group_end:
+ } % end of \diff
+%%%%%%%%%%%%%%%%%%%
+% #2(seq) expr in; #1(tlv) expr out
+\cs_new:Npn \__diffcoeff_calc_tot_order:NN #1 #2
+ {
+ \tl_clear:N \l__diffcoeff_nos_tl
+ \exp_args:Nx\__diffcoeff_digest_expr:n { \seq_use:Nn #1 { + } }
+ \prop_if_empty:NTF \l__diffcoeff_vars_prop
+ { \tl_set:NV #2 \l__diffcoeff_nos_tl }
+ { \__diffcoeff_evaluate:NN \l__diffcoeff_vars_prop #2 }
+ }
+\cs_new:Npn \__diffcoeff_digest_expr:n #1
+ {
+ \tl_set:Nn \l__diffcoeff_curr_num_tl { + }
+ \tl_set:Nn \l__diffcoeff_paren_tl { +1 }
+ \tl_set:Nn \l__diffcoeff_nos_tl { 0 }
+ \int_zero:N \l__diffcoeff_curr_state_int
+ \int_zero:N \l__diffcoeff_curr_tok_int
+ \tl_map_inline:nn { #1+ }
+ {
+ \__diffcoeff_get_curr_ndx:nN { ##1 } \l__diffcoeff_curr_tok_int
+ \__diffcoeff_transitions:nNN { ##1 }
+ \l__diffcoeff_curr_state_int \l__diffcoeff_curr_tok_int
+ }
+ \int_set:Nn \l__diffcoeff_nos_int { \l__diffcoeff_nos_tl }
+ \tl_set:Nx \l__diffcoeff_nos_tl { \int_use:N \l__diffcoeff_nos_int }
+ \int_compare:nNnT { \l__diffcoeff_nos_int } = { 0 }
+ { \tl_clear:N \l__diffcoeff_nos_tl }
+ }
+% #1 curr tok (tl); #2 <== curr tok ndx (int)
+\cs_new_protected:Npn \__diffcoeff_get_curr_ndx:nN #1#2
+ {
+ \tl_if_in:NnTF \c__diffcoeff_digits_tl { #1 }
+ { \int_set:Nn #2 { 1 } } % digit
+ {
+ \str_case:nnF { #1 }
+ {
+ { + } { \int_set:Nn #2 { 0 } }
+ { - } { \int_set:Nn #2 { 0 } }
+ { ( } { \int_set:Nn #2 { 3 } }
+ { ) } { \int_set:Nn #2 { 4 } }
+ }
+ { \int_set:Nn #2 { 2 } } % var
+ }
+ }
+% #1(tl) curr tok; #2(int) curr state; #3(int) curr tok ndx
+\cs_new:Npn \__diffcoeff_transitions:nNN #1#2#3
+ {
+ \int_case:nn { #2 }
+ {
+ { 0 } % sgn + -
+ { \__diffcoeff_sgn_transitions:nNN { #1 }#2#3 }
+ { 1 } % num
+ { \__diffcoeff_num_transitions:nNN { #1 }#2#3 }
+ { 2 } % alg
+ { \__diffcoeff_alg_transitions:nNN { #1 }#2#3 }
+ { 4 } % )
+ { \__diffcoeff_rpar_transitions:nNN { #1 }#2#3 }
+ }
+ }
+% transitions from the signed state
+% #1(tl) curr tok; #2(int) 0, curr state; #3 curr tok ndx
+\cs_new_protected:Npn \__diffcoeff_sgn_transitions:nNN #1#2#3
+ {
+ \int_case:nnT { #3 }
+ {
+ { 0 } % tok = s
+ {
+ \tl_if_eq:nVTF { #1 } \l__diffcoeff_curr_num_tl
+ { \tl_set:Nn \l__diffcoeff_curr_num_tl { + } }
+ { \tl_set:Nn \l__diffcoeff_curr_num_tl { - } }
+ }
+ { 1 } % tok = d
+ { \tl_put_right:Nn \l__diffcoeff_curr_num_tl { #1 } }
+ { 2 } % tok = v
+ {
+ \tl_put_right:Nn \l__diffcoeff_curr_num_tl { 1 }
+ \tl_set:Nn \l__diffcoeff_curr_var_tl { #1 }
+ }
+ { 3 } % tok = (
+ {
+ \seq_push:NV \l__diffcoeff_paren_seq \l__diffcoeff_paren_tl
+ \tl_put_left:NV \l__diffcoeff_paren_tl \l__diffcoeff_curr_num_tl
+ \tl_set:Nn \l__diffcoeff_curr_num_tl { + }
+ \int_set:Nn #3 { 0 }
+ }
+ }
+ { \int_set_eq:NN #2 #3 }
+ }
+% transitions from the numeric state
+% #1 = curr. tok.; #2 = 0, curr. state; #3 curr. tok. index
+\cs_new_protected:Npn \__diffcoeff_num_transitions:nNN #1#2#3
+ {
+ \int_case:nnT { #3 }
+ {
+ { 0 } % tok = s
+ {
+ \tl_put_right:NV\l__diffcoeff_nos_tl
+ { \l__diffcoeff_paren_tl * \l__diffcoeff_curr_num_tl }
+ \tl_set:Nn \l__diffcoeff_curr_num_tl { #1 }
+ }
+ { 1 } % tok = d
+ { \tl_put_right:Nn \l__diffcoeff_curr_num_tl { #1 } }
+ { 2 } % tok = v
+ {
+ \tl_if_in:nnTF { ^ \times * / \div } { #1 }
+ {
+ \msg_error:nnxxx { diffcoeff } { order-specification }
+ { \seq_use:Nn \l__diffcoeff_orders_seq { , } }
+ { #1 } { number }
+ }
+ { \tl_set:Nn \l__diffcoeff_curr_var_tl { #1 } }
+ }
+ { 3 } % tok = (
+ {
+ \seq_push:NV \l__diffcoeff_paren_seq \l__diffcoeff_paren_tl
+ \tl_put_left:Nn \l__diffcoeff_paren_tl { * }
+ \tl_put_left:NV \l__diffcoeff_paren_tl \l__diffcoeff_curr_num_tl
+ \tl_set:Nn \l__diffcoeff_curr_num_tl { + }
+ \int_set:Nn #3 { 0 }
+ }
+ { 4 } % tok = )
+ {
+ \tl_put_right:NV \l__diffcoeff_nos_tl
+ { \l__diffcoeff_paren_tl * \l__diffcoeff_curr_num_tl }
+ }
+ }
+ {
+ \int_set_eq:NN #2 #3 }
+ }
+% transitions from the algebraic state
+% #1 = curr. tok.; #2 = 2, curr. state; #3 curr. tok. index
+\cs_new:Npn \__diffcoeff_alg_transitions:nNN #1#2#3
+ {
+ \int_case:nnT { #3 }
+ {
+ { 0 } % tok = s
+ {
+ \int_compare:nNnTF { \l__diffcoeff_parenvar_int } = { 0 }
+ {
+ \__diffcoeff_store_var:NNN \l__diffcoeff_curr_var_tl
+ \l__diffcoeff_paren_tl \l__diffcoeff_curr_num_tl
+ \tl_clear:N \l__diffcoeff_curr_var_tl
+ \tl_set:Nn \l__diffcoeff_curr_num_tl { #1 }
+ }
+ {
+ \tl_put_right:Nn \l__diffcoeff_curr_var_tl { #1 }
+ \int_set:Nn #3 { 2 }
+ }
+ }
+ { 1 } % tok = d
+ {
+ \tl_put_right:Nn \l__diffcoeff_curr_var_tl { #1 }
+ \int_set:Nn #3 { 2 }
+ }
+ { 2 } % tok = v
+ { \tl_put_right:Nn \l__diffcoeff_curr_var_tl { #1 } }
+ { 3 } % tok = (
+ {
+ \tl_put_right:Nn \l__diffcoeff_curr_var_tl { #1 }
+ \int_set:Nn #3 { 2 }
+ \int_incr:N \l__diffcoeff_parenvar_int
+ }
+ { 4 } % tok = )
+ {
+ \int_compare:nNnTF { \l__diffcoeff_parenvar_int } = { 0 }
+ {
+ \__diffcoeff_store_var:NNN \l__diffcoeff_curr_var_tl
+ \l__diffcoeff_paren_tl \l__diffcoeff_curr_num_tl
+ \tl_clear:N \l__diffcoeff_curr_var_tl
+ }
+ {
+ \tl_put_right:Nn \l__diffcoeff_curr_var_tl { #1 }
+ \int_set:Nn #3 { 2 }
+ \int_decr:N \l__diffcoeff_parenvar_int
+ }
+ }
+ }
+ { \int_set_eq:NN #2 #3 }
+ }
+% transitions from the ) state
+% #1 = curr. tok.; #2 = 4, curr. state; #3 curr. tok. index
+\cs_new:Npn \__diffcoeff_rpar_transitions:nNN #1#2#3
+ {
+ \int_compare:nNnTF { \int_mod:nn { #3 } { 4} } = { 0 }
+ {
+ \tl_set:Nn \l__diffcoeff_curr_num_tl { #1 }
+ \seq_pop:NN \l__diffcoeff_paren_seq \l__diffcoeff_paren_tl
+ \int_set_eq:NN #2 #3
+ }
+ {
+ \msg_error:nnxxx { diffcoeff } { order-specification }
+ { \seq_use:Nn \l__diffcoeff_orders_seq { , } } { #1 } { ) }
+ }
+ }
+% #1 is var. (tlvar); #2 is num. (tlvar); #3 num. coeff. (tlvar)
+\cs_new:Npn \__diffcoeff_store_var:NNN #1#2#3
+ {
+ \prop_get:NVNF \l__diffcoeff_vars_prop #1 \l_tmpa_tl
+ { \tl_clear:N \l_tmpa_tl }
+ \tl_put_right:NV \l_tmpa_tl { #2 * #3 }
+ \prop_put:NVV \l__diffcoeff_vars_prop #1 \l_tmpa_tl
+ }
+% #1 (propv) key=var, val=coeff; #2 <= total order
+\cs_new_protected:Npn \__diffcoeff_evaluate:NN #1#2
+ {
+ \prop_map_inline:Nn #1 { \seq_put_left:Nn \l_tmpa_seq { ##1 } }
+ \seq_sort:Nn \l_tmpa_seq
+ {
+ \int_compare:nNnTF { \tl_count:n { ##1 } } < { \tl_count:n { ##2 } }
+ { \sort_return_same: } { \sort_return_swapped: }
+ }
+ \seq_map_inline:Nn \l_tmpa_seq
+ {
+ \prop_pop:NnN #1 { ##1 } \l_tmpb_tl
+ \seq_put_right:Nx \l_tmpb_seq { \int_eval:n \l_tmpb_tl }
+ }
+ \tl_clear:N \l_tmpa_tl
+ \seq_mapthread_function:NNN \l_tmpa_seq \l_tmpb_seq
+ \__diffcoeff_tot_order:nn
+ \exp_args:NV \tl_if_head_eq_charcode:nNTF \l_tmpa_tl +
+ {
+ \tl_set:Nx \l_tmpb_tl { \tl_tail:N \l_tmpa_tl }
+ \int_compare:nNnT { \l__diffcoeff_nos_int } > { 0 }
+ { \tl_put_left:Nn \l__diffcoeff_nos_tl { + } }
+ \tl_concat:NNN #2 \l_tmpb_tl \l__diffcoeff_nos_tl
+ }
+ {
+ \int_compare:nNnTF { \l__diffcoeff_nos_int } > { 0 }
+ { \tl_concat:NNN #2 \l__diffcoeff_nos_tl \l_tmpa_tl }
+ { \tl_concat:NNN #2 \l_tmpa_tl \l__diffcoeff_nos_tl }
+ }
+ \tl_set_rescan:Nno #2 { } #2
+ }
+\cs_new:Npn \__diffcoeff_tot_order:nn #1#2
+ {
+ \int_compare:nNnTF { #2 } > { 0 }
+ {
+ \int_compare:nNnTF { #2 } = { 1 }
+ { \tl_put_left:Nn \l_tmpa_tl { +#1 } }
+ { \tl_put_left:Nn \l_tmpa_tl { +#2#1 } }
+ }
+ {
+ \int_compare:nNnT { #2 } < { 0 }
+ {
+ \int_compare:nNnTF { #2 } = { -1 }
+ { \tl_put_right:Nn \l_tmpa_tl { -#1 } }
+ { \tl_put_right:Nn \l_tmpa_tl { #2#1 } }
+ }
+ }
+ }
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% create new instances or edit existing ones
+% #1 = name; #2 = key-value list
+\NewDocumentCommand \diffdef { > { \TrimSpaces } m m }
+ {
+ \tl_if_empty:nTF { #1 }
+ {
+ \EditTemplateDefaults { derivative }
+ { DERIV } { #2 }
+ \EditInstance { derivative } { ord } { #2 }
+ }
+ {
+ \IfInstanceExistTF { derivative } { ord.#1 }
+ { \EditInstance { derivative } { ord.#1 } { #2 } }
+ {
+ \DeclareInstance { derivative } { ord.#1 }
+ { DERIV } { #2 }
+ }
+ }
+ }
+% relic from version 1
+\NewDocumentCommand \diffset { o }
+ { \msg_warning:nn { diffcoeff } { obsolete } }
+
+% ordinary & D
+\DeclareInstance { derivative } { ord } { DERIV } { }
+\bool_if:NTF \g__diffcoeff_ISO_bool
+ {
+ \diffdef {}
+ {
+ op-symbol = \mathrm{d},
+ op-order-sep = 0 mu ,
+ left-delim = \left ( ,
+ right-delim = \right ) ,
+ subscr-nudge = -6 mu
+ }
+ \diffdef { D } { op-symbol = \mathrm{D} }
+ }
+ { \diffdef { D } { op-symbol = D } }
+
+% partial
+\diffdef { p }
+ {
+ op-symbol = \partial ,
+ left-delim = \left ( ,
+ right-delim = \right ) ,
+ subscr-nudge = -6 mu
+ }
+\NewDocumentCommand \diffp { } { \diff.p. }
+
+% delta
+\diffdef { delta }
+ {
+ op-symbol = \delta ,
+ op-order-sep = 0 mu
+ }
+\diffdef { Delta }
+ {
+ op-symbol = \Delta ,
+ op-order-sep = 0 mu
+ }
+% for compatibility with version 1
+\NewDocumentCommand \Diff { } { \diff.D. }
+\NewDocumentCommand \diffd { } { \diff.delta. }
+\NewDocumentCommand \Diffd { } { \diff.Delta. }
+
+% user-defined
+\file_if_exist:nT { \g__diffcoeff_def_tl.def }
+ { \file_input:n { \g__diffcoeff_def_tl.def } }
+%%%%%%%%%%%%%%%%%%%%
+% Jacobian
+\NewDocumentCommand \jacob { m t/ m }
+ {
+ \group_begin:
+ \IfBooleanTF #2
+ { \partial(#1) / \partial(#3) }
+ { \frac{ \partial(#1) } { \partial(#3) } }
+ \group_end:
+ }
+%%%%%%%%%%%%%%%%%%%%
+% messages
+\msg_new:nnn { diffcoeff } { order-specification }
+ {
+ #3~followed~by~#2~in~the~order~specification~[#1]~\msg_line_context:.~
+ Diffcoeff~cannot~calculate~the~overall~order~of~differentiation~in~
+ this~case.~Use~the~order-override~option~to~enter~the~overall~order.
+ }
+\msg_new:nnn { diffcoeff } { obsolete }
+ {
+ Obsolete~command:~\diffset is~superseded~by~the~\diffdef\
+ command.~\msg_see_documentation_text:n { diffcoeff }
+ }
+\msg_new:nnn { diffcoeff } { numbers-conflict }
+ {
+ #2~orders~of~differentiation~specified~for~#1~variables;~
+ orders~[#3]\ (\msg_line_context:)~for~variables~#4.
+ }
+% end of file diffcoeff.sty \ No newline at end of file