diff options
Diffstat (limited to 'Master/texmf-dist/tex/generic/polexpr/polexprcore.tex')
-rw-r--r-- | Master/texmf-dist/tex/generic/polexpr/polexprcore.tex | 1366 |
1 files changed, 1366 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/generic/polexpr/polexprcore.tex b/Master/texmf-dist/tex/generic/polexpr/polexprcore.tex new file mode 100644 index 00000000000..e071729e42b --- /dev/null +++ b/Master/texmf-dist/tex/generic/polexpr/polexprcore.tex @@ -0,0 +1,1366 @@ +%% This file polexprcore.tex is part of the polexpr package (0.8, 2021/03/29) +%% Core routines to match infix operators +, -, *, //, /:, ^, ** and some +%% functions +%% The atoms representing polynomials inside \xintexpr are +%% - for constants: a numeric value (indistinguishable. from scalars) +%% - for degree at least 1: P<degree>.{c0}{c1}....{cN} with N = degree +%% Auxiliaries +\long\def\POL_Pfork #1P#2#3\krof{#2}% +\long\def\POL_PPfork #1PP#2#3\krof{#2}% +\long\def\POL_zeroPfork #10P#2#3\krof{#2}% +\long\def\POL_secondofthree#1#2#3{#2}% +% \long\def\POL_Apply:x #1#2% +% {% +% \POL_apply:x_loop {#1}#2% +% \xint_Bye\xint_Bye\xint_Bye\xint_Bye +% \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye +% }% +\long\def\POL_bBye#1\xint_Bye{}% +\long\def\POL_apply:x_loop #1#2#3#4#5#6#7#8#9% +{% + \POL_bBye #2\xint_Bye{#1{#2}}% + \POL_bBye #3\xint_Bye{#1{#3}}% + \POL_bBye #4\xint_Bye{#1{#4}}% + \POL_bBye #5\xint_Bye{#1{#5}}% + \POL_bBye #6\xint_Bye{#1{#6}}% + \POL_bBye #7\xint_Bye{#1{#7}}% + \POL_bBye #8\xint_Bye{#1{#8}}% + \POL_bBye #9\xint_Bye{#1{#9}}% + \POL_apply:x_loop {#1}% +}% +\long\def\POL_apply:x_iloop #1#2#3#4#5#6#7#8#9% +{% + \POL_bBye #2\xint_Bye{#10{#2}}% + \POL_bBye #3\xint_Bye{#11{#3}}% + \POL_bBye #4\xint_Bye{#12{#4}}% + \POL_bBye #5\xint_Bye{#13{#5}}% + \POL_bBye #6\xint_Bye{#14{#6}}% + \POL_bBye #7\xint_Bye{#15{#7}}% + \POL_bBye #8\xint_Bye{#16{#8}}% + \POL_bBye #9\xint_Bye{#17{#9}}% + \POL_apply:x_iloop_a#1% +}% +\def\POL_apply:x_iloop_a#1#2.% +{% + \expandafter\POL_apply:x_iloop + \expandafter{\expandafter#1\the\numexpr\xint_c_viii+#1.}% +}% +\long\def\POL_apply:x_iloop #1#2#3#4#5#6#7#8#9% +{% + \POL_bBye #2\xint_Bye{#10{#2}}% + \POL_bBye #3\xint_Bye{#11{#3}}% + \POL_bBye #4\xint_Bye{#12{#4}}% + \POL_bBye #5\xint_Bye{#13{#5}}% + \POL_bBye #6\xint_Bye{#14{#6}}% + \POL_bBye #7\xint_Bye{#15{#7}}% + \POL_bBye #8\xint_Bye{#16{#8}}% + \POL_bBye #9\xint_Bye{#17{#9}}% + \POL_apply:x_iloop_a#1% +}% +\def\POL_apply:x_iloop_a#1#2.% +{% + \expandafter\POL_apply:x_iloop + \expandafter{\expandafter#1\the\numexpr\xint_c_viii+#1.}% +}% +%% +%% ADDITION +%% +\def\xintPolAdd #1% +{% + \expanded\expandafter\POL_add_in\romannumeral`&&@#1\xint: +}% +\def\POL_add_in #1\xint:#2% +{% + {% + \expandafter\POL_add_fork +% Fragile but this macro is not public anyhow and won't get arbitrary input +% At odds with systematic \xint: style further down + \romannumeral`&&@#2\xint_bye\xint_bye\xint_bye\xint_bye\empty + #1\xint_bye\xint_bye\xint_bye\xint_bye\empty + \empty + }% +}% +% Careful that first means "first here" i.e. the original second argument, +% and vice versa +\def\POL_add_fork #1#2\empty#3% +{% + \POL_PPfork + #1#3{\POL_add_a}% + #1P{\POL_add_second_is_scalar}% + #3P{\POL_add_first_is_scalar}% + PP{\POL_add_both_are_scalar}% + \krof #1#2\empty#3% +}% +\def\POL_add_first_is_scalar #1\xint_bye#2\empty#3.#4% +{% + #3.{\xintAdd{#1}{#4}}% +}% +\def\POL_add_second_is_scalar #1.#2#3\empty#4\xint_bye#5\empty\empty +{% + #1.{\xintAdd{#2}{#4}}#3% +}% +\def\POL_add_both_are_scalar #1\xint_bye#2\empty#3\xint_bye#4\empty\empty +{% + \xintAdd{#1}{#3}% +}% +\def\POL_add_a P#1.#2#3#4#5\empty P#6.#7#8#9% +{% + \expandafter\POL_add_b + \expanded\bgroup\unexpanded{#1.#6.}% + \xint_bye #2\POL_add_Eb\xint_bye + \xint_bye #7\POL_add_Fb\xint_bye {\xintAdd{#2}{#7}}% + \xint_bye #3\POL_add_Ec\xint_bye + \xint_bye #8\POL_add_Fc\xint_bye {\xintAdd{#3}{#8}}% + \xint_bye #4\POL_add_Ed\xint_bye + \xint_bye #9\POL_add_Fd\xint_bye {\xintAdd{#4}{#9}}% + \POL_add_A #5\empty +}% +\def\POL_add_b #1.#2.% +{% + \ifnum#1=#2 \expandafter\POL_add_c + \else + \ifnum#1>#2 P#1.\else P#2.\fi + \fi +}% +% No brace stripping possible, because constant polynomials are really +% represented by scalars in all those internal contexts, so real +% polynomials have at least two coefficients +\def\POL_add_c #1\empty +{% + \expandafter\POL_add_d + \romannumeral0\XINT_revwbr_loop {}% + #1\xint:\xint:\xint:\xint:% + \xint:\xint:\xint:\xint:\xint_bye + \xint_bye +}% +% Attention, reused in various other locations. It is all f-expandable. +\def\POL_add_d #1% +{% +% abuse of \XINT_Sgn internals compatible to #1 being \xint_bye + \if0\XINT_Sgn#1\xint: + \xint_dothis\POL_add_d + \fi + \xint_orthat{\POL_add_e {#1}}% +}% +\def\POL_add_e #1% +{% + \xint_bye#1\POL_add_e_zero\xint_bye \POL_add_f\empty{#1}% +}% +\def\POL_add_e_zero\xint_bye\POL_add_f\empty #1{0/1[0]}% +% #1 starts with \empty to avoid brace stripping. +\def\POL_add_f #1\xint_bye +{% + \expandafter\POL_add_g + \the\numexpr + \xintLength{#1}-\xint_c_ii\expandafter.% + \romannumeral0\expandafter + \XINT_revwbr_loop\expandafter {\expandafter}% + #1\xint:\xint:\xint:\xint:% + \xint:\xint:\xint:\xint:\xint_bye +}% +\def\POL_add_g #1.% +{% + \ifnum#1=\xint_c_\expandafter\POL_add_h\fi + P#1.% +}% +\def\POL_add_h P0.#1{#1}% +% Attention reused in \POL_mul_d and \POL_quorem_c +\def\POL_add_A #1#2#3#4#5\empty#6#7#8#9% +{% + \xint_bye #1\POL_add_Ea\xint_bye + \xint_bye #6\POL_add_Fa\xint_bye {\xintAdd{#1}{#6}}% + \xint_bye #2\POL_add_Eb\xint_bye + \xint_bye #7\POL_add_Fb\xint_bye {\xintAdd{#2}{#7}}% + \xint_bye #3\POL_add_Ec\xint_bye + \xint_bye #8\POL_add_Fc\xint_bye {\xintAdd{#3}{#8}}% + \xint_bye #4\POL_add_Ed\xint_bye + \xint_bye #9\POL_add_Fd\xint_bye {\xintAdd{#4}{#9}}% + \POL_add_A #5\empty +}% +\def\POL_add_Ea\xint_bye + \xint_bye #1\POL_add_Fa\xint_bye #2\xint_bye\xint_bye + \POL_add_Eb\xint_bye\xint_bye#3\POL_add_Fb\xint_bye #4\xint_bye\xint_bye + \POL_add_Ec\xint_bye\xint_bye#5\POL_add_Fc\xint_bye #6\xint_bye\xint_bye + \POL_add_Ed\xint_bye\xint_bye#7\POL_add_Fd\xint_bye #8% + \POL_add_A#9\empty +{% + \xint_bye #1\POL_add_G\xint_bye{#1}% + \xint_bye #3\POL_add_G\xint_bye{#3}% + \xint_bye #5\POL_add_G\xint_bye{#5}% + \xint_bye #7\POL_add_G\xint_bye{#7}% + \iffalse{\fi}% +}% +\def\POL_add_G#1\empty{\iffalse{\fi}}% +\def\POL_add_Fa\xint_bye #1% + \xint_bye #2\POL_add_Eb \xint_bye + \xint_bye\xint_bye\POL_add_Fb\xint_bye #3% + \xint_bye #4\POL_add_Ec \xint_bye + \xint_bye\xint_bye\POL_add_Fc\xint_bye #5% + \xint_bye #6\POL_add_Ed #7\POL_add_A + #8\empty#9\empty +{% + \expandafter\xint_bye\POL_secondofthree #1% + \POL_add_G\xint_bye{\POL_secondofthree#1}% + \xint_bye #2\POL_add_G\xint_bye{#2}% + \xint_bye #4\POL_add_G\xint_bye{#4}% + \xint_bye #6\POL_add_G\xint_bye{#6}% + \iffalse{\fi}#8\empty% +}% +\def\POL_add_Eb\xint_bye + \xint_bye #1\POL_add_Fb\xint_bye #2\xint_bye\xint_bye + \POL_add_Ec\xint_bye\xint_bye#3\POL_add_Fc\xint_bye #4\xint_bye\xint_bye + \POL_add_Ed\xint_bye\xint_bye#5\POL_add_Fd\xint_bye #6% + \POL_add_A#7\empty +{% + \xint_bye #1\POL_add_G\xint_bye{#1}% + \xint_bye #3\POL_add_G\xint_bye{#3}% + \xint_bye #5\POL_add_G\xint_bye{#5}% + \iffalse{\fi}% +}% +\def\POL_add_Fb\xint_bye #1% + \xint_bye #2\POL_add_Ec \xint_bye + \xint_bye\xint_bye\POL_add_Fc\xint_bye #3% + \xint_bye #4\POL_add_Ed #5\POL_add_A + #6\empty#7\empty +{% + \expandafter\xint_bye\POL_secondofthree #1% + \POL_add_G\xint_bye{\POL_secondofthree#1}% + \xint_bye #2\POL_add_G\xint_bye{#2}% + \xint_bye #4\POL_add_G\xint_bye{#4}% + \iffalse{\fi}#6\empty +}% +\def\POL_add_Ec\xint_bye + \xint_bye #1\POL_add_Fc\xint_bye #2\xint_bye\xint_bye + \POL_add_Ed\xint_bye\xint_bye#3\POL_add_Fd\xint_bye #4% + \POL_add_A#5\empty +{% + \xint_bye #1\POL_add_G\xint_bye{#1}% + \xint_bye #3\POL_add_G\xint_bye{#3}% + \iffalse{\fi}% +}% +\def\POL_add_Fc\xint_bye #1\xint_bye #2\POL_add_Ed #3\POL_add_A + #4\empty#5\empty +{% + \expandafter\xint_bye\POL_secondofthree #1% + \POL_add_G\xint_bye{\POL_secondofthree#1}% + \xint_bye #2\POL_add_G\xint_bye{#2}% + \iffalse{\fi}#4\empty +}% +\def\POL_add_Ed\xint_bye\xint_bye#1\POL_add_Fd\xint_bye#2\POL_add_A#3\empty +{% + \xint_bye #1\POL_add_G\xint_bye{#1}% + \iffalse{\fi}% +}% +\def\POL_add_Fd\xint_bye#1\POL_add_A #2\empty#3\empty +{% + \expandafter\xint_bye \POL_secondofthree #1% + \POL_add_G\xint_bye{\POL_secondofthree#1}% + \iffalse{\fi}#2\empty +}% +%% +%% OPPOSITE +%% +\def\xintPolOpp #1% +{% + \expanded{% + \expandafter\POL_opp_fork\romannumeral`&&@#1% + \xint_Bye\xint_Bye\xint_Bye\xint_Bye + \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye + }% +}% +\def\POL_opp_fork #1% +{% + \if P#1\xint_dothis\POL_opp_a\fi + \xint_orthat\POL_opp_scalar #1% +}% +\def\POL_opp_scalar #1\xint_Bye#2\xint_bye +{% + \XINT_Opp #1% +}% +\def\POL_opp_a #1.% +{% + #1.\POL_apply:x_loop{\XINT_Opp}% +}% +%% +%% SUBTRACTION +%% +\def\xintPolSub #1% +{% + \expanded\expandafter\POL@sub\romannumeral`&&@#1\xint: +}% +\def\POL@sub #1\xint:#2% +{% + {% + \expandafter + \POL_add_fork\expanded{% + \expandafter\POL_opp_fork \romannumeral`&&@#2% + \xint_Bye\xint_Bye\xint_Bye\xint_Bye + \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye + }% + \xint_bye\xint_bye\xint_bye\xint_bye\empty + #1\xint_bye\xint_bye\xint_bye\xint_bye\empty + \empty + }% +}% +%% +%% MULTIPLICATION +%% +\def\xintPolSqr #1% +{% + \expanded\expandafter\POL_sqr_in\romannumeral`&&@#1\xint: +}% +\def\POL_sqr_in #1\xint: +{% + {% + \expandafter\POL_mul_fork + #1\xint_bye + #1\xint_Bye\xint_Bye\xint_Bye\xint_Bye + \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye + }% +}% +% +\def\xintPolMul #1% +{% + \expanded\expandafter\POL_mul_in\romannumeral`&&@#1\xint: +}% +\def\POL_mul_in #1\xint:#2% +{% + {% + \expandafter\POL_mul_fork + \romannumeral`&&@#2\xint_bye + #1\xint_Bye\xint_Bye\xint_Bye\xint_Bye + \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye + }% +}% +\def\POL_mul_fork #1#2\xint_bye#3% +{% + \POL_PPfork + #1#3{\POL_mul_a}% + #1P{\POL_mul_second_is_scalar}% + #3P{\POL_mul_first_is_scalar}% + PP{\POL_mul_both_are_scalar}% + \krof #1#2\xint_bye#3% +}% +\def\POL_mul_both_are_scalar #1\xint_bye#2\xint_Bye#3\xint_bye +{% + \xintMul{#1}{#2}% +}% +\def\POL_mul_second_is_scalar #1\xint_bye#2\xint_Bye +{% + \POL_mul_first_is_scalar #2\xint_bye#1\xint_Bye +}% +\def\POL_mul_first_is_scalar #1% +{% + \xint_gob_til_zero#1\POL_mul_zero0\POL_mul_scalar #1% +}% +\def\POL_mul_zero0\POL_mul_scalar #1\xint_bye#2\xint_bye{0/1[0]}% +\def\POL_mul_scalar #1\xint_bye P#2.% +{% + P#2.\POL_apply:x_loop{\xintMul{#1}}% +}% +\def\POL_mul_a P#1.#2#3P#4.#5\xint_bye +{% + P\the\numexpr#1+#4.% + \expandafter\POL_mul_b + \expanded{\POL_apply:x_loop{\xintMul{#2}}#5\xint_bye}% + \xint: + #3\empty#5\xint_bye +}% +\def\POL_mul_b #1{{#1}\POL_mul_c\empty}% +\def\POL_mul_c #1\xint:#2% +{% + \xint_bye#2\POL_mul_E\xint_bye + \expandafter\POL_mul_d\expandafter{#1}{#2}% +}% +\def\POL_mul_d #1#2#3\empty#4\xint_bye +{% + \expandafter\POL_mul_b + \expanded\bgroup + \expandafter\POL_add_A + \expanded{\POL_apply:x_loop{\xintMul{#2}}#4\xint_bye}% + \xint_bye\xint_bye\xint_bye\xint_bye\empty + #1\xint_bye\xint_bye\xint_bye\xint_bye\empty + \xint: + #3\empty#4\xint_bye +}% +\def\POL_mul_E\xint_bye + \expandafter\POL_mul_d\expandafter#1#2\xint_bye +% This #1 starts with \empty +{% + #1% +}% +%% +%% POWERS +%% +\def\xintPolPow #1% +{% + \expanded\expandafter\POL_pow_in\romannumeral`&&@#1\xint: +}% +\def\POL_pow_in #1\xint:#2% +{% + {% + \expandafter\POL_pow_fork\the\numexpr \xintNum{#2}.#1\empty + }% +}% +\def\POL_pow_fork #1#2.% +{% + \xint_UDzerominusfork + #1-\POL_pow_zero + 0#1\POL_pow_neg + 0-\POL_pow_pos + \krof + #1#2.% +}% +\def\POL_pow_zero #1\empty{1/1[0]}% +\def\POL_pow_neg #1.#2% +{% + \POL_Pfork #2{\POL_pow_neg_pol}P{\POL_pow_scalar}\krof #1.#2% +}% +\def\POL_pow_pos #1.#2% +{% + \POL_Pfork #2{\POL_pow_a}P{\POL_pow_scalar}\krof #1.#2% +}% +\def\POL_pow_scalar #1.#2\empty +{% + \xintPow{#2}{#1}% +}% +\def\POL_pow_neg_pol #1.#2\empty +{% + \romannumeral0\XINT_signalcondition{InvalidOperation}% + {Not supported: polynomial to negative power #1}{}{1/1[0]}% +}% +\def\POL_pow_a #1.% +{% +% trailing \empty will disappear in expanded context (old comment) + \ifnum#1=\xint_c_i\xint_afterfi\xint_gob_til_dot\fi + \expandafter\POL_pow_b \the\numexpr#1-\xint_c_i.% +}% +\def\POL_pow_b #1.% +{% + \ifodd #1 \xint_dothis{\expandafter\POL_pow_even}\fi + \xint_orthat{\expandafter\POL_pow_odd}\the\numexpr#1/\xint_c_ii.% +}% +\def\POL_pow_even #1.#2\empty +{% + \expandafter\POL_pow_a + \expanded{\unexpanded{#1.}% + \POL_mul_a#2\xint_bye + #2\xint_Bye\xint_Bye\xint_Bye\xint_Bye + \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye + }\empty +}% +\def\POL_pow_odd #1.#2\empty +{% + \expanded + {\unexpanded{\POL_mul_a #2\xint_bye}% + \expandafter\POL_pow_a + \expanded{\unexpanded{#1.}% + \POL_mul_a#2\xint_bye + #2\xint_Bye\xint_Bye\xint_Bye\xint_Bye + \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye + }% + \empty + }% + \xint_Bye\xint_Bye\xint_Bye\xint_Bye + \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye +}% +%% +%% DIVISION +%% +% +% / is deprecated for polynomial Euclidean division +% +\def\xintPolQuo #1% +{% + \romannumeral0\expandafter\xint_stop_atfirstoftwo + \expanded\expandafter\POL_quorem_in\romannumeral`&&@#1\xint: +}% +% there is no operator, for lack of obvious best notation +\def\xintPolRem #1% +{% + \romannumeral0\expandafter\xint_stop_atsecondoftwo + \expanded\expandafter\POL_quorem_in\romannumeral`&&@#1\xint: +}% +% // +\def\xintPolDivModQ #1% +{% + \romannumeral0\expandafter\xint_stop_atfirstoftwo + \expanded\expandafter\POL_divmod_in\romannumeral`&&@#1\xint: +}% +% /: +\def\xintPolDivModR #1% +{% + \romannumeral0\expandafter\xint_stop_atsecondoftwo + \expanded\expandafter\POL_divmod_in\romannumeral`&&@#1\xint: +}% +% "divmod" will apply coefficient per coefficient when divisor is scalar +% I have found it convenient to treat constant polynomials +% as really being scalars. But I need perhaps to think more about it. +\def\xintPolDivMod #1% +{% + \expanded\expandafter\POL_divmod_in\romannumeral`&&@#1\xint: +}% +% the euclidean division +\def\xintPolQuoRem #1% +{% + \expanded\expandafter\POL_quorem_in\romannumeral`&&@#1\xint: +}% +\def\POL_quorem_in #1\xint:#2% +{% + {% + \expandafter\POL_quorem_fork + \romannumeral`&&@#2\xint_bye#1\xint_bye + }% +}% +% the overloading of divmod which does euclidean division if divisor is not a scalar +\def\POL_divmod_in #1\xint:#2% +{% + {% + \expandafter\POL_divmod_fork + \romannumeral`&&@#2\xint_bye#1\xint_bye + }% +}% +% "first" and "second" refer to the actual positions, permuted compared +% to original arguments +\def\POL_quorem_fork #1#2\xint_bye#3% +{% + \POL_PPfork + #1#3{\POL_quorem_a}% both polynomials -> {eucl. quotient}{remainder} + #1P{\POL_quorem_second_is_scalar}% -> {zero quotient}{scalar} + #3P{\POL_quorem_first_is_scalar}% -> {polynomial/scalar}{zero} + PP{\POL_quorem_both_are_scalar}% -> {scalar/scalar}{zero} + \krof #1#2\xint_bye#3% +}% +\def\POL_quorem_first_is_scalar #1\xint_bye#2\xint_bye +{% + {\expandafter\POL_quorem_first_is_scalar_i\expandafter + {\romannumeral0\xintinv{#1}}% + #2\xint_Bye\xint_Bye\xint_Bye\xint_Bye + \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye}{0/1[0]}% +}% +\def\POL_quorem_first_is_scalar_i #1#2.% +{% + #2.\POL_apply:x_loop{\xintMul{#1}}% +}% +% #2 was initial first argument and is scalar +\def\POL_quorem_second_is_scalar #1\xint_bye#2\xint_bye +{% + {0/1[0]}{#2}% +}% +\def\POL_quorem_both_are_scalar #1\xint_bye#2\xint_bye +{% + {\xintDiv{#2}{#1}}{0/1[0]}% +}% +% attention that "first", "second" refer to the actual arguments positions +\def\POL_divmod_fork #1#2\xint_bye#3% +{% + \POL_PPfork + #1#3{\POL_quorem_a}% both polynomials -> {eucl. quotient}{remainder} + #1P{\POL_quorem_second_is_scalar}% -> {zero quotient}{scalar} + #3P{\POL_divmod_first_is_scalar}% -> {per coeff//scalar}{per coeff/:scalar} + PP{\POL_divmod_both_are_scalar}% -> {s1//s2}{s1/:s2} + \krof #1#2\xint_bye#3% +}% +\def\POL_divmod_both_are_scalar #1\xint_bye#2\xint_bye +{% + \xintDivMod{#2}{#1}% +}% +\def\POL_divmod_first_is_scalar #1\xint_bye #2.#3\xint_bye +{% + \expandafter\POL_divmod_first_is_scalar_a + \expanded{\unexpanded{{#1}}\expandafter}% + \romannumeral0\XINT_revwbr_loop {}% + #3\xint:\xint:\xint:\xint:% + \xint:\xint:\xint:\xint:\xint_bye + \xint_Bye\xint_Bye\xint_Bye\xint_Bye + \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye + \iffalse{\fi}% + \xint: +}% +\long\def\POL_exchange_args#1#2#3{#1{#3}{#2}}% +\def\POL_divmod_first_is_scalar_a #1% +{% + \expandafter\POL_divmod_first_is_scalar_b + \expanded\bgroup + \POL_apply:x_loop{\POL_exchange_args\xintDivMod{#1}}% +}% +% attention re-use of \POL_add_d +\def\POL_divmod_first_is_scalar_b #1\xint: +{% + {\expandafter\POL_add_d\expanded{% + \POL_apply:x_loop{\expandafter\xint_firstoftwo\xint_firstofone}% + #1\xint_Bye\xint_Bye\xint_Bye\xint_Bye + \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye}\xint_bye}% + {\expandafter\POL_add_d\expanded{% + \POL_apply:x_loop{\expandafter\xint_secondoftwo\xint_firstofone}% + #1\xint_Bye\xint_Bye\xint_Bye\xint_Bye + \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye}\xint_bye}% +}% +\def\POL_quorem_a P#1.#2\xint_bye P#3.#4\xint_bye +{% + \ifnum#1>#3 \xint_dothis{\POL_quorem_easy #3.}\fi + \xint_orthat + {\expandafter\POL_quorem_EQuo + \expanded\bgroup + \expandafter\POL_quorem_b\the\numexpr#3-#1\expandafter.% + \expanded\bgroup + \xintRevWithBraces + }% + {#2}% + \noexpand\xint_Bye + \xint: + \expandafter\POL_placemark_loop + \the\numexpr#1-\xint_c_vii\expandafter.% + \romannumeral0\xintrevwithbraces{#4}% +% This added {1} is related to termination clean-up (a bit annoying) process + {1}% + \the\numexpr#3-#1.% + \iffalse{\fi}% +}% +\def\POL_quorem_easy #1.#2\xintrevwithbraces#3#4.#5#6% +{% + {0/1[0]}{P#1.#3}% +}% +\def\POL_placemark_loop #1#2.% +{% + \xint_gob_til_minus#1\POL_placemark_loop_end-% + \expandafter\POL_placemark_step\the\numexpr#1#2-\xint_c_viii.% +}% +\def\POL_placemark_step #1.#2#3#4#5#6#7#8#9% +{% + {#2}{#3}{#4}{#5}{#6}{#7}{#8}{#9}\POL_placemark_loop#1.% +}% +\def\POL_placemark_loop_end-% + \expandafter\POL_placemark_step\the\numexpr-#1-\xint_c_viii.% +{% + \csname POL_placemark_end#1\endcsname +}% +\expandafter\def\csname POL_placemark_end1\endcsname + #1#2#3#4#5#6#7{{#1}{#2}{#3}{#4}{#5}{#6}{#7}\noexpand\xint_bye\xint:}% +\expandafter\def\csname POL_placemark_end2\endcsname + #1#2#3#4#5#6{{#1}{#2}{#3}{#4}{#5}{#6}\noexpand\xint_bye\xint:}% +\expandafter\def\csname POL_placemark_end3\endcsname + #1#2#3#4#5{{#1}{#2}{#3}{#4}{#5}\noexpand\xint_bye\xint:}% +\expandafter\def\csname POL_placemark_end4\endcsname + #1#2#3#4{{#1}{#2}{#3}{#4}\noexpand\xint_bye\xint:}% +\expandafter\def\csname POL_placemark_end5\endcsname + #1#2#3{{#1}{#2}{#3}\noexpand\xint_bye\xint:}% +\expandafter\def\csname POL_placemark_end6\endcsname + #1#2{{#1}{#2}\noexpand\xint_bye\xint:}% +\expandafter\def\csname POL_placemark_end7\endcsname + #1{{#1}\noexpand\xint_bye\xint:}% +\expandafter\def\csname POL_placemark_end8\endcsname + {\noexpand\xint_bye\xint:}% +\def\POL_quorem_b #1.#2#3\xint:#4#5\xint:#6% +{% +% \xintDiv FG computes F/G + \expandafter\POL_quorem_c\romannumeral0\xintdiv{\XINT_Opp#4}{#2}.% + #1.{#2}#3\xint: +% there is already \xint_Bye at ends of #3 + #3\xint_Bye\xint_Bye\xint_Bye + \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye +% this terminates the \expanded from \POL_apply:x_loop + \iffalse{\fi}% + \xint_bye\xint_bye\xint_bye\xint_bye\empty + #5\xint_bye\xint_bye\xint_bye\empty +% a \iffalse{\fi} will get inserted by \POL_add_A here + {#6}\xint_bye\xint: +}% +\def\POL_quorem_c #1.#2.#3\xint:% +{% + {\XINT_Opp#1}% + \expandafter\POL_quorem_d\the\numexpr#2-\xint_c_i\expandafter.% + \expanded\bgroup + \unexpanded{#3}\xint: + \expandafter\POL_add_A + \expanded\bgroup + \POL_apply:x_loop{\xintMul{#1}}% +}% +\def\POL_quorem_d #1#2.% +{% + \xint_gob_til_minus#1\POL_quorem_E-% + \POL_quorem_b #1#2.% +}% +\def\POL_quorem_E-\POL_quorem_b-1.#1\xint:#2\xint_bye\xint:#3.% +{% +% this terminates the \POL_quorem_a \expanded + \iffalse{\fi}\xint:#3.% +% recycling some termination code from addition + {\expandafter\POL_quorem_ERem_fix\expanded{\POL_add_d#2\xint_bye}}% +}% +\def\POL_quorem_ERem_fix #1% +{% + \if P#1\expandafter\POL_quorem_ERem_fix_a\fi 0/1[0]% +}% +\def\POL_quorem_ERem_fix_a 0/1[0]#1.#2% +{% + \ifcase #1 + \or + \expandafter\xint_firstofone + \else + P\the\numexpr#1-\xint_c_i.% + \fi +}% +\def\POL_quorem_EQuo#1\xint:#2.% +{% + {\ifnum#2=\xint_c_ + #1% + \else + P#2.\romannumeral0\XINT_revwbr_loop {}% + #1\xint:\xint:\xint:\xint:% + \xint:\xint:\xint:\xint:\xint_bye + \fi}% +}% +\def\xintPolPRem #1% +{% + \expanded\expandafter\POL_prem_in\romannumeral`&&@#1\xint: +}% +\def\POL_prem_in #1\xint:#2% +{% + \bgroup + \expandafter\POL_prem_fork + \romannumeral`&&@#2\xint:#1\xint: + \POL_prem_end +}% +\def\POL_prem_fork #1#2\xint:#3% +{% + \POL_PPfork + #1#3{\POL_prem_a}% both polynomials + #1P{\POL_prem_second_is_scalar}% -> scalar + #3P{\POL_prem_first_is_scalar}% -> zero + PP{\POL_prem_both_are_scalar}% -> zero + \krof #1#2\xint:#3% +}% +\def\POL_prem_first_is_scalar #1\xint:#2\xint:\POL_prem_end +{% + \iffalse{\fi}{1/1[0]}{0/1[0]}% +}% +\def\POL_prem_second_is_scalar #1\xint:#2\xint:\POL_prem_end +{% + \iffalse{\fi}{1/1[0]}{#2}% +}% +\def\POL_prem_both_are_scalar #1\xint:#2\xint:\POL_prem_end +{% + \iffalse{\fi}{1/1[0]}{0/1[0]}% +}% +\def\POL_prem_a P#1.#2\xint: P#3.#4\xint: +{% + \ifnum#1>#3 \xint_dothis{\POL_prem_easy #3.}\fi + \xint_orthat + {\expandafter\POL_prem_b\the\numexpr#3-#1\expandafter.% + \expanded\bgroup + \xintRevWithBraces + }% + {#2}% + \noexpand\xint_Bye + \xint: + \expandafter\POL_placeBye_loop + \the\numexpr#1-\xint_c_vii\expandafter.% + \romannumeral0\xintrevwithbraces{#4}% + {1/1[0]}% + \iffalse{\fi}% +}% +\def\POL_prem_easy #1.#2\xintrevwithbraces#3#4\POL_prem_end +{% + \iffalse{\fi}{1/1[0]}{P#1.#3}% +}% +\def\POL_placeBye_loop #1#2.% +{% + \xint_gob_til_minus#1\POL_placeBye_loop_end-% + \expandafter\POL_placeBye_step\the\numexpr#1#2-\xint_c_viii.% +}% +\def\POL_placeBye_step #1.#2#3#4#5#6#7#8#9% +{% + {#2}{#3}{#4}{#5}{#6}{#7}{#8}{#9}\POL_placeBye_loop#1.% +}% +\def\POL_placeBye_loop_end-% + \expandafter\POL_placeBye_step\the\numexpr-#1-\xint_c_viii.% +{% + \csname POL_placeBye_end#1\endcsname +}% +\expandafter\def\csname POL_placeBye_end1\endcsname + #1#2#3#4#5#6#7{{#1}{#2}{#3}{#4}{#5}{#6}{#7}\noexpand\xint_Bye\xint:{1}}% +\expandafter\def\csname POL_placeBye_end2\endcsname + #1#2#3#4#5#6{{#1}{#2}{#3}{#4}{#5}{#6}\noexpand\xint_Bye\xint:{1}}% +\expandafter\def\csname POL_placeBye_end3\endcsname + #1#2#3#4#5{{#1}{#2}{#3}{#4}{#5}\noexpand\xint_Bye\xint:{1}}% +\expandafter\def\csname POL_placeBye_end4\endcsname + #1#2#3#4{{#1}{#2}{#3}{#4}\noexpand\xint_Bye\xint:{1}}% +\expandafter\def\csname POL_placeBye_end5\endcsname + #1#2#3{{#1}{#2}{#3}\noexpand\xint_Bye\xint:{1}}% +\expandafter\def\csname POL_placeBye_end6\endcsname + #1#2{{#1}{#2}\noexpand\xint_Bye\xint:{1}}% +\expandafter\def\csname POL_placeBye_end7\endcsname + #1{{#1}\noexpand\xint_Bye\xint:{1}}% +\expandafter\def\csname POL_placeBye_end8\endcsname + {\noexpand\xint_Bye\xint:{1}}% +\def\POL_prem_b_skip#1#2\unexpanded#3#4#5\xint_Bye#6\xint:#7#8#9% +{% + \iffalse{\fi\expandafter}\xint_gobble_i#5#1% +}% +\def\POL_prem_b #1.#2#3\xint:#4#5\xint:#6#7% +{% + \expandafter\POL_prem_c\the\numexpr#1-\xint_c_i\expandafter.% + \expanded\bgroup + \unexpanded{{#2}#3}\xint: + \if0\XINT_Sgn#4\xint:\xint_afterfi + {\expandafter\POL_prem_b_skip\expandafter + {\expandafter{\romannumeral0\xintmul{#6}{#7}}\xint_Bye\xint:{#6}}% + }% + \fi + \expandafter\POL_add_A + \expanded\bgroup + \expanded{\noexpand\POL_apply:x_loop{\noexpand\xintMul + {\if1\XINT_Sgn#2\xint:\expandafter\XINT_Opp\fi#4}}}% +% there is already \xint_Bye at ends of #3 + #3\xint_Bye\xint_Bye\xint_Bye + \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye +% separator for \POL_add_A + \unexpanded{\xint_bye\xint_bye\xint_bye\xint_bye\empty}% +% there is already \xint_Bye at ends of #5 + \expanded{\noexpand\POL_apply:x_loop{\noexpand\xintMul{\XINT_Abs#2}}}% + #5\xint_Bye\xint_Bye\xint_Bye + \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye + \unexpanded{\xint_bye\xint_bye\xint_bye\xint_bye\empty}% +% a \iffalse{\fi} will get inserted by \POL_add_A exit routine and if will +% terminate the \expanded triggered here after \POL_prem_c +% what is next will have already have been expanded + {\xintMul{\xintMul{\XINT_Abs#2}{#6}}{#7}}\noexpand\xint_Bye\xint: + {\xintMul{\XINT_Abs#2}{#6}}% +% This terminates the \expanded following \POL_add_A + \iffalse{\fi}% +}% +\def\POL_prem_c #1% +{% + \xint_gob_til_minus#1\POL_prem_E_-\POL_prem_b#1% +}% +% attention that #2 here has a two dummies at end +% advantage is that \POL_add_a will always think it is non scalar +\def\POL_prem_E_-\POL_prem_b-1.#1\xint:#2\xint_Bye\xint:#3% +{% + \expandafter\POL_prem_E\expanded{\POL_add_d#2\xint_bye}% +}% +\def\POL_prem_E #1% +{% + \if P#1\expandafter\POL_prem_E_i + \else\expandafter\POL_prem_E_zero + \fi #1% +}% +\def\POL_prem_E_zero #1\POL_prem_end{\iffalse{\fi}{#1}{0/1[0]}}% +\def\POL_prem_E_i P#1.% +{% + \ifnum #1>\xint_c_i\POL_prem_E_ii#1.\fi + \POL_prem_E_iii% +}% +\def\POL_prem_E_iii#1\POL_prem_end{\iffalse{\fi}#1}% +\def\POL_prem_E_ii#1.#2\POL_prem_E_iii#3% + {#2{#3}{P\the\numexpr#1-\xint_c_i\iffalse}\fi.}% +\def\POL_prem_end{\iffalse{{\fi}}}% +%% +%% SUPPORT FOR FUNCTIONAL INTERFACE +%% +% should I do a qpol([]) ?, i.e. without testing for leading zeros, hence +% would be faster ? but advantage would arise only for very high degree +% pol([]) this one checks for zeros in the right most coeffs +\def\xintPolPol#1{\romannumeral`&&@\expandafter\POL_add_d + \romannumeral0\expandafter\XINT_revwbr_loop\expandafter + {\expandafter}% + \romannumeral`&&@#1\xint:\xint:\xint:\xint: + \xint:\xint:\xint:\xint:\xint_bye + \xint_bye +}% +% attention to not overwrite macro names (there is a legacy \PolEvalAt) +\def\xintPolEvalAt#1#2% +{% +% generally, #2 will be scalar, but we allow also a polynomial here +% should I test for #2 being the monomial, hence handle it very quickly? + \romannumeral`&&@\expandafter\POL_evalat_in\romannumeral`&&@#2\xint: + #1\xint:\xint:\xint:\xint: + \xint:\xint:\xint:\xint:\xint_bye\xint: +}% +\def\POL_evalat_in #1\xint: +{% + \expandafter\POL_evalat_fork\expanded{\unexpanded{#1\xint:}\expandafter}% + \romannumeral`&&@% +}% +\def\POL_evalat_fork #1\xint:#2% +{% + \POL_Pfork + #2{\POL_evalat_pol}% + P{\POL_evalat_cst}% + \krof #1\xint:#2% +}% +\def\POL_evalat_cst #1\xint: #2\xint:#3\xint_bye\xint:{#2}% +\def\POL_evalat_pol #1\xint: P#2.% +{% + \expanded{\unexpanded{\POL_evalat_a#1\xint:}\expandafter}% + \romannumeral0\XINT_revwbr_loop{}% +}% +\def\POL_evalat_a#1\xint:#2% +{% + \POL_evalat_loop#2\xint:#1\xint: +}% +\def\POL_evalat_loop#1\xint:#2\xint:#3% +{% + \xint_gob_til_xint:#3\POL_evalat_E\xint: +% I have dropped here my old strict \xintFoo = \romannumeral0\xintfoo style +% ATTENTION! We must allow evaluating at a polynomial expression + \expandafter\POL_evalat_loop + \romannumeral`&&@\xintPolAdd{#3}{\xintPolMul{#2}{#1}}\xint:#2\xint: +}% +\def\POL_evalat_E\xint:\expandafter\POL_evalat_loop + \romannumeral`&&@\xintPolAdd #1#2\xint:#3\xint: +{% + \xint_thirdofthree#2% +}% +% +\def\xintPolDeg#1% +{% + \romannumeral`&&@\expandafter\POL_deg_fork\romannumeral`&&@#1\xint: +}% +\def\POL_deg_fork #1% +{% + \POL_zeroPfork + #1P{\POL_deg_zero}% + 0#1{\POL_deg_pol}% + 0P{\POL_deg_cst}% + \krof #1% +}% +% usual hesitations about using or not raw frac format +\def\POL_deg_zero#1\xint:{-1}% +\def\POL_deg_cst #1\xint:{0}% +\def\POL_deg_pol P#1.#2\xint:{#1}% +% +\def\xintPolCoeffs#1% +{% + \romannumeral`&&@\expandafter\POL_coeffs_fork\romannumeral`&&@#1\xint: +}% +\def\POL_coeffs_fork #1% +{% + \POL_Pfork + #1\POL_coeffs_pol + P\POL_coeffs_cst + \krof #1% +}% +% usual hesitations about using or not raw frac format +\def\POL_coeffs_cst #1\xint:{{#1}}% +% no brace stripping possible, at least two coefficients +% annoying that we had to put this delimiter \xint: +\def\POL_coeffs_pol P#1.#2\xint:{#2}% +% +\def\xintPolCoeff#1#2% +{% + \romannumeral`&&@\expandafter\POL_coeff_fork + \the\numexpr\xintNum{#2}\expandafter.% + \romannumeral`&&@#1\xint: +}% +\def\POL_coeff_fork #1.#2% +{% + \POL_Pfork + #2\POL_coeff_pol + P\POL_coeff_cst + \krof #1.#2% +}% +\def\POL_coeff_cst#1% +{% + \xint_UDzerofork + #1\POL_coeff_itself + 0\POL_coeff_zero + \krof #1% +}% +\def\POL_coeff_itself#1.#2\xint:{#2}% +\def\POL_coeff_zero#1\xint:{0/1[0]}% +\def\POL_coeff_pol #1.P#2.% +{% + \ifnum#1<\xint_c_\xint_dothis\POL_coeff_zero\fi + \ifnum#1>#2 \xint_dothis\POL_coeff_zero\fi + \xint_orthat\POL_coeff_a{#1}% +}% +\def\POL_coeff_a#1{\expandafter\POL_coeff_b\romannumeral\xintgobble{#1}}% +\def\POL_coeff_b#1#2\xint:{#1}% +% +\def\xintPolLCoeff#1% +{% + \romannumeral`&&@\expandafter\POL_lcoeff_fork + \romannumeral`&&@#1\xint: +}% +\def\POL_lcoeff_fork #1% +{% + \POL_Pfork + #1\POL_lcoeff_pol + P\POL_lcoeff_cst + \krof #1% +}% +\def\POL_lcoeff_cst#1\xint:{#1}% +\def\POL_lcoeff_pol P#1.% +{% + \expandafter\POL_lcoeff_a\romannumeral\xintgobble{#1}% +}% +\def\POL_lcoeff_a#1\xint:{#1}% +% +\def\xintPolMonicPart#1% +{% + \romannumeral`&&@\expandafter\POL_monicpart_fork + \romannumeral`&&@#1\xint: +}% +\def\POL_monicpart_fork #1% +{% + \POL_Pfork + #1\POL_monicpart_pol + P\POL_monicpart_cst + \krof #1% +}% +% monicpart(0) must be 0 to avoid breaking algorithms +\def\POL_monicpart_cst#1#2\xint:{\if#10\xint_dothis0\fi\xint_orthat1/1[0]}% +\def\POL_monicpart_pol P#1.#2\xint:% +{% + \expanded{% + P#1.% + \expandafter\POL_monicpart_a\romannumeral\xintgobble{#1}% + #2#2\xint_Bye\xint_Bye\xint_Bye\xint_Bye + \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye + }% +}% +\def\POL@DivByFirstAndIrrAndREZ#1#2{\xintREZ{\xintIrr{\xintDiv{#2}{#1}}}}% +\def\POL_monicpart_a#1% +{% + \POL_apply:x_loop{\POL@DivByFirstAndIrrAndREZ{#1}}% +}% +% +\def\xintPolIContent#1% +{% + \romannumeral`&&@\expandafter\POL_icontent_fork + \romannumeral`&&@#1^% +}% +\def\POL_icontent_fork #1% +{% + \POL_Pfork + #1\POL_icontent_pol + P\POL_icontent_cst + \krof #1% +}% +\def\POL_icontent_cst #1^{\xintIrr{\xintAbs{#1}}[0]}% +\def\POL_icontent_pol P#1.% +{% +% 1.4d xintfrac \XINT_fgcdof much saner than 1.4 version ! +% \XINT_fgcd_out does \xintIrr + \expandafter\XINT_fgcd_out\romannumeral0\XINT_fgcdof +}% +% +\def\xintPolPrimPart#1% +{% + \romannumeral`&&@\expandafter\POL_primpart_fork + \romannumeral`&&@#1\xint: +}% +\def\POL_primpart_fork #1% +{% + \POL_Pfork + #1\POL_primpart_pol + P\POL_primpart_cst + \krof #1% +}% +\def\POL_primpart_cst#1#2\xint:{\if#10\xint_dothis0\fi\xint_orthat1/1[0]}% +\def\POL_primpart_pol P#1.#2\xint:% +{% + \expanded{% + P#1.\expandafter\POL_primpart_a + \romannumeral0\expandafter\XINT_fgcd_out + \romannumeral0\XINT_fgcdof#2^\xint: + #2\xint_Bye\xint_Bye\xint_Bye\xint_Bye + \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye + }% +}% +% cf legacy \POL@makeprim@macro +\def\POL@DivByFirstAndNumAndREZ#1#2{\xintREZ{\xintNum{\xintDiv{#2}{#1}}}}% +\def\POL_primpart_a#1\xint:{\POL_apply:x_loop{\POL@DivByFirstAndNumAndREZ{#1}}}% +% +\def\xintPolRedCoeffs#1% +{% + \romannumeral`&&@\expandafter\POL_redcoeffs_fork + \romannumeral`&&@#1\xint: +}% +\def\POL_redcoeffs_fork #1% +{% + \POL_Pfork + #1\POL_redcoeffs_pol + P\POL_redcoeffs_cst + \krof #1% +}% +\def\POL_redcoeffs_cst#1\xint:{\xintIrr{#1}[0]}% +\def\POL_redcoeffs_pol P#1.#2\xint:% +{% + \expanded{% + P#1.\POL_apply:x_loop\POL@xintIrr + #2\xint_Bye\xint_Bye\xint_Bye\xint_Bye + \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye + }% +}% +% +\def\xintPolSRedCoeffs#1% +{% + \romannumeral`&&@\expandafter\POL_sredcoeffs_fork + \romannumeral`&&@#1\xint: +}% +\def\POL_sredcoeffs_fork #1% +{% + \POL_Pfork + #1\POL_sredcoeffs_pol + P\POL_sredcoeffs_cst + \krof #1% +}% +\def\POL_sredcoeffs_cst#1\xint:{\xintREZ{\xintIrr{#1}[0]}}% +\def\POL_sredcoeffs_pol P#1.#2\xint:% +{% + \expanded{% + P#1.\POL_apply:x_loop\POL@xintIrrAndREZ + #2\xint_Bye\xint_Bye\xint_Bye\xint_Bye + \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye + }% +}% +\def\POL@xintIrrAndREZ#1{\xintREZ{\xintIrr{#1}[0]}}% +% +\def\xintPolDiffOne#1% +{% + \romannumeral`&&@\expandafter\POL_diffone_fork + \romannumeral`&&@#1\xint: +}% +\def\POL_diffone_fork #1% +{% + \POL_Pfork + #1\POL_diffone_pol + P\POL_diffone_cst + \krof #1% +}% +\def\POL_diffone_cst#1\xint:{0/1[0]}% +\def\POL_diffone_pol P#1.#2#3\xint:% +{% + \expanded{% + \ifnum#1=\xint_c_i #3% + \else + P\the\numexpr#1-\xint_c_i.% + \POL_apply:x_iloop{\POL_diffone_diff1.}% + #3\xint_Bye\xint_Bye\xint_Bye\xint_Bye + \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye + \fi + }% +}% +\def\POL_diffone_diff#1.#2#3{\xintMul{#1+#2}{#3}}% +% +\def\xintPolAntiOne#1% +{% + \romannumeral`&&@\expandafter\POL_antione_fork + \romannumeral`&&@#1\xint: +}% +\def\POL_antione_fork #1% +{% + \POL_Pfork + #1\POL_antione_pol + P\POL_antione_cst + \krof #1% +}% +\def\POL_antione_cst#1% +{% + \xint_gob_til_zero#1\POL_antione_zero0\POL_antione_cst_i#1% +}% +\def\POL_antione_cst_i#1\xint:{P1.{0/1[O]}{#1}}% +\def\POL_antione_zero#1\xint:{0/1[0]}% +\def\POL_antione_pol P#1.#2\xint:% +{% + \expanded{% + P\the\numexpr#1+\xint_c_i.{0/1[0]}% + \POL_apply:x_iloop{\POL_antione_anti1.}% + #2\xint_Bye\xint_Bye\xint_Bye\xint_Bye + \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye + }% +}% +\def\POL_antione_anti#1.#2#3{\xintDiv{#3}{#1+#2}}% +% +% #2 can be a polynomial +\def\xintPolIntFrom#1%#2% +{% + \romannumeral`&&@\expandafter\POL_intfrom_a\expandafter + {\romannumeral`&&@\xintPolAntiOne{#1}}% +}% +\def\POL_intfrom_a #1#2% +{% + \xintPolSub{#1}{\xintPolEvalAt{#1}{#2}}% +}% +% +\def\xintPolIntegral#1#2% +{% + \romannumeral`&&@\expandafter\POL_integral_a\expanded + {\xintPolAntiOne{#1}\xint:#2\xint:}% +}% +\def\POL_integral_a #1\xint:#2#3\xint: +{% + \xintPolSub{\xintPolEvalAt{#1}{#3}}{\xintPolEvalAt{#1}{#2}}% +}% +% +\def\xintPolDiffTwo#1% +{% + \romannumeral`&&@\expandafter\POL_difftwo_fork + \romannumeral`&&@#1\xint: +}% +\def\POL_difftwo_fork #1% +{% + \POL_Pfork + #1\POL_difftwo_pol + P\POL_difftwo_cst + \krof #1% +}% +\def\POL_difftwo_cst#1\xint:{0/1[0]}% +\def\POL_difftwo_pol P#1.% +{% + \ifcase #1 + \or \expandafter\POL_difftwo_zeroout + \or \expandafter\POL_difftwo_cstout + \else\expandafter\POL_difftwo_polout + \fi #1.% +}% +\def\POL_difftwo_zeroout#1\xint:{0/1[0]}% +\def\POL_difftwo_cstout 2.#1#2#3\xint:{\xintMul{2}{#3}}% +\def\POL_difftwo_polout #1.#2#3#4\xint:% +{% + \expanded{% + P\the\numexpr#1-\xint_c_ii.% + \POL_apply:x_iloop{\POL_difftwo_diff2.}% + #4\xint_Bye\xint_Bye\xint_Bye\xint_Bye + \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye + }% +}% +\def\POL_difftwo_diff#1.#2#3{\xintMul{\the\numexpr(#1+#2)*(#1+#2-\xint_c_i)\relax}{#3}}% +% +\def\POL_diffone_iter_fork #1% +{% + \POL_Pfork + #1\POL_diffone_iter_pol + P\POL_diffone_iter_cst + \krof #1% +}% +\def\POL_diffone_iter_cst#1\xint:{0/1[0]\xint:}% +\def\POL_diffone_iter_pol P#1.#2#3\xint:% +{% + \expanded{% + \ifnum#1=\xint_c_i #3% + \else + P\the\numexpr#1-\xint_c_i.% + \POL_apply:x_iloop{\POL_diffone_diff1.}% + #3\xint_Bye\xint_Bye\xint_Bye\xint_Bye + \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye + \fi + }\xint: +}% +% +\def\POL_antione_iter_fork #1% +{% + \POL_Pfork + #1\POL_antione_iter_pol + P\POL_antione_iter_cst + \krof #1% +}% +\def\POL_antione_iter_cst#1% +{% + \xint_gob_til_zero#1\POL_antione_iter_zero0\POL_antione_iter_cst_i#1% +}% +\def\POL_antione_iter_cst_i#1\xint:{P1.{0/1[O]}{#1}\xint:}% +\def\POL_antione_iter_zero#1\xint:{0/1[0]\xint:}% +\def\POL_antione_iter_pol P#1.#2\xint:% +{% + \expanded{% + P\the\numexpr#1+\xint_c_i.{0/1[0]}% + \POL_apply:x_iloop{\POL_antione_anti1.}% + #2\xint_Bye\xint_Bye\xint_Bye\xint_Bye + \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye + }\xint: +}% +% +\def\xintPolDiffN#1#2% +{% + \romannumeral`&&@\expandafter\POL_diffn_fork + \the\numexpr\xintNum{#2}\expandafter.% + \romannumeral`&&@#1\xint: +}% +\def\POL_diffn_fork #1% +{% + \xint_UDzerominusfork + #1-\POL_diffn_none + 0#1\POL_diffn_anti + 0-\POL_diffn_diff + \krof #1% +}% +\def\POL_diffn_none0.#1\xint:{#1}% +\def\POL_diffn_diff#1.%#2\xint:% +{% + \ifnum#1>\xint_c_i + \expandafter\POL_diffn_diff\the\numexpr#1-\xint_c_i\expandafter.% + \romannumeral`&&@\expandafter\POL_diffone_iter_fork + \else + \expandafter\POL_diffone_fork + \fi +}% +\def\POL_diffn_anti#1.%#2\xint:% +{% + \ifnum#1<-\xint_c_i + \expandafter\POL_diffn_anti\the\numexpr#1+\xint_c_i\expandafter.% + \romannumeral`&&@\expandafter\POL_antione_iter_fork + \else + \expandafter\POL_antione_fork + \fi +}% +% +% Support for (multi-variable) polgcd +% +\def\xintPolGCDof #1% +{% + \romannumeral`&&@\expandafter\POL_polgcdof\romannumeral`&&@#1^% +}% +\def\XINT_PolGCDof{\romannumeral`&&@\POL_polgcdof}% +\def\POL_polgcdof #1% +{% + \romannumeral`&&@\expandafter + \POL_polgcdof_chkempty\romannumeral`&&@#1\xint: +}% +\def\POL_polgcdof_chkempty #1% +{% + \xint_gob_til_^#1\POL_polgcdof_empty ^\POL_polgcdof_in #1% +}% +\def\POL_polgcdof_empty #1\xint:{1/1[0]}% hesitation +\def\POL_polgcdof_in #1\xint: +{% + \expandafter\POL_polgcdof_loop + \romannumeral`&&@\xintPolPrimPart{#1}\xint: +}% +\def\POL_polgcdof_loop #1\xint:#2% +{% + \expandafter\POL_polgcdof_chkend\romannumeral`&&@#2\xint:#1\xint:\xint: +}% +\def\POL_polgcdof_chkend #1% +{% + \xint_gob_til_^#1\POL_polgcdof_end ^\POL_polgcdof_loop_pair #1% +}% +% hesitation with returning a monic polynomial +%\def\POL_polgcdof_end #1\xint:#2\xint:\xint:{\xintPolMonicPart{#2}}% +\def\POL_polgcdof_end #1\xint:#2\xint:\xint:{#2}% +\def\POL_polgcdof_loop_pair #1\xint: +{% + \expandafter\POL_polgcdof_loop + \romannumeral`&&@\expandafter\POL_polgcd_pair + \romannumeral`&&@\xintPolPrimPart{#1}\xint: +}% +% MEMO comme le #2 sera au début le pgcd accumulé il sera souvent de plus +% petit degré donc il y aura souvent un premier mod "easy" un peu inutile +% J'hésite à faire une permutation avant de lancer le polgcd_pair +\def\POL_polgcd_pair#1\xint:#2\xint: +{% + \xintiiifSgn {\xintPolDeg {#1}}% + {#2}% + {1}% + {\expandafter\POL_polgcd_pair + \romannumeral`&&@\xintPolPrimPart + {\expandafter\xint_secondoftwo + \romannumeral`&&@\xintPolPRem {#2}{#1}}\xint: + #1\xint: + }% +}% +% +\endinput |