% 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'