% This is file `numerica-plus.def',
% part of the `numerica' package.
%
% This work may be distributed and/or modified under the conditions
% of the LaTeX Project Public License, either version 1.3c of this 
% license or any later version; see
% http://www.latex-project.org/lppl.txt
%
% Andrew Parsloe (ajparsloe@gmail.com)
% 
\ProvidesExplFile
  {numerica-plus.def}
  {2021/02/15}
  {1.0.0}
  { Iterate functions, find fixed points, zeros, extrema and recurrence terms }
%----------------------------------------------------------
\cs_new_protected:Npn \__nmc_plus_reuse:nNN #1#2#3
  {
    \int_case:nnF { #1 }
      { 
        { 1 }
          {
            \seq_pop:NN #2 \l_tmpa_tl
            \seq_pop:NN #3 \l_tmpb_tl
            \tl_gset:Nx \g__nmc_reuse_tl { { \l_tmpa_tl , \l_tmpb_tl } }
            \seq_mapthread_function:NNN #2 #3 \__nmc_plus_reuse_display:nn
          }
        { 2 }
          { 
            \tl_gset:Nx \g__nmc_reuse_tl 
                { \seq_use:Nn #3 { , } } 
          }
      }
      { \tl_gset_eq:NN \g__nmc_reuse_tl \l_nmc_result_tl }
  }
\cs_new_protected:Npn \__nmc_plus_reuse_display:nn #1#2
  { \tl_gput_right:Nx \g__nmc_reuse_tl { , { #1 , #2 } } }
%--------------------------------------
% \nmcIterate
\int_new:N \l__nmc_iter_total_int
\int_new:N \l__nmc_iter_view_int
\int_new:N \l__nmc_iter_round_int
\tl_new:N  \l__nmc_iter_var_tl
\fp_new:N  \l__nmc_iter_first_fp
\seq_new:N \l__nmc_iter_result_seq
\seq_new:N \l__nmc_iter_index_seq

\fp_new:N \l__nmc_iter_fixedpti_fp
\fp_new:N \l__nmc_iter_fixedptii_fp

\tl_new:N \l__nmc_iter_begin_tl
\tl_new:N \l__nmc_iter_end_tl
\tl_new:N \g__nmc_iter_info_tl

\nmc_define:nnN { \nmcIterate } { iter } \iter

\cs_new_protected:Npn \__nmc_iter_settings_digest:
  {
    \bool_set_false:N \l__nmc_allow_TF_out_bool
    \int_set:Nn \l__nmc_iter_total_int 
        { \int_max:nn { \l__nmc_iter_total_int } { 1 } }
    \int_set:Nn \l__nmc_iter_view_int 
        { \int_min:nn { \int_max:nn { \l__nmc_iter_view_int } 
            { 1 } } { \l__nmc_iter_total_int } }
  }
\cs_new_protected:Npn \__nmc_iter_vv_digest:N #1
  {
    \tl_if_empty:NTF \l__nmc_iter_var_tl
      { \__nmc_vv_digest:N #1 }
      { 
        \clist_push:NV \l__nmc_formula_tl \l__nmc_iter_var_tl
        \__nmc_vv_digest:N #1
        \clist_pop:NN \l__nmc_formula_tl \l__nmc_iter_var_tl
      }
  }
\cs_new_protected:Npn \__nmc_iter_process:
  { 
    \int_set:Nn \l__nmc_iter_round_int 
        { \l__nmc_round_int + \l__nmc_iter_extra_int }
    % first iterate
    \__nmc_error_where:n { formula }
    \tl_clear:N \l__nmc_fp_expr_tl
    \__nmc_fpify:VN \l__nmc_formula_tl \l__nmc_fp_expr_tl
    \fp_set:Nn \l__nmc_result_fp { \l__nmc_fp_expr_tl }
    \__nmc_error_fpflag:

    \bool_if:NF \g__nmc_error_bool
      {
        \fp_set_eq:NN \l__nmc_iter_first_fp \l__nmc_result_fp
        \tl_if_empty:NT \l__nmc_iter_var_tl
          { % get iter. var if unspecified
            \seq_get:NN \l__nmc_vv_all_seq \l_tmpa_tl
            \__nmc_vv_split_item:V \l_tmpa_tl
            \tl_set_eq:NN \l__nmc_iter_var_tl \l__nmc_eq_var_tl
          }
        \__nmc_iter_do:
        \tl_set_eq:NN \l__nmc_fp_expr_tl \l__nmc_fp_exprn_tl
      }
    \bool_if:nF { \g__nmc_error_bool || \l__nmc_num_only_bool }
      { 
        \__nmc_iter_environ:
        \__nmc_iter_write:
      }
  }
%--------------------------------------
\cs_new_protected:Npn \__nmc_iter_do:
  { 
    \bool_if:NTF \l__nmc_num_only_bool
      { 
        \__nmc_iter_fixed_pt:
        \bool_if:NF \g__nmc_error_bool
          { 
            \__nmc_num_format:nNnN { \l__nmc_iter_fixedpti_fp }
                \l_nmc_result_tl { \l__nmc_round_int } 
                    \l__nmc_sci_num_out_bool
            \int_decr:N \l__nmc_iter_total_int
            \tl_gset:Nx \g__nmc_iter_info_tl 
              { \int_use:N \l__nmc_iter_total_int }
          }
      }
      { % don't print initial iterations
        \int_step_function:nnnN { 1 } { 1 }
            { \l__nmc_iter_total_int - \l__nmc_iter_view_int - 1 }
                \__nmc_iter_current:n
        \bool_if:NF \g__nmc_error_bool
          { % store then print these ones
            \seq_clear:N \l__nmc_iter_result_seq
            \int_step_function:nnnN { 1 } { 1 } 
              { \int_min:nn { \l__nmc_iter_view_int } 
                  { \l__nmc_iter_total_int - 1 } } \__nmc_iter_current_store:n
          }
      }
  }
\cs_new_protected:Npn \__nmc_iter_current:n #1
  { % stepping function
    \bool_if:NF \g__nmc_error_bool
      {
        \__nmc_calc_fn_val:VNnN \l__nmc_iter_var_tl \l__nmc_formula_tl
            { \l__nmc_result_fp } \l__nmc_result_fp
      }
  }
\cs_new_protected:Npn \__nmc_iter_current_store:n #1
  { % stepping function
    \__nmc_calc_fn_val:VNnN \l__nmc_iter_var_tl \l__nmc_formula_tl 
        { \l__nmc_result_fp } \l__nmc_result_fp
    \bool_if:NF \g__nmc_error_bool
      {
        \__nmc_num_format:nNnN { \l__nmc_result_fp } \l_nmc_result_tl
             { \l__nmc_round_int } \l__nmc_sci_num_out_bool 
        \seq_put_right:NV \l__nmc_iter_result_seq \l_nmc_result_tl
        \int_set:Nn \l_tmpa_int
            { \l__nmc_iter_total_int - \l__nmc_iter_view_int + #1 }
        \seq_put_right:Nx \l__nmc_iter_index_seq { \int_use:N \l_tmpa_int }
      }
  }
\cs_new_protected:Npn \__nmc_iter_fixed_pt:
  { % already 1 iteration
    \int_set:Nn \l__nmc_iter_total_int { 1 }
    \fp_set_eq:NN \l__nmc_iter_fixedpti_fp \l__nmc_iter_first_fp
    \fp_set:Nn \l__nmc_iter_fixedptii_fp { \l__nmc_iter_fixedpti_fp + 1 }
    \bool_until_do:nn
        { 
          \fp_compare_p:nNn { 0 } = 
              { round( \l__nmc_iter_fixedpti_fp - \l__nmc_iter_fixedptii_fp,
                  \l__nmc_iter_round_int ) }
          || \g__nmc_error_bool
        }
      {
        \int_incr:N \l__nmc_iter_total_int
        \fp_set_eq:NN \l__nmc_iter_fixedptii_fp \l__nmc_iter_fixedpti_fp
        \__nmc_calc_fn_val:VNnN \l__nmc_iter_var_tl \l__nmc_formula_tl
            { \l__nmc_result_fp } \l__nmc_result_fp
        \fp_set_eq:NN \l__nmc_iter_fixedpti_fp \l__nmc_result_fp
        \int_compare:nNnF { \l__nmc_iter_total_int } < 
              { \l__nmc_iter_max_int }
          {
            \bool_gset_true:N \g__nmc_error_bool
            \__nmc_error_what:n 
                { 
                  No~fixed~point~attained~after~$\int_use:N 
                  \l__nmc_iter_total_int$~iterations~of 
                }
          }
      }
  }
\cs_new_protected:Npn \__nmc_iter_environ:
  {
    \tl_set:Nx \l__nmc_iter_begin_tl 
        { 
          \mode_if_math:F { \exp_not:o \l__nmc_math_delimi_tl } 
          \exp_not:N \begin{array}{r@{}l} 
          \bool_if:NTF \l__nmc_wraps_math_bool
            { \exp_not:o \l__nmc_formula_dup_tl &{}= }
            { &{} }
        }
    \tl_set:Nx \l__nmc_iter_end_tl 
        { 
          \exp_not:N \end{array}
          \mode_if_math:F { \exp_not:o \l__nmc_math_delimii_tl } 
        }
  }
\cs_new_protected:Npn \__nmc_iter_write:
  { 
    \__nmc_num_format:nNnN { \l__nmc_iter_first_fp } \l_tmpa_tl
         { \l__nmc_round_int } \l__nmc_sci_num_out_bool
    \tl_gset:Nx \g__nmc_iter_info_tl { \int_use:N \l__nmc_iter_total_int }
    \__nmc_if_mod_zero:nnTF { \l__nmc_debug_int } { 7 }
      { \seq_get_right:NN \l__nmc_iter_result_seq \l_nmc_result_tl }
      {
        \tl_set:Nx \l_nmc_result_tl 
          {
            \exp_not:o \l__nmc_iter_begin_tl
            \l_tmpa_tl \l__nmc_vv_display_tl
            \int_compare:nNnT 
                { \l__nmc_iter_total_int } > { \l__nmc_iter_view_int + 1 }
              {
                \\ & \exp_not:N \ldots
                \ \exp_not:N\mbox{final\ 
                \int_use:N \l__nmc_iter_view_int\ of\ \g__nmc_iter_info_tl :}
              }
            \int_compare:nNnT { \l__nmc_iter_total_int } > { 1 }
              { \\ & \exp_not:N \hookrightarrow }
            \seq_use:Nn \l__nmc_iter_result_seq { \\ & \hookrightarrow } 
            \exp_not:o \l__nmc_iter_end_tl
          }
        }
  }
\cs_new_protected:Npn \__nmc_iter_display:
  { 
    \bool_if:NTF \l__nmc_num_only_bool
      { \tl_gset_eq:NN \g__nmc_reuse_tl \l_nmc_result_tl }
      {
        \__nmc_plus_reuse:nNN { \l__nmc_iter_reuse_int }
            \l__nmc_iter_index_seq \l__nmc_iter_result_seq
      }
    \l_nmc_result_tl
  }
%--------------------------------------
%\nmcSolve
\int_new:N \l__nmc_solve_round_int
\int_new:N \l__nmc_solve_steps_int
\int_new:N \l__nmc_solve_slope_int
\int_new:N \l__nmc_solve_slopei_int 
\int_new:N \l__nmc_solve_signs_int
\fp_new:N \l__nmc_solvea_fp
\fp_new:N \l__nmc_solveb_fp
\fp_new:N \l__nmc_solvec_fp
\fp_new:N \l__nmc_solved_fp

\fp_new:N \l__nmc_solvefa_fp
\fp_new:N \l__nmc_solvefb_fp
\fp_new:N \l__nmc_solvefc_fp
\bool_new:N \l__nmc_solve_stop_bool
\tl_new:N \g__nmc_sove_info_tl

\nmc_define:nnN { \nmcSolve } { solve } \solve

\cs_new_protected:Npn \__nmc_solve_settings_digest: 
  {
    \bool_set_false:N \l__nmc_allow_TF_out_bool
    \tl_if_empty:NF \l__nmc_solve_step_tl
      { 
        \__nmc_fpify_set:NN \l__nmc_solve_step_fp \l__nmc_solve_step_tl 
        \fp_compare:nNnT \l__nmc_solve_step_fp = { 0 }
          { \__nmc_error_what:n { Non-zero~initial~step~required~in } }
      } 
  }
\cs_new_protected:Npn \__nmc_solve_vv_digest:N #1
  {
    \tl_if_empty:NTF \l__nmc_solve_var_tl
      { \__nmc_vv_digest:N #1 }
      { 
        \clist_push:NV \l__nmc_formula_tl \l__nmc_solve_var_tl
        \__nmc_vv_digest:N #1
        \clist_pop:NN \l__nmc_formula_tl \l__nmc_solve_var_tl
      }
  }
\cs_new_protected:Npn \__nmc_solve_process:
  { 
    \int_set:Nn \l__nmc_solve_round_int 
        { \l__nmc_round_int + \l__nmc_solve_extra_int }
    % get equation var if unspecified
    \tl_if_empty:NT \l__nmc_solve_var_tl
      { 
        \seq_get:NN \l__nmc_vv_all_seq \l_tmpa_tl
        \__nmc_vv_split_item:V \l_tmpa_tl
        \tl_set_eq:NN \l__nmc_solve_var_tl \l__nmc_eq_var_tl
      }
    \bool_if:NF \g__nmc_error_bool
      { \__nmc_solve_get_trial_vals: }
    \bool_if:NF \g__nmc_error_bool
      {
        \__nmc_error_where:n { function }
        \__nmc_solve_do:
      }
    \bool_if:NF \g__nmc_error_bool
      { 
        \__nmc_num_format:nNnN { \l__nmc_solvea_fp } \l_nmc_result_tl
            { \l__nmc_round_int } \l__nmc_sci_num_out_bool
        \tl_gset:Nx \g__nmc_solve_info_tl 
          { \clist_use:Nn \g__nmc_solve_info_tl { + } }
        \tl_set_eq:NN \l__nmc_fp_expr_tl \l__nmc_fp_exprn_tl
      }
  }
\cs_new_protected:Npn \__nmc_solve_get_trial_vals:
  {
    \prop_get:NVN \g__nmc_subst_var_prop 
        \l__nmc_solve_var_tl \l__nmc_subst_tl
    % ensure a < b
    \int_case:nn { \fp_sign:n { \l__nmc_solve_step_fp } }
      { 
        { 1 } 
          { 
            \fp_set:Nn \l__nmc_solvea_fp { \l__nmc_subst_tl }
            \fp_set:Nn \l__nmc_solveb_fp 
                  { \l__nmc_solvea_fp + \l__nmc_solve_step_fp }
          }
        { -1 } 
          { 
            \fp_set:Nn \l__nmc_solveb_fp { \l__nmc_subst_tl }
            \fp_set:Nn \l__nmc_solvea_fp 
                  { \l__nmc_solveb_fp + \l__nmc_solve_step_fp }
          }
      }
  }
% find opp. signs, zero, or fn min.
% a b = var vals; fa fb = fn vals
\cs_new_protected:Npn \__nmc_solve_do:
  { 
    \__nmc_solve_calc_values:
    \int_zero:N \l__nmc_solve_steps_int
    \tl_gclear:N \g__nmc_solve_info_tl
    \bool_do_until:nn 
        {
          \g__nmc_error_bool || \l__nmc_solve_stop_bool
          || \int_compare_p:nNn 
              { \l__nmc_solve_steps_int } > { \l__nmc_solve_max_int } 
          || \fp_compare_p:nNn { 0 } = 
                  { round(\l__nmc_solveb_fp - \l__nmc_solvea_fp, 
                      \l__nmc_solve_round_int) }
        }
      {
        \int_incr:N \l__nmc_solve_steps_int
        \int_case:nn { \l__nmc_solve_signs_int }
          {
            { 0 }  { \__nmc_solve_do_bingo: }
            { -1 } { \__nmc_solve_do_bisect: }
            { 1 }  { \__nmc_solve_do_slope: }
          }
      }
    \bool_if:nF { \g__nmc_error_bool || \l__nmc_solve_stop_bool }
      {
        \__nmc_error_where:n { $\l__nmc_formula_tl$ }
        \__nmc_error_what:n 
            { 
              No~zero/extremum~found~after~$\int_use:N 
              \l__nmc_solve_max_int$~steps~for~function 
            }
      } 
  }
\cs_new_protected:Npn \__nmc_solve_do_bingo:
  { % fn = 0 to 16 figures
    \fp_compare:nNnTF { \l__nmc_solvefb_fp } = { 0 }
      { 
        \fp_set_eq:NN \l__nmc_solvea_fp \l__nmc_solveb_fp
        \fp_set_eq:NN \l__nmc_solvefa_fp \l__nmc_solvefb_fp
      }
      {
        \fp_set_eq:NN \l__nmc_solveb_fp \l__nmc_solvea_fp
        \fp_set_eq:NN \l__nmc_solvefb_fp \l__nmc_solvefa_fp
      }
    \bool_set_true:N \l__nmc_solve_stop_bool
  }
\cs_new_protected:Npn \__nmc_solve_do_bisect:
  { 
    \tl_gset:Nx \g__nmc_solve_info_tl { \int_use:N \l__nmc_solve_steps_int }
    \int_zero:N \l__nmc_solve_steps_int
    \fp_set:Nn \l__nmc_solvec_fp { ( \l__nmc_solvea_fp + \l__nmc_solveb_fp ) / 2 }
    \__nmc_calc_fn_val:VNnN \l__nmc_solve_var_tl \l__nmc_formula_tl 
        { \l__nmc_solvec_fp } \l__nmc_solvefc_fp 
    \fp_set:Nn \l__nmc_solved_fp { \l__nmc_solvec_fp + 1 }
    \bool_until_do:nn
        { 
          \g__nmc_error_bool ||
          \fp_compare_p:nNn { 0 } =
              { round( \l__nmc_solvec_fp - \l__nmc_solved_fp ,
                  \l__nmc_solve_round_int ) }
        }
      { 
        \int_incr:N \l__nmc_solve_steps_int
        \fp_set_eq:NN \l__nmc_solved_fp \l__nmc_solvec_fp
        \fp_compare:nNnTF { 0 } = { \l__nmc_solvefc_fp }
          { 
            \fp_set_eq:NN \l__nmc_solvea_fp \l__nmc_solvec_fp 
            \fp_set_eq:NN \l__nmc_solvefa_fp \l__nmc_solvefc_fp
          }
          {
            \fp_compare:nNnTF 
                { sign(\l__nmc_solvefa_fp)sign(\l__nmc_solvefc_fp) } = { 1 }
              { 
                \fp_set_eq:NN \l__nmc_solvea_fp \l__nmc_solvec_fp 
                \fp_set_eq:NN \l__nmc_solvefa_fp \l__nmc_solvefc_fp
              }
              { 
                \fp_set_eq:NN \l__nmc_solveb_fp \l__nmc_solvec_fp 
                \fp_set_eq:NN \l__nmc_solvefb_fp \l__nmc_solvefc_fp
              }
            \fp_set:Nn \l__nmc_solvec_fp 
                { ( \l__nmc_solvea_fp + \l__nmc_solveb_fp ) / 2 }
            \__nmc_calc_fn_val:VNnN \l__nmc_solve_var_tl 
                \l__nmc_formula_tl { \l__nmc_solvec_fp } \l__nmc_solvefc_fp 
          }
      }
    \bool_set_true:N \l__nmc_solve_stop_bool
    \clist_gput_right:Nx \g__nmc_solve_info_tl { \int_use:N \l__nmc_solve_steps_int }
  }
\cs_new_protected:Npn \__nmc_solve_do_slope:
  {
    \bool_if:NF \g__nmc_error_bool
      {
        \int_if_zero:nTF { \l__nmc_solve_slope_int }
          { % contract
            \fp_add:Nn \l__nmc_solvea_fp 
                { ( \l__nmc_solveb_fp - \l__nmc_solvea_fp ) / 4 }
            \fp_sub:Nn \l__nmc_solveb_fp 
                { ( \l__nmc_solveb_fp - \l__nmc_solvea_fp ) / 4 }
          }
          { % always towards x-axis
            \fp_compare:nNnTF { 0 } <
                { \l__nmc_solvefa_fp * \l__nmc_solve_slope_int }
              { \__nmc_solve_do_slope_left: }
              { \__nmc_solve_do_slope_right: }
          }
        \fp_set_eq:NN \l__nmc_solved_fp \l__nmc_solvea_fp
        \int_set_eq:NN \l__nmc_solve_slopei_int \l__nmc_solve_slope_int
        \__nmc_solve_calc_values:
      }
    \bool_if:NF \g__nmc_error_bool
      {
        \int_compare:nNnF { \l__nmc_solve_slope_int } = 
            { \l__nmc_solve_slopei_int }
          { 
            \fp_set:Nn \l__nmc_solvec_fp { ( \l__nmc_solvea_fp + \l__nmc_solveb_fp ) / 2 }
            \int_case:nn { \l__nmc_solve_slopei_int }
              {
                { 1 }  { \fp_set_eq:NN \l__nmc_solvea_fp \l__nmc_solvec_fp }
                { -1 } { \fp_set_eq:NN \l__nmc_solveb_fp \l__nmc_solvec_fp }
              }
            \__nmc_solve_calc_values:
          }
      }
    \fp_compare:nNnT { 0 } = 
        { round(\l__nmc_solveb_fp - \l__nmc_solvea_fp,
            \l__nmc_solve_round_int) }
      { \bool_set_true:N \l__nmc_solve_stop_bool }
  }
\cs_new_protected:Npn \__nmc_solve_do_slope_left:
  {
    \fp_set:Nn \l__nmc_solvec_fp { 2 \l__nmc_solvea_fp - \l__nmc_solveb_fp }
    \fp_set_eq:NN \l__nmc_solveb_fp \l__nmc_solvea_fp
    \fp_set_eq:NN \l__nmc_solvea_fp \l__nmc_solvec_fp
  }
\cs_new_protected:Npn \__nmc_solve_do_slope_right:
  {
    \fp_set:Nn \l__nmc_solvec_fp { 2 \l__nmc_solveb_fp - \l__nmc_solvea_fp }
    \fp_set_eq:NN \l__nmc_solvea_fp \l__nmc_solveb_fp
    \fp_set_eq:NN \l__nmc_solveb_fp \l__nmc_solvec_fp
  }
\cs_new_protected:Npn \__nmc_solve_calc_values:
  {
    \__nmc_calc_fn_val:VNnN \l__nmc_solve_var_tl \l__nmc_formula_tl 
        { \l__nmc_solvea_fp } \l__nmc_solvefa_fp 
    \bool_if:NF \g__nmc_error_bool
      {
        \__nmc_calc_fn_val:VNnN \l__nmc_solve_var_tl \l__nmc_formula_tl 
            { \l__nmc_solveb_fp } \l__nmc_solvefb_fp 
      }
    \bool_if:NF \g__nmc_error_bool
      { 
        \int_set:Nn \l__nmc_solve_slope_int 
          { \fp_eval:n { sign(\l__nmc_solvefb_fp - \l__nmc_solvefa_fp) } }
        \int_set:Nn \l__nmc_solve_signs_int 
          { \fp_eval:n { sign(\l__nmc_solvefa_fp) sign(\l__nmc_solvefb_fp) } }
      }
  }
\cs_new_protected:Npn \__nmc_solve_display:
  { 
    \tl_gset_eq:NN \g__nmc_reuse_tl \l_nmc_result_tl
    \bool_if:NF \l__nmc_num_only_bool
      { 
        \__nmc_num_format:nNnN { \l__nmc_solvefa_fp } \l_tmpa_tl
             { \l__nmc_round_int } \l__nmc_sci_num_out_bool
        \tl_set:Nx \l_nmc_result_tl
            { 
              \exp_not:o \l__nmc_math_delimi_tl
              \bool_if:NTF \l__nmc_wraps_math_bool
                { 
                  \exp_not:o \l__nmc_formula_tl = \l_tmpa_tl
                  \bool_if:NTF \l__nmc_vv_multline_bool
                    { \exp_not:o \l__nmc_vv_display_tl }
                    { 
                     \mathchoice{ \exp_not:o \l__nmc_vv_display_tl }
                          { \exp_not:o \l__nmc_vv_inline_tl }{}{} 
                    }
                  \rightarrow \exp_not:N \quad 
                  \l__nmc_solve_var_tl = \l_nmc_result_tl
                }
                {                
                  \l__nmc_solve_var_tl = \l_nmc_result_tl 
                  \mathchoice{ \exp_not:o \l__nmc_vv_display_tl }
                      { \exp_not:o \l__nmc_vv_inline_tl }{}{}
                }
              \l__nmc_punc_tl
              \exp_not:o \l__nmc_math_delimii_tl
            }
        \int_if_zero:nT { \l__nmc_solve_reuse_int }
          { \tl_gset_eq:NN \g__nmc_reuse_tl \l_nmc_result_tl }
      }
    \l_nmc_result_tl
  }
%--------------------------------------
% \nmcRecur
\bool_new:N \l__nmc_recur_ellipsis_bool
\int_new:N \l__nmc_recur_last_int
\fp_new:N  \l__nmc_recur_result_fp

\int_new:N \l__nmc_recur_subscr_ini_int
\int_new:N \l__nmc_recur_subscr_val_int
\int_new:N \l__nmc_recur_order_int
\int_new:N \l__nmc_recur_var_int

\tl_new:N \l__nmc_recurrence_tl
\tl_new:N \l__nmc_recur_base_var_tl
\tl_new:N \l__nmc_recur_subscr_var_tl

\seq_new:N \l__nmc_recur_result_seq
\seq_new:N \l__nmc_recur_index_seq
\seq_new:N \l__nmc_recur_vars_seq

\nmc_define:nnN { \nmcRecur } { recur } \recur

\cs_new_protected:Npn \__nmc_recur_settings_digest:
  { 
    \bool_set_false:N \l__nmc_allow_TF_out_bool
    \int_set:Nn \l__nmc_recur_total_int 
        { \int_max:nn { \l__nmc_recur_total_int } { 1 } }
    \int_set:Nn \l__nmc_recur_last_int
        { \int_max:nn { 0 } { \int_min:nn
             { \l__nmc_recur_last_int } { \l__nmc_recur_total_int } } }
    \int_set:Nn \l__nmc_recur_first_int
        { \int_max:nn { 0 } { \int_min:nn { \l__nmc_recur_first_int }
             { \l__nmc_recur_total_int - \l__nmc_recur_last_int } } }
    \int_if_zero:nT { \l__nmc_recur_first_int }
      { \int_decr:N \l__nmc_recur_first_int }
  }
\cs_new_protected:Npn \__nmc_recur_vv_digest:N #1
  { % #1 = reversed vv clist
    \bool_set_true:N \l__nmc_multitok_bool
    \__nmc_recur_elements:
    \__nmc_recur_vars_change:N #1
    \__nmc_vv_digest:N #1
    \__nmc_recur_vv_post:
    \tl_set_eq:NN \l__nmc_formula_tl \l__nmc_recurrence_tl
  }
% \l__nmc_recurrence_tl, \l__nmc_recur_base_var_tl,
% \l__nmc_recur_subscr_var_tl, \l__nmc_recur_subscr_val_int
\cs_new_protected:Npn \__nmc_recur_elements:
  {
    \tl_clear:N \l_tmpa_tl
    \bool_set_false:N \l_tmpa_bool
    \tl_map_inline:Nn \l__nmc_formula_tl
      {
        \bool_if:NTF \l_tmpa_bool
          { 
            \tl_set:Nn \l_tmpa_tl { ##1 } 
            \tl_map_break:
          }
          {
            \token_if_math_subscript:NTF ##1
              { 
                \tl_set:NV \l__nmc_recur_base_var_tl \l_tmpa_tl 
                \bool_set_true:N \l_tmpa_bool
              }
              { \tl_put_right:Nn \l_tmpa_tl { ##1 } }
          }
      }
    \__nmc_recur_parse_subscr:N \l_tmpa_tl
    \exp_last_unbraced:NV\__nmc_split_eq:w \l__nmc_formula_tl \q_stop
    \tl_set:NV \l__nmc_recurrence_tl \l__nmc_eq_val_tl
     \tl_set_rescan:Nno \l__nmc_recurrence_tl { \ExplSyntaxOn } \l__nmc_recurrence_tl
  }
\cs_new_protected:Npn \__nmc_recur_parse_subscr:N #1
  {
    \tl_clear:N \l__nmc_recur_subscr_var_tl
    \tl_set:Nn \l_tmpb_tl { 0 }
    \int_zero:N \l__nmc_recur_subscr_val_int
    \bool_set_false:N \l_tmpa_bool
    \tl_map_inline:Nn #1
      {
        \bool_if:NTF \l_tmpa_bool
          { \tl_put_right:Nn \l_tmpb_tl { ##1 } }
          {
            \tl_if_in:nnTF { +- } { ##1 }
              { 
                \tl_put_right:Nn \l_tmpb_tl { ##1 }
                \bool_set_true:N \l_tmpa_bool
              }
              { \tl_put_right:Nn \l__nmc_recur_subscr_var_tl { ##1 } }
          }
      }
    \int_set:Nn \l__nmc_recur_subscr_val_int { \l_tmpb_tl }
  }
\cs_new_protected:Npn \__nmc_recur_vars_change:N #1
  { % f_{1} etc ==> f_{n-1} etc in #1 (reverse order vv-list)
    \clist_reverse:N #1
    \int_zero:N \l__nmc_recur_order_int
    \clist_clear:N \l_tmpa_clist % --> \l__nmc_recur_vars_seq
    \clist_clear:N \l_tmpb_clist % --> #1
    \int_set:Nn \l_tmpb_int { \l__nmc_recur_subscr_val_int - 1 }
    \tl_set_rescan:Nno #1 { \ExplSyntaxOn } #1 
    \clist_map_inline:Nn #1
      {
        \seq_set_split:Nnn \l_tmpa_seq {_} { ##1 }
        \seq_pop:NN \l_tmpa_seq \l_tmpa_tl
        \seq_if_empty:NTF \l_tmpa_seq
          { \clist_put_left:NV \l_tmpb_clist \l_tmpa_tl }
          {
            \tl_if_eq:NNTF \l_tmpa_tl \l__nmc_recur_base_var_tl
              { % change e.g. f_{1}(x) to f_{n-1}(x)
                \int_incr:N \l__nmc_recur_order_int
                \tl_put_right:Nn \l_tmpa_tl { _ }
                \tl_set_eq:NN \l_tmpb_tl \l__nmc_recur_subscr_var_tl
                \int_case:nn { \int_sign:n { \l_tmpb_int } }
                  { 
                    { -1 } 
                      { 
                        \tl_put_right:Nx \l_tmpb_tl 
                            { \int_use:N \l_tmpb_int }
                      }
                    { 0 } { \prg_do_nothing: }
                    { 1 } 
                      { 
                        \tl_put_right:Nn \l_tmpb_tl { + }
                        \tl_put_right:Nx \l_tmpb_tl 
                            { \int_use:N \l_tmpb_int } 
                      }
                  }
                \tl_put_right:Nx \l_tmpa_tl { { \l_tmpb_tl } }
                \int_decr:N \l_tmpb_int
                \seq_pop:NN \l_tmpa_seq \l_tmpb_tl
                \int_set:Nn \l__nmc_recur_subscr_ini_int 
                    { \tl_head:N \l_tmpb_tl }
                \tl_put_right:Nx \l_tmpa_tl 
                    { \tl_range:Nnn \l_tmpb_tl { 2 } { -1 } }
                \clist_put_left:NV \l_tmpb_clist \l_tmpa_tl
                \seq_set_split:NnV \l_tmpb_seq { = } \l_tmpa_tl
                \seq_pop:NN \l_tmpb_seq \l_tmpa_tl
                \clist_put_left:NV \l_tmpa_clist \l_tmpa_tl
              }
              { \clist_put_left:Nn \l_tmpb_clist { ##1 } }
          }
      }
    \int_set:Nn \l__nmc_recur_var_int 
        { \l__nmc_recur_subscr_ini_int + \l__nmc_recur_order_int
            - \l__nmc_recur_subscr_val_int  }
    \clist_set_eq:NN #1 \l_tmpb_clist
    \clist_put_left:NV \l_tmpa_clist \l__nmc_recur_subscr_var_tl
    \clist_concat:NNN \l__nmc_formula_tl \l__nmc_recurrence_tl \l_tmpa_clist
  }
\cs_new_protected:Npn \__nmc_recur_vv_post:
  {
    \clist_pop:NN \l__nmc_formula_tl \l__nmc_recurrence_tl
    \clist_pop:NN \l__nmc_formula_tl \l__nmc_recur_subscr_var_tl
    \tl_set:Nx \l_tmpa_tl { \int_use:N \l__nmc_recur_var_int }
    \__nmc_vv_record:NVN \l__nmc_recur_subscr_var_tl \l_tmpa_tl \c_empty_prop
    \tl_set_eq:NN \l_tmpa_tl \l__nmc_recur_subscr_var_tl
    \tl_put_right:Nn \l_tmpa_tl { =0 } % formal value
    \seq_put_left:NV \l__nmc_calc_fn_seq \l_tmpa_tl
    \seq_set_from_clist:NN \l__nmc_recur_vars_seq \l__nmc_formula_tl
  }
%%%%%%%%%%%%%%%%%%%
\cs_new_protected:Npn \__nmc_recur_process:
  { % store initial vals; generate later vals
    \__nmc_recur_store_ini:
    \__nmc_error_where:n { recurrence~formula }
    \__nmc_recur_generate:
    \seq_get_right:NN \l__nmc_recur_result_seq \l_nmc_result_tl
    \tl_set_eq:NN \l__nmc_fp_expr_tl \l__nmc_fp_exprn_tl
  }
\cs_new_protected:Npn \__nmc_recur_store_ini:
  {
    \seq_set_eq:NN \l_tmpa_seq \l__nmc_recur_vars_seq
    \int_step_inline:nnnn { 1 } { 1 } { \l__nmc_recur_order_int } 
      {
        \seq_pop:NN \l_tmpa_seq \l_tmpa_tl
        \prop_get:NVN \g__nmc_subst_var_prop \l_tmpa_tl \l__nmc_subst_tl
        \__nmc_num_format:nNnN { \l__nmc_subst_tl } \l_tmpa_tl 
            { \l__nmc_round_int } \l__nmc_sci_num_out_bool
        \seq_put_right:NV \l__nmc_recur_result_seq \l_tmpa_tl
        \tl_set:Nx \l_tmpb_tl { \int_eval:n 
            { \l__nmc_recur_subscr_ini_int + ##1 -1 } }
        \seq_put_right:NV \l__nmc_recur_index_seq \l_tmpb_tl
      }
  }
\cs_new_protected:Npn \__nmc_recur_generate:
  {
    \prop_get:NVN \g__nmc_subst_var_prop 
        \l__nmc_recur_subscr_var_tl \l__nmc_subst_tl
    \int_set:Nn \l__nmc_recur_var_int { \l__nmc_subst_tl }
    \int_set:Nn \l_tmpa_int { \l__nmc_recur_var_int +
        \l__nmc_recur_total_int - \l__nmc_recur_order_int - 1 }
    \__nmc_error_where:n { recurrence~relation }
    \__nmc_if_mod_zero:nnT { \l__nmc_debug_int } { 7 }
      { \__nmc_fpify:VN \l__nmc_recurrence_tl \l__nmc_fp_expr_tl }
    \int_step_function:nnnN { \l__nmc_recur_var_int } { 1 }
         {\l_tmpa_int } \__nmc_recur_generate_loop:n
  }
\cs_new_protected:Npn \__nmc_recur_generate_loop:n #1
  { 
    \bool_if:NF \g__nmc_error_bool
      { % calc. the next term
        \fp_set:Nn \l_tmpa_fp { #1 }
        \__nmc_calc_fn_val:VNnN \l__nmc_recur_subscr_var_tl
            \l__nmc_recurrence_tl { \l_tmpa_fp } \l__nmc_recur_result_fp
      }
    \bool_if:NF \g__nmc_error_bool
      { % store the result
        \__nmc_num_format:nNnN { \l__nmc_recur_result_fp } 
            \l_tmpa_tl { \l__nmc_round_int } \l__nmc_sci_num_out_bool
        \seq_put_right:NV \l__nmc_recur_result_seq \l_tmpa_tl
        \seq_put_right:Nn \l__nmc_recur_index_seq { #1 }
        % shift vals "down variable"; tmpa above, tmpb below
        \seq_set_eq:NN \l_tmpa_seq \l__nmc_recur_vars_seq
        \seq_pop:NN \l_tmpa_seq \l_tmpb_tl % low var
        \int_step_inline:nnnn {2} { 1 } { \l__nmc_recur_order_int }
          {
            \seq_pop:NN \l_tmpa_seq \l_tmpa_tl % hi var
            \prop_get:NVN \g__nmc_subst_var_prop \l_tmpa_tl \l__nmc_subst_tl
            \prop_put:NVV \g__nmc_subst_var_prop \l_tmpb_tl \l__nmc_subst_tl
            \prop_put:NVV \l__nmc_vv_change_prop \l_tmpb_tl \l__nmc_subst_tl
            \tl_set_eq:NN \l_tmpb_tl \l_tmpa_tl
          }
          % use tmpb, not tmpa, in case order = 1
          \prop_put:NVx \g__nmc_subst_var_prop \l_tmpb_tl
              { \fp_use:N \l__nmc_recur_result_fp }
          \prop_put:NVx \l__nmc_vv_change_prop \l_tmpb_tl
              { \fp_use:N \l__nmc_recur_result_fp }
      }
  }
\cs_new_protected:Npn \__nmc_recur_display:
  { 
    \bool_if:NTF \l__nmc_num_only_bool
      { \tl_gset_eq:NN \g__nmc_reuse_tl \l_nmc_result_tl }
      { 
        \seq_clear:N \l_tmpa_seq
        \seq_clear:N \l_tmpb_seq
        \seq_clear:N \l_tmpc_seq
        \__nmc_recur_result:NN \l_tmpa_seq \l_tmpb_seq
        \tl_set:Nx \l_nmc_result_tl
            { 
              \exp_not:o \l__nmc_math_delimi_tl
              \bool_if:NT \l__nmc_wraps_math_bool
                { 
                  \exp_not:o \l__nmc_formula_dup_tl
                  \bool_if:NTF \l__nmc_vv_multline_bool
                    { \exp_not:o \l__nmc_vv_display_tl }
                    { 
                      \mathchoice{ \exp_not:o \l__nmc_vv_display_tl }
                          { \exp_not:o \l__nmc_vv_inline_tl }{}{} 
                    }
                  \rightarrow \exp_not:N \quad 
                } 
              \seq_use:Nn \l_tmpa_seq { ,\ }
              \l__nmc_punc_tl
              \exp_not:o \l__nmc_math_delimii_tl
            }
        \__nmc_plus_reuse:nNN { \l__nmc_recur_reuse_int } \l_tmpc_seq \l_tmpb_seq 
      }
    \l_nmc_result_tl
  }
\cs_new_protected:Npn \__nmc_recur_result:NN #1#2
  {
    \int_zero:N \l_tmpa_int
    \seq_map_inline:Nn \l__nmc_recur_result_seq
      { 
        \seq_pop:NN \l__nmc_recur_index_seq \l__nmc_toss_tl
        \int_compare:nNnTF { \l_tmpa_int } < { \l__nmc_recur_first_int }
          { \seq_put_right:Nn #1 { ##1 } }
          {
            \int_compare:nTF { \l_tmpa_int = \l__nmc_recur_first_int 
                < \l__nmc_recur_total_int - \l__nmc_recur_last_int }
              { \seq_put_right:Nn #1 { \ldots } }
              {
                \int_compare:nNnT { 1 + \l_tmpa_int } > 
                    { \l__nmc_recur_total_int - \l__nmc_recur_last_int }
                  { 
                    \seq_put_right:Nn #1 { ##1 }
                    \seq_put_right:Nn #2 { ##1 }
                    \seq_put_right:Nx \l_tmpc_seq { \int_eval:n { \l_tmpa_int + \l__nmc_recur_subscr_val_int } }
                  }
              }
          }
        \int_incr:N \l_tmpa_int
      }
    \bool_if:NT \l__nmc_recur_ellipsis_bool
      { \seq_put_right:Nn #1{ \ldots } }
  }
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\keys_define:nn { numerica }
  { 
    iter-do             .int_set:N = \l__nmc_iter_total_int,
    iter-see-last       .int_set:N = \l__nmc_iter_view_int,
    iter-max-iterations .int_set:N = \l__nmc_iter_max_int,
    iter-extra-rounding .int_set:N = \l__nmc_iter_extra_int,
    iter-reuse          .int_set:N = \l__nmc_iter_reuse_int,

    iter-do             .default:n = 5,
    iter-see-last       .default:n = 4,
    iter-max-iterations .default:n = 100,
    iter-extra-rounding .default:n = 0,
    iter-reuse          .default:n = 0,
%
    solve-max-steps      .int_set:N = \l__nmc_solve_max_int,
    solve-extra-rounding .int_set:N = \l__nmc_solve_extra_int,
    solve-first-step      .tl_set:N = \l__nmc_solve_step_tl,
    solve-reuse          .int_set:N = \l__nmc_solve_reuse_int,

    solve-max-steps      .default:n = 100,
    solve-extra-rounding .default:n = 0,
    solve-first-step     .default:n = 1,
    solve-reuse          .default:n = 0,
%
    recur-do         .int_set:N = \l__nmc_recur_total_int,
    recur-see-first  .int_set:N = \l__nmc_recur_first_int,
    recur-see-last   .int_set:N = \l__nmc_recur_last_int,
    recur-reuse      .int_set:N = \l__nmc_recur_reuse_int,
    
    recur-do         .default:n = 7,
    recur-see-first  .default:n = 3,
    recur-see-last   .default:n = 2,
    recur-reuse      .default:n = 0
  }
\keys_set_known:nn { numerica } 
  { 
    iter-do,iter-see-last,iter-max-iterations,
    iter-extra-rounding,iter-reuse,
    solve-variable,solve-first-step,solve-max-steps,
    solve-extra-rounding,solve-reuse,
    recur-do,recur-see-first,recur-see-last,recur-reuse
  }
\keys_define:nn { numerica/iter }
  {
    var    .tl_set:N = \l__nmc_iter_var_tl,
    +     .int_set:N = \l__nmc_iter_extra_int,
    max   .int_set:N = \l__nmc_iter_max_int,
    do    .int_set:N = \l__nmc_iter_total_int,
    see   .int_set:N = \l__nmc_iter_view_int,
    reuse .int_set:N = \l__nmc_iter_reuse_int
  }
\keys_define:nn { numerica/solve }
  {
    var    .tl_set:N = \l__nmc_solve_var_tl,
    +     .int_set:N = \l__nmc_solve_extra_int,
    max   .int_set:N = \l__nmc_solve_max_int,
    dvar   .tl_set:N = \l__nmc_solve_step_tl,
    reuse .int_set:N = \l__nmc_solve_reuse_int
  }
\keys_define:nn { numerica/recur }
  {
    do    .int_set:N = \l__nmc_recur_total_int,
    see1  .int_set:N = \l__nmc_recur_first_int,
    see2  .int_set:N = \l__nmc_recur_last_int,
    ...      .code:n = \bool_set_true:N \l__nmc_recur_ellipsis_bool,
    reuse .int_set:N = \l__nmc_recur_reuse_int
  }
% end of `numerica-plus.def'