summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/polexpr
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2020-02-02 03:02:06 +0000
committerNorbert Preining <norbert@preining.info>2020-02-02 03:02:06 +0000
commite05dc0bb38b16bfb9ba35591285e40af0adaadc4 (patch)
tree564fc3b7389c845780f5685d16fe13ae29372fb4 /macros/latex/contrib/polexpr
parent5bcf334281674db82263ea71485108bd44a05a5d (diff)
CTAN sync 202002020302
Diffstat (limited to 'macros/latex/contrib/polexpr')
-rw-r--r--macros/latex/contrib/polexpr/README.md6
-rw-r--r--macros/latex/contrib/polexpr/polexpr.html5
-rw-r--r--macros/latex/contrib/polexpr/polexpr.sty424
-rw-r--r--macros/latex/contrib/polexpr/polexpr.txt7
4 files changed, 335 insertions, 107 deletions
diff --git a/macros/latex/contrib/polexpr/README.md b/macros/latex/contrib/polexpr/README.md
index 29c0d2f5ab..a901b56adc 100644
--- a/macros/latex/contrib/polexpr/README.md
+++ b/macros/latex/contrib/polexpr/README.md
@@ -4,7 +4,7 @@ Package polexpr README
License
-------
-Copyright (C) 2018-2019 Jean-François Burnol
+Copyright (C) 2018-2020 Jean-François Burnol
See documentation of package [xint](http://www.ctan.org/pkg/xint) for
contact information.
@@ -81,8 +81,10 @@ Releases
- 0.7.4 (2019/02/12)
Bugfix: 20000000000 is too big for \numexpr, shouldn't I know that?
Thanks to Jürgen Gilg for report.
+- 0.7.5 (2020/01/31)
+ Synced with xint 1.4. Requires it.
-Files of 0.7.4 release:
+Files of 0.7.5 release:
- README.md,
- polexpr.sty (package file),
diff --git a/macros/latex/contrib/polexpr/polexpr.html b/macros/latex/contrib/polexpr/polexpr.html
index 6fc48c2dd6..7496332976 100644
--- a/macros/latex/contrib/polexpr/polexpr.html
+++ b/macros/latex/contrib/polexpr/polexpr.html
@@ -362,7 +362,7 @@ ul.auto-toc {
<body>
<div class="document" id="package-polexpr-documentation">
<h1 class="title">Package polexpr documentation</h1>
-<h2 class="subtitle" id="id1">0.7.4 (2019/02/12)</h2>
+<h2 class="subtitle" id="id1">0.7.5 (2020/01/31)</h2>
<!-- comment: -*- fill-column: 72; mode: rst; -*- -->
<div class="contents topic" id="contents">
@@ -2891,6 +2891,9 @@ Thanks to Jürgen Gilg for report.</li>
</li>
</ul>
</li>
+<li><p class="first">v0.7.5 (2020/01/31)</p>
+<p>Synced with xint 1.4. Requires it.</p>
+</li>
</ul>
</div>
<div class="section" id="acknowledgments">
diff --git a/macros/latex/contrib/polexpr/polexpr.sty b/macros/latex/contrib/polexpr/polexpr.sty
index e9509d8942..30fef28914 100644
--- a/macros/latex/contrib/polexpr/polexpr.sty
+++ b/macros/latex/contrib/polexpr/polexpr.sty
@@ -1,33 +1,178 @@
% author: Jean-François Burnol
% License: LPPL 1.3c (author-maintained)
\ProvidesPackage{polexpr}%
- [2019/02/12 v0.7.4 Polynomial expressions with rational coefficients (JFB)]%
-\RequirePackage{xintexpr}[2018/06/17]% xint 1.3c for \ifxintglobaldefs boolean
-\edef\POL@restorecatcodes
+ [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}%
-%% PATCH xintexpr TO AUTHORIZE ' IN NAMES (0.5.1)
-\catcode`\! 11
+%% 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%
{%
- \ifx !#1\xint_dothis{(_}\fi
- \ifcat \relax#1\xint_dothis{(_}\fi
- \if (#1\xint_dothis{\xint_firstoftwo{(`}}\fi
- \if '#1\xint_dothis \XINT_expr_scanfunc_a \fi
- \if @#1\xint_dothis \XINT_expr_scanfunc_a \fi
- \if _#1\xint_dothis \XINT_expr_scanfunc_a \fi
- \ifnum \xint_c_ix<1\string#1 \xint_dothis \XINT_expr_scanfunc_a \fi
- \ifcat a#1\xint_dothis \XINT_expr_scanfunc_a \fi
- \xint_orthat {(_}%
- #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
@@ -46,7 +191,6 @@
\polexprsetup{norr=_norr, sqfnorr=_sqf_norr}
\newcount\POL@count
-\newif\ifPOL@pol
\newif\ifxintveryverbose
\newif\ifpoltypesetall
\newif\ifPOL@tosturm@makefirstprimitive
@@ -54,7 +198,7 @@
\newif\ifPOL@isolz@nextwillneedrefine
\newif\ifpoltoexprall
%% the main exchange structure (stored in macros \POLuserpol@<name>)
-%% is: degree.\empty{coeff0}{coeff1}....{coeffN}
+%% 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;}%
@@ -67,13 +211,17 @@
%
\def\POL@resultfromarray #1{% ATTENTION, **MUST** be executed with
% \count@ set to 1 + degree (\count@ = 0 for zero polynomial)
- \edef\POL@result{\ifnum\count@>\z@
- \the\numexpr\count@-\@ne.\noexpand\empty
+% 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
- \else-1.\noexpand\empty{0/1[0]}\fi}%
+% 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
@@ -85,12 +233,11 @@
\POL@restoresemicolon
\edef\POL@tmp{\ifxintverbose1\else0\fi}%
\unless\ifxintveryverbose\xintverbosefalse\fi
- \let\POL@originalXINT_expr_scanfunc_b\XINT_expr_scanfunc_b
- \let\XINT_expr_scanfunc_b\POL@XINT_expr_scanfunc_b
+ \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}%
- \let\XINT_expr_scanfunc_b\POL@originalXINT_expr_scanfunc_b
\begingroup
\setbox0\hbox{%
\let\xintScalarAdd\xintAdd
@@ -107,48 +254,79 @@
\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
- \xintAdd{0}%
- {\csname XINT_expr_userfunc___pol\endcsname
- {\global\POL@poltrue\def\POL@result{1.\empty{0/1[0]}{1/1[0]}}}}%
+% 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{%
- \expandafter\POL@ifZero\csname POLuserpol@#1\endcsname
- {\@namedef{XINT_expr_userfunc_#1}##1{0/1[0]}}%
- {\POL@newpolhorner{#1}}%
- \expandafter\XINT_expr_defuserfunc
- \csname XINT_expr_func_#1\endcsname{#1}{expr}%
+%% 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{%
- \expandafter\POL@ifZero\csname POLuserpol@#1\endcsname
- {\@namedef{XINT_flexpr_userfunc_#1}##1{0[0]}}%
- {\POL@newfloatpolhorner{#1}}%
- \expandafter\XINT_expr_defuserfunc
- \csname XINT_flexpr_func_#1\endcsname{#1}{flexpr}%
+%% 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_userfunc_#1\space
+ associated to \string\XINT_expr_polfunc_#1\space
whose meaning uses Horner scheme:
\expandafter\meaning
- \csname XINT_expr_userfunc_#1\endcsname}%
+ \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_userfunc_#1\space
+ associated to \string\XINT_flexpr_polfunc_#1\space
whose meaning uses Horner scheme:
\expandafter\meaning
- \csname XINT_flexpr_userfunc_#1\endcsname}%
+ \csname XINT_flexpr_polfunc_#1\endcsname}%
}%
%
\def\POL@newpolhorner#1{%
@@ -162,7 +340,7 @@
\expandafter\POL@newpol@horner\POL@var@coeffs\relax
\expandafter
\endgroup
- \expandafter\def\csname XINT_expr_userfunc_#1\expandafter\endcsname
+ \expandafter\def\csname XINT_expr_polfunc_#1\expandafter\endcsname
\expandafter##\expandafter1\expandafter{\POL@tmp{##1}}%
}%
\def\POL@newfloatpolhorner#1{%
@@ -176,7 +354,7 @@
\expandafter\POL@newpol@floathorner\POL@var@coeffs\relax
\expandafter
\endgroup
- \expandafter\def\csname XINT_flexpr_userfunc_#1\expandafter\endcsname
+ \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
@@ -211,10 +389,9 @@
\def\POL@let#1#2{%
\expandafter\let\csname POLuserpol@#1\expandafter\endcsname
\csname POLuserpol@#2\endcsname
- \expandafter\let\csname XINT_expr_userfunc_#1\expandafter\endcsname
- \csname XINT_expr_userfunc_#2\endcsname
- \expandafter\XINT_expr_defuserfunc
- \csname XINT_expr_func_#1\endcsname{#1}{expr}%
+ \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
@@ -259,7 +436,7 @@
\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
+ \protected\def\POL@result{-1.\POL@empty{0/1[0]}}% 0.5 fix for empty array
\else
\xintloop
\edef\POL@tmp{#2{\count@}}%
@@ -283,7 +460,7 @@
\repeat
\count@\count\tw@
\def\POL@tmp##1.{{\csname POL@tmparray##1\endcsname}}%
- \edef\POL@result{\the\numexpr\count@-\@ne.\noexpand\empty
+ \protected\edef\POL@result{\the\numexpr\count@-\@ne.\POL@empty
\xintiloop[1+1]%
\expandafter\POL@tmp\xintiloopindex.%
\ifnum\xintiloopindex<\count@
@@ -480,7 +657,7 @@
{\ifnum\POL@degB<\z@
\expandafter\xint_firstoftwo\else\expandafter\xint_secondoftwo
\fi
- {\def\POL@result{-1.\empty{0/1[0]}}}%
+ {\protected\def\POL@result{-1.\POL@empty{0/1[0]}}}%
{\xintAssignArray\POL@polB\to\POL@arrayB
\POL@normalize{B}%
\POL@gcd@exit BA}}%
@@ -606,11 +783,11 @@
\expandafter\expandafter\expandafter\POL@split
\csname POLuserpol@#1\endcsname;\POL@var@deg\POL@var@coeffs
\ifnum\POL@var@deg<\@ne
- \@namedef{POLuserpol@#2}{-1.\empty{0/1[0]}}%
+ \@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.\noexpand\empty\POL@var@coeffs}%
+ {\the\numexpr\POL@var@deg-\@ne.\POL@empty\POL@var@coeffs}%
\fi
}%
% lazy way but allows to share with AntiDiff
@@ -666,11 +843,11 @@
\expandafter\expandafter\expandafter\POL@split
\csname POLuserpol@#1\endcsname;\POL@var@deg\POL@var@coeffs
\ifnum\POL@var@deg<\z@
- \@namedef{POLuserpol@#2}{-1.\empty{0/1[0]}}%
+ \@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.\noexpand\empty{0/1[0]}\POL@var@coeffs}%
+ {\the\numexpr\POL@var@deg+\@ne.\POL@empty{0/1[0]}\POL@var@coeffs}%
\fi
}%
@@ -737,7 +914,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.\empty{1/1[0]}}%
+ \@namedef{POLuserpol@\POL@sturmname _0}{0.\POL@empty{1/1[0]}}%
\else
\ifPOL@tosturm@makefirstprimitive\POL@makeprimitive{\POL@sturmname _0_}\fi
\POL@tosturm@dosturm
@@ -793,7 +970,7 @@
\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]}}%
+ \@namedef{POLuserpol@\POL@sturmname _\POL@sturm@N}{0.\POL@empty{1/1[0]}}%
\else % they are already normalized
\advance\POL@count\@ne % attention to include last one also
\xintloop
@@ -984,7 +1161,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.\noexpand\empty
+ \edef\POLuserpol@_findrat@oneterm{1.\POL@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
@@ -1118,7 +1295,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.\noexpand\empty
+ \edef\POLuserpol@_findrat@oneterm{1.\POL@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
@@ -1185,7 +1362,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.\noexpand\empty
+ \edef\POLuserpol@_findrat@oneterm{1.\POL@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
@@ -1210,11 +1387,11 @@
\begingroup\xintglobaldefstrue
% skip some overhead of \xintdefvar...
\XINT_expr_defvar_one{\POL@sturmname L_\POL@findrat@index}%
- {\csname .=\POL@findrat@x\endcsname}%
+ {\POL@findrat@x}%
\XINT_expr_defvar_one{\POL@sturmname R_\POL@findrat@index}%
- {\csname .=\POL@findrat@x\endcsname}%
+ {\POL@findrat@x}%
\XINT_expr_defvar_one{\POL@sturmname Z_\POL@findrat@index _isknown}%
- {\csname .=1\endcsname}%
+ {1}%
\endgroup
}%
\def\POL@findrat@loop@updatequotients{%
@@ -1326,7 +1503,7 @@
\xintloop
% skip some overhead of \xintdefvar...
\XINT_expr_defvar_one{\POL@sturmname M_\x}%
- {\csname .=\csname POL_ZM\POL@sturmname*\x\endcsname\endcsname}%
+ {\csname POL_ZM\POL@sturmname*\x\endcsname}%
\edef\x{\the\numexpr\x-\@ne}%
\ifnum\x>\z@
\repeat
@@ -1901,17 +2078,16 @@
\begingroup\xintglobaldefstrue
% skip some overhead of \xintdefvar...
\XINT_expr_defvar_one{\POL@sturmname L_\POL@isolz@IntervalIndex}%
- {\csname .=\POL@IsoLeft@rawout\endcsname}%
+ {\POL@IsoLeft@rawout}%
\XINT_expr_defvar_one{\POL@sturmname R_\POL@isolz@IntervalIndex}%
- {\csname .=\POL@IsoRight@rawout\endcsname}%
+ {\POL@IsoRight@rawout}%
% added at 0.7
\XINT_expr_defvar_one{\POL@sturmname Z_\POL@isolz@IntervalIndex _isknown}%
- {\csname .=\ifnum\POL@IsoRightSign=\z@ 1\else 0\fi\endcsname}%
+ {\ifnum\POL@IsoRightSign=\z@ 1\else 0\fi}%
\endgroup
}%
%% \PolRefineInterval
-\def\POL@xintexprGetVar#1{\expandafter\expandafter\expandafter
- \XINT_expr_unlock\csname XINT_expr_var_#1\endcsname}%
+\def\POL@xintexprGetVar#1{\csname XINT_expr_varvalue_#1\endcsname}%
% attention, also used by \POL@findrat@loop@a
\def\POL@get@IsoLeft@rawin{%
\edef\POL@IsoLeft@rawin
@@ -2277,28 +2453,70 @@
%% 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{%
- \global\POL@polfalse
+ \relax %!! part de la tambouille pour fonctionner en xint 1.4
+ \POL@polglobalfalse
\begingroup
- \def\POL@result{#3}%
+ \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.\empty{0/1[0]}}}%
- {\edef#1{0.\noexpand\empty{#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{%
- \global\POL@poltrue
+ \POL@polglobaltrue
\POL@ifZero\POL@A
{\let\POL@result\POL@B}%
{\POL@ifZero\POL@B
@@ -2341,11 +2559,11 @@
\def\POL@mul {\POL@get\POL@A\POL@mul@b}%
\def\POL@mul@b{\POL@get\POL@B\POL@mul@c}%
\def\POL@mul@c{%
- \global\POL@poltrue
+ \POL@polglobaltrue
\POL@ifZero\POL@A
- {\def\POL@result{-1.\empty{0/1[0]}}}%
+ {\protected\def\POL@result{-1.\POL@empty{0/1[0]}}}%
{\POL@ifZero\POL@B
- {\def\POL@result{-1.\empty{0/1[0]}}}%
+ {\protected\def\POL@result{-1.\POL@empty{0/1[0]}}}%
{\POL@@mul}}%
}%
\def\POL@@mul{%
@@ -2436,9 +2654,9 @@
%% POWERS (SCALAR EXPONENT...)
\def\POL@pow #1#2{%
- \global\POL@polfalse
+ \POL@polglobalfalse
\begingroup
- \def\POL@result{#1}%
+ \protected\def\POL@result{#1}%
#1%
\expandafter
\endgroup
@@ -2446,39 +2664,39 @@
\unless\ifPOL@pol
\edef\POL@A{\xintScalarPow{#1}{#2}}% no error check
\xintiiifZero{\POL@A}%
- {\def\POL@result{-1.\empty{0/1[0]}}}%
- {\edef\POL@result{0.\noexpand\empty{\POL@A}}}%
+ {\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
- \def\POL@result{0.\empty{1/1[0]}}%
+ \protected\def\POL@result{0.\POL@empty{1/1[0]}}%
\or
\let\POL@result\POL@A
\else
\POL@@pow@check
\fi
\fi
- \global\POL@poltrue
+ \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
+ % 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}%
- {\def\POL@result{-1.\empty{0/1[0]}}}%
- {\edef\POL@result{0.\noexpand\empty{\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}
- {\edef\POL@result
+ {\protected\edef\POL@result
{\the\POL@B.% here at least 2.
- \noexpand\empty
+ \POL@empty
\romannumeral\xintreplicate{\POL@B}{{0/1[0]}}%
{\xintScalarPow
{\expandafter\xint_secondoftwo\romannumeral`^^@%
@@ -2531,8 +2749,8 @@
{#2}%
\expandafter\POL@mul\expandafter
{\expandafter\def\expandafter\POL@result\expandafter
- {\POL@result}\global\POL@poltrue}%
- {\def\POL@result{#1}\global\POL@poltrue}%
+ {\POL@result}\POL@polglobaltrue}%
+ {\protected\def\POL@result{#1}\POL@polglobaltrue}%
}%
%% DIVISION
@@ -2540,7 +2758,7 @@
\def\POL@div {\POL@get\POL@A\POL@div@b}%
\def\POL@div@b{\POL@get\POL@B\POL@div@c}%
\def\POL@div@c{%
- \global\POL@poltrue
+ \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
@@ -2599,9 +2817,9 @@
%% MINUS SIGN AS UNARY OPERATOR
\def\POL@opp #1{%
- \global\POL@polfalse
+ \POL@polglobalfalse
\begingroup
- \def\POL@result{#1}%
+ \protected\def\POL@result{#1}%
#1%
\expandafter
\endgroup
@@ -2609,13 +2827,13 @@
\unless\ifPOL@pol
\edef\POL@A{\xintScalarOpp{#1}}%
\xintiiifZero{\POL@A}%
- {\def\POL@result{-1.\empty{0/1[0]}}}%
- {\edef\POL@result{0.\noexpand\empty{\POL@A}}}%
+ {\protected\def\POL@result{-1.\POL@empty{0/1[0]}}}%
+ {\protected\edef\POL@result{0.\POL@empty{\POL@A}}}%
\else
- \edef\POL@B{0.\noexpand\empty{-1/1[0]}}%
+ \edef\POL@B{0.\POL@empty{-1/1[0]}}%
\POL@@mul
\fi
- \global\POL@poltrue
+ \POL@polglobaltrue
}%
@@ -2626,9 +2844,9 @@
\At\PolEvalAtExpr\krof {#1}{#3}%
}%
\newcommand\PolEvalAt[2]
- {\xintpraw{\csname XINT_expr_userfunc_#1\endcsname{#2}}}%
+ {\xintpraw{\csname XINT_expr_polfunc_#1\endcsname{#2}}}%
\newcommand\POL@eval[2]
- {\csname XINT_expr_userfunc_#1\endcsname{#2}}%
+ {\csname XINT_expr_polfunc_#1\endcsname{#2}}%
\newcommand\PolEvalAtExpr[2]{\xinttheexpr #1(#2)\relax}%
%
\newcommand\PolEvalReduced[3]{\romannumeral`^^@\POL@eval@fork
@@ -2637,11 +2855,11 @@
}%
\newcommand\PolEvalReducedAt[2]{%
\xintpraw % in order not to print denominator if the latter equals 1
- {\xintIrr{\csname XINT_expr_userfunc_#1\endcsname{#2}}[0]}%
+ {\xintIrr{\csname XINT_expr_polfunc_#1\endcsname{#2}}[0]}%
}%
\newcommand\PolEvalReducedAtExpr[2]{%
\xintpraw
- {\xintIrr{\romannumeral`^^@\xintthebareeval#1(#2)\relax}[0]}%
+ {\expandafter\xintIrr\romannumeral`^^@\xintthebareeval#1(#2)\relax[0]}%
}%
%
\newcommand\PolFloatEval[3]{\romannumeral`^^@\POL@eval@fork
@@ -2649,7 +2867,7 @@
\At\PolFloatEvalAtExpr\krof {#1}{#3}%
}%
\newcommand\PolFloatEvalAt[2]
- {\xintpfloat{\csname XINT_flexpr_userfunc_#1\endcsname{#2}}}%
+ {\xintpfloat{\csname XINT_flexpr_polfunc_#1\endcsname{#2}}}%
\newcommand\PolFloatEvalAtExpr[2]{\xintthefloatexpr #1(#2)\relax}%
@@ -2898,12 +3116,12 @@
\expandafter#1%
\fi {#3}#2}%
%
-\def\POL@toexprA #1#2\empty#3{%
+\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 to prevent brace removal
+\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
}%
diff --git a/macros/latex/contrib/polexpr/polexpr.txt b/macros/latex/contrib/polexpr/polexpr.txt
index 46ea7e32fa..898375926b 100644
--- a/macros/latex/contrib/polexpr/polexpr.txt
+++ b/macros/latex/contrib/polexpr/polexpr.txt
@@ -4,7 +4,7 @@
Package polexpr documentation
===============================
-0.7.4 (2019/02/12)
+0.7.5 (2020/01/31)
==================
.. contents::
@@ -2567,6 +2567,11 @@ CHANGE LOG
- 20000000000 is too big for ``\numexpr``, shouldn't I know that?
Thanks to Jürgen Gilg for report.
+- v0.7.5 (2020/01/31)
+
+ Synced with xint 1.4. Requires it.
+
+
Acknowledgments
---------------