%% filename: polexprcore.tex %% Part of the polexpr package (0.8.7a, 2022/05/19) %% %% Core routines for infix operators +, -, *, //, /:, ^, ** and functions %% %% Memo: the atoms representing polynomials inside \xintexpr are %% - for constants: a numeric value (indistinguishable. from scalars) %% - for degree at least 1: P.{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 % arrgggh, 0.8 had +#1 in place of +#2... again I did not test enough \expandafter{\expandafter#1\the\numexpr\xint_c_viii+#2.}% }% %% %% 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\romannumeral0\xintraw{#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_aa}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 {% \XINT_signalcondition{InvalidOperation}% {Not supported: polynomial to negative power #1}{}{1/1[0]}% }% \def\POL_pow_aa #1.{\expandafter\POL_pow_a\the\numexpr\xintNum{#1}.}% \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 }% % 0.8.1 adds \xintPolLPol. Not much to do... as long as I don't worry about % empty input... (not motivated about this, there are other such places) \def\xintPolLPol#1{\romannumeral`&&@\expandafter\POL_add_d \romannumeral`&&@#1\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\xintPolLCoeffs#1% {% \romannumeral`&&@\expandafter\POL_lcoeffs_fork \romannumeral`&&@#1\xint:\xint:\xint:\xint:% \xint:\xint:\xint:\xint:\xint_bye }% \def\POL_lcoeffs_fork #1% {% \POL_Pfork #1\POL_lcoeffs_pol P\POL_lcoeffs_cst \krof #1% }% \def\POL_lcoeffs_cst #1\xint:#2\xint_bye{{#1}}% \def\POL_lcoeffs_pol P#1.{\XINT_revwbr_loop {}}% % \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\xintPolLC#1% {% \romannumeral`&&@\expandafter\POL_lc_fork \romannumeral`&&@#1\xint: }% \def\POL_lc_fork #1% {% \POL_Pfork #1\POL_lc_pol P\POL_lc_cst \krof #1% }% \def\POL_lc_cst#1\xint:{#1}% \def\POL_lc_pol P#1.% {% \expandafter\POL_lc_a\romannumeral\xintgobble{#1}% }% \def\POL_lc_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\xintPolCont#1% {% \romannumeral`&&@\expandafter\POL_cont_fork \romannumeral`&&@#1^% }% \def\POL_cont_fork #1% {% \POL_Pfork #1\POL_cont_pol P\POL_cont_cst \krof #1% }% \def\POL_cont_cst #1^{\xintIrr{\xintAbs{#1}}[0]}% \def\POL_cont_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