summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2021-04-10 21:13:16 +0000
committerKarl Berry <karl@freefriends.org>2021-04-10 21:13:16 +0000
commitf83ae24524b685073a4bd225d9a814e1b5850daf (patch)
treeb75236a60f69657356a312a2cb911cce756819ee /Master/texmf-dist/tex
parent89f4f0573f09dfd63100d90c8d80d1da160e3550 (diff)
polexpr (now generic)
git-svn-id: svn://tug.org/texlive/trunk@58821 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex')
-rw-r--r--Master/texmf-dist/tex/generic/polexpr/polexpr.sty1057
-rw-r--r--Master/texmf-dist/tex/generic/polexpr/polexprcore.tex1366
-rw-r--r--Master/texmf-dist/tex/generic/polexpr/polexprexpr.tex179
-rw-r--r--Master/texmf-dist/tex/generic/polexpr/polexprsturm.tex (renamed from Master/texmf-dist/tex/latex/polexpr/polexpr.sty)1813
4 files changed, 2814 insertions, 1601 deletions
diff --git a/Master/texmf-dist/tex/generic/polexpr/polexpr.sty b/Master/texmf-dist/tex/generic/polexpr/polexpr.sty
new file mode 100644
index 00000000000..c94a4e8d61d
--- /dev/null
+++ b/Master/texmf-dist/tex/generic/polexpr/polexpr.sty
@@ -0,0 +1,1057 @@
+% author: Jean-François Burnol
+% License: LPPL 1.3c (author-maintained)
+% Usage: \input polexpr.sty (Plain or other macro formats)
+% or \usepackage{polexpr} (LaTeX macro format)
+% polexpr.sty (this file) inputs:
+% polexprcore.tex
+% polexprexpr.tex
+% polexprsturm.tex
+\begingroup\catcode61\catcode48\catcode32=10\relax%
+ \catcode13=5 % ^^M
+ \endlinechar=13 %
+ \catcode123=1 % {
+ \catcode125=2 % }
+ \catcode64=11 % @
+ \catcode35=6 % #
+ \catcode44=12 % ,
+ \catcode45=12 % -
+ \catcode46=12 % .
+ \catcode58=12 % :
+ \def\z {\endgroup}%
+ \expandafter\let\expandafter\x\csname ver@polexpr.sty\endcsname
+ \expandafter\let\expandafter\w\csname ver@xintexpr.sty\endcsname
+ \expandafter
+ \ifx\csname PackageInfo\endcsname\relax
+ \def\y#1#2{\immediate\write-1{Package #1 Info: #2.}}%
+ \else
+ \def\y#1#2{\PackageInfo{#1}{#2}}%
+ \fi
+ \expandafter
+ % I don't think engine exists providing \expanded but not \numexpr
+ \ifx\csname expanded\endcsname\relax
+ \y{polexpr}{\expanded not available, aborting input}%
+ \aftergroup\endinput
+ \else
+ \ifx\x\relax % plain-TeX, first loading of polexpr.sty
+ \ifx\w\relax % but xintexpr.sty not yet loaded.
+ \expandafter\def\expandafter\z\expandafter
+ {\z\input xintexpr.sty\relax}%
+ \fi
+ \else
+ \def\empty {}%
+ \ifx\x\empty % LaTeX, first loading,
+ % variable is initialized, but \ProvidesPackage not yet seen
+ \ifx\w\relax % xintexpr.sty not yet loaded.
+ \expandafter\def\expandafter\z\expandafter
+ {\z\RequirePackage{xintexpr}[2021/02/20]}%
+ \fi
+ \else
+ \aftergroup\endinput % polexpr already loaded.
+ \fi
+ \fi
+ \fi
+\z%
+\XINTsetupcatcodes%
+\XINT_providespackage
+\ProvidesPackage{polexpr}%
+ [2021/03/29 v0.8 Polynomial expressions with rational coefficients (JFB)]%
+\begingroup
+ \def\x#1/#2/#3 #4\xint:{#1#2#3}%
+ \ifnum\expandafter\x\expanded{\csname ver@xintexpr.sty\endcsname}\xint:
+ <20210220 % actually 20200131 (xint 1.4) is presumably ok
+ \immediate\write128{! Package polexpr error: xintexpr too old, aborting input}%
+ \else\expandafter\xint_gobble_i
+ \fi
+\endinput\endgroup
+\let\PolDecToString\xintDecToString
+\long\def\POL@ifstar#1#2%
+{%
+ \begingroup\def\@tempa{#1}\def\@tempb{#2}%
+ \futurelet\@let@token\POL@@ifstar
+}%
+\def\POL@@ifstar
+{%
+ \xint_firstofone{\ifx} \@let@token\def\next{\POL@@again\POL@@ifstar}\else
+ \ifx*\@let@token\def\next##1{\expandafter\endgroup\@tempa}\else
+ \def\next{\expandafter\endgroup\@tempb}\fi\fi\next
+}%
+\xint_firstofone{\def\POL@@again#1} {\futurelet\@let@token#1}%
+\long\def\POL@chkopt#1[#2]%
+{%
+ \begingroup\def\@tempa{#1}\def\@tempb{#1[#2]}%
+ \futurelet\@let@token\POL@@ifopt
+}%
+\def\POL@@ifopt
+{%
+ \xint_firstofone{\ifx} \@let@token\def\next{\POL@@again\POL@@ifopt}\else
+ \ifx[\@let@token\def\next{\expandafter\endgroup\@tempa}\else %]
+ \def\next{\expandafter\endgroup\@tempb}\fi\fi\next
+}%
+% \polexprsetup added at 0.7
+\catcode`! 3
+\def\polexprsetup#1{\POL@setup_parsekeys #1,=!,\xint_bye}%
+\def\POL@setup_parsekeys #1=#2#3,{%
+ \ifx!#2\expandafter\xint_bye\fi
+ \csname POL@setup_setkey_\xint_zapspaces #1 \xint_gobble_i\endcsname
+ \xint_firstoftwo
+ {\PackageWarning{polexpr}{The \detokenize{#1} key is unknown! ignoring}}%
+ {\xintZapLastSpaces{#2#3}}%
+ \POL@setup_parsekeys
+}%
+\def\POL@setup_setkey_norr #1#2{\edef\POL@norr}%
+\def\POL@setup_setkey_sqfnorr #1#2{\edef\POL@sqfnorr}%
+\polexprsetup{norr=_norr, sqfnorr=_sqf_norr}
+\catcode`! 11 % special catcode for ! as used in xintexpr.sty
+%
+\newif\ifxintveryverbose
+\newif\ifpolnewpolverbose
+\newif\ifpoltypesetall
+\newif\ifpoltoexprall
+%%
+%% Main data format for non-expandable manipulations
+%%
+%% The main exchange structure is:
+%% N.\empty{coeff0}{coeff1}....{coeffN}
+%% It is stored in macros \POLuserpol@<name of polynomial>
+%% The \empty is basically there to avoid brace-stripping
+%% in some grabbing contexts (maybe I should revisit this)
+%%
+%% The zero polynomial is stored as -1.\empty{0/1[0]}
+%% Degree zero polynomials are 0.\empty{numeric value}
+%%
+%% Depending on input path the numeric values coeff0, coeff1, ...., coeffN
+%% may have been or not already converted into A/B[n] format.
+%% As a rule, computations are not followed with reducing the fractions
+%% to smallest terms; the innocent may be unaware that computing
+%% with fractions quickly give gigantic numbers. There is \PolReduceCoeffs
+%% to do that.
+%%
+%% This base structure is maintained at 0.8 for legacy reasons but perhaps I
+%% need to revisit this. A characteristic of the package so far is that it
+%% thus stores and manipulate polynomials basically as the complete sequence
+%% of coefficients, (using the xintfrac "zero" for missing coefficients) which
+%% means that it will handle poorly polynomials of high degrees such as X^500.
+%%
+%% Test if zero
+\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}%
+%% Split into degree and coefficients
+% The \expandafter chain removes the \empty token
+\def\POL@split#1.#2;#3#4%
+ {\def#3{#1}\expandafter\def\expandafter#4\expandafter{#2}}%
+%% Define from values stored in a "macros-array"
+\def\POL@resultfromarray #1{%
+ \edef\POL@result{\ifnum\count@>\z@
+ \the\numexpr\count@-\@ne.\noexpand\empty
+ \xintiloop [1+1]%
+ \expandafter\POL@braceit\csname POL@array#1\xintiloopindex\endcsname
+ \ifnum\xintiloopindex<\count@
+ \repeat
+ \else-1.\noexpand\empty{0/1[0]}\fi}%
+}%
+\def\POL@braceit#1{{#1}}% needed as \xintiloopindex can not "see" through braces
+%%
+%% Conversion between legacy data storage and the one used for the
+%% the novel polexpr 0.8 notion of \xintexpr polynomial variables
+%%
+%% The 0.8 expandable implementation of core algebra is also manipulating
+%% the complete list of coefficients. The internal data structure is
+%% (this is the numeric leaf in xintexpr ople terminology) currently:
+%% PN.{coeff0}{coeff1}....{coeffN}
+%% where the P letter identifies the polynomial type.
+%% Here the degree N is *always* at least 1: if some evaluation ends
+%% up in a constant polynomial it will always be output as a genuine
+%% scalar numeric variable, as a rule in in A/B[n] format
+%%
+%% This is not definitive and I need to think about it more (in particular
+%% in the distant perspective of supporting multi-variable polynomials).
+%% However modifying this will be costly labor at this stage.
+%%
+\input polexprcore.tex\relax % load expandable algebra
+\def\POL@vartolegacy #1% \romannumeral\POL@vartolegacy ... \xint:
+{%
+ \if 0#1\xint_dothis\POL@vartolegacy@zero\fi
+ \if P#1\xint_dothis\POL@vartolegacy@pol\fi
+ \xint_orthat\POL@vartolegacy@scalar #1%
+}%
+\def\POL@vartolegacy@zero #1\xint:{\xint_c_ -1.\empty{0/1[0]}}%
+\def\POL@vartolegacy@scalar #1\xint:{\xint_c_ 0.\empty{#1}}%
+\def\POL@vartolegacy@pol P#1.#2\xint:{\xint_c_ #1.\empty#2}%
+%
+\def\POL@tovar#1{\romannumeral\expandafter\expandafter\expandafter
+ \POL@legacytovar\csname POLuserpol@#1\endcsname}%
+\def\POL@legacytovar #1.% \romannumeral\POL@legacytovar N.\empty{c0}...
+{%
+ \ifnum #1<\xint_c_i\xint_dothis\POL@legacytovar@scalar\fi
+ \xint_orthat\POL@legacytovar@pol #1.%
+}%
+\def\POL@legacytovar@scalar #1.\empty#2{\xint_c_ #2}%
+\def\POL@legacytovar@pol #1.\empty{\xint_c_ P#1.}%
+%%
+%% Extend \xintexpr (\xintdefvar, \xintdeffunc) to recognize the new
+%% polynomial type
+%%
+%% **** It does NOT apply to \xintfloatexpr context
+%%
+\input polexprexpr.tex\relax
+%%
+%% \poldef
+%%
+\def\PolDef{\POL@chkopt\POL@oPolDef[x]}%
+\def\POL@oPolDef[#1]#2#3{\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
+ \edef\POL@polname{\xint_zapspaces #1 \xint_gobble_i}%
+\begingroup
+ \unless\ifxintveryverbose\xintverbosefalse\fi
+ %% RADICAL CHANGE AT 0.8:
+ %% we define a **variable** not a **function**
+ %% ever since polexpr initial version, a function was defined and
+ %% the associated macros was then deconstructed in further analysis
+ %% via non-expandable approach. At 0.8 the polynomial algebra has
+ %% been implemented expandably allowing direct plug-in into \xintexpr
+ \xintdefvar __pol = subs(#4,#2=qraw({{P1.{0/1[0]}{1/1[0]}}}));%
+ \expandafter
+\endgroup
+ \expandafter\def\expandafter\POL@result\expandafter
+ {\romannumeral0\expandafter\xint_stop_atfirstofone
+ \romannumeral0\csname XINT_expr_varvalue___pol\endcsname}%
+ \XINT_global\expandafter\def\csname POLuserpol@\POL@polname\expandafter\endcsname
+ \expandafter{\romannumeral\expandafter\POL@vartolegacy\POL@result\xint:}%
+ \expandafter\POL@newpol\expandafter{\POL@polname}%
+}%
+\def\POL@newpol#1{%
+ % 0.7.5 had some complicated special handling of constant
+ % polynomials, but these are complications of the past
+ % First a variable usable in \poldef but not in \xintexpr for arithmetic
+ % only for special dedicated functions such as coeff(), deg()
+ % (when they will be implemented). In \poldef, composition of polynomials
+ % in P(Q) syntax will be more efficient than P(Q(x)).
+ % This will use \XINT_global and obey \xintverbose... setting
+ \XINT_expr_defvar_one{#1}{{\POL@tovar{#1}}}%
+ % Second a function usable not only in \poldef but also in \xintexpr
+ % Will use \XINT_global
+ \POL@newpolhorner{#1}%
+ \POL@defpolfunc{#1}{expr}%
+ \XINT_global\expandafter\let\csname XINT_flexpr_func_#1\endcsname\@undefined
+ \ifpolnewpolverbose\POL@info{#1}\fi
+}%
+\def\POL@newfloatpol#1{%
+ \POL@newfloatpolhorner{#1}%
+ \POL@defpolfunc{#1}{flexpr}%
+ \ifpolnewpolverbose\POL@floatinfo{#1}%
+ \else
+ \ifxintverbose\POL@floatinfo{#1}\fi
+ \fi
+}%
+\def\POL@info #1{%
+ \xintMessage {polexpr}{Info}%
+ {Function #1 for the \string\xintexpr\space parser is
+ \ifxintglobaldefs(globally) \fi
+ associated to \string\XINT_expr_polfunc_#1\space
+ with meaning:
+ \expandafter\meaning
+ \csname XINT_expr_polfunc_#1\endcsname}%
+}%
+\def\POL@floatinfo #1{%
+ \xintMessage {polexpr}{Info}%
+ {Function #1 for the \string\xintfloatexpr\space parser is
+ \ifxintglobaldefs(globally) \fi
+ associated to \string\XINT_flexpr_polfunc_#1\space
+ with meaning:
+ \expandafter\meaning
+ \csname XINT_flexpr_polfunc_#1\endcsname}%
+}%
+%
+\def\POL@newpolhorner#1{%
+ \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\XINT_global
+ \expandafter\def\csname XINT_expr_polfunc_#1\expandafter\endcsname
+ \expandafter##\expandafter1\expandafter{\POL@tmp{##1}}%
+}%
+\def\POL@newfloatpolhorner#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@floathorner\POL@var@coeffs\relax
+ \expandafter
+ \endgroup
+ \expandafter\def\csname XINT_flexpr_polfunc_#1\expandafter\endcsname
+ \expandafter##\expandafter1\expandafter{\POL@tmp{##1}}%
+}%
+\def\POL@newpol@horner#1{\let\xintPolAdd\relax\let\xintPolMul\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}
+ {\xint_firstofone}{\xintPolAdd{#1}}%
+ {\xintPolMul{##1}{\POL@tmp{##1}}}}%
+ \POL@newpol@horner@loop.%
+}%
+\def\POL@newpol@floathorner#1{\let\XINTinFloatAdd\relax\let\XINTinFloatMul\relax
+ \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}
+ {\xint_firstofone}{\XINTinFloatAdd{\XINTinFloatdigits{#1}}}%
+ {\XINTinFloatMul{##1}{\POL@tmp{##1}}}}%
+ \POL@newpol@floathorner@loop.%
+}%
+%%
+%% Non-expandable polynomial manipulations
+%%
+\def\PolGenFloatVariant#1{\POL@newfloatpol{#1}}%
+%
+\def\PolLet#1#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{%
+ \XINT_global
+ \expandafter\let\csname POLuserpol@#1\expandafter\endcsname
+ \csname POLuserpol@#2\endcsname
+ \XINT_expr_defvar_one{#1}{{\POL@tovar{#1}}}%
+ \XINT_global
+ \expandafter\let\csname XINT_expr_polfunc_#1\expandafter\endcsname
+ \csname XINT_expr_polfunc_#2\endcsname
+ \POL@defpolfunc{#1}{expr}%
+ \ifpolnewpolverbose\POL@info{#1}\fi
+}%
+\def\PolGlobalLet#1#2{\begingroup\xintglobaldefstrue\PolLet{#1}{#2}\endgroup}
+%
+\def\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}{ }%
+}%
+\def\PolGet{}%
+\def\PolGet#1#2\fromarray#3{%
+ \begingroup % closed in \POL@getfromarray
+ \POL@getfromarray{#1}{#3}%
+ \POL@newpol{#1}%
+}%
+\def\POL@getfromarray#1#2{%
+ \count@=#2{0} %<- intentional space
+ \ifnum\count@=\z@
+ \def\POL@result{-1.\empty{0/1[0]}}% 0.5 fix for empty array
+ \else
+ \xintloop
+ \edef\POL@tmp{#2{\count@}}%
+ \edef\POL@tmp{\xintRaw{\POL@tmp}}%
+% sadly xinttools (current 1.3a) arrays have no setters for individual items...
+ \expandafter\let\csname POL@tmparray\the\count@\endcsname\POL@tmp
+ \if0\xintiiSgn{\POL@tmp}%
+ \advance\count@\m@ne
+ \repeat
+ \count\tw@\count@
+ \xintloop
+ \ifnum\count@>\@ne
+ \advance\count@\m@ne
+ \edef\POL@tmp{#2{\count@}}%
+ \edef\POL@tmp{\xintRaw{\POL@tmp}}%
+ \expandafter\let\csname POL@tmparray\the\count@\endcsname\POL@tmp
+ \repeat
+ \count@\count\tw@
+ \def\POL@tmp##1.{{\csname POL@tmparray##1\endcsname}}%
+ \edef\POL@result{\the\numexpr\count@-\@ne.\noexpand\empty
+ \xintiloop[1+1]%
+ \expandafter\POL@tmp\xintiloopindex.%
+ \ifnum\xintiloopindex<\count@
+ \repeat}%
+ \fi
+ \expandafter
+ \endgroup
+ \expandafter
+ \XINT_global
+ \expandafter
+ \def\csname POLuserpol@#1\expandafter\endcsname
+ \expandafter{\POL@result}%
+}%
+%
+\def\PolFromCSV#1#2{%
+ \begingroup % closed in \POL@getfromarray
+ \xintAssignArray\xintCSVtoList{#2}\to\POL@arrayA
+ \POL@getfromarray{#1}\POL@arrayA
+ \POL@newpol{#1}%
+}%
+%
+\def\PolMapCoeffs#1#2{% #1 = macro, #2 = name
+ \POL@mapcoeffs{#1}{#2}%
+ \POL@newpol{#2}%
+}%
+\def\POL@mapcoeffs#1#2{%
+ \begingroup
+ \def\POL@mapcoeffs@macro{#1}%
+ \expandafter\expandafter\expandafter\POL@split
+ \csname POLuserpol@#2\endcsname;\POL@mapcoeffs@deg\POL@mapcoeffs@coeffs
+% ATTENTION à ne pas faire un \expandafter ici, car brace removal si 1 item
+ \xintAssignArray\POL@mapcoeffs@coeffs\to\POL@arrayA
+ \def\index{0}%
+ \count@\z@
+ \expandafter\POL@map@loop\expandafter.\POL@mapcoeffs@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
+ \XINT_global
+ \expandafter
+ \def\csname POLuserpol@#2\expandafter\endcsname\expandafter{\POL@result}%
+}%
+\def\POL@map@loop.#1{\if\relax#1\expandafter\xint_gob_til_dot\fi
+ \advance\count@\@ne
+ \edef\POL@map@coeff{\POL@mapcoeffs@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]}%
+\def\PolReduceCoeffs{\POL@ifstar\POL@sreducecoeffs\POL@reducecoeffs}%
+\def\POL@reducecoeffs#1{\PolMapCoeffs{\POL@xintIrr}{#1}}%
+\def\POL@sreducecoeffs#1{\PolMapCoeffs{\xintPIrr}{#1}}%
+%
+\def\PolMakeMonic#1{%
+ \edef\POL@leadingcoeff{\PolLeadingCoeff{#1}}%
+ \edef\POL@leadingcoeff@inverse{\xintDiv{1/1[0]}{\POL@leadingcoeff}}%
+ \PolMapCoeffs{\xintMul{\POL@leadingcoeff@inverse}}{#1}%
+}%
+%
+%% \PolMakePrimitive (0.5)
+% This uses expandable \PolIContent
+% Note: the integer coefficients stored in A/1[n] form with
+% A not having trailing zeroes, due to usage of \xintREZ here.
+\def\POL@makeprim@macro#1%
+ {\xintREZ{\xintNum{\xintDiv{#1}{\POL@makeprim@icontent}}}}%
+\def\PolMakePrimitive#1{%
+ % This does not need a full user declared polynomial on input, only
+ % a \POLuserpol@name macro, but on output it is fully declared
+ \edef\POL@makeprim@icontent{\PolIContent{#1}}%
+ \PolMapCoeffs\POL@makeprim@macro{#1}%
+}%
+\def\POL@makeprimitive#1{%
+ % Avoids declaring the polynomial, internal usage in \PolToSturm
+ \edef\POL@makeprim@icontent{\PolIContent{#1}}%
+ \POL@mapcoeffs\POL@makeprim@macro{#1}%
+}%
+%
+%% Euclidean division
+% now based on the expandable routine from polexprcore.tex
+%
+\def\PolDivide#1#2#3#4{% #3=quotient, #4=remainder of #1 by #2
+ \POL@divide{#1}{#2}%
+ \XINT_global\expandafter\let\csname POLuserpol@#3\endcsname\POL@Q
+ \POL@newpol{#3}%
+ \XINT_global\expandafter\let\csname POLuserpol@#4\endcsname\POL@R
+ \POL@newpol{#4}%
+}%
+\def\PolQuo#1#2#3{% #3=quotient of #1 by #2
+ \POL@divide{#1}{#2}%
+ \XINT_global\expandafter\let\csname POLuserpol@#3\endcsname\POL@Q
+ \POL@newpol{#3}%
+}%
+\def\PolRem#1#2#3{% #3=remainder of #1 by #2
+ \POL@divide{#1}{#2}%
+ \XINT_global\expandafter\let\csname POLuserpol@#3\endcsname\POL@R
+ \POL@newpol{#3}%
+}%
+\def\POL@divide#1#2{%
+ % much simpler at 0.8 thanks to our expandable macros
+ \xintAssign\xintPolQuoRem{\POL@tovar{#1}}{\POL@tovar{#2}}\to\POL@Q\POL@R
+ \odef\POL@Q{\romannumeral\expandafter\POL@vartolegacy\POL@Q\xint:}%
+ \odef\POL@R{\romannumeral\expandafter\POL@vartolegacy\POL@R\xint:}%
+}%
+%% Euclidean special pseudo-remainder
+\def\POL@getprem#1#2{%
+ \let\POL@Q\undefined % trap errors in Sturm code update to use \POL@prem
+ % this was simpler before I converted \xintPolPRem into returning a tuple...
+ \odef\POL@R{\romannumeral\expandafter\POL@vartolegacy
+ \romannumeral0\expandafter\xint_stop_atsecondoftwo
+ \romannumeral`&&@\xintPolPRem{\POL@tovar{#1}}{\POL@tovar{#2}}%
+ \xint:}%
+}%
+%
+%%%%%%%%%%%%
+%%
+%% Things are currenly implemented twice : here the legacy macros
+%% such as GCD or Diff, and in polexprcore.tex the expandable
+%% support macros for the \xinteval interface.
+%%
+%% Soon, I will probably remove all legacy code (like I did already
+%% for division) and make the user macros simple wrappers to the
+%% expandable code.
+%%
+%% But for 0.8 release, I preferred not to yet, as I did not have
+%% really the time to compare speed. Usage of the "special
+%% pseudo euclidean remainder" (expandable) code in Sturm chain
+%% construction proved very beneficial as it divided by 3 the
+%% \PolToSturm execution time on the Wilkinson perturbed type 1
+%% example in the documentation.
+%%
+%%%%%%%%%%%%
+%
+%% GCD
+%
+% It seems I didn't even use here the (now deleted) macros implementing
+% division, and I redid here what was needed: this code, which I leave
+% standing as I have other priorities, does not use the \POL@divide !
+%
+\def\PolGCD#1#2#3{% sets #3 to the (unitary) G.C.D. of #1 and #2
+ \POL@GCD{#1}{#2}{#3}%
+ \POL@newpol{#3}%
+}%
+\def\POL@GCD #1#2#3{%
+ \begingroup
+ \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@tmp
+ \let\POL@tmp\POL@polB\let\POL@polB\POL@polA\let\POL@polA\POL@tmp
+ \fi
+ \xintAssignArray\POL@polA\to\POL@arrayA
+ \xintAssignArray\POL@polB\to\POL@arrayB
+ \POL@gcd AB%
+ }}%
+ \expandafter
+ \endgroup
+ \expandafter
+ \XINT_global
+ \expandafter\def\csname POLuserpol@#3\expandafter\endcsname
+ \expandafter{\POL@result}%
+}%
+\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{\xintDiv
+ {\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
+ {\xintSub
+ {\csname POL@array#1\the\count4\endcsname}%
+ {\xintMul
+ {\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%
+}%
+%
+%% 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.%
+}%
+\def\PolDiff{\POL@chkopt\POL@oPolDiff[1]}%
+\def\POL@oPolDiff[#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\xint_firstoftwo
+ \else
+ \expandafter\xint_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{\POL@Diff@@one {#1}{#2}\POL@newpol{#2}}%
+\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
+ \XINT_global\@namedef{POLuserpol@#2}{-1.\empty{0/1[0]}}%
+ \else
+ \edef\POL@var@coeffs{\expandafter\POL@diff\POL@var@coeffs\relax}%
+ \XINT_global\expandafter\edef\csname POLuserpol@#2\endcsname
+ {\the\numexpr\POL@var@deg-\@ne.\noexpand\empty\POL@var@coeffs}%
+ \fi
+}%
+% 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
+ \XINT_global
+ \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.%
+}%
+\def\PolAntiDiff{\POL@chkopt\POL@oPolAntiDiff[1]}%
+\def\POL@oPolAntiDiff[#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\xint_firstoftwo
+ \else
+ \expandafter\xint_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{\POL@AntiDiff@@one{#1}{#2}\POL@newpol{#2}}%
+\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@
+ \XINT_global\@namedef{POLuserpol@#2}{-1.\empty{0/1[0]}}%
+ \else
+ \edef\POL@var@coeffs{\expandafter\POL@antidiff\POL@var@coeffs\relax}%
+ \XINT_global\expandafter\edef\csname POLuserpol@#2\endcsname
+ {\the\numexpr\POL@var@deg+\@ne.\noexpand\empty{0/1[0]}\POL@var@coeffs}%
+ \fi
+}%
+%
+%%
+%% Localization of roots
+%%
+% this is big. It provides also output macros, of both expandable and
+% non-expandable type
+\input polexprsturm.tex\relax
+%
+%
+%% Non-expandable output macros
+%
+\def\PolTypesetCmdPrefix#1{\xintiiifSgn{#1}{}{+}{+}}%
+\def\PolTypesetCmd#1{\xintifOne{\xintiiAbs{#1}}%
+ {\ifnum\PolIndex=\z@\xintiiSgn{#1}\else
+ \xintiiifSgn{#1}{-}{}{}\fi
+ \let\PolIfCoeffIsPlusOrMinusOne\xint_firstoftwo}%
+ {\PolTypesetOne{#1}%
+ \let\PolIfCoeffIsPlusOrMinusOne\xint_secondoftwo}%
+ }%
+\ifdefined\frac
+\def\PolTypesetOne{\xintSignedFrac}%
+\else
+\def\PolTypesetOne{\xintSignedFwOver}%
+\fi
+\catcode`^ 7
+\def\PolTypesetMonomialCmd{%
+ \ifcase\PolIndex\space
+ %
+ \or\PolVar
+ \else\PolVar^{\PolIndex}%
+ \fi
+}%
+\catcode`^ 11 % normal xint catcode
+\def\PolTypeset{\POL@ifstar
+ {\def\POL@ts@ascending{1}\POL@Typeset}%
+ {\def\POL@ts@ascending{0}\POL@Typeset}%
+}%
+%%
+%% \PolTypeset
+%%
+%% extended at 0.8 to handle arbitrary expressions on input
+%%
+\def\POL@Typeset{\POL@chkopt\POL@oPOL@Typeset[x]}%
+\def\POL@oPOL@Typeset[#1]#2{%
+ \ifmmode\let\POL@endtypeset\empty\else$\def\POL@endtypeset{$}\fi
+ \ifcsname POLuserpol@#2\endcsname
+ \expandafter\expandafter\expandafter\POL@split
+ \csname POLuserpol@#2\endcsname;\POL@var@deg\POL@var@coeffs
+ \else
+ \xintAssign\expandafter\xint_firstofone\romannumeral0\xintbareeval
+ subs((deg(x),coeffs(x)),x=subs(#2,\PolToExprInVar=pol([0,1])))\relax
+ \to\POL@var@deg\POL@var@coeffs
+ \fi
+ \if\POL@ts@ascending1%
+ \def\PolIndex{0}%
+ \let\POL@ts@reverse\xint_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
+ \POL@endtypeset
+}%
+\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.%
+}%
+%
+%%
+%% Expandable output macros (legacy)
+%%
+\def\POL@eval@fork#1\At#2#3\krof{#2}%
+\def\PolEval#1#2#3{\romannumeral`&&@\POL@eval@fork
+ #2\PolEvalAt
+ \At\PolEvalAtExpr\krof {#1}{#3}%
+}%
+\def\PolEvalAt#1#2{%
+ \xintpraw{\csname XINT_expr_polfunc_#1\endcsname{#2}}%
+}%
+\def\POL@eval#1#2{%
+ \csname XINT_expr_polfunc_#1\endcsname{#2}%
+}%
+\def\PolEvalAtExpr#1#2{\xinttheexpr #1(#2)\relax}%
+%
+\def\PolEvalReduced#1#2#3{\romannumeral`&&@\POL@eval@fork
+ #2\PolEvalReducedAt
+ \At\PolEvalReducedAtExpr\krof {#1}{#3}%
+}%
+\def\PolEvalReducedAt#1#2{%
+ \xintpraw % in order not to print denominator if the latter equals 1
+ {\xintIrr{\csname XINT_expr_polfunc_#1\endcsname{#2}}[0]}%
+}%
+\def\PolEvalReducedAtExpr#1#2{%
+ \xintpraw
+ {\expandafter\xintIrr\romannumeral`&&@\xintthebareeval#1(#2)\relax[0]}%
+}%
+%
+\def\PolFloatEval#1#2#3{\romannumeral`&&@\POL@eval@fork
+ #2\PolFloatEvalAt
+ \At\PolFloatEvalAtExpr\krof {#1}{#3}%
+}%
+\def\PolFloatEvalAt#1#2{%
+ \xintpfloat{\csname XINT_flexpr_polfunc_#1\endcsname{#2}}%
+}%
+\def\PolFloatEvalAtExpr#1#2{\xintthefloatexpr #1(#2)\relax}%
+\def\PolLeadingCoeff#1{%
+ \romannumeral`&&@\expandafter\expandafter\expandafter\xintlastitem
+ \expandafter\expandafter\expandafter
+ {\csname POLuserpol@#1\endcsname}%
+}%
+%
+\def\PolNthCoeff#1#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?
+\def\PolDegree#1{\romannumeral`&&@\expandafter\expandafter\expandafter
+ \POL@degree\csname POLuserpol@#1\endcsname;}%
+\def\POL@degree #1.#2;{#1}%
+%
+\def\PolToList#1{\romannumeral`&&@\expandafter\expandafter\expandafter
+ \xint_gob_til_dot\csname POLuserpol@#1\endcsname}%
+%
+\def\PolToCSV#1{\romannumeral0\xintlistwithsep{, }{\PolToList{#1}}}%
+%
+% \PolIContent (0.5)
+% Why did I call this IContent and not Content? Ah, I see Maple terminology
+% But I realize now I misread the Maple doc, its icontent() is the gcd of
+% all coeffs of a multivariate polynomial. Whereas content(,) second argument
+% specifies which variable to consider expression as being univariate in it
+%
+\def\POL@icontent#1{\romannumeral0\expandafter\XINT_fgcd_out
+ \romannumeral0\expandafter\XINT_fgcdof\romannumeral`&&@#1^}%
+% Since xintexpr 1.4d, \xintGCDof always outputs an irreducible fraction A/B.
+% (with B=1 if A/B integer).
+\def\PolIContent#1{\xintGCDof{\PolToList{#1}}}%
+%
+\def\PolToExprCmd#1{\xintPRaw{\xintRawWithZeros{#1}}}%
+\def\PolToFloatExprCmd#1{\xintFloat{#1}}%
+% \def\PolTypesetCmdPrefix#1{\xintiiifSgn{#1}{}{+}{+}}%
+\let\PolToExprTermPrefix\PolTypesetCmdPrefix
+\def\PolToExprOneTermStyleA#1#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\PolToExprCaret\xintiiAbs{#2}%
+ \fi
+}%
+\let\PolToExprOneTerm\PolToExprOneTermStyleA
+\def\PolToExprOneTermStyleB#1#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\PolToExprCaret\xintiiAbs{#2}%
+ \fi
+ \xintiiifOne{\xintDenominator{#1}}{}{/\xintDenominator{#1}}%
+}%
+\def\PolToFloatExprOneTerm#1#2{%
+ \ifnum#2=\z@
+ \PolToFloatExprCmd{#1}%
+ \else
+ \PolToFloatExprCmd{#1}\PolToExprTimes
+ \fi
+ \ifcase\xintiiAbs{#2} %<-- space here mandatory
+ \or\PolToExprVar
+ \else\PolToExprVar\PolToExprCaret\xintiiAbs{#2}%
+ \fi
+}%
+\def\PolToExprTimes{*}%
+\def\PolToExprVar{x}%
+\def\PolToExprInVar{x}%
+\edef\PolToExprCaret{\string ^}%
+%%
+%% \PolToExpr
+%%
+%% extended at 0.8 to handle arbitrary expressions on input
+%%
+\def\PolToExpr#1{%
+ \if*\noexpand#1\expandafter\xint_firstoftwo\else
+ \expandafter\xint_secondoftwo\fi
+ \PolToExprAscending\PolToExprDescending{#1}}%
+\def\PolToFloatExpr#1{%
+ \if*\noexpand#1\expandafter\xint_firstoftwo\else
+ \expandafter\xint_secondoftwo\fi
+ \PolToFloatExprAscending\PolToFloatExprDescending{#1}}%
+\def\PolToExpr@getit#1%
+{%
+ \ifcsname XINT_expr_varvalue_#1\endcsname
+ \csname XINT_expr_varvalue_#1\expandafter\endcsname
+ \else
+ \expandafter\xint_firstofone\romannumeral0%
+ \xintbareeval subs(#1,\PolToExprInVar=pol([0,1]))\expandafter\relax
+ \fi
+}%
+\def\PolToExprAscending#1#2{%
+ \expandafter\POL@toexpr\romannumeral0\PolToExpr@getit{#2}%
+ \PolToExprOneTerm\POL@toexprA
+}%
+\def\PolToFloatExprAscending#1#2{%
+ \expandafter\POL@toexpr\romannumeral0\PolToExpr@getit{#2}%
+ \PolToFloatExprOneTerm\POL@toexprA
+}%
+\def\PolToExprDescending#1{%
+ \expandafter\POL@toexpr\romannumeral0\PolToExpr@getit{#1}%
+ \PolToExprOneTerm\POL@toexprD
+}%
+\def\PolToFloatExprDescending#1{%
+ \expandafter\POL@toexpr\romannumeral0\PolToExpr@getit{#1}%
+ \PolToFloatExprOneTerm\POL@toexprD
+}%
+\def\POL@toexpr#1#2#3{\POL@toexpr@fork#3#2#1\relax}%
+\def\POL@toexpr@fork #1#2#3{%
+ \POL_Pfork
+ #3\POL@toexpr@pol
+ P\POL@toexpr@cst
+ \krof #1#2#3%
+}%
+\def\POL@toexpr@cst#1#2#3\relax{#2{#3}{0}}%
+\def\POL@toexpr@pol#1#2P#3.{#1{#3}#2\empty}%
+% now back to legacy pre 0.8 code
+\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.%
+}%
+\XINT_restorecatcodes_endinput%
diff --git a/Master/texmf-dist/tex/generic/polexpr/polexprcore.tex b/Master/texmf-dist/tex/generic/polexpr/polexprcore.tex
new file mode 100644
index 00000000000..e071729e42b
--- /dev/null
+++ b/Master/texmf-dist/tex/generic/polexpr/polexprcore.tex
@@ -0,0 +1,1366 @@
+%% This file polexprcore.tex is part of the polexpr package (0.8, 2021/03/29)
+%% Core routines to match infix operators +, -, *, //, /:, ^, ** and some
+%% functions
+%% The atoms representing polynomials inside \xintexpr are
+%% - for constants: a numeric value (indistinguishable. from scalars)
+%% - for degree at least 1: P<degree>.{c0}{c1}....{cN} with N = degree
+%% Auxiliaries
+\long\def\POL_Pfork #1P#2#3\krof{#2}%
+\long\def\POL_PPfork #1PP#2#3\krof{#2}%
+\long\def\POL_zeroPfork #10P#2#3\krof{#2}%
+\long\def\POL_secondofthree#1#2#3{#2}%
+% \long\def\POL_Apply:x #1#2%
+% {%
+% \POL_apply:x_loop {#1}#2%
+% \xint_Bye\xint_Bye\xint_Bye\xint_Bye
+% \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+% }%
+\long\def\POL_bBye#1\xint_Bye{}%
+\long\def\POL_apply:x_loop #1#2#3#4#5#6#7#8#9%
+{%
+ \POL_bBye #2\xint_Bye{#1{#2}}%
+ \POL_bBye #3\xint_Bye{#1{#3}}%
+ \POL_bBye #4\xint_Bye{#1{#4}}%
+ \POL_bBye #5\xint_Bye{#1{#5}}%
+ \POL_bBye #6\xint_Bye{#1{#6}}%
+ \POL_bBye #7\xint_Bye{#1{#7}}%
+ \POL_bBye #8\xint_Bye{#1{#8}}%
+ \POL_bBye #9\xint_Bye{#1{#9}}%
+ \POL_apply:x_loop {#1}%
+}%
+\long\def\POL_apply:x_iloop #1#2#3#4#5#6#7#8#9%
+{%
+ \POL_bBye #2\xint_Bye{#10{#2}}%
+ \POL_bBye #3\xint_Bye{#11{#3}}%
+ \POL_bBye #4\xint_Bye{#12{#4}}%
+ \POL_bBye #5\xint_Bye{#13{#5}}%
+ \POL_bBye #6\xint_Bye{#14{#6}}%
+ \POL_bBye #7\xint_Bye{#15{#7}}%
+ \POL_bBye #8\xint_Bye{#16{#8}}%
+ \POL_bBye #9\xint_Bye{#17{#9}}%
+ \POL_apply:x_iloop_a#1%
+}%
+\def\POL_apply:x_iloop_a#1#2.%
+{%
+ \expandafter\POL_apply:x_iloop
+ \expandafter{\expandafter#1\the\numexpr\xint_c_viii+#1.}%
+}%
+\long\def\POL_apply:x_iloop #1#2#3#4#5#6#7#8#9%
+{%
+ \POL_bBye #2\xint_Bye{#10{#2}}%
+ \POL_bBye #3\xint_Bye{#11{#3}}%
+ \POL_bBye #4\xint_Bye{#12{#4}}%
+ \POL_bBye #5\xint_Bye{#13{#5}}%
+ \POL_bBye #6\xint_Bye{#14{#6}}%
+ \POL_bBye #7\xint_Bye{#15{#7}}%
+ \POL_bBye #8\xint_Bye{#16{#8}}%
+ \POL_bBye #9\xint_Bye{#17{#9}}%
+ \POL_apply:x_iloop_a#1%
+}%
+\def\POL_apply:x_iloop_a#1#2.%
+{%
+ \expandafter\POL_apply:x_iloop
+ \expandafter{\expandafter#1\the\numexpr\xint_c_viii+#1.}%
+}%
+%%
+%% ADDITION
+%%
+\def\xintPolAdd #1%
+{%
+ \expanded\expandafter\POL_add_in\romannumeral`&&@#1\xint:
+}%
+\def\POL_add_in #1\xint:#2%
+{%
+ {%
+ \expandafter\POL_add_fork
+% Fragile but this macro is not public anyhow and won't get arbitrary input
+% At odds with systematic \xint: style further down
+ \romannumeral`&&@#2\xint_bye\xint_bye\xint_bye\xint_bye\empty
+ #1\xint_bye\xint_bye\xint_bye\xint_bye\empty
+ \empty
+ }%
+}%
+% Careful that first means "first here" i.e. the original second argument,
+% and vice versa
+\def\POL_add_fork #1#2\empty#3%
+{%
+ \POL_PPfork
+ #1#3{\POL_add_a}%
+ #1P{\POL_add_second_is_scalar}%
+ #3P{\POL_add_first_is_scalar}%
+ PP{\POL_add_both_are_scalar}%
+ \krof #1#2\empty#3%
+}%
+\def\POL_add_first_is_scalar #1\xint_bye#2\empty#3.#4%
+{%
+ #3.{\xintAdd{#1}{#4}}%
+}%
+\def\POL_add_second_is_scalar #1.#2#3\empty#4\xint_bye#5\empty\empty
+{%
+ #1.{\xintAdd{#2}{#4}}#3%
+}%
+\def\POL_add_both_are_scalar #1\xint_bye#2\empty#3\xint_bye#4\empty\empty
+{%
+ \xintAdd{#1}{#3}%
+}%
+\def\POL_add_a P#1.#2#3#4#5\empty P#6.#7#8#9%
+{%
+ \expandafter\POL_add_b
+ \expanded\bgroup\unexpanded{#1.#6.}%
+ \xint_bye #2\POL_add_Eb\xint_bye
+ \xint_bye #7\POL_add_Fb\xint_bye {\xintAdd{#2}{#7}}%
+ \xint_bye #3\POL_add_Ec\xint_bye
+ \xint_bye #8\POL_add_Fc\xint_bye {\xintAdd{#3}{#8}}%
+ \xint_bye #4\POL_add_Ed\xint_bye
+ \xint_bye #9\POL_add_Fd\xint_bye {\xintAdd{#4}{#9}}%
+ \POL_add_A #5\empty
+}%
+\def\POL_add_b #1.#2.%
+{%
+ \ifnum#1=#2 \expandafter\POL_add_c
+ \else
+ \ifnum#1>#2 P#1.\else P#2.\fi
+ \fi
+}%
+% No brace stripping possible, because constant polynomials are really
+% represented by scalars in all those internal contexts, so real
+% polynomials have at least two coefficients
+\def\POL_add_c #1\empty
+{%
+ \expandafter\POL_add_d
+ \romannumeral0\XINT_revwbr_loop {}%
+ #1\xint:\xint:\xint:\xint:%
+ \xint:\xint:\xint:\xint:\xint_bye
+ \xint_bye
+}%
+% Attention, reused in various other locations. It is all f-expandable.
+\def\POL_add_d #1%
+{%
+% abuse of \XINT_Sgn internals compatible to #1 being \xint_bye
+ \if0\XINT_Sgn#1\xint:
+ \xint_dothis\POL_add_d
+ \fi
+ \xint_orthat{\POL_add_e {#1}}%
+}%
+\def\POL_add_e #1%
+{%
+ \xint_bye#1\POL_add_e_zero\xint_bye \POL_add_f\empty{#1}%
+}%
+\def\POL_add_e_zero\xint_bye\POL_add_f\empty #1{0/1[0]}%
+% #1 starts with \empty to avoid brace stripping.
+\def\POL_add_f #1\xint_bye
+{%
+ \expandafter\POL_add_g
+ \the\numexpr
+ \xintLength{#1}-\xint_c_ii\expandafter.%
+ \romannumeral0\expandafter
+ \XINT_revwbr_loop\expandafter {\expandafter}%
+ #1\xint:\xint:\xint:\xint:%
+ \xint:\xint:\xint:\xint:\xint_bye
+}%
+\def\POL_add_g #1.%
+{%
+ \ifnum#1=\xint_c_\expandafter\POL_add_h\fi
+ P#1.%
+}%
+\def\POL_add_h P0.#1{#1}%
+% Attention reused in \POL_mul_d and \POL_quorem_c
+\def\POL_add_A #1#2#3#4#5\empty#6#7#8#9%
+{%
+ \xint_bye #1\POL_add_Ea\xint_bye
+ \xint_bye #6\POL_add_Fa\xint_bye {\xintAdd{#1}{#6}}%
+ \xint_bye #2\POL_add_Eb\xint_bye
+ \xint_bye #7\POL_add_Fb\xint_bye {\xintAdd{#2}{#7}}%
+ \xint_bye #3\POL_add_Ec\xint_bye
+ \xint_bye #8\POL_add_Fc\xint_bye {\xintAdd{#3}{#8}}%
+ \xint_bye #4\POL_add_Ed\xint_bye
+ \xint_bye #9\POL_add_Fd\xint_bye {\xintAdd{#4}{#9}}%
+ \POL_add_A #5\empty
+}%
+\def\POL_add_Ea\xint_bye
+ \xint_bye #1\POL_add_Fa\xint_bye #2\xint_bye\xint_bye
+ \POL_add_Eb\xint_bye\xint_bye#3\POL_add_Fb\xint_bye #4\xint_bye\xint_bye
+ \POL_add_Ec\xint_bye\xint_bye#5\POL_add_Fc\xint_bye #6\xint_bye\xint_bye
+ \POL_add_Ed\xint_bye\xint_bye#7\POL_add_Fd\xint_bye #8%
+ \POL_add_A#9\empty
+{%
+ \xint_bye #1\POL_add_G\xint_bye{#1}%
+ \xint_bye #3\POL_add_G\xint_bye{#3}%
+ \xint_bye #5\POL_add_G\xint_bye{#5}%
+ \xint_bye #7\POL_add_G\xint_bye{#7}%
+ \iffalse{\fi}%
+}%
+\def\POL_add_G#1\empty{\iffalse{\fi}}%
+\def\POL_add_Fa\xint_bye #1%
+ \xint_bye #2\POL_add_Eb \xint_bye
+ \xint_bye\xint_bye\POL_add_Fb\xint_bye #3%
+ \xint_bye #4\POL_add_Ec \xint_bye
+ \xint_bye\xint_bye\POL_add_Fc\xint_bye #5%
+ \xint_bye #6\POL_add_Ed #7\POL_add_A
+ #8\empty#9\empty
+{%
+ \expandafter\xint_bye\POL_secondofthree #1%
+ \POL_add_G\xint_bye{\POL_secondofthree#1}%
+ \xint_bye #2\POL_add_G\xint_bye{#2}%
+ \xint_bye #4\POL_add_G\xint_bye{#4}%
+ \xint_bye #6\POL_add_G\xint_bye{#6}%
+ \iffalse{\fi}#8\empty%
+}%
+\def\POL_add_Eb\xint_bye
+ \xint_bye #1\POL_add_Fb\xint_bye #2\xint_bye\xint_bye
+ \POL_add_Ec\xint_bye\xint_bye#3\POL_add_Fc\xint_bye #4\xint_bye\xint_bye
+ \POL_add_Ed\xint_bye\xint_bye#5\POL_add_Fd\xint_bye #6%
+ \POL_add_A#7\empty
+{%
+ \xint_bye #1\POL_add_G\xint_bye{#1}%
+ \xint_bye #3\POL_add_G\xint_bye{#3}%
+ \xint_bye #5\POL_add_G\xint_bye{#5}%
+ \iffalse{\fi}%
+}%
+\def\POL_add_Fb\xint_bye #1%
+ \xint_bye #2\POL_add_Ec \xint_bye
+ \xint_bye\xint_bye\POL_add_Fc\xint_bye #3%
+ \xint_bye #4\POL_add_Ed #5\POL_add_A
+ #6\empty#7\empty
+{%
+ \expandafter\xint_bye\POL_secondofthree #1%
+ \POL_add_G\xint_bye{\POL_secondofthree#1}%
+ \xint_bye #2\POL_add_G\xint_bye{#2}%
+ \xint_bye #4\POL_add_G\xint_bye{#4}%
+ \iffalse{\fi}#6\empty
+}%
+\def\POL_add_Ec\xint_bye
+ \xint_bye #1\POL_add_Fc\xint_bye #2\xint_bye\xint_bye
+ \POL_add_Ed\xint_bye\xint_bye#3\POL_add_Fd\xint_bye #4%
+ \POL_add_A#5\empty
+{%
+ \xint_bye #1\POL_add_G\xint_bye{#1}%
+ \xint_bye #3\POL_add_G\xint_bye{#3}%
+ \iffalse{\fi}%
+}%
+\def\POL_add_Fc\xint_bye #1\xint_bye #2\POL_add_Ed #3\POL_add_A
+ #4\empty#5\empty
+{%
+ \expandafter\xint_bye\POL_secondofthree #1%
+ \POL_add_G\xint_bye{\POL_secondofthree#1}%
+ \xint_bye #2\POL_add_G\xint_bye{#2}%
+ \iffalse{\fi}#4\empty
+}%
+\def\POL_add_Ed\xint_bye\xint_bye#1\POL_add_Fd\xint_bye#2\POL_add_A#3\empty
+{%
+ \xint_bye #1\POL_add_G\xint_bye{#1}%
+ \iffalse{\fi}%
+}%
+\def\POL_add_Fd\xint_bye#1\POL_add_A #2\empty#3\empty
+{%
+ \expandafter\xint_bye \POL_secondofthree #1%
+ \POL_add_G\xint_bye{\POL_secondofthree#1}%
+ \iffalse{\fi}#2\empty
+}%
+%%
+%% OPPOSITE
+%%
+\def\xintPolOpp #1%
+{%
+ \expanded{%
+ \expandafter\POL_opp_fork\romannumeral`&&@#1%
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ }%
+}%
+\def\POL_opp_fork #1%
+{%
+ \if P#1\xint_dothis\POL_opp_a\fi
+ \xint_orthat\POL_opp_scalar #1%
+}%
+\def\POL_opp_scalar #1\xint_Bye#2\xint_bye
+{%
+ \XINT_Opp #1%
+}%
+\def\POL_opp_a #1.%
+{%
+ #1.\POL_apply:x_loop{\XINT_Opp}%
+}%
+%%
+%% SUBTRACTION
+%%
+\def\xintPolSub #1%
+{%
+ \expanded\expandafter\POL@sub\romannumeral`&&@#1\xint:
+}%
+\def\POL@sub #1\xint:#2%
+{%
+ {%
+ \expandafter
+ \POL_add_fork\expanded{%
+ \expandafter\POL_opp_fork \romannumeral`&&@#2%
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ }%
+ \xint_bye\xint_bye\xint_bye\xint_bye\empty
+ #1\xint_bye\xint_bye\xint_bye\xint_bye\empty
+ \empty
+ }%
+}%
+%%
+%% MULTIPLICATION
+%%
+\def\xintPolSqr #1%
+{%
+ \expanded\expandafter\POL_sqr_in\romannumeral`&&@#1\xint:
+}%
+\def\POL_sqr_in #1\xint:
+{%
+ {%
+ \expandafter\POL_mul_fork
+ #1\xint_bye
+ #1\xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ }%
+}%
+%
+\def\xintPolMul #1%
+{%
+ \expanded\expandafter\POL_mul_in\romannumeral`&&@#1\xint:
+}%
+\def\POL_mul_in #1\xint:#2%
+{%
+ {%
+ \expandafter\POL_mul_fork
+ \romannumeral`&&@#2\xint_bye
+ #1\xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ }%
+}%
+\def\POL_mul_fork #1#2\xint_bye#3%
+{%
+ \POL_PPfork
+ #1#3{\POL_mul_a}%
+ #1P{\POL_mul_second_is_scalar}%
+ #3P{\POL_mul_first_is_scalar}%
+ PP{\POL_mul_both_are_scalar}%
+ \krof #1#2\xint_bye#3%
+}%
+\def\POL_mul_both_are_scalar #1\xint_bye#2\xint_Bye#3\xint_bye
+{%
+ \xintMul{#1}{#2}%
+}%
+\def\POL_mul_second_is_scalar #1\xint_bye#2\xint_Bye
+{%
+ \POL_mul_first_is_scalar #2\xint_bye#1\xint_Bye
+}%
+\def\POL_mul_first_is_scalar #1%
+{%
+ \xint_gob_til_zero#1\POL_mul_zero0\POL_mul_scalar #1%
+}%
+\def\POL_mul_zero0\POL_mul_scalar #1\xint_bye#2\xint_bye{0/1[0]}%
+\def\POL_mul_scalar #1\xint_bye P#2.%
+{%
+ P#2.\POL_apply:x_loop{\xintMul{#1}}%
+}%
+\def\POL_mul_a P#1.#2#3P#4.#5\xint_bye
+{%
+ P\the\numexpr#1+#4.%
+ \expandafter\POL_mul_b
+ \expanded{\POL_apply:x_loop{\xintMul{#2}}#5\xint_bye}%
+ \xint:
+ #3\empty#5\xint_bye
+}%
+\def\POL_mul_b #1{{#1}\POL_mul_c\empty}%
+\def\POL_mul_c #1\xint:#2%
+{%
+ \xint_bye#2\POL_mul_E\xint_bye
+ \expandafter\POL_mul_d\expandafter{#1}{#2}%
+}%
+\def\POL_mul_d #1#2#3\empty#4\xint_bye
+{%
+ \expandafter\POL_mul_b
+ \expanded\bgroup
+ \expandafter\POL_add_A
+ \expanded{\POL_apply:x_loop{\xintMul{#2}}#4\xint_bye}%
+ \xint_bye\xint_bye\xint_bye\xint_bye\empty
+ #1\xint_bye\xint_bye\xint_bye\xint_bye\empty
+ \xint:
+ #3\empty#4\xint_bye
+}%
+\def\POL_mul_E\xint_bye
+ \expandafter\POL_mul_d\expandafter#1#2\xint_bye
+% This #1 starts with \empty
+{%
+ #1%
+}%
+%%
+%% POWERS
+%%
+\def\xintPolPow #1%
+{%
+ \expanded\expandafter\POL_pow_in\romannumeral`&&@#1\xint:
+}%
+\def\POL_pow_in #1\xint:#2%
+{%
+ {%
+ \expandafter\POL_pow_fork\the\numexpr \xintNum{#2}.#1\empty
+ }%
+}%
+\def\POL_pow_fork #1#2.%
+{%
+ \xint_UDzerominusfork
+ #1-\POL_pow_zero
+ 0#1\POL_pow_neg
+ 0-\POL_pow_pos
+ \krof
+ #1#2.%
+}%
+\def\POL_pow_zero #1\empty{1/1[0]}%
+\def\POL_pow_neg #1.#2%
+{%
+ \POL_Pfork #2{\POL_pow_neg_pol}P{\POL_pow_scalar}\krof #1.#2%
+}%
+\def\POL_pow_pos #1.#2%
+{%
+ \POL_Pfork #2{\POL_pow_a}P{\POL_pow_scalar}\krof #1.#2%
+}%
+\def\POL_pow_scalar #1.#2\empty
+{%
+ \xintPow{#2}{#1}%
+}%
+\def\POL_pow_neg_pol #1.#2\empty
+{%
+ \romannumeral0\XINT_signalcondition{InvalidOperation}%
+ {Not supported: polynomial to negative power #1}{}{1/1[0]}%
+}%
+\def\POL_pow_a #1.%
+{%
+% trailing \empty will disappear in expanded context (old comment)
+ \ifnum#1=\xint_c_i\xint_afterfi\xint_gob_til_dot\fi
+ \expandafter\POL_pow_b \the\numexpr#1-\xint_c_i.%
+}%
+\def\POL_pow_b #1.%
+{%
+ \ifodd #1 \xint_dothis{\expandafter\POL_pow_even}\fi
+ \xint_orthat{\expandafter\POL_pow_odd}\the\numexpr#1/\xint_c_ii.%
+}%
+\def\POL_pow_even #1.#2\empty
+{%
+ \expandafter\POL_pow_a
+ \expanded{\unexpanded{#1.}%
+ \POL_mul_a#2\xint_bye
+ #2\xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ }\empty
+}%
+\def\POL_pow_odd #1.#2\empty
+{%
+ \expanded
+ {\unexpanded{\POL_mul_a #2\xint_bye}%
+ \expandafter\POL_pow_a
+ \expanded{\unexpanded{#1.}%
+ \POL_mul_a#2\xint_bye
+ #2\xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ }%
+ \empty
+ }%
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+}%
+%%
+%% DIVISION
+%%
+%
+% / is deprecated for polynomial Euclidean division
+%
+\def\xintPolQuo #1%
+{%
+ \romannumeral0\expandafter\xint_stop_atfirstoftwo
+ \expanded\expandafter\POL_quorem_in\romannumeral`&&@#1\xint:
+}%
+% there is no operator, for lack of obvious best notation
+\def\xintPolRem #1%
+{%
+ \romannumeral0\expandafter\xint_stop_atsecondoftwo
+ \expanded\expandafter\POL_quorem_in\romannumeral`&&@#1\xint:
+}%
+% //
+\def\xintPolDivModQ #1%
+{%
+ \romannumeral0\expandafter\xint_stop_atfirstoftwo
+ \expanded\expandafter\POL_divmod_in\romannumeral`&&@#1\xint:
+}%
+% /:
+\def\xintPolDivModR #1%
+{%
+ \romannumeral0\expandafter\xint_stop_atsecondoftwo
+ \expanded\expandafter\POL_divmod_in\romannumeral`&&@#1\xint:
+}%
+% "divmod" will apply coefficient per coefficient when divisor is scalar
+% I have found it convenient to treat constant polynomials
+% as really being scalars. But I need perhaps to think more about it.
+\def\xintPolDivMod #1%
+{%
+ \expanded\expandafter\POL_divmod_in\romannumeral`&&@#1\xint:
+}%
+% the euclidean division
+\def\xintPolQuoRem #1%
+{%
+ \expanded\expandafter\POL_quorem_in\romannumeral`&&@#1\xint:
+}%
+\def\POL_quorem_in #1\xint:#2%
+{%
+ {%
+ \expandafter\POL_quorem_fork
+ \romannumeral`&&@#2\xint_bye#1\xint_bye
+ }%
+}%
+% the overloading of divmod which does euclidean division if divisor is not a scalar
+\def\POL_divmod_in #1\xint:#2%
+{%
+ {%
+ \expandafter\POL_divmod_fork
+ \romannumeral`&&@#2\xint_bye#1\xint_bye
+ }%
+}%
+% "first" and "second" refer to the actual positions, permuted compared
+% to original arguments
+\def\POL_quorem_fork #1#2\xint_bye#3%
+{%
+ \POL_PPfork
+ #1#3{\POL_quorem_a}% both polynomials -> {eucl. quotient}{remainder}
+ #1P{\POL_quorem_second_is_scalar}% -> {zero quotient}{scalar}
+ #3P{\POL_quorem_first_is_scalar}% -> {polynomial/scalar}{zero}
+ PP{\POL_quorem_both_are_scalar}% -> {scalar/scalar}{zero}
+ \krof #1#2\xint_bye#3%
+}%
+\def\POL_quorem_first_is_scalar #1\xint_bye#2\xint_bye
+{%
+ {\expandafter\POL_quorem_first_is_scalar_i\expandafter
+ {\romannumeral0\xintinv{#1}}%
+ #2\xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye}{0/1[0]}%
+}%
+\def\POL_quorem_first_is_scalar_i #1#2.%
+{%
+ #2.\POL_apply:x_loop{\xintMul{#1}}%
+}%
+% #2 was initial first argument and is scalar
+\def\POL_quorem_second_is_scalar #1\xint_bye#2\xint_bye
+{%
+ {0/1[0]}{#2}%
+}%
+\def\POL_quorem_both_are_scalar #1\xint_bye#2\xint_bye
+{%
+ {\xintDiv{#2}{#1}}{0/1[0]}%
+}%
+% attention that "first", "second" refer to the actual arguments positions
+\def\POL_divmod_fork #1#2\xint_bye#3%
+{%
+ \POL_PPfork
+ #1#3{\POL_quorem_a}% both polynomials -> {eucl. quotient}{remainder}
+ #1P{\POL_quorem_second_is_scalar}% -> {zero quotient}{scalar}
+ #3P{\POL_divmod_first_is_scalar}% -> {per coeff//scalar}{per coeff/:scalar}
+ PP{\POL_divmod_both_are_scalar}% -> {s1//s2}{s1/:s2}
+ \krof #1#2\xint_bye#3%
+}%
+\def\POL_divmod_both_are_scalar #1\xint_bye#2\xint_bye
+{%
+ \xintDivMod{#2}{#1}%
+}%
+\def\POL_divmod_first_is_scalar #1\xint_bye #2.#3\xint_bye
+{%
+ \expandafter\POL_divmod_first_is_scalar_a
+ \expanded{\unexpanded{{#1}}\expandafter}%
+ \romannumeral0\XINT_revwbr_loop {}%
+ #3\xint:\xint:\xint:\xint:%
+ \xint:\xint:\xint:\xint:\xint_bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ \iffalse{\fi}%
+ \xint:
+}%
+\long\def\POL_exchange_args#1#2#3{#1{#3}{#2}}%
+\def\POL_divmod_first_is_scalar_a #1%
+{%
+ \expandafter\POL_divmod_first_is_scalar_b
+ \expanded\bgroup
+ \POL_apply:x_loop{\POL_exchange_args\xintDivMod{#1}}%
+}%
+% attention re-use of \POL_add_d
+\def\POL_divmod_first_is_scalar_b #1\xint:
+{%
+ {\expandafter\POL_add_d\expanded{%
+ \POL_apply:x_loop{\expandafter\xint_firstoftwo\xint_firstofone}%
+ #1\xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye}\xint_bye}%
+ {\expandafter\POL_add_d\expanded{%
+ \POL_apply:x_loop{\expandafter\xint_secondoftwo\xint_firstofone}%
+ #1\xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye}\xint_bye}%
+}%
+\def\POL_quorem_a P#1.#2\xint_bye P#3.#4\xint_bye
+{%
+ \ifnum#1>#3 \xint_dothis{\POL_quorem_easy #3.}\fi
+ \xint_orthat
+ {\expandafter\POL_quorem_EQuo
+ \expanded\bgroup
+ \expandafter\POL_quorem_b\the\numexpr#3-#1\expandafter.%
+ \expanded\bgroup
+ \xintRevWithBraces
+ }%
+ {#2}%
+ \noexpand\xint_Bye
+ \xint:
+ \expandafter\POL_placemark_loop
+ \the\numexpr#1-\xint_c_vii\expandafter.%
+ \romannumeral0\xintrevwithbraces{#4}%
+% This added {1} is related to termination clean-up (a bit annoying) process
+ {1}%
+ \the\numexpr#3-#1.%
+ \iffalse{\fi}%
+}%
+\def\POL_quorem_easy #1.#2\xintrevwithbraces#3#4.#5#6%
+{%
+ {0/1[0]}{P#1.#3}%
+}%
+\def\POL_placemark_loop #1#2.%
+{%
+ \xint_gob_til_minus#1\POL_placemark_loop_end-%
+ \expandafter\POL_placemark_step\the\numexpr#1#2-\xint_c_viii.%
+}%
+\def\POL_placemark_step #1.#2#3#4#5#6#7#8#9%
+{%
+ {#2}{#3}{#4}{#5}{#6}{#7}{#8}{#9}\POL_placemark_loop#1.%
+}%
+\def\POL_placemark_loop_end-%
+ \expandafter\POL_placemark_step\the\numexpr-#1-\xint_c_viii.%
+{%
+ \csname POL_placemark_end#1\endcsname
+}%
+\expandafter\def\csname POL_placemark_end1\endcsname
+ #1#2#3#4#5#6#7{{#1}{#2}{#3}{#4}{#5}{#6}{#7}\noexpand\xint_bye\xint:}%
+\expandafter\def\csname POL_placemark_end2\endcsname
+ #1#2#3#4#5#6{{#1}{#2}{#3}{#4}{#5}{#6}\noexpand\xint_bye\xint:}%
+\expandafter\def\csname POL_placemark_end3\endcsname
+ #1#2#3#4#5{{#1}{#2}{#3}{#4}{#5}\noexpand\xint_bye\xint:}%
+\expandafter\def\csname POL_placemark_end4\endcsname
+ #1#2#3#4{{#1}{#2}{#3}{#4}\noexpand\xint_bye\xint:}%
+\expandafter\def\csname POL_placemark_end5\endcsname
+ #1#2#3{{#1}{#2}{#3}\noexpand\xint_bye\xint:}%
+\expandafter\def\csname POL_placemark_end6\endcsname
+ #1#2{{#1}{#2}\noexpand\xint_bye\xint:}%
+\expandafter\def\csname POL_placemark_end7\endcsname
+ #1{{#1}\noexpand\xint_bye\xint:}%
+\expandafter\def\csname POL_placemark_end8\endcsname
+ {\noexpand\xint_bye\xint:}%
+\def\POL_quorem_b #1.#2#3\xint:#4#5\xint:#6%
+{%
+% \xintDiv FG computes F/G
+ \expandafter\POL_quorem_c\romannumeral0\xintdiv{\XINT_Opp#4}{#2}.%
+ #1.{#2}#3\xint:
+% there is already \xint_Bye at ends of #3
+ #3\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+% this terminates the \expanded from \POL_apply:x_loop
+ \iffalse{\fi}%
+ \xint_bye\xint_bye\xint_bye\xint_bye\empty
+ #5\xint_bye\xint_bye\xint_bye\empty
+% a \iffalse{\fi} will get inserted by \POL_add_A here
+ {#6}\xint_bye\xint:
+}%
+\def\POL_quorem_c #1.#2.#3\xint:%
+{%
+ {\XINT_Opp#1}%
+ \expandafter\POL_quorem_d\the\numexpr#2-\xint_c_i\expandafter.%
+ \expanded\bgroup
+ \unexpanded{#3}\xint:
+ \expandafter\POL_add_A
+ \expanded\bgroup
+ \POL_apply:x_loop{\xintMul{#1}}%
+}%
+\def\POL_quorem_d #1#2.%
+{%
+ \xint_gob_til_minus#1\POL_quorem_E-%
+ \POL_quorem_b #1#2.%
+}%
+\def\POL_quorem_E-\POL_quorem_b-1.#1\xint:#2\xint_bye\xint:#3.%
+{%
+% this terminates the \POL_quorem_a \expanded
+ \iffalse{\fi}\xint:#3.%
+% recycling some termination code from addition
+ {\expandafter\POL_quorem_ERem_fix\expanded{\POL_add_d#2\xint_bye}}%
+}%
+\def\POL_quorem_ERem_fix #1%
+{%
+ \if P#1\expandafter\POL_quorem_ERem_fix_a\fi 0/1[0]%
+}%
+\def\POL_quorem_ERem_fix_a 0/1[0]#1.#2%
+{%
+ \ifcase #1
+ \or
+ \expandafter\xint_firstofone
+ \else
+ P\the\numexpr#1-\xint_c_i.%
+ \fi
+}%
+\def\POL_quorem_EQuo#1\xint:#2.%
+{%
+ {\ifnum#2=\xint_c_
+ #1%
+ \else
+ P#2.\romannumeral0\XINT_revwbr_loop {}%
+ #1\xint:\xint:\xint:\xint:%
+ \xint:\xint:\xint:\xint:\xint_bye
+ \fi}%
+}%
+\def\xintPolPRem #1%
+{%
+ \expanded\expandafter\POL_prem_in\romannumeral`&&@#1\xint:
+}%
+\def\POL_prem_in #1\xint:#2%
+{%
+ \bgroup
+ \expandafter\POL_prem_fork
+ \romannumeral`&&@#2\xint:#1\xint:
+ \POL_prem_end
+}%
+\def\POL_prem_fork #1#2\xint:#3%
+{%
+ \POL_PPfork
+ #1#3{\POL_prem_a}% both polynomials
+ #1P{\POL_prem_second_is_scalar}% -> scalar
+ #3P{\POL_prem_first_is_scalar}% -> zero
+ PP{\POL_prem_both_are_scalar}% -> zero
+ \krof #1#2\xint:#3%
+}%
+\def\POL_prem_first_is_scalar #1\xint:#2\xint:\POL_prem_end
+{%
+ \iffalse{\fi}{1/1[0]}{0/1[0]}%
+}%
+\def\POL_prem_second_is_scalar #1\xint:#2\xint:\POL_prem_end
+{%
+ \iffalse{\fi}{1/1[0]}{#2}%
+}%
+\def\POL_prem_both_are_scalar #1\xint:#2\xint:\POL_prem_end
+{%
+ \iffalse{\fi}{1/1[0]}{0/1[0]}%
+}%
+\def\POL_prem_a P#1.#2\xint: P#3.#4\xint:
+{%
+ \ifnum#1>#3 \xint_dothis{\POL_prem_easy #3.}\fi
+ \xint_orthat
+ {\expandafter\POL_prem_b\the\numexpr#3-#1\expandafter.%
+ \expanded\bgroup
+ \xintRevWithBraces
+ }%
+ {#2}%
+ \noexpand\xint_Bye
+ \xint:
+ \expandafter\POL_placeBye_loop
+ \the\numexpr#1-\xint_c_vii\expandafter.%
+ \romannumeral0\xintrevwithbraces{#4}%
+ {1/1[0]}%
+ \iffalse{\fi}%
+}%
+\def\POL_prem_easy #1.#2\xintrevwithbraces#3#4\POL_prem_end
+{%
+ \iffalse{\fi}{1/1[0]}{P#1.#3}%
+}%
+\def\POL_placeBye_loop #1#2.%
+{%
+ \xint_gob_til_minus#1\POL_placeBye_loop_end-%
+ \expandafter\POL_placeBye_step\the\numexpr#1#2-\xint_c_viii.%
+}%
+\def\POL_placeBye_step #1.#2#3#4#5#6#7#8#9%
+{%
+ {#2}{#3}{#4}{#5}{#6}{#7}{#8}{#9}\POL_placeBye_loop#1.%
+}%
+\def\POL_placeBye_loop_end-%
+ \expandafter\POL_placeBye_step\the\numexpr-#1-\xint_c_viii.%
+{%
+ \csname POL_placeBye_end#1\endcsname
+}%
+\expandafter\def\csname POL_placeBye_end1\endcsname
+ #1#2#3#4#5#6#7{{#1}{#2}{#3}{#4}{#5}{#6}{#7}\noexpand\xint_Bye\xint:{1}}%
+\expandafter\def\csname POL_placeBye_end2\endcsname
+ #1#2#3#4#5#6{{#1}{#2}{#3}{#4}{#5}{#6}\noexpand\xint_Bye\xint:{1}}%
+\expandafter\def\csname POL_placeBye_end3\endcsname
+ #1#2#3#4#5{{#1}{#2}{#3}{#4}{#5}\noexpand\xint_Bye\xint:{1}}%
+\expandafter\def\csname POL_placeBye_end4\endcsname
+ #1#2#3#4{{#1}{#2}{#3}{#4}\noexpand\xint_Bye\xint:{1}}%
+\expandafter\def\csname POL_placeBye_end5\endcsname
+ #1#2#3{{#1}{#2}{#3}\noexpand\xint_Bye\xint:{1}}%
+\expandafter\def\csname POL_placeBye_end6\endcsname
+ #1#2{{#1}{#2}\noexpand\xint_Bye\xint:{1}}%
+\expandafter\def\csname POL_placeBye_end7\endcsname
+ #1{{#1}\noexpand\xint_Bye\xint:{1}}%
+\expandafter\def\csname POL_placeBye_end8\endcsname
+ {\noexpand\xint_Bye\xint:{1}}%
+\def\POL_prem_b_skip#1#2\unexpanded#3#4#5\xint_Bye#6\xint:#7#8#9%
+{%
+ \iffalse{\fi\expandafter}\xint_gobble_i#5#1%
+}%
+\def\POL_prem_b #1.#2#3\xint:#4#5\xint:#6#7%
+{%
+ \expandafter\POL_prem_c\the\numexpr#1-\xint_c_i\expandafter.%
+ \expanded\bgroup
+ \unexpanded{{#2}#3}\xint:
+ \if0\XINT_Sgn#4\xint:\xint_afterfi
+ {\expandafter\POL_prem_b_skip\expandafter
+ {\expandafter{\romannumeral0\xintmul{#6}{#7}}\xint_Bye\xint:{#6}}%
+ }%
+ \fi
+ \expandafter\POL_add_A
+ \expanded\bgroup
+ \expanded{\noexpand\POL_apply:x_loop{\noexpand\xintMul
+ {\if1\XINT_Sgn#2\xint:\expandafter\XINT_Opp\fi#4}}}%
+% there is already \xint_Bye at ends of #3
+ #3\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+% separator for \POL_add_A
+ \unexpanded{\xint_bye\xint_bye\xint_bye\xint_bye\empty}%
+% there is already \xint_Bye at ends of #5
+ \expanded{\noexpand\POL_apply:x_loop{\noexpand\xintMul{\XINT_Abs#2}}}%
+ #5\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ \unexpanded{\xint_bye\xint_bye\xint_bye\xint_bye\empty}%
+% a \iffalse{\fi} will get inserted by \POL_add_A exit routine and if will
+% terminate the \expanded triggered here after \POL_prem_c
+% what is next will have already have been expanded
+ {\xintMul{\xintMul{\XINT_Abs#2}{#6}}{#7}}\noexpand\xint_Bye\xint:
+ {\xintMul{\XINT_Abs#2}{#6}}%
+% This terminates the \expanded following \POL_add_A
+ \iffalse{\fi}%
+}%
+\def\POL_prem_c #1%
+{%
+ \xint_gob_til_minus#1\POL_prem_E_-\POL_prem_b#1%
+}%
+% attention that #2 here has a two dummies at end
+% advantage is that \POL_add_a will always think it is non scalar
+\def\POL_prem_E_-\POL_prem_b-1.#1\xint:#2\xint_Bye\xint:#3%
+{%
+ \expandafter\POL_prem_E\expanded{\POL_add_d#2\xint_bye}%
+}%
+\def\POL_prem_E #1%
+{%
+ \if P#1\expandafter\POL_prem_E_i
+ \else\expandafter\POL_prem_E_zero
+ \fi #1%
+}%
+\def\POL_prem_E_zero #1\POL_prem_end{\iffalse{\fi}{#1}{0/1[0]}}%
+\def\POL_prem_E_i P#1.%
+{%
+ \ifnum #1>\xint_c_i\POL_prem_E_ii#1.\fi
+ \POL_prem_E_iii%
+}%
+\def\POL_prem_E_iii#1\POL_prem_end{\iffalse{\fi}#1}%
+\def\POL_prem_E_ii#1.#2\POL_prem_E_iii#3%
+ {#2{#3}{P\the\numexpr#1-\xint_c_i\iffalse}\fi.}%
+\def\POL_prem_end{\iffalse{{\fi}}}%
+%%
+%% SUPPORT FOR FUNCTIONAL INTERFACE
+%%
+% should I do a qpol([]) ?, i.e. without testing for leading zeros, hence
+% would be faster ? but advantage would arise only for very high degree
+% pol([]) this one checks for zeros in the right most coeffs
+\def\xintPolPol#1{\romannumeral`&&@\expandafter\POL_add_d
+ \romannumeral0\expandafter\XINT_revwbr_loop\expandafter
+ {\expandafter}%
+ \romannumeral`&&@#1\xint:\xint:\xint:\xint:
+ \xint:\xint:\xint:\xint:\xint_bye
+ \xint_bye
+}%
+% attention to not overwrite macro names (there is a legacy \PolEvalAt)
+\def\xintPolEvalAt#1#2%
+{%
+% generally, #2 will be scalar, but we allow also a polynomial here
+% should I test for #2 being the monomial, hence handle it very quickly?
+ \romannumeral`&&@\expandafter\POL_evalat_in\romannumeral`&&@#2\xint:
+ #1\xint:\xint:\xint:\xint:
+ \xint:\xint:\xint:\xint:\xint_bye\xint:
+}%
+\def\POL_evalat_in #1\xint:
+{%
+ \expandafter\POL_evalat_fork\expanded{\unexpanded{#1\xint:}\expandafter}%
+ \romannumeral`&&@%
+}%
+\def\POL_evalat_fork #1\xint:#2%
+{%
+ \POL_Pfork
+ #2{\POL_evalat_pol}%
+ P{\POL_evalat_cst}%
+ \krof #1\xint:#2%
+}%
+\def\POL_evalat_cst #1\xint: #2\xint:#3\xint_bye\xint:{#2}%
+\def\POL_evalat_pol #1\xint: P#2.%
+{%
+ \expanded{\unexpanded{\POL_evalat_a#1\xint:}\expandafter}%
+ \romannumeral0\XINT_revwbr_loop{}%
+}%
+\def\POL_evalat_a#1\xint:#2%
+{%
+ \POL_evalat_loop#2\xint:#1\xint:
+}%
+\def\POL_evalat_loop#1\xint:#2\xint:#3%
+{%
+ \xint_gob_til_xint:#3\POL_evalat_E\xint:
+% I have dropped here my old strict \xintFoo = \romannumeral0\xintfoo style
+% ATTENTION! We must allow evaluating at a polynomial expression
+ \expandafter\POL_evalat_loop
+ \romannumeral`&&@\xintPolAdd{#3}{\xintPolMul{#2}{#1}}\xint:#2\xint:
+}%
+\def\POL_evalat_E\xint:\expandafter\POL_evalat_loop
+ \romannumeral`&&@\xintPolAdd #1#2\xint:#3\xint:
+{%
+ \xint_thirdofthree#2%
+}%
+%
+\def\xintPolDeg#1%
+{%
+ \romannumeral`&&@\expandafter\POL_deg_fork\romannumeral`&&@#1\xint:
+}%
+\def\POL_deg_fork #1%
+{%
+ \POL_zeroPfork
+ #1P{\POL_deg_zero}%
+ 0#1{\POL_deg_pol}%
+ 0P{\POL_deg_cst}%
+ \krof #1%
+}%
+% usual hesitations about using or not raw frac format
+\def\POL_deg_zero#1\xint:{-1}%
+\def\POL_deg_cst #1\xint:{0}%
+\def\POL_deg_pol P#1.#2\xint:{#1}%
+%
+\def\xintPolCoeffs#1%
+{%
+ \romannumeral`&&@\expandafter\POL_coeffs_fork\romannumeral`&&@#1\xint:
+}%
+\def\POL_coeffs_fork #1%
+{%
+ \POL_Pfork
+ #1\POL_coeffs_pol
+ P\POL_coeffs_cst
+ \krof #1%
+}%
+% usual hesitations about using or not raw frac format
+\def\POL_coeffs_cst #1\xint:{{#1}}%
+% no brace stripping possible, at least two coefficients
+% annoying that we had to put this delimiter \xint:
+\def\POL_coeffs_pol P#1.#2\xint:{#2}%
+%
+\def\xintPolCoeff#1#2%
+{%
+ \romannumeral`&&@\expandafter\POL_coeff_fork
+ \the\numexpr\xintNum{#2}\expandafter.%
+ \romannumeral`&&@#1\xint:
+}%
+\def\POL_coeff_fork #1.#2%
+{%
+ \POL_Pfork
+ #2\POL_coeff_pol
+ P\POL_coeff_cst
+ \krof #1.#2%
+}%
+\def\POL_coeff_cst#1%
+{%
+ \xint_UDzerofork
+ #1\POL_coeff_itself
+ 0\POL_coeff_zero
+ \krof #1%
+}%
+\def\POL_coeff_itself#1.#2\xint:{#2}%
+\def\POL_coeff_zero#1\xint:{0/1[0]}%
+\def\POL_coeff_pol #1.P#2.%
+{%
+ \ifnum#1<\xint_c_\xint_dothis\POL_coeff_zero\fi
+ \ifnum#1>#2 \xint_dothis\POL_coeff_zero\fi
+ \xint_orthat\POL_coeff_a{#1}%
+}%
+\def\POL_coeff_a#1{\expandafter\POL_coeff_b\romannumeral\xintgobble{#1}}%
+\def\POL_coeff_b#1#2\xint:{#1}%
+%
+\def\xintPolLCoeff#1%
+{%
+ \romannumeral`&&@\expandafter\POL_lcoeff_fork
+ \romannumeral`&&@#1\xint:
+}%
+\def\POL_lcoeff_fork #1%
+{%
+ \POL_Pfork
+ #1\POL_lcoeff_pol
+ P\POL_lcoeff_cst
+ \krof #1%
+}%
+\def\POL_lcoeff_cst#1\xint:{#1}%
+\def\POL_lcoeff_pol P#1.%
+{%
+ \expandafter\POL_lcoeff_a\romannumeral\xintgobble{#1}%
+}%
+\def\POL_lcoeff_a#1\xint:{#1}%
+%
+\def\xintPolMonicPart#1%
+{%
+ \romannumeral`&&@\expandafter\POL_monicpart_fork
+ \romannumeral`&&@#1\xint:
+}%
+\def\POL_monicpart_fork #1%
+{%
+ \POL_Pfork
+ #1\POL_monicpart_pol
+ P\POL_monicpart_cst
+ \krof #1%
+}%
+% monicpart(0) must be 0 to avoid breaking algorithms
+\def\POL_monicpart_cst#1#2\xint:{\if#10\xint_dothis0\fi\xint_orthat1/1[0]}%
+\def\POL_monicpart_pol P#1.#2\xint:%
+{%
+ \expanded{%
+ P#1.%
+ \expandafter\POL_monicpart_a\romannumeral\xintgobble{#1}%
+ #2#2\xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ }%
+}%
+\def\POL@DivByFirstAndIrrAndREZ#1#2{\xintREZ{\xintIrr{\xintDiv{#2}{#1}}}}%
+\def\POL_monicpart_a#1%
+{%
+ \POL_apply:x_loop{\POL@DivByFirstAndIrrAndREZ{#1}}%
+}%
+%
+\def\xintPolIContent#1%
+{%
+ \romannumeral`&&@\expandafter\POL_icontent_fork
+ \romannumeral`&&@#1^%
+}%
+\def\POL_icontent_fork #1%
+{%
+ \POL_Pfork
+ #1\POL_icontent_pol
+ P\POL_icontent_cst
+ \krof #1%
+}%
+\def\POL_icontent_cst #1^{\xintIrr{\xintAbs{#1}}[0]}%
+\def\POL_icontent_pol P#1.%
+{%
+% 1.4d xintfrac \XINT_fgcdof much saner than 1.4 version !
+% \XINT_fgcd_out does \xintIrr
+ \expandafter\XINT_fgcd_out\romannumeral0\XINT_fgcdof
+}%
+%
+\def\xintPolPrimPart#1%
+{%
+ \romannumeral`&&@\expandafter\POL_primpart_fork
+ \romannumeral`&&@#1\xint:
+}%
+\def\POL_primpart_fork #1%
+{%
+ \POL_Pfork
+ #1\POL_primpart_pol
+ P\POL_primpart_cst
+ \krof #1%
+}%
+\def\POL_primpart_cst#1#2\xint:{\if#10\xint_dothis0\fi\xint_orthat1/1[0]}%
+\def\POL_primpart_pol P#1.#2\xint:%
+{%
+ \expanded{%
+ P#1.\expandafter\POL_primpart_a
+ \romannumeral0\expandafter\XINT_fgcd_out
+ \romannumeral0\XINT_fgcdof#2^\xint:
+ #2\xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ }%
+}%
+% cf legacy \POL@makeprim@macro
+\def\POL@DivByFirstAndNumAndREZ#1#2{\xintREZ{\xintNum{\xintDiv{#2}{#1}}}}%
+\def\POL_primpart_a#1\xint:{\POL_apply:x_loop{\POL@DivByFirstAndNumAndREZ{#1}}}%
+%
+\def\xintPolRedCoeffs#1%
+{%
+ \romannumeral`&&@\expandafter\POL_redcoeffs_fork
+ \romannumeral`&&@#1\xint:
+}%
+\def\POL_redcoeffs_fork #1%
+{%
+ \POL_Pfork
+ #1\POL_redcoeffs_pol
+ P\POL_redcoeffs_cst
+ \krof #1%
+}%
+\def\POL_redcoeffs_cst#1\xint:{\xintIrr{#1}[0]}%
+\def\POL_redcoeffs_pol P#1.#2\xint:%
+{%
+ \expanded{%
+ P#1.\POL_apply:x_loop\POL@xintIrr
+ #2\xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ }%
+}%
+%
+\def\xintPolSRedCoeffs#1%
+{%
+ \romannumeral`&&@\expandafter\POL_sredcoeffs_fork
+ \romannumeral`&&@#1\xint:
+}%
+\def\POL_sredcoeffs_fork #1%
+{%
+ \POL_Pfork
+ #1\POL_sredcoeffs_pol
+ P\POL_sredcoeffs_cst
+ \krof #1%
+}%
+\def\POL_sredcoeffs_cst#1\xint:{\xintREZ{\xintIrr{#1}[0]}}%
+\def\POL_sredcoeffs_pol P#1.#2\xint:%
+{%
+ \expanded{%
+ P#1.\POL_apply:x_loop\POL@xintIrrAndREZ
+ #2\xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ }%
+}%
+\def\POL@xintIrrAndREZ#1{\xintREZ{\xintIrr{#1}[0]}}%
+%
+\def\xintPolDiffOne#1%
+{%
+ \romannumeral`&&@\expandafter\POL_diffone_fork
+ \romannumeral`&&@#1\xint:
+}%
+\def\POL_diffone_fork #1%
+{%
+ \POL_Pfork
+ #1\POL_diffone_pol
+ P\POL_diffone_cst
+ \krof #1%
+}%
+\def\POL_diffone_cst#1\xint:{0/1[0]}%
+\def\POL_diffone_pol P#1.#2#3\xint:%
+{%
+ \expanded{%
+ \ifnum#1=\xint_c_i #3%
+ \else
+ P\the\numexpr#1-\xint_c_i.%
+ \POL_apply:x_iloop{\POL_diffone_diff1.}%
+ #3\xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ \fi
+ }%
+}%
+\def\POL_diffone_diff#1.#2#3{\xintMul{#1+#2}{#3}}%
+%
+\def\xintPolAntiOne#1%
+{%
+ \romannumeral`&&@\expandafter\POL_antione_fork
+ \romannumeral`&&@#1\xint:
+}%
+\def\POL_antione_fork #1%
+{%
+ \POL_Pfork
+ #1\POL_antione_pol
+ P\POL_antione_cst
+ \krof #1%
+}%
+\def\POL_antione_cst#1%
+{%
+ \xint_gob_til_zero#1\POL_antione_zero0\POL_antione_cst_i#1%
+}%
+\def\POL_antione_cst_i#1\xint:{P1.{0/1[O]}{#1}}%
+\def\POL_antione_zero#1\xint:{0/1[0]}%
+\def\POL_antione_pol P#1.#2\xint:%
+{%
+ \expanded{%
+ P\the\numexpr#1+\xint_c_i.{0/1[0]}%
+ \POL_apply:x_iloop{\POL_antione_anti1.}%
+ #2\xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ }%
+}%
+\def\POL_antione_anti#1.#2#3{\xintDiv{#3}{#1+#2}}%
+%
+% #2 can be a polynomial
+\def\xintPolIntFrom#1%#2%
+{%
+ \romannumeral`&&@\expandafter\POL_intfrom_a\expandafter
+ {\romannumeral`&&@\xintPolAntiOne{#1}}%
+}%
+\def\POL_intfrom_a #1#2%
+{%
+ \xintPolSub{#1}{\xintPolEvalAt{#1}{#2}}%
+}%
+%
+\def\xintPolIntegral#1#2%
+{%
+ \romannumeral`&&@\expandafter\POL_integral_a\expanded
+ {\xintPolAntiOne{#1}\xint:#2\xint:}%
+}%
+\def\POL_integral_a #1\xint:#2#3\xint:
+{%
+ \xintPolSub{\xintPolEvalAt{#1}{#3}}{\xintPolEvalAt{#1}{#2}}%
+}%
+%
+\def\xintPolDiffTwo#1%
+{%
+ \romannumeral`&&@\expandafter\POL_difftwo_fork
+ \romannumeral`&&@#1\xint:
+}%
+\def\POL_difftwo_fork #1%
+{%
+ \POL_Pfork
+ #1\POL_difftwo_pol
+ P\POL_difftwo_cst
+ \krof #1%
+}%
+\def\POL_difftwo_cst#1\xint:{0/1[0]}%
+\def\POL_difftwo_pol P#1.%
+{%
+ \ifcase #1
+ \or \expandafter\POL_difftwo_zeroout
+ \or \expandafter\POL_difftwo_cstout
+ \else\expandafter\POL_difftwo_polout
+ \fi #1.%
+}%
+\def\POL_difftwo_zeroout#1\xint:{0/1[0]}%
+\def\POL_difftwo_cstout 2.#1#2#3\xint:{\xintMul{2}{#3}}%
+\def\POL_difftwo_polout #1.#2#3#4\xint:%
+{%
+ \expanded{%
+ P\the\numexpr#1-\xint_c_ii.%
+ \POL_apply:x_iloop{\POL_difftwo_diff2.}%
+ #4\xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ }%
+}%
+\def\POL_difftwo_diff#1.#2#3{\xintMul{\the\numexpr(#1+#2)*(#1+#2-\xint_c_i)\relax}{#3}}%
+%
+\def\POL_diffone_iter_fork #1%
+{%
+ \POL_Pfork
+ #1\POL_diffone_iter_pol
+ P\POL_diffone_iter_cst
+ \krof #1%
+}%
+\def\POL_diffone_iter_cst#1\xint:{0/1[0]\xint:}%
+\def\POL_diffone_iter_pol P#1.#2#3\xint:%
+{%
+ \expanded{%
+ \ifnum#1=\xint_c_i #3%
+ \else
+ P\the\numexpr#1-\xint_c_i.%
+ \POL_apply:x_iloop{\POL_diffone_diff1.}%
+ #3\xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ \fi
+ }\xint:
+}%
+%
+\def\POL_antione_iter_fork #1%
+{%
+ \POL_Pfork
+ #1\POL_antione_iter_pol
+ P\POL_antione_iter_cst
+ \krof #1%
+}%
+\def\POL_antione_iter_cst#1%
+{%
+ \xint_gob_til_zero#1\POL_antione_iter_zero0\POL_antione_iter_cst_i#1%
+}%
+\def\POL_antione_iter_cst_i#1\xint:{P1.{0/1[O]}{#1}\xint:}%
+\def\POL_antione_iter_zero#1\xint:{0/1[0]\xint:}%
+\def\POL_antione_iter_pol P#1.#2\xint:%
+{%
+ \expanded{%
+ P\the\numexpr#1+\xint_c_i.{0/1[0]}%
+ \POL_apply:x_iloop{\POL_antione_anti1.}%
+ #2\xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ }\xint:
+}%
+%
+\def\xintPolDiffN#1#2%
+{%
+ \romannumeral`&&@\expandafter\POL_diffn_fork
+ \the\numexpr\xintNum{#2}\expandafter.%
+ \romannumeral`&&@#1\xint:
+}%
+\def\POL_diffn_fork #1%
+{%
+ \xint_UDzerominusfork
+ #1-\POL_diffn_none
+ 0#1\POL_diffn_anti
+ 0-\POL_diffn_diff
+ \krof #1%
+}%
+\def\POL_diffn_none0.#1\xint:{#1}%
+\def\POL_diffn_diff#1.%#2\xint:%
+{%
+ \ifnum#1>\xint_c_i
+ \expandafter\POL_diffn_diff\the\numexpr#1-\xint_c_i\expandafter.%
+ \romannumeral`&&@\expandafter\POL_diffone_iter_fork
+ \else
+ \expandafter\POL_diffone_fork
+ \fi
+}%
+\def\POL_diffn_anti#1.%#2\xint:%
+{%
+ \ifnum#1<-\xint_c_i
+ \expandafter\POL_diffn_anti\the\numexpr#1+\xint_c_i\expandafter.%
+ \romannumeral`&&@\expandafter\POL_antione_iter_fork
+ \else
+ \expandafter\POL_antione_fork
+ \fi
+}%
+%
+% Support for (multi-variable) polgcd
+%
+\def\xintPolGCDof #1%
+{%
+ \romannumeral`&&@\expandafter\POL_polgcdof\romannumeral`&&@#1^%
+}%
+\def\XINT_PolGCDof{\romannumeral`&&@\POL_polgcdof}%
+\def\POL_polgcdof #1%
+{%
+ \romannumeral`&&@\expandafter
+ \POL_polgcdof_chkempty\romannumeral`&&@#1\xint:
+}%
+\def\POL_polgcdof_chkempty #1%
+{%
+ \xint_gob_til_^#1\POL_polgcdof_empty ^\POL_polgcdof_in #1%
+}%
+\def\POL_polgcdof_empty #1\xint:{1/1[0]}% hesitation
+\def\POL_polgcdof_in #1\xint:
+{%
+ \expandafter\POL_polgcdof_loop
+ \romannumeral`&&@\xintPolPrimPart{#1}\xint:
+}%
+\def\POL_polgcdof_loop #1\xint:#2%
+{%
+ \expandafter\POL_polgcdof_chkend\romannumeral`&&@#2\xint:#1\xint:\xint:
+}%
+\def\POL_polgcdof_chkend #1%
+{%
+ \xint_gob_til_^#1\POL_polgcdof_end ^\POL_polgcdof_loop_pair #1%
+}%
+% hesitation with returning a monic polynomial
+%\def\POL_polgcdof_end #1\xint:#2\xint:\xint:{\xintPolMonicPart{#2}}%
+\def\POL_polgcdof_end #1\xint:#2\xint:\xint:{#2}%
+\def\POL_polgcdof_loop_pair #1\xint:
+{%
+ \expandafter\POL_polgcdof_loop
+ \romannumeral`&&@\expandafter\POL_polgcd_pair
+ \romannumeral`&&@\xintPolPrimPart{#1}\xint:
+}%
+% MEMO comme le #2 sera au début le pgcd accumulé il sera souvent de plus
+% petit degré donc il y aura souvent un premier mod "easy" un peu inutile
+% J'hésite à faire une permutation avant de lancer le polgcd_pair
+\def\POL_polgcd_pair#1\xint:#2\xint:
+{%
+ \xintiiifSgn {\xintPolDeg {#1}}%
+ {#2}%
+ {1}%
+ {\expandafter\POL_polgcd_pair
+ \romannumeral`&&@\xintPolPrimPart
+ {\expandafter\xint_secondoftwo
+ \romannumeral`&&@\xintPolPRem {#2}{#1}}\xint:
+ #1\xint:
+ }%
+}%
+%
+\endinput
diff --git a/Master/texmf-dist/tex/generic/polexpr/polexprexpr.tex b/Master/texmf-dist/tex/generic/polexpr/polexprexpr.tex
new file mode 100644
index 00000000000..9b60e7bab00
--- /dev/null
+++ b/Master/texmf-dist/tex/generic/polexpr/polexprexpr.tex
@@ -0,0 +1,179 @@
+%% This file polexprexpr.tex is part of the polexpr package (0.8, 2021/03/29)
+%% Extending \xintexpr syntax:
+%%
+%% 1. Authorize ' in variable and function names
+%% This currently breaks infix operators 'and', 'or', 'xor', 'mod'
+%% hence forces usage everywhere of &&, ||, /: and xor() syntax
+%% (if : is active then use /\string : input syntax!)
+%%
+%% 2. Map infix operators to the polexprcore macros
+%%
+%% Overloading of infix operators must be done even outside of \poldef's
+%% scope else functions declared via \xintdeffunc would not be usable in
+%% \poldef as they would be using the xintfrac macros unaware of polynomials
+%%
+%% The overloading of // and /: is experimental.
+%%
+%% 3. Support for the polynomial functions to work in \xintdeffunc
+%%
+%% 4. Support macros for the new functions acting on polynomial variables
+%
+% 1.
+\def\XINT_expr_scanfunc_b #1%
+{%
+ \ifcat \relax#1\xint_dothis{\iffalse{\fi}(_#1}\fi
+ \if (#1\xint_dothis{\iffalse{\fi}(`}\fi
+ \if 1\ifcat a#10\fi
+ \ifnum\xint_c_ix<1\string#1 0\fi
+ \if @#10\fi
+ \if _#10\fi
+ \if '#10\fi
+ 1%
+ \xint_dothis{\iffalse{\fi}(_#1}\fi
+ \xint_orthat {#1\XINT_expr_scanfunc_a}%
+}%
+% 2.
+% the minus sign as prefix
+\def\POL_tmp #1#2%
+{%
+ \expandafter\def\csname XINT_expr_exec_#1\endcsname##1##2##3% \XINT_expr_exec_<op><level>
+ {%
+ \expandafter ##1\expandafter ##2\expandafter
+ {\romannumeral`&&@\XINT:NEhook:f:one:from:one{\romannumeral`&&@#2##3}}%
+ }%
+}%
+\POL_tmp{-xii} \xintPolOpp
+\POL_tmp{-xiv} \xintPolOpp
+\POL_tmp{-xvi} \xintPolOpp
+\POL_tmp{-xviii}\xintPolOpp
+% infix operators
+\def\POL_tmp #1#2%
+{%
+ \expandafter\def\csname XINT_expr_exec_#1\endcsname##1##2##3##4% \XINT_expr_exec_<op>
+ {%
+ \expandafter##2\expandafter##3\expandafter
+ {\romannumeral`&&@\XINT:NEhook:f:one:from:two{\romannumeral`&&@#2##1##4}}%
+ }%
+}%
+\POL_tmp + \xintPolAdd
+\POL_tmp - \xintPolSub
+\POL_tmp * \xintPolMul
+\POL_tmp / \xintPolQuo
+% there is no infix operator mapped to \xintPolRem
+% for lack of notation: perhaps /; ? advices welcome
+\POL_tmp{//}\xintPolDivModQ
+\POL_tmp{/:}\xintPolDivModR
+\POL_tmp ^ \xintPolPow
+\expandafter\let\csname XINT_expr_op_**\expandafter\endcsname
+ \csname XINT_expr_op_^\endcsname
+% 3.
+% Matches with "mysterious stuff" section of xintexpr source code
+\let\POL:NEhook:polfunc\expandafter
+\toks0\expandafter{\XINT_expr_redefinemacros}%
+\toks2 {\let\POL:NEhook:polfunc\POL:NE:polfunc}%
+\edef\XINT_expr_redefinemacros{\the\toks0 \the\toks2}%
+\catcode`~ 12
+\def\POL@defpolfunc #1#2%
+{%
+ \expandafter\POL@defpolfunc_a
+ \csname XINT_#2_func_#1\expandafter\endcsname
+ \csname XINT_#2_polfunc_#1\endcsname
+}%
+\def\POL@defpolfunc_a #1#2%
+{%
+ \XINT_global
+ \def#1##1##2##3%
+ {%
+ \expandafter##1\expandafter##2\expandafter{%
+ \romannumeral`&&@\POL:NEhook:polfunc{\romannumeral`&&@#2##3}}%
+ }%
+}%
+\def\POL:NE:polfunc #1{%
+\def\POL:NE:polfunc ##1%
+{%
+ \if0\XINT:NE:hastilde ##1~!\relax % this ! of catcode 11
+ \XINT:NE:hashash ##1#1!\relax 0\else
+ \xint_dothis\POL:NE:polfunc_a\fi
+ \xint_orthat\POL:NE:polfunc_b
+ ##1&&A%
+}}\expandafter\POL:NE:polfunc\string#%
+\def\POL:NE:polfunc_a\romannumeral`&&@#1#2&&A%
+{%
+% If we are here #2 was not braced; \string is done with \escapechar126
+ \expandafter{\expanded{~romannumeral~POL:NE:usepolfunc%
+ {\expandafter\xint_gobble_i\string#1}}#2}%
+}%
+\def\POL:NE:polfunc_b#1{%
+\def\POL:NE:polfunc_b\romannumeral`&&@##1##2&&A%
+{%
+ \expandafter{%
+ \romannumeral`&&@%
+ \if0\XINT:NE:hastilde ##2~!\relax
+ \XINT:NE:hashash ##2#1!\relax 0\else
+ \POL:NE:polfunc_c\fi
+ ##1{##2}}%
+}}\expandafter\POL:NE:polfunc_b\string#%
+% In this case the \expandafter inserted by \POL:NE:usepolfunc
+% expansion will be superfluous
+\def\POL:NE:polfunc_c#1#2% #1=\fi
+{%
+ \expanded{#1~romannumeral~POL:NE:usepolfunc%
+ {\expandafter\xint_gobble_i\string#2}}%
+}%
+% This \expandafter is in case there is an \expanded after that due
+% to some slicing constructs
+% Call: \romannumeral\POL:NE:usepolfunc
+\def\POL:NE:usepolfunc#1{`&&@\csname#1\expandafter\endcsname}%
+\catcode`~ 3 % its normal catcode in xint bundle
+% 4.
+\def\POL_tmp #1#2#3%
+{%
+ \expandafter\def\csname XINT_expr_func_#1\endcsname##1##2##3%
+ {%
+ \expandafter ##1\expandafter ##2\expandafter
+ {%
+ \romannumeral`&&@#2{\romannumeral`&&@#3##3}%
+ }%
+ }%
+}%
+\POL_tmp {sqr} \XINT:NEhook:f:one:from:one \xintPolSqr
+\POL_tmp {pol} \XINT:NEhook:f:one:from:one \xintPolPol
+\POL_tmp {deg} \XINT:NEhook:f:one:from:one \xintPolDeg
+\POL_tmp {coeffs} \XINT:NEhook:f:one:from:one \xintPolCoeffs
+\POL_tmp {coeff} \XINT:NEhook:f:one:from:two \xintPolCoeff
+\POL_tmp {lcoeff} \XINT:NEhook:f:one:from:one \xintPolLCoeff
+\POL_tmp {monicpart} \XINT:NEhook:f:one:from:one \xintPolMonicPart
+\POL_tmp {icontent} \XINT:NEhook:f:one:from:one \xintPolIContent
+\POL_tmp {primpart} \XINT:NEhook:f:one:from:one \xintPolPrimPart
+\POL_tmp {rdcoeffs} \XINT:NEhook:f:one:from:one \xintPolRedCoeffs
+\POL_tmp {rdzcoeffs} \XINT:NEhook:f:one:from:one \xintPolSRedCoeffs
+\POL_tmp {diff1} \XINT:NEhook:f:one:from:one \xintPolDiffOne
+\POL_tmp {diff2} \XINT:NEhook:f:one:from:one \xintPolDiffTwo
+\POL_tmp {diffn} \XINT:NEhook:f:one:from:two \xintPolDiffN
+\POL_tmp {antider} \XINT:NEhook:f:one:from:one \xintPolAntiOne
+\POL_tmp {integral} \XINT:NEhook:f:one:from:two \xintPolIntegral
+\POL_tmp {quorem} \XINT:NEhook:f:one:from:two \xintPolQuoRem
+\POL_tmp {quo} \XINT:NEhook:f:one:from:two \xintPolQuo
+\POL_tmp {rem} \XINT:NEhook:f:one:from:two \xintPolRem
+\POL_tmp {prem} \XINT:NEhook:f:one:from:two \xintPolPRem
+\POL_tmp {divmod} \XINT:NEhook:f:one:from:two \xintPolDivMod
+\POL_tmp {mod} \XINT:NEhook:f:one:from:two \xintPolDivModR
+\POL_tmp {evalp} \XINT:NEhook:f:one:from:two \xintPolEvalAt
+\def\XINT_expr_func_polgcd #1#2#3%
+{%
+ \expandafter #1\expandafter #2\expandafter{\expandafter
+ {\romannumeral`&&@\XINT:NEhook:f:from:delim:u\XINT_PolGCDof#3^}}%
+}%
+% this is provisory
+\xintdeffunc polpowmod_(P, m, Q) :=
+ isone(m)?
+ % m=1: return P modulo Q
+ { mod(P,Q) }
+ % m > 1: test if odd or even and do recursive call
+ { odd(m)? { mod(P*sqr(polpowmod_(P, m//2, Q)), Q) }
+ { mod( sqr(polpowmod_(P, m//2, Q)), Q) }
+ }
+ ;%
+\xintdeffunc polpowmod(P, m, Q) := (m)?{polpowmod_(P, m, Q)}{1};%
+%
+\endinput
diff --git a/Master/texmf-dist/tex/latex/polexpr/polexpr.sty b/Master/texmf-dist/tex/generic/polexpr/polexprsturm.tex
index 30fef289141..3fa1861558d 100644
--- a/Master/texmf-dist/tex/latex/polexpr/polexpr.sty
+++ b/Master/texmf-dist/tex/generic/polexpr/polexprsturm.tex
@@ -1,893 +1,4 @@
-% author: Jean-François Burnol
-% License: LPPL 1.3c (author-maintained)
-\ProvidesPackage{polexpr}%
- [2020/01/31 v0.7.5 Polynomial expressions with rational coefficients (JFB)]%
-\RequirePackage{xintexpr}[2020/01/31]% xint 1.4
-\edef\POL@restorecatcodes % TODO: think better about what is reasonable here
- {\catcode`\noexpand\_ \the\catcode`\_ %
- \catcode`\noexpand\! \the\catcode`\! %
- \catcode`\noexpand\* \the\catcode`\* %
- \catcode`\noexpand\~ \the\catcode`\~ %
- \catcode`\noexpand\: \the\catcode`\: %
- \catcode0 \the\catcode0\relax}%
-\catcode`\_ 11 \catcode0 12 \catcode`\* 12
-\long\def\xint_stop_atfirstoftwo #1#2{ #1}% not yet in xint 1.3c
-\long\def\xint_stop_atsecondoftwo #1#2{ #2}%
-
-%% 0.7.5 VERY SERIOUS TROUBLES TO GET polexpr TO WORK WITH xintexpr 1.4
-
-%% I hesitated about incorporating it directly into xint 1.4
-%% Don't do this at home, only xint gurus are allowed.
-\let\POL@originalXINT_expr_redefinemacros\XINT_expr_redefinemacros
-\def\XINT_expr_redefinemacros
-{%
- \POL@originalXINT_expr_redefinemacros
- \POL@activateNEhook
-}%
-%% Using \def's and not \let's to get better readable trace
-%% in case I need to debug but this never happens
-\def\POL@activateNEhook@xint % done in a group
-{%
- \def\POL@NEhook@polfunc{\POL@NE@polfunc}%
-}%
-\def\POL@activateNEhook@pol
-{%
- \def\POL@NEhook@polfunc{\POL@NP@polfunc}%
-}%
-\def\POL@activateNEhook{\POL@activateNEhook@xint}%
-%
-%
-\catcode`~ 12
-\catcode`! 11
-\catcode`: 11
-% We drop consideration of \XINT_global matters
-% because we have other more urgent and arduous problems
-\def\POL@defpolfunc #1#2%
-{%
- \expandafter\POL@defpolfunc_a
- \csname XINT_#2_func_#1\expandafter\endcsname
- \csname XINT_#2_polfunc_#1\endcsname {#1}{#2}%
-}%
-\def\POL@defpolfunc_a #1#2#3#4%
-{%
- \protected % xintexpr 1.4 does things such as \expandafter\xintAdd\expanded
- \expandafter\def\expandafter#2\expandafter##\expandafter1\expandafter
- {%
- #2{##1}%
- }%
- \def#1##1##2##3%
- {%
- % put it directly at the correct level of bracing
- % don't worry for now about minimizing how many times ##3 is grabbed
- \expandafter##1\expandafter##2\expandafter{\expandafter
- {\romannumeral`^^@\POL@NEhook@polfunc{XINT_#4_polfunc_#3}#2{##3}}}%
- }%
-}%
-%
-\def\POL@polfunc@go #1#2#3{#2#3}% brace stripping intentional
-\def\POL@NEhook@polfunc{\POL@polfunc@go}% default for pure numerics
-%
-% Hook for expansion in \poldef
-\def\POL@NP@polfunc #1{%
-\def\POL@NP@polfunc ##1##2##3%
-{%
- \if0\expandafter\XINT:NE:hastilde\detokenize{##3}~!\relax
- \expandafter\XINT:NE:hashash\detokenize{##3}#1!\relax 0%
- \expandafter\POL@polfunc@go
- \else
- \expandafter\POL:NP:polfunc:p
- \fi {##1}{##2}{##3}%
-}}\expandafter\POL@NP@polfunc\string#%
-\def\POL:NP:polfunc:p #1#2#3%
-{%
- ~romannumeral~POL:usepolfunc:pol{#1}{#3}%
-}%
-\def\POL:usepolfunc:pol #1%#2%
-{%
-% Here we are in the core of \poldef and we really
-% need to get rid of some \expanded tokens so
-% we accept being exposed to \expanded but arrange to
-% remain invariant. Then we will try to speed up
-% polynomial composition (at this time the \#1
-% is a nested Horner type macro) by «pre-expanding»
-% the argument, but this means using the \POL@get
-% methods inside an \hbox
-%
-% \POL@applypolfunc will be defined \protected
-%
- \expandafter\xint_c_\expandafter\POL@applypolfunc
-% This will be \protected
- \csname#1\endcsname
-% #2% brace stripping is deliberate
-}%
-%
-% Hook for expansion in \xintexpr
-\def\POL@NE@polfunc #1{%
-\def\POL@NE@polfunc ##1##2##3%
-{%
- \if0\expandafter\XINT:NE:hastilde\detokenize{##3}~!\relax
- \expandafter\XINT:NE:hashash\detokenize{##3}#1!\relax 0%
- \expandafter\POL@polfunc@go
- \else
- \expandafter\POL:NE:polfunc:p
- \fi {##1}{##2}{##3}%
-}}\expandafter\POL@NE@polfunc\string#%
-\def\POL:NE:polfunc:p #1#2#3%
-{%
- ~romannumeral~POL:usepolfunc:xint{#1}{#3}%
-}%
-\def\POL:usepolfunc:xint #1%
-{%
-% This is done to overcome \protected and is useful
-% in case the polynomial function ends up nested
-% in some non-polynomial user declared function
-% as the latter (and other things) tries to pre-expand
-% its arguments (as they may be used multiple time)
-% using \expanded, but \#1 is protected.
-% And this works recursively. We are inside braces.
-% However we have a very big problem with constant
-% polynomial functions. We have to handle them
-% in a special way.
- -`0\csname#1\expandafter\endcsname\expanded
-}%
-\catcode`~ 13
-\catcode`: 12
-
-
-%% Start defining some \protected ones here
-\protected\def\POL@empty{}%
-\newif\ifPOL@pol
-\protected\def\POL@polglobaltrue {\global\let\ifPOL@pol\iftrue}%
-\protected\def\POL@polglobalfalse{\global\let\ifPOL@pol\iffalse}%
-
-
-%% Patch xintexpr to authorize ' in names (0.5.1)
-%% Adapted 0.7.5 to follow-up on xintexpr 1.4 internal changes
-%% (much simpler than previous stuff...)
-%% This allows ' as a character in a polynomial name (not initial one)
-\def\POL@XINT_expr_scanfunc_b #1%
-{%
- \ifcat \relax#1\xint_dothis{\iffalse{\fi}(_#1}\fi
- \if (#1\xint_dothis{\iffalse{\fi}(`}\fi
- \if 1\ifcat a#10\fi
- \ifnum\xint_c_ix<1\string#1 0\fi
- \if @#10\fi
- \if _#10\fi
- \if '#10\fi
- 1%
- \xint_dothis{\iffalse{\fi}(_#1}\fi
- \xint_orthat {#1\XINT_expr_scanfunc_a}%
-}%
-
-
-%% Activate polexp's modified xintexpr (only during definitions
-%% of polynomials)
-\def\POL@hackxintexpr {%
- \let\POL@originalXINT_expr_scanfunc_b\XINT_expr_scanfunc_b
- \let\XINT_expr_scanfunc_b\POL@XINT_expr_scanfunc_b
- \def\POL@activateNEhook{\POL@activateNEhook@pol}%
-}%
-\def\POL@restorexintexpr {%
- \let\XINT_expr_scanfunc_b\POL@originalXINT_expr_scanfunc_b
- \def\POL@activateNEhook{\POL@activateNEhook@xint}%
-}%
-
-
-%% AUXILIARIES
-\catcode`! 3
-%% added at 0.7
-\newcommand\polexprsetup[1]{\POL@setup_parsekeys #1,=!,\xint_bye}%
-\def\POL@setup_parsekeys #1=#2#3,{%
- \ifx!#2\expandafter\xint_bye\fi
- \csname POL@setup_setkey_\xint_zapspaces #1 \xint_gobble_i\endcsname
- \xint_firstoftwo
- {\PackageWarning{polexpr}{The \detokenize{#1} key is unknown! ignoring}}%
- {\xintZapLastSpaces{#2#3}}%
- \POL@setup_parsekeys
-}%
-\catcode`! 11
-\def\POL@setup_setkey_norr #1#2{\edef\POL@norr}%
-\def\POL@setup_setkey_sqfnorr #1#2{\edef\POL@sqfnorr}%
-\polexprsetup{norr=_norr, sqfnorr=_sqf_norr}
-
-\newcount\POL@count
-\newif\ifxintveryverbose
-\newif\ifpoltypesetall
-\newif\ifPOL@tosturm@makefirstprimitive
-\POL@tosturm@makefirstprimitivetrue
-\newif\ifPOL@isolz@nextwillneedrefine
-\newif\ifpoltoexprall
-%% the main exchange structure (stored in macros \POLuserpol@<name>)
-%% is: degree.\POL@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 \expandafter chain removes the \empty token
- {\def#3{#1}\expandafter\def\expandafter#4\expandafter{#2}}%
-%
-\def\POL@resultfromarray #1{% ATTENTION, **MUST** be executed with
-% \count@ set to 1 + degree (\count@ = 0 for zero polynomial)
-% Attention to the \protected here at 0.7.5
-% They are many all over the place
- \protected\edef\POL@result{\ifnum\count@>\z@
- \the\numexpr\count@-\@ne.\POL@empty
- \xintiloop [1+1]%
- \expandafter\POL@braceit\csname POL@array#1\xintiloopindex\endcsname
- \ifnum\xintiloopindex<\count@
- \repeat
-% Attention to this \protected\POL@empty
-% They are many all over the place
- \else-1.\POL@empty{0/1[0]}\fi}%
-}%
-\def\POL@braceit#1{{#1}}% needed as \xintiloopindex can not "see" through braces
-
-
-\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
- \edef\POL@tmp{\ifxintverbose1\else0\fi}%
- \unless\ifxintveryverbose\xintverbosefalse\fi
- \POL@hackxintexpr
- \xintdeffunc __pol(#2):=0+(#4);% force conversion to raw if a constant
- \POL@restorexintexpr
- \if1\POL@tmp\xintverbosetrue\fi
- \edef\POL@polname{\xint_zapspaces #1 \xint_gobble_i}%
- \begingroup
- \setbox0\hbox{%
- \let\xintScalarAdd\xintAdd
- \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{0} to get \POL@result defined even if numerical only expression
- % I could also test \ifPOL@pol, but this is anyhow small overhead
-% Attention that xintexpr 1.4 has braces all over the place
- \expandafter\xintAdd\expandafter{\expandafter0\expandafter}%
- \romannumeral0\csname XINT_expr_userfunc___pol\endcsname
- {\POL@polglobaltrue\protected\def\POL@result{1.\POL@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{%
-%% We must handle specially constant polynomials because they must
-%% be made to work expandably in \poldef of other polynomials due
-%% to complicated matters having to do with the \POL@ifpol conditional
- \ifnum\PolDegree{#1}<\@ne
- % non-zero constant
- % I am defining this one only for the Info message, no time now
- \expandafter\edef\csname XINT_expr_polfunc_#1\endcsname
- ##1{\PolNthCoeff{#1}{0}}%
- % No hooks here!
- \expandafter\edef\csname XINT_expr_func_#1\endcsname ##1##2##3%
- {##1##2{{\PolNthCoeff{#1}{0}}}}%
- \else
- % polynomial of degree at least 1. This means that mechanism
- % to get \POL@result will get activated and we must be very careful
- % to never \edef when the Horner macro will be converted to
- % a polynomial
- \POL@newpolhorner{#1}%
- \POL@defpolfunc{#1}{expr}%
- \fi
- \expandafter\let\csname XINT_flexpr_func_#1\endcsname\@undefined
- \ifxintverbose\POL@info{#1}\fi
-}%
-\def\POL@newfloatpol#1{%
-%% We must handle specially constant polynomials because they must
-%% be made to work expandably in \poldef of other polynomials due
-%% to complicated matters having to do with the \POL@ifpol conditional
- \ifnum\PolDegree{#1}<\@ne
- % non-zero constant
- % I am defining this one only for the Info message, no time now
- \expandafter\edef\csname XINT_flexpr_polfunc_#1\endcsname
- ##1{\PolNthCoeff{#1}{0}}%
- % No hooks here!
- \expandafter\edef\csname XINT_flexpr_func_#1\endcsname ##1##2##3%
- {##1##2{{\PolNthCoeff{#1}{0}}}}%
- \else
- % polynomial of degree at least 1. This means that mechanism
- % to get \POL@result will get activated and we must be very careful
- % to never \edef when the Horner macro will be converted to
- % a polynomial
- \POL@newfloatpolhorner{#1}%
- \POL@defpolfunc{#1}{flexpr}%
- \fi
- \ifxintverbose\POL@floatinfo{#1}\fi
-}%
-\def\POL@info #1{%
- \xintMessage {polexpr}{Info}%
- {Function #1 for the \string\xintexpr\space parser is
- associated to \string\XINT_expr_polfunc_#1\space
- whose meaning uses Horner scheme:
- \expandafter\meaning
- \csname XINT_expr_polfunc_#1\endcsname}%
-}%
-\def\POL@floatinfo #1{%
- \xintMessage {polexpr}{Info}%
- {Function #1 for the \string\xintfloatexpr\space parser is
- associated to \string\XINT_flexpr_polfunc_#1\space
- whose meaning uses Horner scheme:
- \expandafter\meaning
- \csname XINT_flexpr_polfunc_#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_polfunc_#1\expandafter\endcsname
- \expandafter##\expandafter1\expandafter{\POL@tmp{##1}}%
-}%
-\def\POL@newfloatpolhorner#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@floathorner\POL@var@coeffs\relax
- \expandafter
- \endgroup
- \expandafter\def\csname XINT_flexpr_polfunc_#1\expandafter\endcsname
- \expandafter##\expandafter1\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.%
-}%
-
-
-\newcommand\PolGenFloatVariant[1]{\POL@newfloatpol{#1}}%
-
-
-\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
- \expandafter\let\csname XINT_expr_polfunc_#1\expandafter\endcsname
- \csname XINT_expr_polfunc_#2\endcsname
- \POL@defpolfunc{#1}{expr}%
- \ifxintverbose\POL@info{#1}\fi
-}%
-\newcommand\PolGlobalLet[2]{\begingroup
- \globaldefs\@ne
- \if=\noexpand#2\expandafter\xint_firstoftwo
- \else\expandafter\xint_secondoftwo\fi
-% do I need to check something here relative to \xintNewExpr?
- \POL@@globallet\POL@globallet {#1}{#2}}%
-\def\POL@@globallet#1#2#3{\POL@globallet{#1}{#3}}%
-\def\POL@globallet#1#2{\POL@let{#1}{#2}\endgroup}%
-
-\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{}%
-\def\PolGet#1#2\fromarray#3{%
- \begingroup % closed in \POL@getfromarray
- \POL@getfromarray{#1}{#3}%
- \POL@newpol{#1}%
-}%
-\def\POL@getfromarray#1#2{%
- \count@=#2{0} %<- intentional space
- \ifnum\count@=\z@
- \protected\def\POL@result{-1.\POL@empty{0/1[0]}}% 0.5 fix for empty array
- \else
- \xintloop
- \edef\POL@tmp{#2{\count@}}%
- \edef\POL@tmp{\xintRaw{\POL@tmp}}%
-% sadly xinttools (current 1.3a) arrays have no setters for individual items...
- \expandafter\let\csname POL@tmparray\the\count@\endcsname\POL@tmp
- \if0\xintiiSgn{\POL@tmp}%
- \advance\count@\m@ne
- \repeat
-% dans le cas particulier d'un array avec que des éléments nuls, \count@ est
-% ici devenu 0 et la boucle s'est arrêtée car #2{0} était au moins 1. De plus
-% \POL@tmparray1 est bien 0/1[0] donc ok pour polynôme nul dans \POL@result
- \count\tw@\count@
- \xintloop
-% on mouline tous les coeffs via \xintRaw
- \ifnum\count@>\@ne
- \advance\count@\m@ne
- \edef\POL@tmp{#2{\count@}}%
- \edef\POL@tmp{\xintRaw{\POL@tmp}}%
- \expandafter\let\csname POL@tmparray\the\count@\endcsname\POL@tmp
- \repeat
- \count@\count\tw@
- \def\POL@tmp##1.{{\csname POL@tmparray##1\endcsname}}%
- \protected\edef\POL@result{\the\numexpr\count@-\@ne.\POL@empty
- \xintiloop[1+1]%
- \expandafter\POL@tmp\xintiloopindex.%
- \ifnum\xintiloopindex<\count@
- \repeat}%
- \fi
- \expandafter
- \endgroup
- \expandafter
- \def\csname POLuserpol@#1\expandafter\endcsname
- \expandafter{\POL@result}%
-}%
-
-
-\newcommand\PolFromCSV[2]{%
- \begingroup % closed in \POL@getfromarray
- \xintAssignArray\xintCSVtoList{#2}\to\POL@arrayA
- \POL@getfromarray{#1}\POL@arrayA
- \POL@newpol{#1}%
-% semble un peu indirect et sous-optimal
-% mais je veux élaguer les coefficients nuls. Peut-être à revoir.
-}%
-
-
-\newcommand\PolTypesetCmdPrefix[1]{\xintiiifSgn{#1}{}{+}{+}}%
-\newcommand\PolTypesetCmd[1]{\xintifOne{\xintiiAbs{#1}}%
- {\ifnum\PolIndex=\z@\xintiiSgn{#1}\else
- \xintiiifSgn{#1}{-}{}{}\fi
- \let\PolIfCoeffIsPlusOrMinusOne\@firstoftwo}%
- {\PolTypesetOne{#1}%
- \let\PolIfCoeffIsPlusOrMinusOne\@secondoftwo}%
- }%
-\newcommand\PolTypesetOne{\xintSignedFrac}%
-\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
- \POL@mapcoeffs{#1}{#2}%
- \POL@newpol{#2}%
-}%
-\def\POL@mapcoeffs#1#2{%
- \begingroup
- \def\POL@mapcoeffs@macro{#1}%
- \expandafter\expandafter\expandafter\POL@split
- \csname POLuserpol@#2\endcsname;\POL@mapcoeffs@deg\POL@mapcoeffs@coeffs
-% ATTENTION à ne pas faire un \expandafter ici, car brace removal si 1 item
- \xintAssignArray\POL@mapcoeffs@coeffs\to\POL@arrayA
- \def\index{0}%
- \count@\z@
- \expandafter\POL@map@loop\expandafter.\POL@mapcoeffs@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}%
-}%
-\def\POL@map@loop.#1{\if\relax#1\expandafter\xint_gob_til_dot\fi
- \advance\count@\@ne
- \edef\POL@map@coeff{\POL@mapcoeffs@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{\@ifstar\POL@sreducecoeffs\POL@reducecoeffs}%
-\def\POL@reducecoeffs#1{\PolMapCoeffs{\POL@xintIrr}{#1}}%
-\def\POL@sreducecoeffs#1{\PolMapCoeffs{\xintPIrr}{#1}}%
-
-
-%% EUCLIDEAN DIVISION
-\newcommand\PolDivide[4]{% #3=quotient, #4=remainder of #1 by #2
- \POL@divide{#1}{#2}%
- \expandafter\let\csname POLuserpol@#3\endcsname\POL@Q
- \POL@newpol{#3}%
- \expandafter\let\csname POLuserpol@#4\endcsname\POL@R
- \POL@newpol{#4}%
-}%
-\newcommand\PolQuo[3]{% #3=quotient of #1 by #2
- \POL@divide{#1}{#2}%
- \expandafter\let\csname POLuserpol@#3\endcsname\POL@Q
- \POL@newpol{#3}%
-}%
-\newcommand\PolRem[3]{% #3=remainder of #1 by #2
- \POL@divide{#1}{#2}%
- \expandafter\let\csname POLuserpol@#3\endcsname\POL@R
- \POL@newpol{#3}%
-}%
-\newcommand\POL@divide[2]{%
- \begingroup
- \let\xintScalarSub\xintSub
- \let\xintScalarAdd\xintAdd
- \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 POL@Q\expandafter\expandafter\expandafter\endcsname
- \expandafter\expandafter\expandafter{\expandafter\POL@Q\expandafter}%
- \expandafter
- \def\csname POL@R\expandafter\endcsname\expandafter{\POL@R}%
-}%
-
-
-%% GCD
-\newcommand\PolGCD[3]{% sets #3 to the (unitary) G.C.D. of #1 and #2
- \POL@GCD{#1}{#2}{#3}%
- \POL@newpol{#3}%
-}%
-\def\POL@GCD #1#2#3{%
- \begingroup
- \let\xintScalarSub\xintSub
- \let\xintScalarAdd\xintAdd
- \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
- {\protected\def\POL@result{-1.\POL@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@tmp
- \let\POL@tmp\POL@polB\let\POL@polB\POL@polA\let\POL@polA\POL@tmp
- \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}%
-}%
-\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{\POL@Diff@@one {#1}{#2}\POL@newpol{#2}}%
-\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.\POL@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.\POL@empty\POL@var@coeffs}%
- \fi
-}%
-% 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{\POL@AntiDiff@@one{#1}{#2}\POL@newpol{#2}}%
-\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.\POL@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.\POL@empty{0/1[0]}\POL@var@coeffs}%
- \fi
-}%
-
-%% IContent and \PolMakePrimitive (0.5)
-\def\POL@aux@mgcd@loop#1#2{%
- \if\relax#2\expandafter\POL@aux@mgcd@exit\fi
- \expandafter
- \POL@aux@mgcd@loop\romannumeral0\POL@aux@gcd#1.#2.%
-}%
-\def\POL@aux@mgcd@exit
- \expandafter
- \POL@aux@mgcd@loop\romannumeral0\POL@aux@gcd#1.\relax.{\xintiiabs{#1}}%
-\def\POL@aux@gcd#1.#2.{%
- \if0\xintiiSgn{#1}\expandafter\POL@aux@gcd@exit\fi
- \expandafter\POL@aux@gcd\romannumeral0\xintmod {#2}{#1}.#1.}%
-\def\POL@aux@gcd@exit
- \expandafter\POL@aux@gcd\romannumeral0\xintmod #1#2.#3.{{#1}}%
-
-\def\POL@icontent #1{\romannumeral0\expandafter
- \POL@aux@mgcd@loop\romannumeral`^^@#1\relax}%
-
-\newcommand\PolIContent[1]{\romannumeral0\expandafter
- \POL@aux@mgcd@loop\romannumeral`^^@\PolToList{#1}\relax}%
-
-
-\def\POL@makeprim@macro#1%
- {\xintREZ{\xintNum{\xintDiv{#1}{\POL@makeprim@icontent}}}}%
-\newcommand\PolMakePrimitive[1]{%
- % This does not need a full user declared polynomial on input, only
- % a \POLuserpol@name macro, but on output it is fully declared
- \edef\POL@makeprim@icontent{\PolIContent{#1}}%
- \PolMapCoeffs\POL@makeprim@macro{#1}%
-}%
-\def\POL@makeprimitive#1{%
- % Avoids declaring the polynomial, internal usage in \PolToSturm
- \edef\POL@makeprim@icontent{\PolIContent{#1}}%
- \POL@mapcoeffs\POL@makeprim@macro{#1}%
-}%
-
-
+%% This file polexprsturm.tex is part of the polexpr package (0.8, 2021/03/29)
%% Sturm Algorithm (polexpr 0.4)
%% 0.5 uses primitive polynomials for faster evaluations afterwards
%% 0.6 corrects misuse of \@ifstar! (mumble). \PolToSturm* was broken.
@@ -898,7 +9,16 @@
%% holding the coefficients in memory
%% 0.6 fixes the case of a constant polynomial P which caused division
%% by zero error from P'.
-\newcommand\PolToSturm{\@ifstar{\PolToSturm@@}{\PolToSturm@}}%
+%% 0.8 - fixes 0.7.5 failure to have updated to xint 1.4 format the defined
+%% \xintexpr variables holding the localization intervals extremities
+%% - also, it uses the prem() in computing the Sturm chain, for a 3X
+%% speed gain in the case of the "perturbed" first Wilkinson example
+%%
+\newcount\POL@count
+\newif\ifPOL@tosturm@makefirstprimitive\POL@tosturm@makefirstprimitivetrue
+\newif\ifPOL@isolz@nextwillneedrefine
+%%
+\def\PolToSturm{\POL@ifstar{\PolToSturm@@}{\PolToSturm@}}%
\def\POL@aux@toint#1{\xintREZ{\xintNum{#1}}}% for polynomials with int. coeffs!
%% Attention that some macros rely upon this one setting \POL@sturmname
%% and \POL@sturm@N as it does
@@ -914,7 +34,7 @@
\POL@count\z@
% if I applied the same as for positive degree, I should make it -1
% if constant is negative. I also don't worry if polynomial is zero.
- \@namedef{POLuserpol@\POL@sturmname _0}{0.\POL@empty{1/1[0]}}%
+ \XINT_global\@namedef{POLuserpol@\POL@sturmname _0}{0.\empty{1/1[0]}}%
\else
\ifPOL@tosturm@makefirstprimitive\POL@makeprimitive{\POL@sturmname _0_}\fi
\POL@tosturm@dosturm
@@ -945,12 +65,13 @@
\POL@makeprimitive{\POL@sturmname _1_}% does not do \POL@newpol
\POL@count\@ne
\xintloop
- \POL@divide{\POL@sturmname _\the\numexpr\POL@count-\@ne\relax _}%
- {\POL@sturmname _\the\POL@count _}%
+ % prior to 0.8, code was using here \POL@divide
+ \POL@getprem{\POL@sturmname _\the\numexpr\POL@count-\@ne\relax _}%
+ {\POL@sturmname _\the\POL@count _}%
\expandafter\POL@split\POL@R;\POL@degR\POL@polR
\unless\ifnum\POL@degR=\m@ne
\advance\POL@count\@ne
- \expandafter\let
+ \XINT_global\expandafter\let
\csname POLuserpol@\POL@sturmname _\the\POL@count _\endcsname\POL@R
\edef\POL@makeprim@icontent{-\POL@icontent\POL@polR}%
% this avoids the \POL@newpol from \PolMapCoeffs
@@ -964,18 +85,18 @@
\advance\POL@count\m@ne
\POL@divide{\POL@sturmname _\the\POL@count _}%
{\POL@sturmname _\POL@sturm@N _}%
- \expandafter
- \let\csname POLuserpol@\POL@sturmname _\the\POL@count\endcsname\POL@Q
+ \XINT_global\expandafter
+ \let\csname POLuserpol@\POL@sturmname _\the\POL@count\endcsname\POL@Q
% quotient actually belongs to Z[X] and is primitive
\POL@mapcoeffs\POL@aux@toint{\POL@sturmname _\the\POL@count}%
\ifnum\POL@count>\z@
\repeat
- \@namedef{POLuserpol@\POL@sturmname _\POL@sturm@N}{0.\POL@empty{1/1[0]}}%
+ \XINT_global\@namedef{POLuserpol@\POL@sturmname _\POL@sturm@N}{0.\empty{1/1[0]}}%
\else % they are already normalized
\advance\POL@count\@ne % attention to include last one also
\xintloop
\advance\POL@count\m@ne
- \expandafter\let
+ \XINT_global\expandafter\let
\csname POLuserpol@\POL@sturmname _\the\POL@count\expandafter\endcsname
\csname POLuserpol@\POL@sturmname _\the\POL@count _\endcsname
\ifnum\POL@count>\z@
@@ -983,10 +104,13 @@
\fi
% Back to \PolToSturm@, \POL@count holds 0
}%
-\newcommand\PolSturmChainLength[1]
- {\romannumeral`^^@\csname PolSturmChainLength_#1\endcsname}%
-
-\newcommand\PolSetToSturmChainSignChangesAt[4][\global]{%
+\def\PolSturmChainLength#1{%
+ \romannumeral`&&@\csname PolSturmChainLength_#1\endcsname
+}%
+\def\PolSetToSturmChainSignChangesAt{%
+ \POL@chkopt\POL@oPolSetToSturmChainSignChangesAt[\global]%
+}%
+\def\POL@oPolSetToSturmChainSignChangesAt[#1]#2#3#4{%
\edef\POL@sturmchain@X{\xintREZ{#4}}%
\edef\POL@sturmname{#3}%
\edef\POL@sturmlength{\PolSturmChainLength{\POL@sturmname}}%
@@ -1014,7 +138,10 @@
\fi
\repeat
}%
-\newcommand\PolSetToNbOfZerosWithin[5][\global]{%
+\def\PolSetToNbOfZerosWithin{%
+ \POL@chkopt\POL@oPolSetToNbOfZerosWithin[\global]%
+}%
+\def\POL@oPolSetToNbOfZerosWithin[#1]#2#3#4#5{%
\edef\POL@tmpA{\xintREZ{#4}}%
\edef\POL@tmpB{\xintREZ{#5}}%
\edef\POL@sturmname{#3}%
@@ -1029,23 +156,25 @@
#1\edef#2{\the\numexpr\POL@SVA-\POL@SVB}%
\fi
}%
-
-
% 0.6 added starred variant to count multiplicities
% 0.7 added double starred variant to locate all rational roots
-\newcommand\PolSturmIsolateZeros{\@ifstar
+\def\PolSturmIsolateZeros{\POL@ifstar
{\PolSturmIsolateZerosAndGetMultiplicities}%
{\PolSturmIsolateZeros@}%
}%
-\newcommand\PolSturmIsolateZerosAndGetMultiplicities{\@ifstar
+\def\PolSturmIsolateZerosAndGetMultiplicities{\POL@ifstar
{\PolSturmIsolateZerosGetMultiplicitiesAndRationalRoots}%
{\PolSturmIsolateZerosAndGetMultiplicities@}%
}%
% on aurait besoin de ça dans xint, mais il aurait un \xintRaw{#1} alors
\def\POL@xintfrac@getNDE #1%
- {\expandafter\POL@xintfrac@getNDE@i\romannumeral`^^@#1}%
+ {\expandafter\POL@xintfrac@getNDE@i\romannumeral`&&@#1}%
\def\POL@xintfrac@getNDE@i #1/#2[#3]#4#5#6{\def#4{#1}\def#5{#2}\def#6{#3}}%
-\newcommand\PolSturmIsolateZerosGetMultiplicitiesAndRationalRoots[2][\empty]{%
+%
+\def\PolSturmIsolateZerosGetMultiplicitiesAndRationalRoots{%
+ \POL@chkopt\POL@oPolSturmIsolateZerosGetMultiplicitiesAndRationalRoots[\empty]%
+}%
+\def\POL@oPolSturmIsolateZerosGetMultiplicitiesAndRationalRoots[#1]#2{%
\PolSturmIsolateZerosAndFindRationalRoots[#1]{#2}%
\ifnum\POL@isolz@NbOfRoots>\z@
% get multiplicities of irrational (real) roots, if any
@@ -1056,7 +185,10 @@
\fi
}%
% added at 0.7
-\newcommand\PolSturmIsolateZerosAndFindRationalRoots[2][\empty]{%
+\def\PolSturmIsolateZerosAndFindRationalRoots{%
+ \POL@chkopt\POL@oPolSturmIsolateZerosAndFindRationalRoots[\empty]%
+}%
+\def\POL@oPolSturmIsolateZerosAndFindRationalRoots[#1]#2{%
% #1 optional E such that roots are searched in -10^E < x < 10^E
% both -10^E and +10^E must not be roots!
% #2 name of Sturm chain (already pre-computed)
@@ -1078,9 +210,11 @@
% on ne va pas utiliser de Horner, mais des divisions par X - x, et ces
% choses vont évoluer, ainsi que le coefficient dominant entier
% (pour \POL@divide entre autres if faut des noms de user pol)
+ \XINT_global
\expandafter\let
\csname POLuserpol@\POL@sturmname\POL@sqfnorr\expandafter\endcsname
\csname POLuserpol@\POL@sturmname _0\endcsname
+ \XINT_global
\expandafter\let
\csname POLuserpol@\POL@sturmname\POL@norr\expandafter\endcsname
\csname POLuserpol@\POL@sturmname _0_\endcsname
@@ -1161,7 +295,7 @@
\POL@findrat@xN\POL@findrat@xD\POl@_
% we can't move this to updatequotients because other branch will
% need to do the division first anyhow
- \edef\POLuserpol@_findrat@oneterm{1.\POL@empty
+ \edef\POLuserpol@_findrat@oneterm{1.\noexpand\empty
{\xintiiOpp\POL@findrat@xN/1[0]}{\POL@findrat@xD/1[0]}}%
\POL@divide{\POL@sturmname\POL@sqfnorr}{_findrat@oneterm}% the one without mult.
%\expandafter\POL@split\POL@R;\POL@degR\POL@polR
@@ -1295,7 +429,7 @@
% zero should never occur here
\POL@findrat@ifnegative{\edef\POL@findrat@x{-\POL@findrat@x}}{}%
\POL@xintfrac@getNDE\POL@findrat@x\POL@findrat@xN\POL@findrat@xD\POL@_
- \edef\POLuserpol@_findrat@oneterm{1.\POL@empty
+ \edef\POLuserpol@_findrat@oneterm{1.\noexpand\empty
{\xintiiOpp{\POL@findrat@xN}/1[0]}{\POL@findrat@xD/1[0]}}%
\POL@divide{\POL@sturmname\POL@sqfnorr}{_findrat@oneterm}% the one without mult.
\expandafter\POL@split\POL@R;\POL@degR\POL@polR
@@ -1362,7 +496,7 @@
% safer to do the edef as \POL@findrat@x used later in storeit
\edef\POL@findrat@x{\xintIrr{\xintDiv\POL@findrat@Num\POL@findrat@D}[0]}%
\POL@xintfrac@getNDE\POL@findrat@x\POL@findrat@xN\POL@findrat@xD\POL@_
- \edef\POLuserpol@_findrat@oneterm{1.\POL@empty
+ \edef\POLuserpol@_findrat@oneterm{1.\noexpand\empty
{\xintiiOpp{\POL@findrat@xN}/1[0]}{\POL@findrat@xD/1[0]}}%
\POL@divide{\POL@sturmname\POL@sqfnorr}{_findrat@oneterm}% the one without mult.
\expandafter\POL@split\POL@R;\POL@degR\POL@polR
@@ -1385,23 +519,24 @@
\let\csname POL_ZK\POL@sturmname*\POL@findrat@index\endcsname
\xint_stop_atfirstoftwo
\begingroup\xintglobaldefstrue
- % skip some overhead of \xintdefvar...
+ % skip some overhead of \xintdefvar...
+ % BUT attention to changes in xint 1.4 internal format !
\XINT_expr_defvar_one{\POL@sturmname L_\POL@findrat@index}%
- {\POL@findrat@x}%
+ {{\POL@findrat@x}}%
\XINT_expr_defvar_one{\POL@sturmname R_\POL@findrat@index}%
- {\POL@findrat@x}%
+ {{\POL@findrat@x}}%
\XINT_expr_defvar_one{\POL@sturmname Z_\POL@findrat@index _isknown}%
- {1}%
+ {{1}}%
\endgroup
}%
\def\POL@findrat@loop@updatequotients{%
% attention last division must have been one testing vanishing of\POL@sqfnorr
- \expandafter\let\csname POLuserpol@\POL@sturmname\POL@sqfnorr\endcsname\POL@Q
+ \XINT_global\expandafter\let\csname POLuserpol@\POL@sturmname\POL@sqfnorr\endcsname\POL@Q
% quotient belongs to Z[X] and is primitive
\POL@mapcoeffs\POL@aux@toint{\POL@sturmname\POL@sqfnorr}%
% update the one with multiplicities
\POL@divide{\POL@sturmname\POL@norr}{_findrat@oneterm}%
- \expandafter\let\csname POLuserpol@\POL@sturmname\POL@norr\endcsname\POL@Q
+ \XINT_global\expandafter\let\csname POLuserpol@\POL@sturmname\POL@norr\endcsname\POL@Q
\POL@mapcoeffs\POL@aux@toint{\POL@sturmname\POL@norr}
% updating of \POL@findrat@D at end of execution of getmultiplicity
}%
@@ -1411,7 +546,7 @@
\POL@divide{\POL@sturmname\POL@norr}{_findrat@oneterm}%
\expandafter\POL@split\POL@R;\POL@degR\POL@polR
\ifnum\POL@degR=\m@ne % yes
- \expandafter\let\csname POLuserpol@\POL@sturmname\POL@norr\endcsname\POL@Q
+ \XINT_global\expandafter\let\csname POLuserpol@\POL@sturmname\POL@norr\endcsname\POL@Q
\POL@mapcoeffs\POL@aux@toint{\POL@sturmname\POL@norr}%
\expandafter
\xdef
@@ -1451,14 +586,19 @@
\let\POL@sturm@N\@gobble% !
\let\POL@isolz@NbOfRoots@with_unknown_mult\POL@findrat@nbofirrroots
\POL@tosturm@makefirstprimitivefalse
+\expanded{\unexpanded{%
+ \unless\ifxintveryverbose\xintverbosefalse\polnewpolverbosefalse\fi
\POL@isolzmult@loop
+}\ifxintverbose\noexpand\xintverbosetrue\fi
+ \ifpolnewpolverbose\noexpand\polnewpolverbosetrue\fi}%
\POL@tosturm@makefirstprimitivetrue
\let\POL@sturmname\POL@originalsturmname
\fi
}%
-
-
-\newcommand\PolSturmIsolateZerosAndGetMultiplicities@[2][\empty]{%
+\def\PolSturmIsolateZerosAndGetMultiplicities@{%
+ \POL@chkopt\POL@oPolSturmIsolateZerosAndGetMultiplicities@[\empty]%
+}%
+\def\POL@oPolSturmIsolateZerosAndGetMultiplicities@[#1]#2{%
% #1 optional E such that roots are searched in -10^E < x < 10^E
% both -10^E and +10^E must not be roots!
% #2 name of Sturm chain (already pre-computed)
@@ -1487,7 +627,11 @@
% store Sturm chain name, it is needed and altered in isolzmult@loop
\let\POL@originalsturmname\POL@sturmname
\POL@tosturm@makefirstprimitivefalse
- \POL@isolzmult@loop
+\expanded{\unexpanded{%
+ \unless\ifxintveryverbose\xintverbosefalse\polnewpolverbosefalse\fi
+ \POL@isolzmult@loop
+}\ifxintverbose\noexpand\xintverbosetrue\fi
+ \ifpolnewpolverbose\noexpand\polnewpolverbosetrue\fi}%
\POL@tosturm@makefirstprimitivetrue
\let\POL@sturmname\POL@originalsturmname
\fi
@@ -1502,8 +646,9 @@
\let\x\POL@isolz@NbOfRoots
\xintloop
% skip some overhead of \xintdefvar...
+ % ATTENTION to xint 1.4 internal changes !
\XINT_expr_defvar_one{\POL@sturmname M_\x}%
- {\csname POL_ZM\POL@sturmname*\x\endcsname}%
+ {{\csname POL_ZM\POL@sturmname*\x\endcsname}}%
\edef\x{\the\numexpr\x-\@ne}%
\ifnum\x>\z@
\repeat
@@ -1586,9 +731,10 @@
{\the\numexpr\POL@isolz@NbOfRoots@with_unknown_mult-\@ne}%
\fi
}%
-
-
-\newcommand\PolSturmIsolateZeros@[2][\empty]{%
+\def\PolSturmIsolateZeros@{%
+ \POL@chkopt\POL@oPolSturmIsolateZeros@[\empty]%
+}%
+\def\POL@oPolSturmIsolateZeros@[#1]#2{%
% #1 optional E such that roots are searched in -10^E < x < 10^E
% both -10^E and +10^E must not be roots!
% #2 name of Sturm chain (already pre-computed from a given polynomial)
@@ -2077,17 +1223,20 @@
\fi
\begingroup\xintglobaldefstrue
% skip some overhead of \xintdefvar...
+ % Let me repeat: ATTENTION to change of internal format at xint 1.4
\XINT_expr_defvar_one{\POL@sturmname L_\POL@isolz@IntervalIndex}%
- {\POL@IsoLeft@rawout}%
+ {{\POL@IsoLeft@rawout}}%
\XINT_expr_defvar_one{\POL@sturmname R_\POL@isolz@IntervalIndex}%
- {\POL@IsoRight@rawout}%
+ {{\POL@IsoRight@rawout}}%
% added at 0.7
\XINT_expr_defvar_one{\POL@sturmname Z_\POL@isolz@IntervalIndex _isknown}%
- {\ifnum\POL@IsoRightSign=\z@ 1\else 0\fi}%
+ {{\ifnum\POL@IsoRightSign=\z@ 1\else 0\fi}}%
\endgroup
}%
%% \PolRefineInterval
-\def\POL@xintexprGetVar#1{\csname XINT_expr_varvalue_#1\endcsname}%
+%% ATTENTION TO xint 1.4 INTERNAL CHANGES
+\def\POL@xintexprGetVar#1{\expandafter\expandafter\expandafter\xint_firstofone
+ \csname XINT_expr_varvalue_#1\endcsname}%
% attention, also used by \POL@findrat@loop@a
\def\POL@get@IsoLeft@rawin{%
\edef\POL@IsoLeft@rawin
@@ -2103,8 +1252,11 @@
\def\POL@get@IsoLeft@Int{%
\expandafter\POL@get@Int@aux\POL@IsoLeft@rawin\POL@IsoLeft@Int\POL@isolz@E
}%
-\newcommand\PolRefineInterval{\@ifstar\POL@srefine@start\POL@refine@start}%
-\newcommand\POL@refine@start[3][1]{%
+\def\PolRefineInterval{\POL@ifstar\POL@srefine@start\POL@refine@start}%
+\def\POL@refine@start{%
+ \POL@chkopt\POL@oPOL@refine@start[1]%
+}%
+\def\POL@oPOL@refine@start[#1]#2#3{%
\edef\POL@isolz@IntervalIndex{\the\numexpr#3}%
\edef\POL@sturmname{#2}%
\expandafter\POL@refine@sharedbody\expandafter
@@ -2138,8 +1290,8 @@
\fi
}%
\def\POL@refine@loop#1{%
- \let\POL@refine@left@next \@empty % no recursion at end sub-intervals
- \let\POL@refine@right@next\@empty
+ \let\POL@refine@left@next \empty % no recursion at end sub-intervals
+ \let\POL@refine@right@next\empty
\xintiloop[1+1]
\POL@refine@main
\ifnum\POL@IsoRightSign=\z@
@@ -2160,11 +1312,11 @@
\ifnum\POL@IsoRightSign=\z@
\let\POL@IsoLeft@Int\POL@IsoRight@Int % root at 1
\def\POL@IsoLeftSign{0}%
- \let\POL@next\@empty
+ \let\POL@next\empty
\else
\ifnum\POL@IsoRightSign=\POL@@IsoRightSign\space
- \let\POL@next\POL@refine@left@next % may be \@empty or \POL@refine@main for recursion
- \let\POL@refine@right@next\@empty
+ \let\POL@next\POL@refine@left@next % may be \empty or \POL@refine@main for recursion
+ \let\POL@refine@right@next\empty
\else
\let\POL@IsoLeft@Int\POL@IsoRight@Int
\edef\POL@IsoRight@Int{\xintDec{\POL@@IsoRight@Int}}%
@@ -2173,7 +1325,7 @@
\ifnum\POL@IsoRightSign=\z@
\let\POL@IsoLeft@Int\POL@IsoRight@Int % root at 9
\def\POL@IsoLeftSign{0}%
- \let\POL@next\@empty
+ \let\POL@next\empty
\else
\ifnum\POL@IsoRightSign=\POL@@IsoRightSign\space
\let\POL@next\POL@refine@doonce
@@ -2182,7 +1334,7 @@
\let\POL@IsoRight@Int\POL@@IsoRight@Int
\let\POL@IsoRightSign\POL@@IsoRightSign
\let\POL@next\POL@refine@right@next
- \let\POL@refine@left@next\@empty
+ \let\POL@refine@left@next\empty
\fi
\fi
\fi\fi
@@ -2190,18 +1342,16 @@
}%
% lacking pre-defined xintfrac macro here (such as an \xintRawExponent)
\def\POL@refine@getE#1[#2]{#2}% \xintREZ already applied, for safety
-
-
-\newcommand\PolIntervalWidth[2]{%
+%
+%
+\def\PolIntervalWidth#1#2{%
% le \xintRez est à cause des E positifs, car trailing zéros explicites
% si je travaillais à partir des variables xintexpr directement ne devrait
% pas être nécessaire, mais trop fragile par rapport à chgt internes possibles
\romannumeral0\xintrez{\xintSub{\@nameuse{POL_ZR#1*}{#2}}%
{\@nameuse{POL_ZL#1*}{#2}}}
}%
-
-
-\newcommand\PolEnsureIntervalLengths[2]{% #1 = Sturm chain name,
+\def\PolEnsureIntervalLengths#1#2{% #1 = Sturm chain name,
% localize roots in intervals of length at most 10^{#2}
\edef\POL@sturmname{#1}%
\edef\POL@ensure@targetE{\the\numexpr#2}%
@@ -2220,7 +1370,7 @@
\ifnum\POL@nbofroots>\POL@count
\repeat
}%
-\newcommand\PolEnsureIntervalLength[3]{% #1 = Sturm chain name,
+\def\PolEnsureIntervalLength#1#2#3{% #1 = Sturm chain name,
% #2 = index of interval
% localize roots in intervals of length at most 10^{#3}
\edef\POL@sturmname{#1}%
@@ -2230,7 +1380,7 @@
\ifnum\POL@isolz@IntervalIndex>\z@
% 0.7, add this safeguard but attention means this structure must be in place
\ifnum\csname POL_ZL\POL@sturmname*0\endcsname>\z@
-% je ne fais pas les \expandafter mais je préfèrerai ne pas être à l'intérieur
+% je ne fais pas les \expandafter mais je préfèrerais ne pas être à l'intérieur
\POL@ensure@one
\fi
\fi
@@ -2282,24 +1432,39 @@
\expandafter\xintbreakloop
\fi
}%
-
-
+%
+%% \PolPrintIntervals
\catcode`_ 8
-\newcommand\PolPrintIntervals
- {\@ifstar{\PolPrintIntervals@@}{\PolPrintIntervals@}}%
-\newcommand\PolPrintIntervals@@{%
+\catcode`& 4
+\def\PolPrintIntervals{\POL@ifstar{\PolPrintIntervals@@}{\PolPrintIntervals@}}%
+% As explained in the docs, this is an example of customization so is not
+% itself customizable, apart from redefining it entirely!
+\def\PolPrintIntervals@@{%
\begingroup
\def\POL@AfterPrintIntervals{\endgroup}%
- \def\arraystretch{2}%
\let\PolPrintIntervalsPrintExactZero\POL@@PrintIntervalsPrintExactZero
\let\PolPrintIntervalsUnknownRoot\POL@@PrintIntervalsUnknownRoot
\let\PolPrintIntervalsKnownRoot\POL@@PrintIntervalsKnownRoot
+\ifdefined\array
+ \def\arraystretch{2}%
\def\PolPrintIntervalsBeginEnv{\[\begin{array}{cl}}%\]
\def\PolPrintIntervalsEndEnv{\end{array}\]}%
+\else
+ \def\PolPrintIntervalsBeginEnv{$$\tabskip0pt plus 1000pt minus 1000pt
+ \halign to\displaywidth\bgroup
+ \hfil\vrule height 2\ht\strutbox
+ depth 2\dp\strutbox
+ width \z@
+ $####$\tabskip6pt&$####$\hfil
+ \tabskip0pt plus 1000pt minus 1000pt\cr}%$$
+ \def\PolPrintIntervalsEndEnv{\crcr\egroup$$}%$$
+\fi
\PolPrintIntervals@
}%
-\newcommand\PolPrintIntervals@[2][Z]{\POL@PrintIntervals{#1}{#2}}%
-\newcommand\POL@PrintIntervals[2]{%
+\def\PolPrintIntervals@{%
+ \POL@chkopt\POL@oPolPrintIntervals@[Z]%
+}%
+\def\POL@oPolPrintIntervals@[#1]#2{%
\def\PolPrintIntervalsTheVar{#1}%
\def\PolPrintIntervalsTheSturmName{#2}%
\ifnum\@nameuse{POL_ZL#2*}{0}=\z@
@@ -2317,34 +1482,60 @@
\def\PolPrintIntervalsTheVar{#1}%
\def\PolPrintIntervalsTheSturmName{#2}%
}%
-\let\POL@AfterPrintIntervals\@empty
-\newcommand\PolPrintIntervalsNoRealRoots{}%
-\newcommand\PolPrintIntervalsBeginEnv{\[\begin{array}{rcccl}}%
-\newcommand\PolPrintIntervalsEndEnv{\end{array}\]}%
-\newcommand\PolPrintIntervalsKnownRoot{%
+\let\POL@AfterPrintIntervals\empty
+\let\PolPrintIntervalsNoRealRoots\empty
+\def\PolPrintIntervalsArrayStretch{1}%
+\ifdefined\array
+ \def\PolPrintIntervalsBeginEnv{\[\begin{array}{rcccl}}%
+ \def\PolPrintIntervalsEndEnv{\end{array}\]}%
+\else
+ \def\PolPrintIntervalsBeginEnv
+ {$$\tabskip 0pt plus 1000pt minus 1000pt
+ \halign to\displaywidth\bgroup
+ \hfil\vrule height\PolPrintIntervalsArrayStretch\ht\strutbox
+ depth \PolPrintIntervalsArrayStretch\dp\strutbox
+ width \z@
+ $##$\tabskip 6pt &\hfil $##$\hfil &\hfil $##$\hfil &\hfil $##$\hfil &$##$\hfil
+ \tabskip 0pt plus 1000pt minus 1000pt \cr
+ }%$$
+ \def\PolPrintIntervalsEndEnv{\crcr\egroup$$}%$$
+\fi
+\def\PolPrintIntervalsKnownRoot{%
&&\PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}%
&=&\PolPrintIntervalsPrintExactZero
}%
-\newcommand\PolPrintIntervalsUnknownRoot{%
+\def\PolPrintIntervalsUnknownRoot{%
\PolPrintIntervalsPrintLeftEndPoint&<&%
\PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}&<&%
\PolPrintIntervalsPrintRightEndPoint
}%
-\newcommand\PolPrintIntervalsPrintExactZero {\PolPrintIntervalsTheLeftEndPoint}%
-\newcommand\PolPrintIntervalsPrintLeftEndPoint {\PolPrintIntervalsTheLeftEndPoint}%
-\newcommand\PolPrintIntervalsPrintRightEndPoint{\PolPrintIntervalsTheRightEndPoint}%
-\newcommand\PolPrintIntervalsPrintMultiplicity{(\mbox{mult. }\PolPrintIntervalsTheMultiplicity)}%
+\def\PolPrintIntervalsPrintExactZero {\PolPrintIntervalsTheLeftEndPoint}%
+\def\PolPrintIntervalsPrintLeftEndPoint {\PolPrintIntervalsTheLeftEndPoint}%
+\def\PolPrintIntervalsPrintRightEndPoint{\PolPrintIntervalsTheRightEndPoint}%
+%
+\ifdefined\mbox
+\def\PolPrintIntervalsPrintMultiplicity{(\mbox{mult. }\PolPrintIntervalsTheMultiplicity)}%
+\else
+\def\PolPrintIntervalsPrintMultiplicity{(\hbox{mult. }\PolPrintIntervalsTheMultiplicity)}%
+\fi
%
-\newcommand\POL@@PrintIntervalsKnownRoot{%
+\def\POL@@PrintIntervalsKnownRoot{%
\PolPrintIntervalsPrintMultiplicity&%
\PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}=%
\PolPrintIntervalsPrintExactZero
}%
-\newcommand\POL@@PrintIntervalsPrintExactZero{%
+\ifdefined\frac
+\def\POL@@PrintIntervalsPrintExactZero{%
\displaystyle
\xintSignedFrac{\PolPrintIntervalsTheLeftEndPoint}%
}%
-\newcommand\POL@@PrintIntervalsUnknownRoot{%
+\else
+\def\POL@@PrintIntervalsPrintExactZero{%
+ \displaystyle
+ \xintSignedFwOver{\PolPrintIntervalsTheLeftEndPoint}%
+}%
+\fi
+\def\POL@@PrintIntervalsUnknownRoot{%
\PolPrintIntervalsPrintMultiplicity&%
\xintifSgn{\PolPrintIntervalsTheLeftEndPoint}%
{\xintifSgn{\PolPrintIntervalsTheRightEndPoint}
@@ -2364,8 +1555,9 @@
{\PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}=%
\PolPrintIntervalsPrintLeftEndPoint\dots}}%
}%
-%
+\catcode`& 7
\catcode`_ 11
+\def\POL@PrintIntervals@Loop#1{%
\def\POL@PrintIntervals@Loop{%
\POL@SturmIfZeroExactlyKnown\PolPrintIntervalsTheSturmName
\PolPrintIntervalsTheIndex
@@ -2375,9 +1567,10 @@
\unless\ifnum\PolPrintIntervalsTheIndex>
\@nameuse{POL_ZL\PolPrintIntervalsTheSturmName*0}
\POL@PrintIntervals@DoDefs
- \xint_afterfi{\\\POL@PrintIntervals@Loop}%
+ \xint_afterfi{#1\POL@PrintIntervals@Loop}%
\fi
-}%
+}}%
+\ifdefined\array\POL@PrintIntervals@Loop{\\}\else\POL@PrintIntervals@Loop{\cr}\fi
\def\POL@PrintIntervals@DoDefs{%
\xdef\PolPrintIntervalsTheLeftEndPoint{%
\csname POL_ZL\PolPrintIntervalsTheSturmName*\PolPrintIntervalsTheIndex
@@ -2397,492 +1590,60 @@
\fi
}%
}%
-
-
-\newcommand\PolSturmIfZeroExactlyKnown[2]{% #1 = sturmname, #2=index
+%
+%% Expandable interface
+%
+\def\PolSturmIfZeroExactlyKnown#1#2{% #1 = sturmname, #2=index
\romannumeral0\csname POL_ZK#1*\endcsname{#2}%
}%
-\newcommand\POL@SturmIfZeroExactlyKnown[2]{% #1 = sturmname, #2=index
+\def\POL@SturmIfZeroExactlyKnown#1#2{% #1 = sturmname, #2=index
\romannumeral0\csname POL_ZK#1*\the\numexpr#2\endcsname
}%
-\newcommand\PolSturmIsolatedZeroMultiplicity[2]{%
- \romannumeral`^^@\csname POL_ZM#1*\endcsname{#2}%
+\def\PolSturmIsolatedZeroMultiplicity#1#2{%
+ \romannumeral`&&@\csname POL_ZM#1*\endcsname{#2}%
}%
-\newcommand\PolSturmIsolatedZeroLeft[2]{%
- \romannumeral`^^@\csname POL_ZL#1*\endcsname{#2}%
+\def\PolSturmIsolatedZeroLeft#1#2{%
+ \romannumeral`&&@\csname POL_ZL#1*\endcsname{#2}%
}%
-\newcommand\PolSturmIsolatedZeroRight[2]{%
- \romannumeral`^^@\csname POL_ZR#1*\endcsname{#2}%
+\def\PolSturmIsolatedZeroRight#1#2{%
+ \romannumeral`&&@\csname POL_ZR#1*\endcsname{#2}%
}%
-\newcommand\PolSturmNbOfIsolatedZeros[1]{%
- \romannumeral`^^@\csname POL_ZL#1*0\endcsname
+\def\PolSturmNbOfIsolatedZeros#1{%
+ \romannumeral`&&@\csname POL_ZL#1*0\endcsname
}%
-\newcommand\PolSturmRationalRoot[2]{%
- \romannumeral`^^@\csname POL_ZL#1*%
+\def\PolSturmRationalRoot#1#2{%
+ \romannumeral`&&@\csname POL_ZL#1*%
\csname POL_RI#1*\endcsname{#2}\endcsname
}%
-\newcommand\PolSturmRationalRootIndex[2]{%
- \romannumeral`^^@\csname POL_RI#1*\endcsname{#2}%
+\def\PolSturmRationalRootIndex#1#2{%
+ \romannumeral`&&@\csname POL_RI#1*\endcsname{#2}%
}%
-\newcommand\PolSturmRationalRootMultiplicity[2]{%
- \romannumeral`^^@\csname POL_ZM#1%
+\def\PolSturmRationalRootMultiplicity#1#2{%
+ \romannumeral`&&@\csname POL_ZM#1%
*\csname POL_RI#1*\endcsname{#2}\endcsname
}%
-\newcommand\PolSturmNbOfRationalRoots[1]{%
- \romannumeral`^^@\csname POL_RI#1*0\endcsname
+\def\PolSturmNbOfRationalRoots#1{%
+ \romannumeral`&&@\csname POL_RI#1*0\endcsname
}%
-\newcommand\PolSturmNbOfRationalRootsWithMultiplicities[1]{%
+\def\PolSturmNbOfRationalRootsWithMultiplicities#1{%
% means the \POL@norr must not have been changed in-between...
\the\numexpr\PolDegree{#1}-\PolDegree{#1\POL@norr}\relax
}%
-
-
-\let\PolDecToString\xintDecToString
-
-
-\newcommand\PolMakeMonic[1]{%
- \edef\POL@leadingcoeff{\PolLeadingCoeff{#1}}%
- \edef\POL@leadingcoeff@inverse{\xintDiv{1/1[0]}{\POL@leadingcoeff}}%
- \PolMapCoeffs{\xintMul{\POL@leadingcoeff@inverse}}{#1}%
-}%
-
-
-%% 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.
-%%
-%% And it was complicated to let it work with xintexpr 1.4
-%%
-\def\POL@get#1#2#3{%
- \relax %!! part de la tambouille pour fonctionner en xint 1.4
- \POL@polglobalfalse
- \begingroup
- \protected\def\POL@result{#3}%
- #3%
- \expandafter
- \endgroup
- \expandafter\def\expandafter#1\expandafter{\POL@result}%
- \unless\ifPOL@pol
- % avoid expanding more than twice #3
- % #3 must be purely numerical or at least compatible with \edef
- % this is why at 0.7.5 I had to handle especially constant
- % polynomial functions to remove any protection from them
- % (because the protection triggers the COMPOSITION when
- % the polynomial is found as argument of another one and
- % this is not expandable)
- \edef#1{#3}%
- \xintiiifZero{#1}%
- {\def#1{-1.\POL@empty{0/1[0]}}}%
- {\edef#1{0.\POL@empty{#1}}}%
- \fi
- #2%
-}%
-
-%% COMPOSITION
-%% This did not exist before 0.7.5 and is part of its adaptation to xint 1.4
-%% We thus took up this opportunity to speed up substantially composition.
-%% Very serious difficulties with constant polynomials. Had to handle them
-%% especially.
-%% OK, that was really tough, but advantage now is that composition
-%% at 0.7.5 should be more efficient than before. However when polynomials
-%% become big via composition, coefficients also are big and the time
-%% taken by arithmetic dominates. No time to test really, though, relieved
-%% I can release xint 1.4 at last. My basic polexpr test suite passes,
-%% but it goes back already to old releases.
-\protected\def\POL@applypolfunc#1#2%
-{%
-% This #2 may be also invoing \POL@applypolfunc...
- \POL@get\POL@A\POL@applypolfunc@b#2#1%
-}%
-\def\POL@applypolfunc@b #1%
-{%
-% and now the have our Horner scheme nested macro
-% which hopefully will do its job with \POL@add, \POL@mul etc...
- \POL@polglobalfalse
- \expandafter#1\expanded
- {{\POL@polglobaltrue\protected\def\noexpand\POL@result{\POL@A}}}%
- \unless\ifPOL@pol
- \odef\POL@result{#1{0}}%
- \xintiiifZero{\POL@result}%
- {\protected\def\POL@result{-1.\POL@empty{0/1[0]}}}%
- {\protected\edef\POL@result{0.\POL@empty{\POL@result}}}%
- \fi
-}%
-
-%% 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{%
- \POL@polglobaltrue
- \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{%
- \POL@polglobaltrue
- \POL@ifZero\POL@A
- {\protected\def\POL@result{-1.\POL@empty{0/1[0]}}}%
- {\POL@ifZero\POL@B
- {\protected\def\POL@result{-1.\POL@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{%
- \POL@polglobalfalse
- \begingroup
- \protected\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}%
- {\protected\def\POL@result{-1.\POL@empty{0/1[0]}}}%
- {\protected\edef\POL@result{0.\POL@empty{\POL@A}}}%
- \else
- \edef\POL@B{\numexpr\xintNum{#2}\relax}% no check on exponent >= 0
- \ifcase\POL@B
- \protected\def\POL@result{0.\POL@empty{1/1[0]}}%
- \or
- \let\POL@result\POL@A
- \else
- \POL@@pow@check
- \fi
- \fi
- \POL@polglobaltrue
-}%
-\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 (\POL@empty)
- \edef\POL@A{\expandafter\xintScalarPow\romannumeral`^^@%
- \expandafter\xint_gob_til_dot\POL@A{\POL@B}}%
- \xintiiifZero{\POL@A}%
- {\protected\def\POL@result{-1.\POL@empty{0/1[0]}}}%
- {\protected\edef\POL@result{0.\POL@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}
- {\protected\edef\POL@result
- {\the\POL@B.% here at least 2.
- \POL@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}\POL@polglobaltrue}%
- {\protected\def\POL@result{#1}\POL@polglobaltrue}%
-}%
-
-%% 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{%
- \POL@polglobaltrue
- \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{%
- \POL@polglobalfalse
- \begingroup
- \protected\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}%
- {\protected\def\POL@result{-1.\POL@empty{0/1[0]}}}%
- {\protected\edef\POL@result{0.\POL@empty{\POL@A}}}%
- \else
- \edef\POL@B{0.\POL@empty{-1/1[0]}}%
- \POL@@mul
- \fi
- \POL@polglobaltrue
-}%
-
-
-%% EXPANDABLE MACROS
-\def\POL@eval@fork#1\At#2#3\krof{#2}%
-\newcommand\PolEval[3]{\romannumeral`^^@\POL@eval@fork
- #2\PolEvalAt
- \At\PolEvalAtExpr\krof {#1}{#3}%
-}%
-\newcommand\PolEvalAt[2]
- {\xintpraw{\csname XINT_expr_polfunc_#1\endcsname{#2}}}%
-\newcommand\POL@eval[2]
- {\csname XINT_expr_polfunc_#1\endcsname{#2}}%
-\newcommand\PolEvalAtExpr[2]{\xinttheexpr #1(#2)\relax}%
-%
-\newcommand\PolEvalReduced[3]{\romannumeral`^^@\POL@eval@fork
- #2\PolEvalReducedAt
- \At\PolEvalReducedAtExpr\krof {#1}{#3}%
-}%
-\newcommand\PolEvalReducedAt[2]{%
- \xintpraw % in order not to print denominator if the latter equals 1
- {\xintIrr{\csname XINT_expr_polfunc_#1\endcsname{#2}}[0]}%
-}%
-\newcommand\PolEvalReducedAtExpr[2]{%
- \xintpraw
- {\expandafter\xintIrr\romannumeral`^^@\xintthebareeval#1(#2)\relax[0]}%
-}%
-%
-\newcommand\PolFloatEval[3]{\romannumeral`^^@\POL@eval@fork
- #2\PolFloatEvalAt
- \At\PolFloatEvalAtExpr\krof {#1}{#3}%
-}%
-\newcommand\PolFloatEvalAt[2]
- {\xintpfloat{\csname XINT_flexpr_polfunc_#1\endcsname{#2}}}%
-\newcommand\PolFloatEvalAtExpr[2]{\xintthefloatexpr #1(#2)\relax}%
-
-
-\newcommand\PolSturmIntervalIndex[3]{\the\numexpr\POL@eval@fork
+\def\PolSturmIntervalIndex#1#2#3{\the\numexpr\POL@eval@fork
#2\PolSturmIntervalIndexAt
\At\PolSturmIntervalIndexAtExpr\krof {#1}{#3}%
}%
-\newcommand\PolSturmIntervalIndexAtExpr[2]
- {\PolSturmIntervalIndexAt{#1}{\xinttheexpr#2\relax}}%
-\newcommand\PolSturmIntervalIndexAt[2]
- {\expandafter\POL@sturm@index@at\romannumeral`^^@#2!{#1}\xint_bye\relax}%
+\def\PolSturmIntervalIndexAtExpr#1#2{%
+ \PolSturmIntervalIndexAt{#1}{\xinttheexpr#2\relax}%
+}%
+% ! is of catcode 11 in all of polexpr
+\def\PolSturmIntervalIndexAt#1#2{%
+ \expandafter\POL@sturm@index@at\romannumeral`&&@#2!{#1}\xint_bye\relax
+}%
\def\POL@sturm@index@at#1!#2%
{%
\expandafter\POL@sturm@index@at@iloop
- \romannumeral`^^@\PolSturmNbOfIsolatedZeros{#2}!{#2}{#1}%
+ \romannumeral`&&@\PolSturmNbOfIsolatedZeros{#2}!{#2}{#1}%
}%
% implementation is sub-optimal as it should use some kind of binary tree
% search rather than comparing to the intervals from right to left as here
@@ -2906,19 +1667,18 @@
}%
{}%
}%
- % catcode of ! is 11 in polexpr.sty
+ % attention that catcode of ! is 11 in polexpr.sty
\expandafter\POL@sturm@index@at@iloop\the\numexpr#1-\@ne !{#2}{#3}%
}%
-
-
+%
\def\POL@leq@fork#1\LessThanOrEqualTo#2#3\krof{#2}%
-\newcommand\PolSturmNbOfRootsOf[3]{\romannumeral`^^@\POL@leq@fork
+\def\PolSturmNbOfRootsOf#1#2#3{\romannumeral`&&@\POL@leq@fork
#2\PolNbOfRootsLessThanOrEqualTo
\LessThanOrEqualTo\PolNbOfRootsLessThanOrEqualToExpr\krof {#1}{#3}%
}%
-\newcommand\PolNbOfRootsLessThanOrEqualToExpr[2]
+\def\PolNbOfRootsLessThanOrEqualToExpr#1#2
{\PolNbOfRootsLessThanOrEqualTo{#1}{\xinttheexpr#2\relax}}%
-\newcommand\PolNbOfRootsLessThanOrEqualTo[1]{%
+\def\PolNbOfRootsLessThanOrEqualTo#1{%
\ifnum\PolSturmNbOfIsolatedZeros{#1}=\z@
\expandafter\xint_firstofthree\expandafter0%
\else
@@ -2927,7 +1687,7 @@
}%
\def\PolNbOfRootsLessThanOrEqualTo@ #1#2%
{%
- \expandafter\POL@nbofrootsleq@prep\romannumeral`^^@#2!{#1}%
+ \expandafter\POL@nbofrootsleq@prep\romannumeral`&&@#2!{#1}%
}%
\def\POL@nbofrootsleq@prep#1!#2%
{%
@@ -2959,16 +1719,16 @@
\def\POL@nbofrootsleq@return #1!#2!#3!#4!#5{\the\numexpr #1\relax}%
\def\POL@nbofrootsleq@rightmost\expandafter\POL@nbofrootsleq@iloop
\the\numexpr\@ne+#1!#2!#3!#4{#1}%
-
-
-\newcommand\PolSturmNbWithMultOfRootsOf[3]
-{\the\numexpr0\POL@leq@fork
+%
+\def\PolSturmNbWithMultOfRootsOf#1#2#3{%
+ \the\numexpr0\POL@leq@fork
#2\PolNbWithMultOfRootsLessThanOrEqualTo
\LessThanOrEqualTo\PolNbWithMultOfRootsLessThanOrEqualToExpr\krof {#1}{#3}%
}%
-\newcommand\PolNbWithMultOfRootsLessThanOrEqualToExpr[2]
- {\PolNbWithMultOfRootsLessThanOrEqualTo{#1}{\xinttheexpr#2\relax}}%
-\newcommand\PolNbWithMultOfRootsLessThanOrEqualTo[1]{%
+\def\PolNbWithMultOfRootsLessThanOrEqualToExpr#1#2{%
+ \PolNbWithMultOfRootsLessThanOrEqualTo{#1}{\xinttheexpr#2\relax}%
+}%
+\def\PolNbWithMultOfRootsLessThanOrEqualTo#1{%
\ifnum\PolSturmNbOfIsolatedZeros{#1}=\z@
\expandafter\POL@nbwmofroots@noroots
\else
@@ -2978,7 +1738,7 @@
\def\POL@nbwmofroots@noroots#1#2{\relax}%
\def\PolNbWithMultOfRootsLessThanOrEqualTo@ #1#2%
{%
- \expandafter\POL@nbwmofrootsleq@prep\romannumeral`^^@#2!{#1}%
+ \expandafter\POL@nbwmofrootsleq@prep\romannumeral`&&@#2!{#1}%
}%
\def\POL@nbwmofrootsleq@prep#1!#2%
{%
@@ -3012,153 +1772,4 @@
#1!#2!#3!{#4}%
}%
\def\POL@nbwmofrootsleq@return #1!#2!#3!#4!#5{#1\relax}%
-
-
-\newcommand\PolLeadingCoeff[1]{%
- \romannumeral`^^@\expandafter\expandafter\expandafter\xintlastitem
- \expandafter\expandafter\expandafter
- {\csname POLuserpol@#1\endcsname}%
-}%
-%
-\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}}}%
-
-
-\newcommand\PolToExprCmd[1]{\xintPRaw{\xintRawWithZeros{#1}}}%
-\newcommand\PolToFloatExprCmd[1]{\xintFloat{#1}}%
-\let\PolToExprTermPrefix\PolTypesetCmdPrefix
-\newcommand\PolToExprOneTermStyleA[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
-}%
-\let\PolToExprOneTerm\PolToExprOneTermStyleA
-\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\POL@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 (\POL@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.%
-}%
-
-
-\POL@restorecatcodes
\endinput