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