From f6a51c75352a2ec3f36f78893ab07879ea22bf77 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Mon, 9 Apr 2018 21:18:59 +0000 Subject: polexpr (9apr18) git-svn-id: svn://tug.org/texlive/trunk@47412 c570f23f-e606-0410-a88d-b1316a301751 --- Master/texmf-dist/tex/latex/polexpr/polexpr.sty | 237 ++++++++++++++++-------- 1 file changed, 159 insertions(+), 78 deletions(-) (limited to 'Master/texmf-dist/tex') diff --git a/Master/texmf-dist/tex/latex/polexpr/polexpr.sty b/Master/texmf-dist/tex/latex/polexpr/polexpr.sty index 7e132905392..02d3ecdec76 100644 --- a/Master/texmf-dist/tex/latex/polexpr/polexpr.sty +++ b/Master/texmf-dist/tex/latex/polexpr/polexpr.sty @@ -1,7 +1,7 @@ % author: Jean-François Burnol % License: LPPL 1.3c (author-maintained) \ProvidesPackage{polexpr}% - [2018/03/03 v0.4.2 Polynomial expressions with rational coefficients (JFB)]% + [2018/04/08 v0.5 Polynomial expressions with rational coefficients (JFB)]% \RequirePackage{xintexpr}[2018/03/01]% xint 1.3 \edef\POL@restorecatcodes {\catcode`\noexpand\_ \the\catcode`\_ \catcode0 \the\catcode0\relax}% @@ -24,7 +24,7 @@ \else\expandafter\xint_secondoftwo \fi}% \def\POL@split#1.#2;#3#4% separates degree and list of coefficients -% The \empty token is to avoid brace removal issues for degree 0 polynomials +% 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 @@ -64,8 +64,8 @@ \let\xintPow\POL@pow \let\xintOpp\POL@opp \def\xintSub ##1##2{\xintAdd{##1}{\xintOpp{##2}}}% - % \xintAdd to get \POL@result defined even if numerical only expression - % I could also test \ifPOL@pol, but well, this is very small overhead + % \xintAdd{0} to get \POL@result defined even if numerical only expression + % I could also test \ifPOL@pol, but this is anyhow small overhead \xintAdd{0}% {\csname XINT_expr_userfunc___pol\endcsname {\global\POL@poltrue\def\POL@result{1.\empty{0/1[0]}{1/1[0]}}}}% @@ -209,32 +209,45 @@ }% -\newcommand\PolGet{} +\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, - % must be > 0, else could create infinite loop + \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 +% 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@}}% - \xintiiifZero{\POL@tmp}% - {\iftrue}% - {\iffalse}% - \advance\count@\m@ne + \edef\POL@tmp{\xintRaw{\POL@tmp}}% + \expandafter\let\csname POL@tmparray\the\count@\endcsname\POL@tmp \repeat -% should I use \xintRaw ? but if #2 expands only in an \edef, problem -% (but it is not very probable the #2 macro does not already give completely -% expanded contents), I would need to proceed in two steps. Or the \xintRaw -% could get injected at level of \POL@newpol - \def\POL@tmp##1.{{#2{##1}}}% + \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 @@ -325,14 +338,14 @@ }% \def\POL@mapcoeffs#1#2{% \begingroup - \def\POL@map@macro{#1}% + \def\POL@mapcoeffs@macro{#1}% \expandafter\expandafter\expandafter\POL@split - \csname POLuserpol@#2\endcsname;\POL@var@deg\POL@var@coeffs + \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@var@coeffs\to\POL@arrayA + \xintAssignArray\POL@mapcoeffs@coeffs\to\POL@arrayA \def\index{0}% \count@\z@ - \expandafter\POL@map@loop\expandafter.\POL@var@coeffs\relax + \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}% @@ -349,7 +362,7 @@ }% \def\POL@map@loop.#1{\if\relax#1\expandafter\xint_gob_til_dot\fi \advance\count@\@ne - \edef\POL@map@coeff{\POL@map@macro{#1}}% + \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}% @@ -620,28 +633,61 @@ \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]{% + \edef\POL@makeprim@icontent{\PolIContent{#1}}% + \PolMapCoeffs\POL@makeprim@macro{#1}% +}% + %% Sturm Algorithm (polexpr 0.4) +%% 0.5 uses primitive polynomials for faster evaluations afterwards \newcommand\PolToSturm{% \@ifstar{\POL@sturm@normalizefalse}{\POL@sturm@normalizetrue}% \POL@ToSturm }% -\newcommand\POL@ToSturm[2]{% +\def\POL@aux@toint#1{\xintREZ{\xintNum{#1}}}% +\def\POL@ToSturm#1#2{% \edef\POL@sturmname{#2}% \POL@let{\POL@sturmname _0}{#1}% - \POL@mapcoeffs{\xintPIrr}{\POL@sturmname _0}% + \PolMakePrimitive{\POL@sturmname _0}% \POL@Diff@@one{\POL@sturmname _0}{\POL@sturmname _1}% + % re-utiliser \POL@varcoeffs directement? + \PolMakePrimitive{\POL@sturmname _1}% \POL@count\@ne \xintloop \POL@divide{\POL@sturmname _\the\numexpr\POL@count-\@ne}% {\POL@sturmname _\the\POL@count}% \expandafter\POL@split\POL@R;\POL@degR\POL@polR \unless\ifnum\POL@degR=\m@ne - % suis-je sûr format raw certain? - \edef\POL@polR{\xintApply{\POL@dooppandirr}{\POL@polR}}% \advance\POL@count\@ne - \expandafter\edef\csname POLuserpol@\POL@sturmname _\the\POL@count\endcsname - {\POL@degR.\noexpand\empty\POL@polR}% + \expandafter\let + \csname POLuserpol@\POL@sturmname _\the\POL@count\endcsname\POL@R + \edef\POL@makeprim@icontent{-\POL@icontent\POL@polR}% + \POL@mapcoeffs\POL@makeprim@macro{\POL@sturmname _\the\POL@count}% \repeat \edef\POL@sturm@N{\the\POL@count}% \ifPOL@sturm@normalize @@ -650,12 +696,10 @@ \advance\POL@count\m@ne \POL@divide{\POL@sturmname _\the\POL@count}% {\POL@sturmname _\POL@sturm@N}% - \expandafter\POL@split\POL@Q;\POL@degQ\POL@polQ - \edef\POL@polQ % suis-je sûr format raw certain? - {\xintApply{\expandafter\XINT_pirr_start\xint_firstofone}{\POL@polQ}}% - \edef\POL@Q{\POL@degQ.\noexpand\empty\POL@polQ}% - \expandafter\edef\csname POLuserpol@\POL@sturmname _\the\POL@count\endcsname - {\POL@degQ.\noexpand\empty\POL@polQ}% + \expandafter\let + \csname POLuserpol@\POL@sturmname _\the\POL@count\endcsname\POL@Q + % quotient actually belongs to Z[X] + \POL@mapcoeffs{\POL@aux@toint}{\POL@sturmname _\the\POL@count}% \ifnum\POL@count>\z@ \repeat \@namedef{POLuserpol@\POL@sturmname _\POL@sturm@N}{0.\empty{1/1[0]}}% @@ -667,9 +711,10 @@ \unless\ifnum\POL@sturm@N=\POL@count \advance\POL@count\@ne \repeat - \expandafter\let\csname PolSturmChainLength_\POL@sturmname \endcsname\POL@sturm@N + \expandafter\let + \csname PolSturmChainLength_\POL@sturmname \endcsname\POL@sturm@N }% -\def\POL@dooppandirr#1{\xintiiOpp{\XINT_pirr_start#1}}% + \newcommand\PolSturmChainLength[1] {\romannumeral`^^@\csname PolSturmChainLength_#1\endcsname}% \newcommand\PolSetToSturmChainSignChangesAt[4][\global]{% @@ -681,8 +726,8 @@ }% \def\POL@sturmchain@getSV@at#1{% ATTENTION USES \POL@count \def\POL@sturmchain@SV{0}% - \edef\POL@isolz@lastsign{\xintiiSgn{\PolEval{\POL@sturmname _0}\At{#1}}}% - \let\POL@IsoRightSign\POL@isolz@lastsign % needed only for SturmIsolate etc... + \edef\POL@sturmchain@sign{\xintiiSgn{\PolEval{\POL@sturmname _0}\At{#1}}}% + \let\POL@isolz@lastsign\POL@sturmchain@sign \POL@count \z@ \ifnum\POL@isolz@lastsign=\z@ \edef\POL@isolz@lastsign @@ -717,17 +762,63 @@ }% -\newcommand\PolSturmIsolateZeros[1]{% - % #1 name of Sturm chain (already pre-computed from a given polynomial) - \edef\POL@sturmname{#1}% - \edef\POL@sturmlength{\PolSturmChainLength{#1}}% +\newcommand\PolSturmIsolateZeros[2][\empty]{% + % #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) + \edef\POL@sturmname{#2}% + \edef\POL@sturmlength{\PolSturmChainLength{#2}}% + \ifx\empty#1\relax + \POL@isolz@getsignchanges@plusinf + \POL@isolz@getsignchanges@minusinf + \else + \edef\POL@isolz@E{\the\numexpr\xint_zapspaces #1 \xint_gobble_i\relax}% + \POL@sturmchain@getSV@at{1[\POL@isolz@E]}% + \let\POL@isolz@plusinf@SV \POL@sturmchain@SV + \let\POL@isolz@plusinf@sign\POL@sturmchain@sign + \POL@sturmchain@getSV@at{-1[\POL@isolz@E]}% + \let\POL@isolz@minusinf@SV \POL@sturmchain@SV + \let\POL@isolz@minusinf@sign\POL@sturmchain@sign + \ifnum\POL@isolz@plusinf@sign=\z@ + \PackageError{polexpr}% +{The polynomial #2 vanishes at set upper bound 10^\POL@isolz@E}% +{Compile again with a bigger exponent in source. (X to abort).}% + \fi + \ifnum\POL@isolz@minusinf@sign=\z@ + \PackageError{polexpr}% +{The polynomial #2 vanishes at set lower bound -10^\POL@isolz@E}% +{Compile again with a bigger exponent in source. (X to abort).}% + \fi + \fi + \edef\POL@isolz@NbOfRoots + {\the\numexpr\POL@isolz@minusinf@SV-\POL@isolz@plusinf@SV}% + \ifnum\POL@isolz@NbOfRoots=\z@ + \begingroup\globaldefs\@ne + \expandafter\xintAssignArray\expandafter\to\csname POL_ZeroInt#2L\endcsname + \expandafter\xintAssignArray\expandafter\to\csname POL_ZeroInt#2R\endcsname + \endgroup + \else + \begingroup\globaldefs\@ne + \expandafter\POL@isolz@initarray\csname POL_ZeroInt#2L\endcsname + \expandafter\POL@isolz@initarray\csname POL_ZeroInt#2R\endcsname + \endgroup + \ifx\empty#1\relax\expandafter\POL@isolz@getaprioribound\fi + \expandafter\POL@isolz@main + \fi +}% +\def\POL@isolz@initarray#1{% + \expandafter\xintAssignArray + \romannumeral\xintreplicate{\POL@isolz@NbOfRoots}{{0}}\to#1% +}% +\def\POL@isolz@getsignchanges@plusinf{% % Count number of sign changes at plus infinity in Sturm sequence \def\POL@isolz@plusinf@SV{0}% - \edef\POL@isolz@lastsign{\xintiiSgn{\PolLeadingCoeff{#1_0}}}% + \edef\POL@isolz@lastsign{\xintiiSgn{\PolLeadingCoeff{\POL@sturmname _0}}}% \let\POL@isolz@plusinf@sign\POL@isolz@lastsign \POL@count\@ne \xintloop - \edef\POL@isolz@newsign{\xintiiSgn{\PolLeadingCoeff{#1_\the\POL@count}}}% + \edef\POL@isolz@newsign + {\xintiiSgn{\PolLeadingCoeff{\POL@sturmname _\the\POL@count}}}% \unless\ifnum\POL@isolz@newsign=\POL@isolz@lastsign \edef\POL@isolz@plusinf@SV{\the\numexpr\POL@isolz@plusinf@SV+\@ne}% \fi @@ -735,17 +826,20 @@ \ifnum\POL@sturmlength>\POL@count \advance\POL@count\@ne \repeat +}% +\def\POL@isolz@getsignchanges@minusinf{% % Count number of sign changes at minus infinity in Sturm sequence \def\POL@isolz@minusinf@SV{0}% - \edef\POL@isolz@lastsign{\xintiiSgn{\PolLeadingCoeff{#1_0}}}% - \ifodd\PolDegree{#1_0} + \edef\POL@isolz@lastsign{\xintiiSgn{\PolLeadingCoeff{\POL@sturmname _0}}}% + \ifodd\PolDegree{\POL@sturmname _0} \edef\POL@isolz@lastsign{\xintiiOpp{\POL@isolz@lastsign}}% \fi \let\POL@isolz@minusinf@sign\POL@isolz@lastsign \POL@count\@ne \xintloop - \edef\POL@isolz@newsign{\xintiiSgn{\PolLeadingCoeff{#1_\the\POL@count}}}% - \ifodd\PolDegree{#1_\the\POL@count} + \edef\POL@isolz@newsign + {\xintiiSgn{\PolLeadingCoeff{\POL@sturmname _\the\POL@count}}}% + \ifodd\PolDegree{\POL@sturmname _\the\POL@count} \edef\POL@isolz@newsign{\xintiiOpp{\POL@isolz@newsign}}% \fi \unless\ifnum\POL@isolz@newsign=\POL@isolz@lastsign @@ -755,24 +849,6 @@ \ifnum\POL@sturmlength>\POL@count \advance\POL@count\@ne \repeat - \edef\POL@isolz@NbOfRoots - {\the\numexpr\POL@isolz@minusinf@SV-\POL@isolz@plusinf@SV}% - \ifnum\POL@isolz@NbOfRoots=\z@ - \begingroup\globaldefs\@ne - \expandafter\xintAssignArray\expandafter\to\csname POL_ZeroInt#1L\endcsname - \expandafter\xintAssignArray\expandafter\to\csname POL_ZeroInt#1R\endcsname - \endgroup - \else - \begingroup\globaldefs\@ne - \expandafter\POL@isolz@initarray\csname POL_ZeroInt#1L\endcsname - \expandafter\POL@isolz@initarray\csname POL_ZeroInt#1R\endcsname - \endgroup - \expandafter\POL@isolz@getaprioribound - \fi -}% -\def\POL@isolz@initarray#1{% - \expandafter\xintAssignArray - \romannumeral\xintreplicate{\POL@isolz@NbOfRoots}{{0}}\to#1% }% % utility macro for a priori bound on root decimal exponent, via Float Rounding \def\POL@isolz@updateE #1e#2;% @@ -800,7 +876,6 @@ % \ifxintverbose\xintMessage{polexpr}{Info}% % {Roots a priori bounded in absolute value by 10 to the \POL@isolz@E.}% % \fi - \POL@isolz@main }% \def\POL@IsoRight@raw{\POL@IsoRight@Int/1[\POL@isolz@E]}% \def\POL@IsoLeft@raw {\POL@IsoLeft@Int/1[\POL@isolz@E]}% @@ -817,8 +892,9 @@ \global\POL@isolz@nextwillneedrefinefalse \def\POL@IsoRight@Int{0}% \POL@sturmchain@getSV@at\POL@IsoRight@raw - \let\POL@IsoRightSV\POL@sturmchain@SV - \let\POL@IsoAtZeroSV\POL@IsoRightSV + \let\POL@IsoRightSV \POL@sturmchain@SV + \let\POL@IsoRightSign\POL@sturmchain@sign + \let\POL@IsoAtZeroSV \POL@IsoRightSV \let\POL@IsoAtZeroSign\POL@IsoRightSign \ifnum\POL@IsoAtZeroSign=\z@ \xdef\POL@isolz@IntervalIndex @@ -830,7 +906,7 @@ {\xintiiOpp{\xintiiSgn{\PolEval{\POL@sturmname _1}\At{0/1[0]}}}}% \fi \def\POL@IsoLeft@Int{-1}% -10^E isn't a root! - \let\POL@IsoLeftSV\POL@isolz@minusinf@SV + \let\POL@IsoLeftSV \POL@isolz@minusinf@SV \let\POL@IsoLeftSign\POL@isolz@minusinf@sign \edef\POL@isolz@NbOfNegRoots{\the\numexpr\POL@IsoLeftSV-\POL@IsoRightSV}% \gdef\POL@isolz@IntervalIndex{0}% @@ -842,7 +918,8 @@ \xintloop \edef\POL@isolz@E{\the\numexpr\POL@isolz@E-\@ne}% \POL@sturmchain@getSV@at\POL@IsoRight@raw - \let\POL@IsoRightSV\POL@sturmchain@SV + \let\POL@IsoRightSV \POL@sturmchain@SV + \let\POL@IsoRightSign\POL@sturmchain@sign % would an \ifx test be quicker? (to be checked) \ifnum\POL@IsoRightSV=\POL@IsoLeftSV\space % no roots in-between, sign and SV kept @@ -854,7 +931,8 @@ \edef\POL@IsoRight@Int{\the\numexpr\POL@IsoLeft@Int+\@ne}% % we could arguably do a more efficient dichotomy here \POL@sturmchain@getSV@at\POL@IsoRight@raw - \let\POL@IsoRightSV\POL@sturmchain@SV + \let\POL@IsoRightSV \POL@sturmchain@SV + \let\POL@IsoRightSign\POL@sturmchain@sign \POL@isolz@check \ifnum\POL@isolz@IntervalIndex=\POL@isolz@NbOfNegRoots\space \expandafter\xintbreakloop @@ -883,7 +961,7 @@ \fi \endgroup \def\POL@IsoLeft@Int{0}% - \let\POL@IsoLeftSV\POL@IsoAtZeroSV + \let\POL@IsoLeftSV \POL@IsoAtZeroSV \let\POL@IsoLeftSign\POL@IsoAtZeroSign \ifnum\POL@IsoLeftSign=\z@ \xdef\POL@isolz@IntervalIndex{\the\numexpr\POL@isolz@IntervalIndex+\@ne}% @@ -891,8 +969,8 @@ \else \global\POL@isolz@nextwillneedrefinefalse \fi - \let\POL@@IsoRightSV=\POL@isolz@plusinf@SV - \let\POL@@IsoRightSign=\POL@isolz@plusinf@sign % 10^E not a root! + \let\POL@@IsoRightSV \POL@isolz@plusinf@SV + \let\POL@@IsoRightSign\POL@isolz@plusinf@sign % 10^E not a root! \edef\POL@isolz@NbOfPosRoots {\the\numexpr\POL@IsoLeftSV-\POL@@IsoRightSV}% attention @@ \ifnum\POL@isolz@NbOfPosRoots>\z@ @@ -900,7 +978,8 @@ \xintloop \edef\POL@isolz@E{\the\numexpr\POL@isolz@E-\@ne}% \POL@sturmchain@getSV@at\POL@IsoRight@raw - \let\POL@IsoRightSV\POL@sturmchain@SV + \let\POL@IsoRightSV \POL@sturmchain@SV + \let\POL@IsoRightSign\POL@sturmchain@sign \ifnum\POL@IsoRightSV=\POL@@IsoRightSV\space \let\POL@@IsoRightSign\POL@IsoRightSign % root here possible! \repeat @@ -914,7 +993,8 @@ % we could arguably do a more efficient dichotomy here \edef\POL@IsoRight@Int{\the\numexpr\POL@IsoLeft@Int+\@ne}% \POL@sturmchain@getSV@at\POL@IsoRight@raw - \let\POL@IsoRightSV\POL@sturmchain@SV + \let\POL@IsoRightSV \POL@sturmchain@SV + \let\POL@IsoRightSign\POL@sturmchain@sign \POL@isolz@check \let\POL@IsoLeft@Int\POL@IsoRight@Int \let\POL@IsoLeftSign\POL@IsoRightSign @@ -925,7 +1005,7 @@ \ifnum\POL@IsoLeft@Int < \xint_c_ix \repeat \ifnum\POL@isolz@IntervalIndex<\POL@isolz@NbOfRoots\space - % get now the last, right most, root (or roots) + % get now the last, rightmost, root (or roots) \def\POL@IsoRight@Int{10}% \let\POL@IsoRightSign\POL@@IsoRightSign \let\POL@IsoRightSV\POL@@IsoRightSV @@ -976,7 +1056,8 @@ \xintiloop[1+1] \edef\POL@IsoRight@Int{\xintInc{\POL@IsoLeft@Int}}% \POL@sturmchain@getSV@at\POL@IsoRight@raw - \let\POL@IsoRightSV\POL@sturmchain@SV + \let\POL@IsoRightSV \POL@sturmchain@SV + \let\POL@IsoRightSign\POL@sturmchain@sign \POL@isolz@check \let\POL@IsoLeft@Int\POL@IsoRight@Int \let\POL@IsoLeftSV\POL@IsoRightSV -- cgit v1.2.3