% author: Jean-François Burnol
% License: LPPL 1.3c (author-maintained)
\ProvidesPackage{polexpr}%
  [2018/01/18 v0.3.1 Polynomial expressions with rational coefficients (JFB)]%
\RequirePackage{xintexpr}[2016/03/19]% xint 1.2g (or 1.2c 2015/11/16 at least)
\edef\POL@restorecatcodes
    {\catcode`\noexpand\_ \the\catcode`\_ \catcode0 \the\catcode0\relax}%
\catcode`\_ 11 \catcode0 12

%% AUXILIARIES
\newif\ifPOL@pol % (cf core algebra macros)
%% the main exchange structure (stored in macros \POLuserpol@<name>)
%% is: degree.\empty{coeff0}{coeff1}....{coeffN}
%% (degree=N except zero polynomial recognized from degree set to -1
%%  but it has always the {0/1[0]} coeff0.)
\def\POL@ifZero#1{\expandafter\POL@ifZero@aux#1;}%
\def\POL@ifZero@aux #1#2;{\if-#1\expandafter\xint_firstoftwo
                             \else\expandafter\xint_secondoftwo
                          \fi}%
\def\POL@split#1.#2;#3#4% separates degree and list of coefficients
% The \empty token is to avoid brace removal issues for degree 0 polynomials
   {\def#3{#1}\expandafter\def\expandafter#4\expandafter{#2}}%
%
\def\POL@resultfromarray #1{% ATTENTION, **MUST** be executed with
% \count@ set to 1 + degree (thus \count@ = 0 for zero polynomial)
    \edef\POL@result{%
      \the\numexpr\count@-\@ne.\noexpand\empty
      \xintiloop [1+1]%
% always done at least once with index 1, hence ok for zero polynomial
      \expandafter\POL@braceit\csname POL@array#1\xintiloopindex\endcsname
      \ifnum\xintiloopindex<\count@
      \repeat}%
}%
\def\POL@braceit#1{{#1}}% needed as \xintiloopindex can not "see" through braces


\newif\ifxintveryverbose
\newcommand\PolDef[3][x]{\poldef #2(#1):=#3;}%
\def\poldef{\edef\POL@restoresemicolon{\catcode59=\the\catcode59\relax}%
                \catcode59 12 \POL@defpol}%
\def\POL@defpol #1(#2)#3=#4;{%
   \POL@restoresemicolon
   \let\POL@original_redefinemacros\XINT_expr_redefinemacros
   \let\XINT_expr_redefinemacros\POL@redefinemacros
   \edef\POL@tmp{\ifxintverbose1\else0\fi}%
   \unless\ifxintveryverbose\xintverbosefalse\fi
   \xintdeffunc __pol(#2):=#4;\if1\POL@tmp\xintverbosetrue\fi
   \let\XINT_expr_redefinemacros\POL@original_redefinemacros
   \edef\POL@polname{\xint_zapspaces #1 \xint_gobble_i}%
   \begingroup
     \setbox0\hbox{%
     \let\xintScalarAdd\xintAdd
     \let\XINT_fadd_C\POL_fadd_C % patch Add to use l.c.m.
     \let\xintScalarSub\xintSub
     \let\xintScalarMul\xintMul
     \let\xintScalarDiv\xintDiv
     \let\xintScalarPow\xintPow
     \let\xintScalarOpp\xintOpp
     \let\xintAdd\POL@add
     \let\xintMul\POL@mul
     \let\xintDiv\POL@div
     \let\xintPow\POL@pow
     \let\xintOpp\POL@opp
     \def\xintSub ##1##2{\xintAdd{##1}{\xintOpp{##2}}}%
     % \xintAdd to get \POL@result defined even if numerical only expression
     \xintAdd{0}%
       {\csname XINT_expr_userfunc___pol\endcsname
% comma delimited from xintexpr at 1.2p or earlier. Might change.
        {\global\POL@poltrue\def\POL@result{1.\empty{0/1[0]}{1/1[0]}}},}%
     \expandafter}\expandafter
   \endgroup\expandafter
   \def\csname POLuserpol@\POL@polname\expandafter\endcsname
        \expandafter{\POL@result}%
   \expandafter\POL@newpol\expandafter{\POL@polname}%
}%
%%
\def\POL@newpol#1{%
   \expandafter\POL@ifZero\csname POLuserpol@#1\endcsname
      {\@namedef{XINT_expr_userfunc_#1}##1,{0/1[0]}%
       \@namedef{XINT_flexpr_userfunc_#1}##1,{0[0]}}%
      {\POL@newpolhorner{#1}}%
   \unless\ifcsname XINT_expr_userfuncNE:#1\endcsname\POL@addtoextras{#1}\fi
   \expandafter\XINT_expr_defuserfunc
     \csname XINT_expr_func_#1\expandafter\endcsname
     \csname XINT_expr_userfunc_#1\endcsname
   \expandafter\XINT_expr_defuserfunc
     \csname XINT_flexpr_func_#1\expandafter\endcsname
     \csname XINT_flexpr_userfunc_#1\endcsname
   \ifxintverbose\POL@info{#1}\fi
}%
\def\POL@info #1{%
   \xintMessage {polexpr}{Info}%
        {Function #1 for the \string\xintexpr\space parser is
         associated to \string\XINT_expr_userfunc_#1\space
         whose meaning uses Horner scheme:
         \expandafter\meaning
         \csname XINT_expr_userfunc_#1\endcsname^^J%
         \@spaces And \string\XINT_flexpr_userfunc_#1\space for
         the \string\xintfloatexpr\space parser has meaning
         \expandafter\meaning
         \csname XINT_flexpr_userfunc_#1\endcsname}%
}%
%
\def\POL@newpolhorner#1{%
   %% redefine function to expand by Horner scheme. Is this useful?
   %% perhaps bad idea for numerical evaluation of thing such as (1+x)^10?
% note: I added {0/1[0]} item to zero polynomial also to facilitate this
   \expandafter\expandafter\expandafter\POL@split
      \csname POLuserpol@#1\endcsname;\POL@var@deg\POL@var@coeffs
   \edef\POL@var@coeffs{\xintRevWithBraces{\POL@var@coeffs}}%
   \begingroup
      \expandafter\POL@newpol@horner\POL@var@coeffs\relax
   \expandafter
   \endgroup
   \expandafter\def\csname XINT_expr_userfunc_#1\expandafter\endcsname
      \expandafter##\expandafter1\expandafter,\expandafter{\POL@tmp{##1}}%
   \begingroup
      \expandafter\POL@newpol@floathorner\POL@var@coeffs\relax
   \expandafter
   \endgroup
   \expandafter\def\csname XINT_flexpr_userfunc_#1\expandafter\endcsname
      \expandafter##\expandafter1\expandafter,\expandafter{\POL@tmp{##1}}%
}%
\def\POL@newpol@horner#1{\let\xintAdd\relax\let\xintMul\relax
                  \def\POL@tmp##1{#1}\POL@newpol@horner@loop.}%
\def\POL@newpol@horner@loop.#1{%
  \if\relax#1\expandafter\xint_gob_til_dot\fi
  \edef\POL@tmp##1{\xintiiifZero{#1}
                    {\@firstofone}{\xintAdd{#1}}%
                    {\xintMul{##1}{\POL@tmp{##1}}}}%
  \POL@newpol@horner@loop.%
}%
\def\POL@newpol@floathorner#1{\let\XINTinFloatAdd\relax\let\XINTinFloatMul\relax
                  \def\xintAdd{\XINTinFloatAdd}\def\xintMul{\XINTinFloatMul}%
                  \edef\POL@tmp##1{\XINTinFloatdigits{#1}}%
                  \POL@newpol@floathorner@loop.}%
\def\POL@newpol@floathorner@loop.#1{%
  \if\relax#1\expandafter\xint_gob_til_dot\fi
  \edef\POL@tmp##1{\xintiiifZero{#1}
                    {\@firstofone}{\xintAdd{\XINTinFloatdigits{#1}}}%
                    {\xintMul{##1}{\POL@tmp{##1}}}}%
  \POL@newpol@floathorner@loop.%
}%
%% Customizes xintexpr.sty's \XINT_NewExpr (\POL@addtoextras{name})
\begingroup
\catcode`~ 12
\catcode`$ 12 % $
\catcode`! 11
\gdef\POL@NEfork_one #1#2!#3#4{%
    \if ###1\xint_dothis {\POL__settopol{#4}}\fi
    \if  ~#1\xint_dothis {\POL__userfunc{#4}}\fi
    \if  $#1\xint_dothis {~xintApply::csv{~POL_userfunc{#4}}}\fi %$
    \xint_orthat {#3}#1#2\endcsname
}%
\gdef\POL@@redefineone #1#2#3{% #3 = name
    % Used for immediate f(numerical)
    \let#2#1%
    % \XINT_expr_userfunc_name
    \def#1##1\endcsname % key trick is to fetch up to \endcsname!
      {\expandafter\POL@NEfork_one\romannumeral`^^@##1!#2{#3}}%
}%
    % Used when f(x) is encountered: great gain here!
\gdef\POL__settopol#1#2,{~POL_settopol{#1}}%
\gdef\POL_settopol#1{\global\POL@poltrue\expandafter\let\expandafter
                     \POL@result\csname POLuserpol@#1\endcsname}%
    % Used when argument is neither numerical nor a macro parameter
    % Quite some magic here! (braces couldn't be used this way in \xintexpr)
\gdef\POL__userfunc#1#2,\endcsname{~POL_userfunc{#1}{#2},\endcsname}%
\gdef\POL_userfunc#1{\csname XINT_expr_userfunc_#1\endcsname}%
\endgroup
\def\POL@addtoextras#1{%
    \oodef\POL@redefineextras{\expandafter\POL@redefineextras
      \expandafter\POL@@redefineone
      \csname XINT_expr_userfunc_#1\expandafter\endcsname
      \csname XINT_expr_userfuncNE:#1\endcsname{#1}}%
}%
%\let\POL@original@redefinemacros\XINT_expr_redefinemacros % do locally
\def\POL@redefinemacros{\POL@original_redefinemacros\POL@redefineextras}%
\let\POL@redefineextras\@empty
%
\newcommand\PolLet[2]{\if=\noexpand#2\expandafter\xint_firstoftwo
                      \else\expandafter\xint_secondoftwo\fi
                      \POL@@let\POL@let {#1}{#2}}%
\def\POL@@let#1#2#3{\POL@let{#1}{#3}}%
\def\POL@let#1#2{%
    \expandafter\let\csname POLuserpol@#1\expandafter\endcsname
                    \csname POLuserpol@#2\endcsname
    \unless\ifcsname XINT_expr_userfuncNE:#1\endcsname\POL@addtoextras{#1}\fi
    \expandafter\let\csname XINT_expr_userfunc_#1\expandafter\endcsname
                    \csname XINT_expr_userfunc_#2\endcsname
    \expandafter\let\csname XINT_flexpr_userfunc_#1\expandafter\endcsname
                    \csname XINT_flexpr_userfunc_#2\endcsname
    \expandafter\XINT_expr_defuserfunc
       \csname XINT_expr_func_#1\expandafter\endcsname
       \csname XINT_expr_userfunc_#1\endcsname
    \expandafter\XINT_expr_defuserfunc
       \csname XINT_flexpr_func_#1\expandafter\endcsname
       \csname XINT_flexpr_userfunc_#1\endcsname
    \ifxintverbose\POL@info{#1}\fi
}%


\newcommand\PolAssign[1]{\def\POL@polname{#1}\POL@assign}% zap spaces in #1?
\def\POL@assign#1\toarray#2{%
    \expandafter\expandafter\expandafter\POL@split
    \csname POLuserpol@\POL@polname\endcsname;\POL@var@deg\POL@var@coeffs
    \xintAssignArray\POL@var@coeffs\to#2%
    % modify \#200 macro to return 0/1[0] for out of range indices
    \@namedef{\xint_arrayname00}##1##2##3{%
    \@namedef{\xint_arrayname00}####1{%
        \ifnum####1>##1 \xint_dothis{ 0/1[0]}\fi
        \ifnum####1>\m@ne \xint_dothis
                {\expandafter\expandafter\expandafter##3%
                 \csname##2####1\endcsname}\fi
        \unless\ifnum-####1>##1 \xint_dothis
                {\expandafter\expandafter\expandafter##3%
                 \csname##2\the\numexpr##1+####1+\@ne\endcsname}\fi
        \xint_orthat{ 0/1[0]}}% space stops a \romannumeral0
    }%
    \csname\xint_arrayname00\expandafter\expandafter\expandafter\endcsname
      \expandafter\expandafter\expandafter
      {\csname\xint_arrayname0\expandafter\endcsname\expandafter}\expandafter
      {\xint_arrayname}{ }%
}%


\newcommand\PolGet[1]{\def\POL@polname{#1}% zap spaces in #1?
    \begingroup  % closed in \POL@getfrom
    \POL@getfrom}% 
% attention au name clash proche avec \POL@get auxiliaire de \POL@add etc..
\def\POL@getfrom#1\fromarray#2{%
        \count@#2{0} % must be > 0, else could create infinite loop
        % \ifnum\count@>\z@\else\InvalidArrayError_PolGet\fi
        \xintloop
          \edef\POL@tmp{#2{\count@}}%
          \xintiiifZero{\POL@tmp}%
            {\iftrue}%
            {\iffalse}%
        \advance\count@\m@ne
        \repeat
% should I use \xintRaw ? but if #2 expands only in an \edef, problem
% (but it is not very probable the #2 macro does not already give completely
% expanded contents), I would need to proceed in two steps. Or the \xintRaw
% could get injected at level of \POL@newpol
        \def\POL@tmp##1.{{#2{##1}}}%
        \edef\POL@result{\the\numexpr\count@-\@ne.\noexpand\empty
                         \xintiloop[1+1]%
                         \expandafter\POL@tmp\xintiloopindex.%
                         \ifnum\xintiloopindex<\count@
                         \repeat}%
    \expandafter
    \endgroup
    \expandafter
    \def\csname POLuserpol@\POL@polname\expandafter\endcsname
        \expandafter{\POL@result}%
    \expandafter\POL@newpol\expandafter{\POL@polname}%
}%


\newcommand\PolFromCSV[2]{\def\POL@polname{#1}%
    \begingroup % closed in \POL@getfrom
    \xintAssignArray\xintCSVtoList{#2}\to\POL@arrayA
    \POL@getfrom\fromarray\POL@arrayA
% semble un peu indirect et sous-optimal
% mais je veux élaguer les coefficients nuls. Peut-être à revoir.
}%


\newif\ifpoltypesetall
\newcommand\PolTypesetCmdPrefix[1]{\xintiiifSgn{#1}{}{+}{+}}%
\newcommand\PolTypesetCmd[1]{\xintifOne{\xintiiAbs{#1}}%
                               {\ifnum\PolIndex=\z@\xintiiSgn{#1}\else
                                \xintiiifSgn{#1}{-}{}{}\fi}%
                               {\xintSignedFrac{#1}}}%
\newcommand\PolTypesetMonomialCmd{%
  \ifcase\PolIndex\space
  %
  \or\PolVar
  \else\PolVar^{\PolIndex}%
  \fi
}%
\newcommand\PolTypeset{\@ifstar
  {\def\POL@ts@ascending{1}\POL@Typeset}%
  {\def\POL@ts@ascending{0}\POL@Typeset}%
}%
\newcommand\POL@Typeset[2][x]{% LaTeX \newcommand forces optional argument first
   \ensuremath{%
        \expandafter\expandafter\expandafter\POL@split
        \csname POLuserpol@#2\endcsname;\POL@var@deg\POL@var@coeffs
        \if\POL@ts@ascending1%
           \def\PolIndex{0}%
           \let\POL@ts@reverse\@firstofone
           \let\POL@@ne@or@m@ne\@ne
        \else
           \let\PolIndex\POL@var@deg
           \ifnum\PolIndex<\z@\def\PolIndex{0}\fi
           \let\POL@ts@reverse\xintRevWithBraces
           \let\POL@@ne@or@m@ne\m@ne
        \fi
        \def\PolVar{#1}%
        \ifnum\POL@var@deg<\z@
            \PolTypesetCmd{0/1[0]}\PolTypesetMonomialCmd
        \else
         \ifnum\POL@var@deg=\z@
           \expandafter\PolTypesetCmd\POL@var@coeffs\PolTypesetMonomialCmd
         \else
           \def\POL@ts@prefix##1{\let\POL@ts@prefix\PolTypesetCmdPrefix}%
           \expandafter\POL@ts@loop
              \romannumeral-`0\POL@ts@reverse{\POL@var@coeffs}\relax
         \fi
        \fi
   }%
}%
\def\POL@ts@loop{\ifpoltypesetall\expandafter\xint_firstoftwo
                 \else\expandafter\xint_secondoftwo\fi
    {\POL@ts@nocheck}{\POL@ts@check}.%
}%
\def\POL@ts@check.#1{%
  \if\relax#1\expandafter\xint_gob_til_dot\fi
  \xintiiifZero{#1}%
      {}%
      {\POL@ts@prefix{#1}\PolTypesetCmd{#1}\PolTypesetMonomialCmd}%
  \edef\PolIndex{\the\numexpr\PolIndex+\POL@@ne@or@m@ne}\POL@ts@check.%
}%
\def\POL@ts@nocheck.#1{%
  \if\relax#1\expandafter\xint_gob_til_dot\fi
  \POL@ts@prefix{#1}\PolTypesetCmd{#1}\PolTypesetMonomialCmd
  \edef\PolIndex{\the\numexpr\PolIndex+\POL@@ne@or@m@ne}\POL@ts@nocheck.%
}%


\newcommand\PolMapCoeffs[2]{% #1 = macro, #2 = name
    \begingroup
       \def\POL@map@macro{#1}%
       \expandafter\expandafter\expandafter\POL@split
         \csname POLuserpol@#2\endcsname;\POL@var@deg\POL@var@coeffs
% attention à ne pas faire un \expandafter ici, car brace removal si 1 item
       \xintAssignArray\POL@var@coeffs\to\POL@arrayA
       \def\index{0}%
       \count@\z@
       \expandafter\POL@map@loop\expandafter.\POL@var@coeffs\relax
       \xintloop
% this abuses that \POL@arrayA0 is never 0.
       \xintiiifZero{\csname POL@arrayA\the\count@\endcsname}%
         {\iftrue}%
         {\iffalse}%
       \advance\count@\m@ne
       \repeat
% donc en sortie \count@ est 0 ssi pol nul.
       \POL@resultfromarray A%
     \expandafter
    \endgroup
    \expandafter
    \def\csname POLuserpol@#2\expandafter\endcsname\expandafter{\POL@result}%
    \POL@newpol{#2}%
}%
\def\POL@map@loop.#1{\if\relax#1\expandafter\xint_gob_til_dot\fi
    \advance\count@\@ne
    \edef\POL@map@coeff{\POL@map@macro{#1}}%
    \expandafter
    \let\csname POL@arrayA\the\count@\endcsname\POL@map@coeff
    \edef\index{\the\numexpr\index+\@ne}%
    \POL@map@loop.}%
\def\POL@xintIrr#1{\xintIrr{#1}[0]}%
\newcommand\PolReduceCoeffs[1]{\PolMapCoeffs{\POL@xintIrr}{#1}}%


%% EUCLIDEAN DIVISION
\newcommand\PolDivide[4]{% #3=quotient, #4=remainder of #1 by #2
    \begingroup
      \let\xintScalarSub\xintSub
      \let\XINT_fadd_C\POL_fadd_C
      \let\xintScalarMul\xintMul
      \let\xintScalarDiv\xintDiv
      \expandafter\let\expandafter\POL@A\csname POLuserpol@#1\endcsname
      \expandafter\let\expandafter\POL@B\csname POLuserpol@#2\endcsname
      \POL@div@c
      \let\POL@Q\POL@result
      \ifnum\POL@degQ<\z@
          \let\POL@R\POL@A
      \else
        \count@\numexpr\POL@degR+\@ne\relax
        \POL@resultfromarray R%
        \let\POL@R\POL@result
      \fi
    \expandafter
    \endgroup
    \expandafter
    \def\csname POLuserpol@#3\expandafter\expandafter\expandafter\endcsname
        \expandafter\expandafter\expandafter{\expandafter\POL@Q\expandafter}%
        \expandafter
    \def\csname POLuserpol@#4\expandafter\endcsname\expandafter{\POL@R}%
    \POL@newpol{#3}%
    \POL@newpol{#4}%
}%


%% GCD
\newcommand\PolGCD[3]{% sets #3 to the (unitary) G.C.D. of #1 and #2
    \begingroup
      \let\xintScalarSub\xintSub
      \let\XINT_fadd_C\POL_fadd_C
      \let\xintScalarMul\xintMul
      \let\xintScalarDiv\xintDiv
      \expandafter\let\expandafter\POL@A\csname POLuserpol@#1\endcsname
      \expandafter\let\expandafter\POL@B\csname POLuserpol@#2\endcsname
      \expandafter\POL@split\POL@A;\POL@degA\POL@polA
      \expandafter\POL@split\POL@B;\POL@degB\POL@polB
      \ifnum\POL@degA<\z@
        \expandafter\xint_firstoftwo\else\expandafter\xint_secondoftwo
      \fi
        {\ifnum\POL@degB<\z@
          \expandafter\xint_firstoftwo\else\expandafter\xint_secondoftwo
        \fi
          {\def\POL@result{-1.\empty{0/1[0]}}}%
          {\xintAssignArray\POL@polB\to\POL@arrayB
           \POL@normalize{B}%
           \POL@gcd@exit BA}}%
        {\ifnum\POL@degB<\z@
          \expandafter\xint_firstoftwo\else\expandafter\xint_secondoftwo
        \fi
          {\xintAssignArray\POL@polA\to\POL@arrayA
           \POL@normalize{A}%
           \POL@gcd@exit AB}%
          {\ifnum\POL@degA<\POL@degB\space
             \let\POL@tmp\POL@B\let\POL@B\POL@A\let\POL@A\POL@tmp
             \let\POL@tmp\POL@degB\let\POL@degB\POL@degA\let\POL@degA\POL@degB
           \fi
           \xintAssignArray\POL@polA\to\POL@arrayA
           \xintAssignArray\POL@polB\to\POL@arrayB
           \POL@gcd AB%
           }}%
    \expandafter
    \endgroup
    \expandafter\def\csname POLuserpol@#3\expandafter\endcsname
        \expandafter{\POL@result}%
    \POL@newpol{#3}%
}%
\def\POL@normalize#1{%
    \expandafter\def\expandafter\POL@tmp\expandafter
        {\csname POL@array#1\csname POL@array#10\endcsname\endcsname}%
    \edef\POL@normalize@leading{\POL@tmp}%
    \expandafter\def\POL@tmp{1/1[0]}%
    \count@\csname POL@deg#1\endcsname\space
    \xintloop
    \ifnum\count@>\z@
      \expandafter\edef\csname POL@array#1\the\count@\endcsname
      {\xintIrr{\xintScalarDiv
                   {\csname POL@array#1\the\count@\endcsname}%
                   {\POL@normalize@leading}}[0]}%
    \advance\count@\m@ne
    \repeat
}%                     
\def\POL@gcd#1#2{%
    \POL@normalize{#2}%
    \edef\POL@degQ{\the\numexpr\csname POL@deg#1\endcsname
                              -\csname POL@deg#2\endcsname}%
    \count@\numexpr\csname POL@deg#1\endcsname+\@ne\relax
    \count\tw@\numexpr\POL@degQ+\@ne\relax
    \xintloop
      \POL@gcd@getremainder@loopbody#1#2%
    \ifnum\count\tw@>\z@
    \repeat
    \expandafter\def\csname POL@array#10\endcsname{1}%
    \xintloop
    \xintiiifZero{\csname POL@array#1\the\count@\endcsname}%
      {\iftrue}%
      {\iffalse}%
    \advance\count@\m@ne
    \repeat
    \expandafter\edef\csname POL@deg#1\endcsname{\the\numexpr\count@-\@ne}%
    \ifnum\count@<\@ne
      \expandafter\POL@gcd@exit
    \else
      \expandafter\edef\csname POL@array#10\endcsname{\the\count@}%
      \expandafter\POL@gcd
    \fi{#2}{#1}%
}%
\def\POL@gcd@getremainder@loopbody#1#2{%
  \edef\POL@gcd@ratio{\csname POL@array#1\the\count@\endcsname}%
  \advance\count@\m@ne
  \advance\count\tw@\m@ne
  \count4 \count@
  \count6 \csname POL@deg#2\endcsname\space
  \xintloop
  \ifnum\count6>\z@
    \expandafter\edef\csname POL@array#1\the\count4\endcsname
      {\xintScalarSub
          {\csname POL@array#1\the\count4\endcsname}%
          {\xintScalarMul
            {\POL@gcd@ratio}%
            {\csname POL@array#2\the\count6\endcsname}}}%
    \advance\count4 \m@ne
    \advance\count6 \m@ne
  \repeat
}%
\def\POL@gcd@exit#1#2{%
    \count@\numexpr\csname POL@deg#1\endcsname+\@ne\relax
    \POL@resultfromarray #1%
}%
                 

%% TODO: BEZOUT


%% DIFFERENTIATION
\def\POL@diff@loop@one #1/#2[#3]#4%
  {\xintIrr{\xintiiMul{#4}{#1}/#2[0]}[#3]}%
\def\POL@diff#1{\POL@diff@loop1.}%
\def\POL@diff@loop#1.#2{%
  \if\relax#2\expandafter\xint_gob_til_dot\fi
  {\expandafter\POL@diff@loop@one\romannumeral0\xintraw{#2}{#1}}%
  \expandafter\POL@diff@loop\the\numexpr#1+\@ne.%
}%
\newcommand\PolDiff[1][1]{%
   % optional parameter is how many times to derivate
   % first mandatory arg is name of polynomial function to derivate,
   % same name as in \NewPolExpr
   % second mandatory arg name of derivative
   \edef\POL@iterindex{\the\numexpr#1\relax}%
   \ifnum\POL@iterindex<\z@
       \expandafter\@firstoftwo
   \else
       \expandafter\@secondoftwo
   \fi
   {\PolAntiDiff[-\POL@iterindex]}{\POL@Diff}%
}%
\def\POL@Diff{%
   \ifcase\POL@iterindex\space
      \expandafter\POL@Diff@no
   \or\expandafter\POL@Diff@one
   \else\xint_afterfi{\POL@Iterate\POL@Diff@one}%
   \fi
}%
\def\POL@Diff@no #1#2{\POL@let{#2}{#1}}%
\def\POL@Diff@one #1#2{%
   \expandafter\expandafter\expandafter\POL@split
      \csname POLuserpol@#1\endcsname;\POL@var@deg\POL@var@coeffs
   \ifnum\POL@var@deg<\@ne
      \@namedef{POLuserpol@#2}{-1.\empty{0/1[0]}}%
   \else
     \edef\POL@var@coeffs{\expandafter\POL@diff\POL@var@coeffs\relax}%
     \expandafter\edef\csname POLuserpol@#2\endcsname
        {\the\numexpr\POL@var@deg-\@ne.\noexpand\empty\POL@var@coeffs}%
   \fi
   \POL@newpol{#2}%
}%
% lazy way but allows to share with AntiDiff
\def\POL@Iterate#1#2#3{%
    \begingroup
    \xintverbosefalse
        #1{#2}{#3}%
        \xintloop
        \ifnum\POL@iterindex>\tw@
          #1{#3}{#3}%
          \edef\POL@iterindex{\the\numexpr\POL@iterindex-\@ne}%
        \repeat
   \expandafter
   \endgroup\expandafter
   \def\csname POLuserpol@#3\expandafter\endcsname
       \expandafter{\romannumeral`^^@\csname POLuserpol@#3\endcsname}%
   #1{#3}{#3}%
}%


%% ANTI-DIFFERENTIATION
\def\POL@antidiff@loop@one #1/#2[#3]#4%
  {\xintIrr{#1/\xintiiMul{#4}{#2}[0]}[#3]}%
\def\POL@antidiff{\POL@antidiff@loop1.}%
\def\POL@antidiff@loop#1.#2{%
  \if\relax#2\expandafter\xint_gob_til_dot\fi
  {\expandafter\POL@antidiff@loop@one\romannumeral0\xintraw{#2}{#1}}%
  \expandafter\POL@antidiff@loop\the\numexpr#1+\@ne.%
}%
\newcommand\PolAntiDiff[1][1]{%
   % optional parameter is how many times to derivate
   % first mandatory arg is name of polynomial function to derivate,
   % same name as in \NewPolExpr
   % second mandatory arg name of derivative
   \edef\POL@iterindex{\the\numexpr#1\relax}%
   \ifnum\POL@iterindex<\z@
       \expandafter\@firstoftwo
   \else
       \expandafter\@secondoftwo
   \fi
   {\PolDiff[-\POL@iterindex]}{\POL@AntiDiff}%
}%
\def\POL@AntiDiff{%
   \ifcase\POL@iterindex\space
      \expandafter\POL@AntiDiff@no
   \or\expandafter\POL@AntiDiff@one
   \else\xint_afterfi{\POL@Iterate\POL@AntiDiff@one}%
   \fi
}%
\let\POL@AntiDiff@no\POL@Diff@no
\def\POL@AntiDiff@one #1#2{%
   \expandafter\expandafter\expandafter\POL@split
      \csname POLuserpol@#1\endcsname;\POL@var@deg\POL@var@coeffs
   \ifnum\POL@var@deg<\z@
      \@namedef{POLuserpol@#2}{-1.\empty{0/1[0]}}%
   \else
     \edef\POL@var@coeffs{\expandafter\POL@antidiff\POL@var@coeffs\relax}%
     \expandafter\edef\csname POLuserpol@#2\endcsname
         {\the\numexpr\POL@var@deg+\@ne.\noexpand\empty{0/1[0]}\POL@var@coeffs}%
   \fi
   \POL@newpol{#2}%
}%


%% CORE ALGEBRA MACROS
%% We do this non-expandably, but in a nestable way... this is the whole
%% point because \xintdeffunc as used by \poldef creates a big nested macro.
%% The idea is to execute it with another meaning given to \xintAdd etc..,
%% so that it operates on "polynomials". This is a mixture of expandable
%% and non-expandable techniques.
\def\POL@get#1#2#3{%
    \global\POL@polfalse
    \begingroup
        \def\POL@result{#3}%
        #3%
        \expandafter
    \endgroup
    \expandafter\def\expandafter#1\expandafter{\POL@result}%
    \unless\ifPOL@pol
        % avoid expanding more than twice #3
        \edef#1{#3}%
        \xintiiifZero{#1}%
            {\def#1{-1.\empty{0/1[0]}}}%
            {\edef#1{0.\noexpand\empty{#1}}}%
    \fi
    #2%
}%
%% ADDITION
\def\POL@add  {\POL@get\POL@A\POL@add@b}%
\def\POL@add@b{\POL@get\POL@B\POL@add@c}%
\def\POL@add@c{%
    \global\POL@poltrue
    \POL@ifZero\POL@A 
        {\let\POL@result\POL@B}%
        {\POL@ifZero\POL@B
             {\let\POL@result\POL@A}%
             {\POL@@add}}%
}%
\def\POL@@add{%
  \expandafter\POL@split\POL@A;\POL@degA\POL@polA
  \expandafter\POL@split\POL@B;\POL@degB\POL@polB
  \ifnum\POL@degA>\POL@degB\relax
    \xintAssignArray\POL@polA\to\POL@arrayA
    \xintAssignArray\POL@polB\to\POL@arrayB
  \else
    \xintAssignArray\POL@polB\to\POL@arrayA
    \xintAssignArray\POL@polA\to\POL@arrayB
    \let\POL@tmp\POL@degB\let\POL@degB\POL@degA\let\POL@degA\POL@tmp
  \fi
  \count@\z@
  \xintloop
     \advance\count@\@ne
     \expandafter\edef\csname POL@arrayA\the\count@\endcsname
          {\xintScalarAdd{\@nameuse{POL@arrayA\the\count@}}%
                         {\@nameuse{POL@arrayB\the\count@}}}%
  \unless\ifnum\POL@degB<\count@
  \repeat
  \count@\@nameuse{POL@arrayA0} % 1+\POL@degA
  % trim zero leading coefficients (we could check for equal degrees,
  % but would not bring much as anyhow loop exists immediately if not)
  \xintloop
   % this abuses that \POL@arrayA0 is never zero
   \xintiiifZero{\@nameuse{POL@arrayA\the\count@}}%
      {\iftrue}%
      {\iffalse}%
  \advance\count@\m@ne
  \repeat
  \POL@resultfromarray A% attention that \POL@arrayA0 not updated
}%

%% MULTIPLICATION
\def\POL@mul  {\POL@get\POL@A\POL@mul@b}%
\def\POL@mul@b{\POL@get\POL@B\POL@mul@c}%
\def\POL@mul@c{%
    \global\POL@poltrue
    \POL@ifZero\POL@A 
        {\def\POL@result{-1.\empty{0/1[0]}}}%
        {\POL@ifZero\POL@B
             {\def\POL@result{-1.\empty{0/1[0]}}}%
             {\POL@@mul}}%
}%
\def\POL@@mul{%
  \expandafter\POL@split\POL@A;\POL@degA\POL@polA
  \expandafter\POL@split\POL@B;\POL@degB\POL@polB
  \ifnum\POL@degA>\POL@degB\relax
    \xintAssignArray\POL@polA\to\POL@arrayA
    \xintAssignArray\POL@polB\to\POL@arrayB
  \else
    \xintAssignArray\POL@polB\to\POL@arrayA
    \xintAssignArray\POL@polA\to\POL@arrayB
    \let\POL@tmp\POL@degB
    \let\POL@degB\POL@degA
    \let\POL@degA\POL@tmp
  \fi
  \count@\z@
  \xintloop
    \POL@@mul@phaseIloopbody
  \unless\ifnum\POL@degB<\count@
  \repeat
  \xintloop
  \unless\ifnum\POL@degA<\count@ % car attention au cas de mêmes degrés
    \POL@@mul@phaseIIloopbody
  \repeat
  \edef\POL@degC{\the\numexpr\POL@degA+\POL@degB}%
  \xintloop
  \unless\ifnum\POL@degC<\count@
    \POL@@mul@phaseIIIloopbody
  \repeat
  %\count@\the\numexpr\POL@degC+\@ne\relax % never zero polynomial here
  \POL@resultfromarray C%
}%
\def\POL@@mul@phaseIloopbody{%
    \advance\count@\@ne
    \def\POL@tmp{0[0]}%
    \count\tw@\z@
    \xintloop
       \advance\count\tw@\@ne
       \edef\POL@tmp{%
         \xintScalarAdd
           {\POL@tmp}%
           {\xintScalarMul
             {\@nameuse{POL@arrayA\the\count\tw@}}%
             {\@nameuse{POL@arrayB\the\numexpr\count@+\@ne-\count\tw@}}%
           }%
          }%
    \ifnum\count\tw@<\count@
    \repeat
    \expandafter\let\csname POL@arrayC\the\count@\endcsname\POL@tmp
}%  
\def\POL@@mul@phaseIIloopbody{%
    \advance\count@\@ne
    \def\POL@tmp{0[0]}%
    \count\tw@\count@
    \advance\count\tw@-\@nameuse{POL@arrayB0} %
    \xintloop
    \ifnum\count\tw@<\count@
      \advance\count\tw@\@ne
      \edef\POL@tmp{%
        \xintScalarAdd
          {\POL@tmp}%
          {\xintScalarMul
            {\@nameuse{POL@arrayA\the\count\tw@}}%
            {\@nameuse{POL@arrayB\the\numexpr\count@+\@ne-\count\tw@}}%
          }%
         }%
    \repeat 
    \expandafter\let\csname POL@arrayC\the\count@\endcsname\POL@tmp
}%
\def\POL@@mul@phaseIIIloopbody{%
    \advance\count@\@ne
    \def\POL@tmp{0[0]}%
    \count\tw@\count@
    \advance\count\tw@-\@nameuse{POL@arrayB0} %
    \xintloop
      \advance\count\tw@\@ne
      \edef\POL@tmp{%
        \xintScalarAdd{\POL@tmp}%
          {\xintScalarMul
            {\@nameuse{POL@arrayA\the\count\tw@}}%
            {\@nameuse{POL@arrayB\the\numexpr\count@+\@ne-\count\tw@}}%
          }%
         }%
    \ifnum\@nameuse{POL@arrayA0}>\count\tw@
    \repeat 
    \expandafter\let\csname POL@arrayC\the\count@\endcsname\POL@tmp
}%

%% POWERS (SCALAR EXPONENT...)
\def\POL@pow #1#2{%
    \global\POL@polfalse
    \begingroup
        \def\POL@result{#1}%
        #1%
        \expandafter
    \endgroup
    \expandafter\def\expandafter\POL@A\expandafter{\POL@result}%
    \unless\ifPOL@pol
        \edef\POL@A{\xintScalarPow{#1}{#2}}% no error check
        \xintiiifZero{\POL@A}%
            {\def\POL@result{-1.\empty{0/1[0]}}}%
            {\edef\POL@result{0.\noexpand\empty{\POL@A}}}%
    \else
      \edef\POL@B{\numexpr\xintNum{#2}\relax}% no check on exponent >= 0
      \ifcase\POL@B
        \def\POL@result{0.\empty{1/1[0]}}%
      \or
        \let\POL@result\POL@A
      \else
        \POL@@pow@check
      \fi
    \fi
    \global\POL@poltrue
}%
\def\POL@@pow@check {%
% no problem here with leftover tokens!
% should I have used that I-don't-care technique more elsewhere?
    \ifnum\@ne>\POL@A
    % polynomial is a constant, must get rid of dot and \empty
        \edef\POL@A{\expandafter\xintScalarPow\romannumeral`^^@%
                    \expandafter\xint_gob_til_dot\POL@A{\POL@B}}%
        \xintiiifZero{\POL@A}%
            {\def\POL@result{-1.\empty{0/1[0]}}}%
            {\edef\POL@result{0.\noexpand\empty{\POL@A}}}%
    \else
    \ifnum\@ne=\POL@A
    % perhaps a constant times X, check constant term
        \xintiiifZero
        {\expandafter\xint_firstoftwo\romannumeral`^^@%
         \expandafter\xint_gob_til_dot\POL@A}
        {\edef\POL@result
          {\the\POL@B.% here at least 2.
           \noexpand\empty
           \romannumeral\xintreplicate{\POL@B}{{0/1[0]}}%
           {\xintScalarPow
             {\expandafter\xint_secondoftwo\romannumeral`^^@%
              \expandafter\xint_gob_til_dot\POL@A}%
             {\POL@B}}}}%
        {\POL@@pow}% not constant times X, use general recursion
    \else
        \POL@@pow% general recursion
    \fi\fi
}%
\def\POL@@pow@recurse#1#2{%
    \begingroup
        #1%
        \expandafter
    \endgroup
    \expandafter\def\expandafter\POL@A\expandafter{\POL@result}%
    \edef\POL@B{\numexpr\xintNum{#2}\relax}%
    \ifcase\POL@B
        \POL@thisshouldneverhappen
    \or
        \let\POL@result\POL@A
    \else
        \expandafter\POL@@pow
    \fi
}%
\def\POL@@pow {%
    \let\POL@pow@exp\POL@B
    \let\POL@B\POL@A
    \POL@@mul
    \let\POL@sqA\POL@result
    \ifodd\POL@pow@exp\space
       \expandafter\POL@@pow@odd
          \the\numexpr(\POL@pow@exp+\@ne)/\tw@-\@ne\expandafter.%
    \else 
       \expandafter\POL@@pow@even
          \the\numexpr(\POL@pow@exp+\@ne)/\tw@-\@ne\expandafter.%
    \fi
}%
\def\POL@@pow@even#1.{%
    \expandafter\POL@@pow@recurse\expandafter
       {\expandafter\def\expandafter\POL@result\expandafter{\POL@sqA}}%
       {#1}%
}%
\def\POL@@pow@odd#1.{%
    \expandafter\POL@@pow@odd@i\expandafter{\POL@A}{#1}%
}%
\def\POL@@pow@odd@i #1#2{%
    \expandafter\POL@@pow@recurse\expandafter
       {\expandafter\def\expandafter\POL@result\expandafter{\POL@sqA}}%
       {#2}%
    \expandafter\POL@mul\expandafter
        {\expandafter\def\expandafter\POL@result\expandafter
         {\POL@result}\global\POL@poltrue}%
        {\def\POL@result{#1}\global\POL@poltrue}%
}%

%% DIVISION
%% no check on divisor being non-zero
\def\POL@div  {\POL@get\POL@A\POL@div@b}%
\def\POL@div@b{\POL@get\POL@B\POL@div@c}%
\def\POL@div@c{%
    \global\POL@poltrue
    \expandafter\POL@split\POL@A;\POL@degA\POL@polA
    \expandafter\POL@split\POL@B;\POL@degB\POL@polB
    \ifnum\POL@degA<\POL@degB\space
       \@namedef{POL@arrayQ1}{0/1[0]}%
       \def\POL@degQ{-1}%
    \else
       \xintAssignArray\POL@polA\to\POL@arrayR
       \xintAssignArray\POL@polB\to\POL@arrayB
       \POL@@div
    \fi
    \count@\numexpr\POL@degQ+\@ne\relax
    \POL@resultfromarray Q%
}%
\def\POL@@div{%
    \xintAssignArray\POL@polA\to\POL@arrayR
    \xintAssignArray\POL@polB\to\POL@arrayB
    \edef\POL@B@leading{\csname POL@arrayB\the\numexpr\POL@degB+\@ne\endcsname}%
    \edef\POL@degQ{\the\numexpr\POL@degA-\POL@degB}%
    \count@\numexpr\POL@degA+\@ne\relax
    \count\tw@\numexpr\POL@degQ+\@ne\relax
    \xintloop
      \POL@@div@loopbody
    \ifnum\count\tw@>\z@
    \repeat
    %%\expandafter\def\csname POL@arrayR0\endcsname{1}%
    \xintloop
    \xintiiifZero{\csname POL@arrayR\the\count@\endcsname}%
      {\iftrue}%
      {\iffalse}%
    \advance\count@\m@ne
    \repeat
    \edef\POL@degR{\the\numexpr\count@-\@ne}%
}%
\def\POL@@div@loopbody{%
    \edef\POL@@div@ratio{%
          \xintScalarDiv{\csname POL@arrayR\the\count@\endcsname}%
                        {\POL@B@leading}}%
    \expandafter\let\csname POL@arrayQ\the\count\tw@\endcsname
          \POL@@div@ratio  
    \advance\count@\m@ne
    \advance\count\tw@\m@ne
    \count4 \count@
    \count6 \POL@degB\space
    \xintloop
    \ifnum\count6>\z@
      \expandafter\edef\csname POL@arrayR\the\count4\endcsname
        {\xintScalarSub
            {\csname POL@arrayR\the\count4\endcsname}%
            {\xintScalarMul
              {\POL@@div@ratio}%
              {\csname POL@arrayB\the\count6\endcsname}}}%
      \advance\count4 \m@ne
      \advance\count6 \m@ne
    \repeat
}%

%% MINUS SIGN AS UNARY OPERATOR
\def\POL@opp #1{%
    \global\POL@polfalse
    \begingroup
        \def\POL@result{#1}%
        #1%
        \expandafter
    \endgroup
    \expandafter\def\expandafter\POL@A\expandafter{\POL@result}%
    \unless\ifPOL@pol
        \edef\POL@A{\xintScalarOpp{#1}}%
        \xintiiifZero{\POL@A}%
            {\def\POL@result{-1.\empty{0/1[0]}}}%
            {\edef\POL@result{0.\noexpand\empty{\POL@A}}}%
    \else
      \edef\POL@B{0.\noexpand\empty{-1/1[0]}}%
      \POL@@mul
    \fi
    \global\POL@poltrue
}%


%% EXPANDABLE MACROS
\newcommand\PolEval{}%
\def\PolEval#1#2\At#3{\romannumeral`^^@\xinttheexpr #1(#3)\relax}%
%
\newcommand\PolEvalReduced{}%
\def\PolEvalReduced#1#2\At#3{%
    \romannumeral0\xintpraw % only serves to not print denominator if = 1
    {\xintIrr{\romannumeral`^^@\xintthebareeval#1(#3)\relax}[0]}%
}%
%
\newcommand\PolFloatEval{}%
\def\PolFloatEval#1#2\At#3{\romannumeral`^^@\xintthefloatexpr #1(#3)\relax}%
%
\newcommand\PolNthCoeff[2]{\romannumeral`^^@%
    \expandafter\POL@nthcoeff
    \romannumeral0\xintnthelt{\ifnum\numexpr#2<\z@#2\else(#2)+1\fi}%
                  {\expandafter\expandafter\expandafter
                        \xint_gob_til_dot\csname POLuserpol@#1\endcsname}@%
}%
\def\POL@nthcoeff#1@{\if @#1@\expandafter\xint_firstoftwo
                  \else\expandafter\xint_secondoftwo\fi
                  {0/1[0]}{#1}}%
%
% returns -1 for zero polynomial for context of numerical expression
% should it return -\infty?
\newcommand\PolDegree[1]{\romannumeral`^^@\expandafter\expandafter\expandafter
                         \POL@degree\csname POLuserpol@#1\endcsname;}%
\def\POL@degree #1.#2;{#1}%
%
\newcommand\PolToList[1]{\romannumeral`^^@\expandafter\expandafter\expandafter
                         \xint_gob_til_dot\csname POLuserpol@#1\endcsname}%
%
\newcommand\PolToCSV[1]{\romannumeral0\xintlistwithsep{, }{\PolToList{#1}}}%


\newif\ifpoltoexprall
\newcommand\PolToExprCmd[1]{\xintPRaw{\xintRawWithZeros{#1}}}%
\newcommand\PolToFloatExprCmd[1]{\xintFloat{#1}}%
\let\PolToExprTermPrefix\PolTypesetCmdPrefix
\newcommand\PolToExprOneTerm[2]{%
    \ifnum#2=\z@
      \PolToExprCmd{#1}%
    \else
      \xintifOne{\xintiiAbs{#1}}
        {\xintiiifSgn{#1}{-}{}{}}% + from \PolToExprTermPrefix
        {\PolToExprCmd{#1}\PolToExprTimes}%
    \fi
    \ifcase\xintiiAbs{#2} %<-- space here mandatory
         \or\PolToExprVar
       \else\PolToExprVar^\xintiiAbs{#2}%
    \fi
}%
\newcommand\PolToExprOneTermStyleB[2]{%
    \ifnum#2=\z@
      \xintNumerator{#1}%
    \else
      \xintifOne{\xintiiAbs{\xintNumerator{#1}}}
        {\xintiiifSgn{#1}{-}{}{}}% + from \PolToExprTermPrefix
        {\xintNumerator{#1}\PolToExprTimes}%
    \fi
    \ifcase\xintiiAbs{#2} %<-- space here mandatory
         \or\PolToExprVar
       \else\PolToExprVar^\xintiiAbs{#2}%
    \fi
    \xintiiifOne{\xintDenominator{#1}}{}{/\xintDenominator{#1}}%
}%
\newcommand\PolToFloatExprOneTerm[2]{%
    \ifnum#2=\z@
      \PolToFloatExprCmd{#1}%
    \else
      \PolToFloatExprCmd{#1}\PolToExprTimes
    \fi
    \ifcase\xintiiAbs{#2} %<-- space here mandatory
         \or\PolToExprVar
       \else\PolToExprVar^\xintiiAbs{#2}%
    \fi
}%
\newcommand\PolToExprTimes{*}%
\newcommand\PolToExprVar{x}%
\newcommand\PolToExpr[1]{%
    \if*\noexpand#1\expandafter\xint_firstoftwo\else
    \expandafter\xint_secondoftwo\fi
    \PolToExprAscending\PolToExprDescending{#1}}%
\newcommand\PolToFloatExpr[1]{%
    \if*\noexpand#1\expandafter\xint_firstoftwo\else
    \expandafter\xint_secondoftwo\fi
    \PolToFloatExprAscending\PolToFloatExprDescending{#1}}%
\newcommand\PolToExprAscending[2]{%
   \expandafter\POL@toexpr\csname POLuserpol@#2\endcsname
   \PolToExprOneTerm\POL@toexprA}%
\newcommand\PolToFloatExprAscending[2]{%
   \expandafter\POL@toexpr\csname POLuserpol@#2\endcsname
   \PolToFloatExprOneTerm\POL@toexprA}%
\newcommand\PolToExprDescending[1]{%
   \expandafter\POL@toexpr\csname POLuserpol@#1\endcsname
   \PolToExprOneTerm\POL@toexprD}%
\newcommand\PolToFloatExprDescending[1]{%
   \expandafter\POL@toexpr\csname POLuserpol@#1\endcsname
   \PolToFloatExprOneTerm\POL@toexprD}%
%
\def\POL@toexpr#1#2#3{\expandafter\POL@toexpr@
                      \expandafter#3\expandafter#2#1\relax}%
\def\POL@toexpr@#1#2#3.{%
    \ifnum#3<\z@
       #2{0/1[0]}{0}\expandafter\xint_gobble_v
    \else
       \expandafter#1%
    \fi {#3}#2}%
%
\def\POL@toexprA #1#2\empty#3{%
    \ifpoltoexprall\expandafter\POL@toexprall@b
              \else\expandafter\POL@toexpr@b
    \fi {#3}#2{0}1.%
}%
\def\POL@toexprD #1#2#3\relax{% #3 has \empty to prevent brace removal
    \expandafter\POL@toexprD@a\expandafter#2%
    \the\numexpr #1\expandafter.\romannumeral0\xintrevwithbraces{#3}\relax
}%
\def\POL@toexprD@a #1#2.#3{%
    \ifpoltoexprall\expandafter\POL@toexprall@b
              \else\expandafter\POL@toexpr@b
    \fi{#3}#1{-#2}\the\numexpr\@ne+-#2.%
}%
\def\POL@toexpr@b #1#2#3{%
    \xintiiifZero{#1}%
      {\expandafter\POL@toexpr@loop\expandafter\POL@toexpr@b}%
      {#2{#1}{#3}%
      \expandafter\POL@toexpr@loop\expandafter\POL@toexpr@c}%
   \expandafter#2%
}%
\def\POL@toexpr@c #1#2#3{%
    \xintiiifZero{#1}%
      {}%
      {\PolToExprTermPrefix{#1}#2{#1}{#3}}%
    \expandafter\POL@toexpr@loop\expandafter\POL@toexpr@c
    \expandafter#2%
}%
\def\POL@toexprall@b #1#2#3{%
    #2{#1}{#3}%
    \expandafter\POL@toexpr@loop\expandafter\POL@toexprall@c
    \expandafter#2%
}%
\def\POL@toexprall@c #1#2#3{%
    \PolToExprTermPrefix{#1}#2{#1}{#3}%
    \expandafter\POL@toexpr@loop\expandafter\POL@toexprall@c
    \expandafter#2%
}%
\def\POL@toexpr@loop#1#2#3.#4{%
  \if\relax#4\expandafter\xint_gob_til_dot\fi
  #1{#4}#2{#3}\the\numexpr\@ne+#3.%
}%


%% Patch of xintfrac.sty's \xintAdd: for a/b + c/d, use lcm(b,d)
\RequirePackage{xintgcd}
\def\POL_fadd_C #1#2#3%
{%
   \expandafter\POL_fadd_D
      \romannumeral0\xintiigcd{#2}{#3}.%
   {#2}{#3}{#1}%
}%
\def\POL_fadd_D #1.#2#3%
{%
    \expandafter\POL_fadd_E
       \romannumeral0\xintiiquo{#3}{#1}.%
       {\romannumeral0\xintiiquo{#2}{#1}}{#2}{#3}%
}%
\def\POL_fadd_E #1.#2#3#4#5%
{%
    \expandafter\POL_fadd_F\romannumeral0\xintiimul{#1}{#3}.{#2}%
                               {\xintiiMul{#1}{#5}}%
}%
\def\POL_fadd_F #1.#2#3#4%
{%
    \expandafter\POL_fadd_G
    \romannumeral0\xintiiadd{#3}{\xintiiMul{#2}{#4}}/#1%
}%
\def\POL_fadd_G #1{%
\def\POL_fadd_G ##1{\if0##1\expandafter\XINT_fadd_iszero\fi#1##1}%
}\POL_fadd_G{ }%

\POL@restorecatcodes
\endinput
