% This is file `numerica-plus.sty'. % % 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.sty} {2023/08/13} {3.0.0} {Iterate functions, find zeros/extrema of functions, evaluate recurrences} \msg_new:nnn {numerica-plus} {version} { Package~too~old!~This~version~of~numerica-plus~requires~ numerica~version~3. } \msg_new:nnn {numerica-plus} {load-order} { Please~load~version~3~of~numerica~*before*~numerica~plus. } \cs_if_exist:NTF \c_nmc_version_tl { \int_compare:nNnT { \c_nmc_version_tl } < { 30 } { \msg_fatal:nn {numerica-plus} {version} } } { \msg_fatal:nn {numerica-plus} {load-order} } %---------------------------------------------------------- \cs_generate_variant:Nn \tl_if_novalue:nTF { o } \clist_map_inline:nn { iter,solve } { \tl_new:c { g__nmc_info_#1_tl } \tl_gset:cn { g__nmc_info_#1_tl } { 0 } } \clist_gput_right:Nn \g__nmc_info_proc_clist { iter, solve } \int_if_zero:nT { \g__nmc_consts_vv_int } { \int_incr:N \g__nmc_consts_vv_int } \cs_new_protected:Npn \__nmc_plus_get_var:NNn #1#2#3 { \tl_if_empty:NT #1 { \tl_set:Nx \l_tmpa_tl { \seq_item:Nn \l__nmc_vv_all_seq { \g__nmc_consts_vv_int } } \quark_if_no_value:NTF \l_tmpa_tl { \__nmc_error_where:n { #2 } \__nmc_error_what:n { No~#3~variable~specified~in } } { \__nmc_vv_split_item:V \l_tmpa_tl \tl_set_eq:NN #1 \l__nmc_eq_var_tl } } } % #1 vv-seq reversed #2 var_tl #3 \nmc #4 {adjective} \cs_new_protected:Npn \__nmc_plus_vv_digest:NNNn #1#2#3#4 { \clist_push:NV \l__nmc_formula_tl #2 \__nmc_vv_digest:N #1 \tl_if_empty:NTF #2 { \__nmc_plus_get_var:NNn #2 #3 { #4 } } { \clist_pop:NN \l__nmc_formula_tl #2 } } \cs_new_protected:Npn \__nmc_plus_reuse:N #1 { \tl_gclear:N \g__nmc_reuse_tl \seq_map_inline:Nn #1 { \tl_gput_right:Nn \g__nmc_reuse_tl { ,{##1} } } \tl_gset:Nx \g__nmc_reuse_tl { \exp_last_unbraced:NV \use_none:n \g__nmc_reuse_tl } } \NewDocumentCommand \clitem { m m } { \clist_item:Nn #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 \nmc_define:NnN \nmcIterate { iter } \iter \cs_set_protected:Npn \__nmc_iter_initialize: { \tl_set:Nn \l__nmc_dbg_idii_tl { function } \tl_set:Nn \l__nmc_dbg_idv_tl { stored } \__nmc_env_initialize: } \cs_set_protected:Npn \__nmc_iter_settings: { \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 } } \__nmc_env_settings: } \cs_gset_protected:Npn \__nmc_iter_formula: { \__nmc_env_formula: \tl_set_eq:NN \l__nmc_formula_dup_tl \l__nmc_formula_tl } \cs_gset_protected:Npn \__nmc_iter_vv_digest:N #1 { \__nmc_plus_vv_digest:NNNn #1 \l__nmc_iter_var_tl \nmcIterate {iteration} } \cs_gset_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 } \bool_if:NF \g__nmc_error_bool { \__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: } \int_if_zero:nF \l__nmc_dbg_int { \__nmc_dbg_get_data: \__nmc_if_mod_zero:nnT \l__nmc_dbg_int { 11 } { \__nmc_iter_display: } } } \cs_gset_protected:Npn \__nmc_iter_display: { \tl_gset_eq:NN \l__nmc_show_tl \l__nmc_result_tl \__nmc_if_mod_zero:nnF { \l__nmc_dbg_int } { 11 } { \l__nmc_show_tl } } %-------------------------------------- \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 \tl_gset_eq:NN \g__nmc_reuse_tl \l__nmc_result_tl \int_decr:N \l__nmc_iter_total_int % for checking iter. \tl_gset:Nx \g__nmc_info_iter_tl { \int_use:N \l__nmc_iter_total_int } } } { % don't print initial iters \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 & 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 } \int_incr:N \l__nmc_iter_max_int % for fx pt checking iter \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:nNnT {\l__nmc_iter_total_int} > {\l__nmc_iter_max_int} { \bool_gset_true:N \g__nmc_error_bool \int_decr:N \l__nmc_iter_max_int \__nmc_error_what:n { No~fixed~point~attained~after~$ \int_use:N \l__nmc_iter_max_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_see_formula_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_info_iter_tl { \int_use:N \l__nmc_iter_total_int } \tl_set:Nx \l__nmc_result_tl { \exp_not:o \l__nmc_iter_begin_tl \l_tmpa_tl \exp_not:o \l__nmc_vv_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_info_iter_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 } \__nmc_plus_reuse:N \l__nmc_iter_result_seq } %-------------------------------------- %\nmcSolve \tl_new:N \l__nmc_solve_to_tl \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 \nmc_define:NnN \nmcSolve { solve } \solve \cs_gset_protected:Npn \__nmc_solve_initialize: { \tl_set:Nn \l__nmc_dbg_idii_tl { function } \tl_set:Nn \l__nmc_dbg_idv_tl { stored } \tl_clear:N \l__nmc_show_tl \__nmc_env_initialize: } \cs_gset_protected:Npn \__nmc_solve_settings: { \bool_set_false:N \l__nmc_allow_TF_out_bool \tl_if_empty:NF \l__nmc_solve_step_tl { \__nmc_fpify_set:NV \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 } } } \__nmc_env_settings: } \cs_gset_protected:Npn \__nmc_solve_formula: { \__nmc_env_formula: } \cs_gset_protected:Npn \__nmc_solve_vv_digest:N #1 { \__nmc_plus_vv_digest:NNNn #1 \l__nmc_solve_var_tl \nmcSolve {equation} } \cs_gset_protected:Npn \__nmc_solve_process: { \int_set:Nn \l__nmc_solve_round_int { \l__nmc_round_int + \l__nmc_solve_extra_int } \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_info_solve_tl { \clist_use:Nn \g__nmc_info_solve_tl { + } } \tl_set_eq:NN \l__nmc_fp_expr_tl \l__nmc_fp_exprn_tl } \int_if_zero:nF \l__nmc_dbg_int { \__nmc_dbg_get_data: \__nmc_if_mod_zero:nnT \l__nmc_dbg_int { 11 } { \__nmc_solve_display: } } } \cs_gset_protected:Npn \__nmc_solve_display: { \tl_gset_eq:NN \g__nmc_reuse_tl \l__nmc_result_tl \bool_if:NTF \l__nmc_num_only_bool { \tl_set_eq:NN \l__nmc_show_tl \l__nmc_result_tl } { \__nmc_num_format:nNnN { \l__nmc_solvefa_fp } \l_tmpa_tl { \l__nmc_round_int } \l__nmc_sci_num_out_bool \tl_clear:N \l__nmc_display_tl \tl_put_right:Nx \l__nmc_display_tl { \bool_if:NTF \l__nmc_see_formula_bool { \exp_not:o \l__nmc_formula_tl = \l_tmpa_tl \bool_if:nT { \l__nmc_see_vv_bool && !\l__nmc_env_rbrace_bool } { \exp_not:o \l__nmc_vv_tl } \l__nmc_solve_to_tl \l__nmc_solve_var_tl = \l__nmc_result_tl } { \exp_not:o \l__nmc_solve_var_tl = \l__nmc_result_tl } } \__nmc_eval_rdisplay:ooo \l__nmc_display_tl \l__nmc_punc_tl \l__nmc_math_delimii_tl \__nmc_eval_ldisplay:noo {} \l__nmc_math_delimi_tl \l__nmc_env_arg_tl } \__nmc_if_mod_zero:nnF { \l__nmc_dbg_int } { 11 } { \l__nmc_show_tl } } %%%%%%%%% \cs_new_protected:Npn \__nmc_solve_get_trial_vals: { \prop_get:NVN \l__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_info_solve_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_info_solve_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_info_solve_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) } } } } %-------------------------------------- % \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_vars_seq \nmc_define:NnN \nmcRecur { recur } \recur \cs_set_protected:Npn \__nmc_recur_initialize: { \tl_set:Nn \l__nmc_dbg_idii_tl { relation } \tl_set:Nn \l__nmc_dbg_idv_tl { stored } \__nmc_env_initialize: } \cs_set_protected:Npn \__nmc_recur_settings: { \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 } \__nmc_env_settings: } \cs_set_protected:Npn \__nmc_recur_formula: { \__nmc_env_formula: \tl_set_eq:NN \l__nmc_formula_dup_tl \l__nmc_formula_tl } \cs_set_protected:Npn \__nmc_recur_vv_digest:N #1 { % #1 = reversed vv seq \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 \int_if_zero:nF \l__nmc_dbg_int { \__nmc_dbg_get_data: } } \cs_set_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_set_protected:Npn \__nmc_recur_display: { \tl_clear:N \l__nmc_show_tl \bool_if:NTF \l__nmc_num_only_bool { \tl_gset_eq:NN \g__nmc_reuse_tl \l__nmc_result_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_clear:N \l__nmc_display_tl \tl_set:Nx \l__nmc_display_tl { \bool_if:NT \l__nmc_see_formula_bool { \exp_not:o \l__nmc_formula_dup_tl \exp_not:o \l__nmc_vv_tl \l__nmc_recur_to_tl } \seq_use:Nn \l_tmpa_seq { \c__nmc_vv_delim_tl\ } } \__nmc_plus_reuse:N \l_tmpb_seq \__nmc_eval_rdisplay:ooo \l__nmc_display_tl \l__nmc_punc_tl \l__nmc_math_delimii_tl \__nmc_eval_ldisplay:noo {} \l__nmc_math_delimi_tl \l__nmc_env_arg_tl \l__nmc_show_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 } } \clist_new:N \l__nmca_clist \cs_new_protected:Npn \__nmc_recur_vars_change:N #1 { % f_{1} etc ==> f_{n-1} etc in #1 (reverse order vv-list) \seq_reverse:N #1 \clist_set:Nx \l__nmca_clist { \seq_use:Nn #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 \tl_set_rescan:Nno \l__nmca_clist { \ExplSyntaxOn } \l__nmca_clist \clist_map_inline:Nn \l__nmca_clist { \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 \l__nmca_clist \l_tmpb_clist \seq_set_from_clist:NN #1 \l__nmca_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_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 \l__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 } } } } \cs_new_protected:Npn \__nmc_recur_generate: { \prop_get:NVN \l__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_dbg_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. next \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 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 % 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 \l__nmc_subst_var_prop \l_tmpa_tl \l__nmc_subst_tl \prop_put:NVV \l__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 \l__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_result:NN #1#2 { \int_zero:N \l_tmpa_int \seq_map_inline:Nn \l__nmc_recur_result_seq { \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_ini_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 } { view .code:n = \__nmc_dbg_int:nn { 1 } { 2*3*5*7*11 }, var .tl_set:N = \l__nmc_iter_var_tl, + .int_set:N = \l__nmc_iter_extra_int, + .initial:n = 0, max .int_set:N = \l__nmc_iter_max_int, max .initial:n = 100, do .int_set:N = \l__nmc_iter_total_int, do .initial:n = 5, see .int_set:N = \l__nmc_iter_view_int, see .initial:n = 4 } \keys_define:nn { numerica/solve } { view .code:n = \__nmc_dbg_int:nn { 1 } { 2*3*5*7*11 }, var .tl_set:N = \l__nmc_solve_var_tl, + .int_set:N = \l__nmc_solve_extra_int, + .initial:n = 0, max .int_set:N = \l__nmc_solve_max_int, max .initial:n = 100, dvar .tl_set:N = \l__nmc_solve_step_tl, dvar .initial:n = 1, to .tl_set:N = \l__nmc_solve_to_tl, to .initial:n = {\,\to\,} , } \keys_define:nn { numerica/recur } { do .int_set:N = \l__nmc_recur_total_int, do .initial:n = 7, see1 .int_set:N = \l__nmc_recur_first_int, see1 .initial:n = 3, see2 .int_set:N = \l__nmc_recur_last_int, see2 .initial:n = 2, ... .code:n = \bool_set_true:N \l__nmc_recur_ellipsis_bool, to .tl_set:N = \l__nmc_recur_to_tl, to .initial:n = {\,\to\,} } % end of `numerica-plus.sty'.