texlive[46291] Master: polexpr (12jan18)

commits+karl at tug.org commits+karl at tug.org
Fri Jan 12 23:35:39 CET 2018


Revision: 46291
          http://tug.org/svn/texlive?view=revision&revision=46291
Author:   karl
Date:     2018-01-12 23:35:39 +0100 (Fri, 12 Jan 2018)
Log Message:
-----------
polexpr (12jan18)

Modified Paths:
--------------
    trunk/Master/tlpkg/bin/tlpkg-ctan-check
    trunk/Master/tlpkg/tlpsrc/collection-mathscience.tlpsrc

Added Paths:
-----------
    trunk/Master/texmf-dist/doc/latex/polexpr/
    trunk/Master/texmf-dist/doc/latex/polexpr/README
    trunk/Master/texmf-dist/tex/latex/polexpr/
    trunk/Master/texmf-dist/tex/latex/polexpr/polexpr.sty
    trunk/Master/tlpkg/tlpsrc/polexpr.tlpsrc

Added: trunk/Master/texmf-dist/doc/latex/polexpr/README
===================================================================
--- trunk/Master/texmf-dist/doc/latex/polexpr/README	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/polexpr/README	2018-01-12 22:35:39 UTC (rev 46291)
@@ -0,0 +1,373 @@
+-*- fill-column: 72; mode: text; -*-
+
+Package polexpr
+===============
+
+License
+-------
+
+Copyright (C) 2018 Jean-Francois Burnol
+
+See documentation of package xint for contact information.
+
+This Work may be distributed and/or modified under the
+conditions of the LaTeX Project Public License version 1.3c.
+This version of this license is in
+
+  http://www.latex-project.org/lppl/lppl-1-3c.txt
+
+and version 1.3 or later is part of all distributions of
+LaTeX version 2005/12/01 or later.
+
+This Work has the LPPL maintenance status author-maintained.
+
+The Author of this Work is Jean-Francois Burnol.
+
+This Work consists of the package file polexpr.sty and this README.
+
+
+Abstract
+--------
+
+The package provides "\poldef": a parser of polynomial expressions
+based upon the "\xintdeffunc" mechanism of package xintexpr.
+
+The syntax is
+
+    \poldef <name>(x):=<expression in variable x>;
+
+where in place of "x" an arbitrary letter is authorized. The expression
+uses the operations of algebra (including composition of functions) with
+standard operators, fractional numbers (possibly in scientific notation)
+and previously defined polynomial functions or other constructs as
+recognized by the \xintexpr numerical parser.
+
+The so-defined name() \xintexpr-function is also known to the package
+via its polynomial coefficients, thus allowing dedicated macros to
+implement polynomial algorithmics.
+
+Examples
+--------
+
+\poldef f(x):= 1-x+x^2;
+
+This defines polynomial "f". Polynomial names must start with a letter
+and may contain letters, digits, and underscores. The variable must be a
+single letter. The colon character is optional. The semi-colon at end of
+expression is mandatory.
+
+\PolDef{f}{1-x+x^2} does the same as \poldef f(x):= 1-x+x^2;
+To use another letter than x in the expression, one must pass it as
+an extra optional argument to \PolDef. Useful if the semi-colon has
+been assigned some non-standard catcode by some package.
+
+\PolLet{g}{f} saves a copy of "f" under name "g".
+
+\poldef f(z):= f(z)^2; redefines "f" in terms of itself.
+
+\poldef f(T):= f(f(T)); again redefines "f" in terms of its (new) self.
+
+\poldef k(z):= f(z)-g(g(z)^2)^2; should now define the zero
+polynomial... Let's check:
+\[ k(z) = \PolTypeset[z]{k} \]
+
+\PolDiff{f}{df_dx} sets "df_dx" to the derivative of "f".
+
+\PolDiff{df_dx}{f_xx} obtains second derivative
+
+\PolDiff[3]{f}{d3f_dx3} computes directly the third derivative
+
+$f(z)   = \PolTypeset[z]{f}    $\newline
+$f'(z)  = \PolTypeset[z]{df_dx}$\newline
+$f''(z) = \PolTypeset[z]{f_xx}$\newline
+$f'''(z)= \PolTypeset[z]{d3f_dx3}$\par
+
+*Important*: the package does not currently know rational functions.
+and  "/" in a parsed polynomial expression does the Euclidean quotient:
+
+  (1-x^2)/(1-x) does give 1+x but (1/(1-x))*(1-x^2) evaluates to zero.
+
+*Attention*: "1/2 x" skips the space and is treated like "1/(2x)"
+because of the tacit multiplication rules of \xintexpr. But this means
+it gives zero! Thus one must use (1/2)x or 1/2*x or (1/2)*x for
+disambiguation.
+
+\poldef k(x):= (x-1)(x-2)(x-3)(x-4)/(x^2-5x+4);%
+
+\PolTypeset{k} gives the expected x^2-5x+6
+
+\poldef f1(x):= 25(x-1)(x^2-2)(x-3)(x-4)(x-5);%
+\poldef f2(x):= 37(x-1)(x^2-2)(x-6)(x-7)(x-8);%
+
+\PolGCD{f1}{f2}{k} sets "k" to the (unitary) GCD of "f1" and "f2".
+
+\PolToExpr{k} expandably gives 2-2*x^1-1*x^2+1*x^3 for console
+or file output (this is Maple-compatible input syntax).
+
+Non-expandable macros
+---------------------
+
+\poldef name(letter):= polynomial expression using letter;
+    This evaluates the polynomial expression and stores the
+    coefficients in a private structure accessible later via other
+    package macros, under the user-chosen "name". Of course
+    previously defined polynomials are allowed in a new expression.
+    Names must start with a letter and are constituted of letters,
+    digits and underscore characters. See Examples above.
+
+    As a side effect the function name() is recognized as a genuine
+    \xintexpr...\relax function for (exact) numerical evaluation. It
+    computes values not according to the original expression but via
+    the Horner scheme corresponding to the polynomial coefficients.
+
+    The original expression is lost after parsing, and in particular
+    the package provides no way to typeset it. This has to be done
+    manually, if needed.
+
+\PolDef{name}{P(x)}
+    Does the same but the variable is assumed to be "x". To use another
+    letter, pass it as first optional argument.
+
+\PolLet{g}{f}
+    Makes a copy of already defined polynomial f to new one g.
+    Same effect as \PolDef{g}{f(x)} but faster.
+
+\PolAssign{f}\toarray\Array
+    Defines a one-argument expandable macro \Array{#1} which expands
+    to the (raw) #1th polynomial coefficient.
+
+    - Attention, coefficients here are indexed starting at 1.
+
+    - With #1=-1, -2, ..., \Array{#1} returns leading coefficients.
+
+    - With #1=0, returns the number of coefficients, i.e. 1+degree(f)
+      for non-zero polynomials.
+
+    - Out-of-range #1's return 0/1[0].
+
+\PolGet{f}\fromarray\Array
+    Does the reverse operation to \PolAssign{f}\toarray\Array. No error
+    checks on validity of coefficients as numbers. Each \Array{index}
+    is expanded in an \edef before being assigned to a coefficient.
+    Leading zero coefficients are removed from the polynomial.
+    
+    (contrived) Example: \xintAssignArray{1}{-2}{5}{-3}\to\foo
+                         \PolGet{f}\fromarray\foo
+    This will define "f" as would have \poldef f(x):=1-2x+5x^2-3x^3;
+    However the coefficients are still in their original form (i.e.
+    they were not subjected to \xintRaw or similar xintfrac macro.)
+
+\PolFromCSV{f}{comma separated coefficients}
+    Defines a polynomial directly from the comma separated list (or a
+    macro expanding to such a list) of its coefficients, the constant
+    term being the first item. No validity checks. Spaces from the list
+    argument are trimmed. List items are expanded in an \edef, but
+    currently they are left in their original form like e.g. 1.5e3
+    which is not converted to 15/1[2] "raw" xintfrac format (this may
+    change).
+
+    Leading zero coefficients are removed:
+    \PolFromCSV{J}{0, 0, 0, 0, 0, 0, 0, 0, 0, 0} defines the zero
+    polynomial, which has only one (zero) coefficient.
+
+    See also expandable macro \PolToCSV.
+
+\PolTypeset[x]{name}
+    Typesets in descending powers in math mode using the specified
+    variable (default x.) By default zero coefficients are skipped
+    (issue \poltypesetalltrue to get all of them in output).
+
+    Macros \PolTypesetCmd, \PolTypesetPlus, \PolTypesetMonomial
+    can help configure the output. See the package code.
+
+\PolTypeset*[x]{name}
+    Typesets in ascending powers.
+
+\PolDiff{f1}{f2}
+    This sets f2 to the first derivative of f1. It is allowed to issue
+    \PolDiff{f}{f}, effectively replacing f by f'.
+
+    Coefficients of the result f2 are irreducible fractions
+    (see `Technicalities`_ for the whole story.)
+
+\PolDiff[N]{f1}{f2}
+    This sets f2 to the Nth derivative of f1. Identical arguments
+    is allowed. With N=0, same effect as \PolLet{f2}{f1}.
+    With negative N, switched to using \PolAntiDiff.
+
+\PolAntiDiff{f1}{f2}
+    This sets f2 to the primitive of f1 vanishing at zero.
+
+    Coefficients of the result f2 are irreducible fractions
+    (see `Technicalities`_ for the whole story.)
+
+\PolAntiDiff[N]{f1}{f2}
+    This sets f2 to the result of N successive integrations on f1.
+    With negative N, it switches to using \PolDiff.
+
+\PolDivide{f1}{f2}{Q}{R}
+    This sets Q and R to be the quotient and remainder in the Euclidean
+    division of f1 by f2.
+
+\PolGCD{f}{g}{k}
+    This sets k to be the G.C.D. It is a unitary polynomial except if
+    both f and g vanish, then k is the zero polynomial.
+
+\PolMapCoeffs{\macro}{name}
+    It modifies each coefficient of the defined polynomial via
+    the *expandable* macro \macro. The degree is adjusted as necessary
+    if some leading coefficients vanish after the operation.
+    In replacement text of \macro, \index expands to the coefficient
+    index (which is defined to be zero for the constant term).
+
+    Notice that \macro will have to handle inputs of the shape A/B[N]
+    (xintfrac internal notation). This means that it probably will
+    have to be expressed in terms of macros from xintfrac package.
+
+    Example: \def\foo#1{\xintMul{#1}{\the\numexpr\index^2\relax}}
+    to replace nth coefficient f_n by f_n * n^2.
+
+\PolReduceCoeffs{name}
+    About the same as \PolMapCoeffs{\xintIrr}{name} (but adds [0]
+    postfix which speeds up xintfrac operations when evaluating.)
+
+Expandable macros
+-----------------
+
+All these macros expand completely in two steps except \PolToExpr
+which needs a \write, \edef or a \csname...\endcsname context.
+
+\PolEval{name}\At{value}
+    It boils down to \xinttheexpr reduce(name(value))\relax.
+
+\PolNthCoeff{name}{N}
+    It expands to the raw Nth coefficient (0/1[0] if index is out of
+    range). With N=-1, -2, ... expands to the leading coefficients.
+
+\PolDegree{name}
+    It expands to the degree. This is -1 if zero polynomial but this may
+    change in future. Should it then expand to -\infty ?
+
+\PolToExpr{f}
+    Expands to f_0 + f_1*x + f_2*x^2 + ... (ascending powers). [1, 2]
+
+    [1] in a \write, \edef, or \csname...\endcsname, but not under 
+        \romannumeral-`0
+
+    [2] the letter x is (in this release) not customizable.
+
+    By default zero coefficients are skipped (issue \poltoexprtrue to
+    get all of them in output).
+
+    No + sign before negative coefficients, for compliance with Maple
+    input format. This means though that parsing the result back via
+    naive delimited macros is difficult, see \PolToList and \PolToCSV
+    for more low-level formats making it easier to get expandably some
+    output of one's choice, which may possibly be parsed later on by
+    other macros of one's design, or from other packages.
+
+    Of course "\PolToExpr{f}" can be inserted in a \poldef, as the
+    latter expands token by token, hence will force complete expansion
+    of \PolToExpr{f}, but simply "f(x)" will be more efficient for the
+    identical result.
+
+    \PolToExprCmd is the one-argument macro used by \PolToExpr for the
+    coefficients, it defaults to \xintPRaw{\xintRawWithZeros{#1}}. One
+    will have to redefine it to use \xintIrr{#1} in place of
+    \xintRawWithZeros{#1} to get in output reduced coefficients.
+
+\PolToList{f}
+    Expands to {f_0}{f_1}...{f_N} with N = degree of f (except zero
+    polynomial which does give {0/1[0]} and not an empty output.)
+
+\PolToCSV{f}
+    Expands to f_0, f_1, f_2, ....., f_N. Converse of \PolFromCSV.
+
+Technicalities
+--------------
+
+- The catcode of the semi-colon is reset temporarily by \poldef macro in
+  case some other package (for example the French babel module) may have
+  made it active. This will fail though if the whole thing was already
+  part of a macro argument, in such cases one can use \PolDef rather.
+  The colon in := may be active with no consequences.
+
+- Beware the 1/2 x problem: as mentioned above, it will be give zero due
+  to the tacit multiplication rules of \xintexpr and to the fact that
+  the package will do the Euclidean division of 1 by polynomial 2x.
+
+- During execution of polynomial operations by \poldef (but not during
+  the initial purely numerical parsing of the expression), the xintfrac
+  macro \xintAdd is temporarily patched to always express a/b + c/d with
+  L.C.M.(b,d) as denominator. Indeed the current (xint 1.2p) \xintAdd
+  uses (ad+bc)/bd formula except if b divides d or d divides b, which
+  quickly leads in real life to big denominators.
+
+  It is probable that this convention will be backported as default
+  behaviour of xintfrac's \xintAdd in a future xint release. When this
+  change is merged, there will be an impact on coefficients computed by
+  \poldef because the change will apply even to the pure numerical
+  evaluations arising during the initial stage of the parsing. Of course
+  the coefficients are still the same rational numbers, only
+  representation as fractions may change.
+
+- As a consequence of previous rule, user-chosen common denominators
+  survive addition and multiplications:
+
+  \poldef P(x):= 1/2 + 2/2*x + 3/2*x^3 + 4/2*x^4;
+  \poldef Q(x):= 1/3 + (2/3)x + (3/3)x^3 + (4/3)x^4;
+  \poldef PQ(x):= P(x)*Q(x);
+
+  gives the polynomial
+
+  1/6+4/6*x^1+4/6*x^2+6/6*x^3+20/6*x^4+16/6*x^5+9/6*x^6+24/6*x^7+16/6*x^8
+
+  where all coefficients have the same denominator 6 (which in this
+  example is the l.c.m of the denominators of the reduced coefficients.)
+
+- \PolDiff always applies \xintIrr to the resulting coefficients, except
+  that the "decimal" part [N] (for example an input in scientific
+  notation such as 1.23e5 gives 123/1[3] internally in xintfrac) is not
+  taken into account in the reduction of the fraction. This is tentative
+  and may change.
+
+  Same remark for \PolAntiDiff.
+
+- If f was created from comma separated values by macro \PolFromCSV,
+  then the exact same coefficients (except those zero coefficients
+  beyond the leading monomial) will be in the output of \PolToList and
+  \PolToCSV in their original input form: a 1.3e2 will again be a 1.3e2.
+  
+  In contrast when such coefficients are used in a \poldef (or \PolDef)
+  expression, they get transformed during the parsing to the xintfrac
+  "raw" format. This is an unavoidable consequence of usage by \poldef
+  of \xintdeffunc which itself is based on \xintexpr. This "raw" format
+  speeds up expansion of xintfrac macros for numerical evaluations.
+
+- Currently, the package does not as a result of \poldef add to the TeX
+  memory an already pre-computed "array" structure for the polynomial
+  coefficients, as would be constructed by \PolAssign{f}\toarray\Macro.
+  Such structures are used, but for internal calculations in temporarily
+  restricted scopes. Apart from the function f() known to the
+  (numerical) \xintexpr parser (whose meaning can be found in the log
+  file after \xintverbosetrue), the data is (currently) stored in a
+  single other macro encapsulating the degree, and the coefficients as a
+  list. This may evolve in future.
+
+- As is to be expected internal structures of the package are barely
+  documented and unstable. Don't use them.
+
+
+CHANGE LOG
+----------
+
+- v0.1 (2018/01/11): initial release. Features:
+
+  *. differentiation and anti-differentiation,
+  *. Euclidean division and GCDs,
+  *. various utilities such as \PolFromCSV, \PolToCSV, \PolToExpr.
+
+  Only one-variable polynomials so far.
+
+  Due to lack of available time I have not really yet set-up a
+  sufficient enough test suite. Bug reports very welcome!


Property changes on: trunk/Master/texmf-dist/doc/latex/polexpr/README
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/tex/latex/polexpr/polexpr.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/polexpr/polexpr.sty	                        (rev 0)
+++ trunk/Master/texmf-dist/tex/latex/polexpr/polexpr.sty	2018-01-12 22:35:39 UTC (rev 46291)
@@ -0,0 +1,1009 @@
+% author: Jean-François Burnol
+% License: LPPL 1.3c (author-maintained)
+\ProvidesPackage{polexpr}%
+  [2018/01/11 v0.1 Polynomial expressions with rational coefficients (JFB)]%
+\RequirePackage{xintexpr}[2016/03/19]% xint 1.2g (or 1.2c 2015/11/16 at least)
+\edef\POL at restorecatcodes
+    {\catcode`\noexpand\_ \the\catcode`\_ \catcode0 \the\catcode0\relax}%
+\catcode`\_ 11 \catcode0 12
+
+%% AUXILIARIES
+\newif\ifPOL at pol % (cf core algebra macros)
+%% the main exchange structure (stored in macros \POLuserpol@<name>)
+%% is: degree.\empty{coeff0}{coeff1}....{coeffN}
+%% (degree=N except zero polynomial recognized from degree set to -1
+%%  but it has always the {0/1[0]} coeff0.)
+\def\POL at ifZero#1{\expandafter\POL at ifZero@aux#1;}%
+\def\POL at ifZero@aux #1#2;{\if-#1\expandafter\xint_firstoftwo
+                             \else\expandafter\xint_secondoftwo
+                          \fi}%
+\def\POL at split#1.#2;#3#4% separates degree and list of coefficients
+% The \empty token is to avoid brace removal issues for degree 0 polynomials
+   {\def#3{#1}\expandafter\def\expandafter#4\expandafter{#2}}%
+%
+\def\POL at resultfromarray #1{% ATTENTION, **MUST** be executed with
+% \count@ set to 1 + degree (thus \count@ = 0 for zero polynomial)
+    \edef\POL at result{%
+      \the\numexpr\count at -\@ne.\noexpand\empty
+      \xintiloop [1+1]%
+% always done at least once with index 1, hence ok for zero polynomial
+      \expandafter\POL at braceit\csname POL at array#1\xintiloopindex\endcsname
+      \ifnum\xintiloopindex<\count@
+      \repeat}%
+}%
+\def\POL at braceit#1{{#1}}% needed as \xintiloopindex can not "see" through braces
+
+
+\newif\ifxintveryverbose
+\newcommand\PolDef[3][x]{\poldef #2(#1):=#3;}%
+\def\poldef{\edef\POL at restoresemicolon{\catcode59=\the\catcode59\relax}%
+                \catcode59 12 \POL at defpol}%
+\def\POL at defpol #1(#2)#3=#4;{%
+   \POL at restoresemicolon
+   \let\POL at original_redefinemacros\XINT_expr_redefinemacros
+   \let\XINT_expr_redefinemacros\POL at redefinemacros
+   \edef\POL at tmp{\ifxintverbose1\else0\fi}%
+   \unless\ifxintveryverbose\xintverbosefalse\fi
+   \xintdeffunc __pol(#2):=#4;\if1\POL at tmp\xintverbosetrue\fi
+   \let\XINT_expr_redefinemacros\POL at original_redefinemacros
+   \edef\POL at polname{\xint_zapspaces #1 \xint_gobble_i}%
+   \begingroup
+     \setbox0\hbox{%
+     \let\xintScalarAdd\xintAdd
+     \let\XINT_fadd_C\POL_fadd_C % patch Add to use l.c.m.
+     \let\xintScalarSub\xintSub
+     \let\xintScalarMul\xintMul
+     \let\xintScalarDiv\xintDiv
+     \let\xintScalarPow\xintPow
+     \let\xintScalarOpp\xintOpp
+     \let\xintAdd\POL at add
+     \let\xintMul\POL at mul
+     \let\xintDiv\POL at div
+     \let\xintPow\POL at pow
+     \let\xintOpp\POL at opp
+     \def\xintSub ##1##2{\xintAdd{##1}{\xintOpp{##2}}}%
+     % \xintAdd to get \POL at result defined even if numerical only expression
+     \xintAdd{0}%
+       {\csname XINT_expr_userfunc___pol\endcsname
+% comma delimited from xintexpr at 1.2p or earlier. Might change.
+        {\global\POL at poltrue\def\POL at result{1.\empty{0/1[0]}{1/1[0]}}},}%
+     \expandafter}\expandafter
+   \endgroup\expandafter
+   \def\csname POLuserpol@\POL at polname\expandafter\endcsname
+        \expandafter{\POL at result}%
+   \expandafter\POL at newpol\expandafter{\POL at polname}%
+}%
+%%
+\def\POL at newpol#1{%
+   \expandafter\POL at ifZero\csname POLuserpol@#1\endcsname
+      {\@namedef{XINT_expr_userfunc_#1}##1,{0/1[0]}}%
+      {\POL at newpolhorner{#1}}%
+   \unless\ifcsname XINT_expr_userfuncNE:#1\endcsname\POL at addtoextras{#1}\fi
+   \expandafter\XINT_expr_defuserfunc
+     \csname XINT_expr_func_#1\expandafter\endcsname
+     \csname XINT_expr_userfunc_#1\endcsname
+   \ifxintverbose\POL at info{#1}\fi
+}%
+\def\POL at info #1{%
+   \xintMessage {polexpr}{Info}%
+        {Function #1 for the \string\xintexpr\space parser is
+         associated to \string\XINT_expr_userfunc_#1\space
+         whose meaning uses Horner scheme:
+         \expandafter\meaning
+         \csname XINT_expr_userfunc_#1\endcsname}%
+}%
+%
+\def\POL at 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 at split
+      \csname POLuserpol@#1\endcsname;\POL at var@deg\POL at var@coeffs
+   \edef\POL at var@coeffs{\xintRevWithBraces{\POL at var@coeffs}}%
+   \begingroup
+      \expandafter\POL at newpol@horner\POL at var@coeffs\relax
+   \endgroup
+   \expandafter\let\csname XINT_expr_userfunc_#1\endcsname\POL at tmp
+}%
+\def\POL at newpol@horner#1{\let\xintAdd\relax\let\xintMul\relax
+                  \gdef\POL at tmp##1,{#1}\POL at newpol@horner at loop.}%
+\def\POL at newpol@horner at loop.#1{%
+  \if\relax#1\expandafter\xint_gob_til_dot\fi
+  \xdef\POL at tmp##1,{\xintiiifZero{#1}{\@firstofone}{\xintAdd{#1}}%
+                    {\xintMul{##1}{\POL at tmp##1,}}}%
+  \POL at newpol@horner at loop.%
+}%
+%% Customizes xintexpr.sty's \XINT_NewExpr (\POL at addtoextras{name})
+\begingroup
+\catcode`~ 12
+\catcode`$ 12 % $
+\catcode`! 11
+\gdef\POL at NEfork_one #1#2!#3#4{%
+    \if ###1\xint_dothis {\POL__settopol{#4}}\fi
+    \if  ~#1\xint_dothis {\POL__userfunc{#4}}\fi
+    \if  $#1\xint_dothis {~xintApply::csv{~POL_userfunc{#4}}}\fi %$
+    \xint_orthat {#3}#1#2\endcsname
+}%
+\gdef\POL@@redefineone #1#2#3{% #3 = name
+    % Used for immediate f(numerical)
+    \let#2#1%
+    % \XINT_expr_userfunc_name
+    \def#1##1\endcsname % key trick is to fetch up to \endcsname!
+      {\expandafter\POL at NEfork_one\romannumeral`^^@##1!#2{#3}}%
+}%
+    % Used when f(x) is encountered: great gain here!
+\gdef\POL__settopol#1#2,{~POL_settopol{#1}}%
+\gdef\POL_settopol#1{\global\POL at poltrue\expandafter\let\expandafter
+                     \POL at result\csname POLuserpol@#1\endcsname}%
+    % Used when argument is neither numerical nor a macro parameter
+    % Quite some magic here! (braces couldn't be used this way in \xintexpr)
+\gdef\POL__userfunc#1#2,\endcsname{~POL_userfunc{#1}{#2},\endcsname}%
+\gdef\POL_userfunc#1{\csname XINT_expr_userfunc_#1\endcsname}%
+\endgroup
+\def\POL at addtoextras#1{%
+    \oodef\POL at redefineextras{\expandafter\POL at redefineextras
+      \expandafter\POL@@redefineone
+      \csname XINT_expr_userfunc_#1\expandafter\endcsname
+      \csname XINT_expr_userfuncNE:#1\endcsname{#1}}%
+}%
+%\let\POL at original@redefinemacros\XINT_expr_redefinemacros % do locally
+\def\POL at redefinemacros{\POL at original_redefinemacros\POL at redefineextras}%
+\let\POL at redefineextras\@empty
+%
+\newcommand\PolLet[2]{%
+    \expandafter\let\csname POLuserpol@#1\expandafter\endcsname
+                    \csname POLuserpol@#2\endcsname
+    \unless\ifcsname XINT_expr_userfuncNE:#1\endcsname\POL at addtoextras{#1}\fi
+    \expandafter\let\csname XINT_expr_userfunc_#1\expandafter\endcsname
+                    \csname XINT_expr_userfunc_#2\endcsname
+    \expandafter\XINT_expr_defuserfunc
+       \csname XINT_expr_func_#1\expandafter\endcsname
+       \csname XINT_expr_userfunc_#1\endcsname
+    \ifxintverbose\POL at info{#1}\fi
+}%
+
+
+\newcommand\PolAssign[1]{\def\POL at polname{#1}\POL at assign}% zap spaces in #1?
+\def\POL at assign#1\toarray#2{%
+    \expandafter\expandafter\expandafter\POL at split
+    \csname POLuserpol@\POL at polname\endcsname;\POL at var@deg\POL at var@coeffs
+    \xintAssignArray\POL at 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 at ne \xint_dothis
+                {\expandafter\expandafter\expandafter##3%
+                 \csname##2####1\endcsname}\fi
+        \unless\ifnum-####1>##1 \xint_dothis
+                {\expandafter\expandafter\expandafter##3%
+                 \csname##2\the\numexpr##1+####1+\@ne\endcsname}\fi
+        \xint_orthat{ 0/1[0]}}% space stops a \romannumeral0
+    }%
+    \csname\xint_arrayname00\expandafter\expandafter\expandafter\endcsname
+      \expandafter\expandafter\expandafter
+      {\csname\xint_arrayname0\expandafter\endcsname\expandafter}\expandafter
+      {\xint_arrayname}{ }%
+}%
+
+
+\newcommand\PolGet[1]{\def\POL at polname{#1}% zap spaces in #1?
+    \begingroup  % closed in \POL at getfrom
+    \POL at getfrom}% 
+% attention au name clash proche avec \POL at get auxiliaire de \POL at add etc..
+\def\POL at getfrom#1\fromarray#2{%
+        \count@#2{0} % must be > 0, else could create infinite loop
+        % \ifnum\count@>\z@\else\InvalidArrayError_PolGet\fi
+        \xintloop
+          \edef\POL at tmp{#2{\count@}}%
+          \xintiiifZero{\POL at tmp}%
+            {\iftrue}%
+            {\iffalse}%
+        \advance\count@\m at ne
+        \repeat
+% should I use \xintRaw ? but if #2 expands only in an \edef, problem
+% (but it is not very probable the #2 macro does not already give completely
+% expanded contents), I would need to proceed in two steps. Or the \xintRaw
+% could get injected at level of \POL at newpol
+        \def\POL at tmp##1.{{#2{##1}}}%
+        \edef\POL at result{\the\numexpr\count at -\@ne.\noexpand\empty
+                         \xintiloop[1+1]%
+                         \expandafter\POL at tmp\xintiloopindex.%
+                         \ifnum\xintiloopindex<\count@
+                         \repeat}%
+    \expandafter
+    \endgroup
+    \expandafter
+    \def\csname POLuserpol@\POL at polname\expandafter\endcsname
+        \expandafter{\POL at result}%
+    \expandafter\POL at newpol\expandafter{\POL at polname}%
+}%
+
+
+\newcommand\PolFromCSV[2]{\def\POL at polname{#1}%
+    \begingroup % closed in \POL at getfrom
+    \xintAssignArray\xintCSVtoList{#2}\to\POL at arrayA
+    \POL at getfrom\fromarray\POL at arrayA
+% semble un peu indirect et sous-optimal
+% mais je veux élaguer les coefficients nuls. Peut-être à revoir.
+}%
+
+
+\newif\ifpoltypesetall
+\newcommand\PolTypesetPlus[1]{\xintiiifSgn{#1}{}{+}{+}}%
+\newcommand\PolTypesetCmd[1]{\xintifOne{\xintiiAbs{#1}}%
+                               {\ifnum\PolIndex=\z@\xintiiSgn{#1}\else
+                                \xintiiifSgn{#1}{-}{}{}\fi}%
+                               {\xintSignedFrac{#1}}}%
+\newcommand\PolTypesetMonomial{%
+  \ifcase\PolIndex\space
+  %
+  \or\PolVar
+  \else\PolVar^{\PolIndex}%
+  \fi
+}%
+\newcommand\PolTypeset{\@ifstar
+  {\def\POL at ts@ascending{1}\POL at Typeset}%
+  {\def\POL at ts@ascending{0}\POL at Typeset}%
+}%
+\newcommand\POL at Typeset[2][x]{% LaTeX \newcommand forces optional argument first
+   \ensuremath{%
+        \expandafter\expandafter\expandafter\POL at split
+        \csname POLuserpol@#2\endcsname;\POL at var@deg\POL at var@coeffs
+        \if\POL at ts@ascending1%
+           \def\PolIndex{0}%
+           \let\POL at ts@reverse\@firstofone
+           \let\POL@@ne at or@m at ne\@ne
+        \else
+           \let\PolIndex\POL at var@deg
+           \ifnum\PolIndex<\z@\def\PolIndex{0}\fi
+           \let\POL at ts@reverse\xintRevWithBraces
+           \let\POL@@ne at or@m at ne\m at ne
+        \fi
+        \def\PolVar{#1}%
+        \ifnum\POL at var@deg<\z@
+            \PolTypesetCmd{0/1[0]}%
+        \else
+         \ifnum\POL at var@deg=\z@
+           \expandafter\PolTypesetCmd\POL at var@coeffs
+         \else
+           \def\POL at ts@plus##1{\let\POL at ts@plus\PolTypesetPlus}%
+           \expandafter\POL at ts@loop
+              \romannumeral-`0\POL at ts@reverse{\POL at var@coeffs}\relax
+         \fi
+        \fi
+   }%
+}%
+\def\POL at ts@loop{\ifpoltypesetall\expandafter\xint_firstoftwo
+                 \else\expandafter\xint_secondoftwo\fi
+    {\POL at ts@nocheck}{\POL at ts@check}.%
+}%
+\def\POL at ts@check.#1{%
+  \if\relax#1\expandafter\xint_gob_til_dot\fi
+  \xintiiifZero{#1}%
+      {}%
+      {\POL at ts@plus{#1}\PolTypesetCmd{#1}\PolTypesetMonomial}%
+  \edef\PolIndex{\the\numexpr\PolIndex+\POL@@ne at or@m at ne}\POL at ts@check.%
+}%
+\def\POL at ts@nocheck.#1{%
+  \if\relax#1\expandafter\xint_gob_til_dot\fi
+  \POL at ts@plus{#1}\PolTypesetCmd{#1}\PolTypesetMonomial
+  \edef\PolIndex{\the\numexpr\PolIndex+\POL@@ne at or@m at ne}\POL at ts@nocheck.%
+}%
+
+
+\newcommand\PolMapCoeffs[2]{% #1 = macro, #2 = name
+    \begingroup
+       \def\POL at map@macro{#1}%
+       \expandafter\expandafter\expandafter\POL at split
+         \csname POLuserpol@#2\endcsname;\POL at var@deg\POL at var@coeffs
+% attention à ne pas faire un \expandafter ici, car brace removal si 1 item
+       \xintAssignArray\POL at var@coeffs\to\POL at arrayA
+       \def\index{0}%
+       \count@\z@
+       \expandafter\POL at map@loop\expandafter.\POL at var@coeffs\relax
+       \xintloop
+% this abuses that \POL at arrayA0 is never 0.
+       \xintiiifZero{\csname POL at arrayA\the\count@\endcsname}%
+         {\iftrue}%
+         {\iffalse}%
+       \advance\count@\m at ne
+       \repeat
+% donc en sortie \count@ est 0 ssi pol nul.
+       \POL at resultfromarray A%
+     \expandafter
+    \endgroup
+    \expandafter
+    \def\csname POLuserpol@#2\expandafter\endcsname\expandafter{\POL at result}%
+    \POL at newpol{#2}%
+}%
+\def\POL at map@loop.#1{\if\relax#1\expandafter\xint_gob_til_dot\fi
+    \advance\count@\@ne
+    \edef\POL at map@coeff{\POL at map@macro{#1}}%
+    \expandafter
+    \let\csname POL at arrayA\the\count@\endcsname\POL at map@coeff
+    \edef\index{\the\numexpr\index+\@ne}%
+    \POL at map@loop.}%
+\def\POL at xintIrr#1{\xintIrr{#1}[0]}%
+\newcommand\PolReduceCoeffs[1]{\PolMapCoeffs{\POL at xintIrr}{#1}}%
+
+
+%% EUCLIDEAN DIVISION
+\newcommand\PolDivide[4]{% #3=quotient, #4=remainder of #1 by #2
+    \begingroup
+      \let\xintScalarSub\xintSub
+      \let\XINT_fadd_C\POL_fadd_C
+      \let\xintScalarMul\xintMul
+      \let\xintScalarDiv\xintDiv
+      \expandafter\let\expandafter\POL at A\csname POLuserpol@#1\endcsname
+      \expandafter\let\expandafter\POL at B\csname POLuserpol@#2\endcsname
+      \POL at div@c
+      \let\POL at Q\POL at result
+      \ifnum\POL at degQ<\z@
+          \let\POL at R\POL at A
+      \else
+        \count@\numexpr\POL at degR+\@ne\relax
+        \POL at resultfromarray R%
+        \let\POL at R\POL at result
+      \fi
+    \expandafter
+    \endgroup
+    \expandafter
+    \def\csname POLuserpol@#3\expandafter\expandafter\expandafter\endcsname
+        \expandafter\expandafter\expandafter{\expandafter\POL at Q\expandafter}%
+        \expandafter
+    \def\csname POLuserpol@#4\expandafter\endcsname\expandafter{\POL at R}%
+    \POL at newpol{#3}%
+    \POL at newpol{#4}%
+}%
+
+
+%% GCD
+\newcommand\PolGCD[3]{% sets #3 to the (unitary) G.C.D. of #1 and #2
+    \begingroup
+      \let\xintScalarSub\xintSub
+      \let\XINT_fadd_C\POL_fadd_C
+      \let\xintScalarMul\xintMul
+      \let\xintScalarDiv\xintDiv
+      \expandafter\let\expandafter\POL at A\csname POLuserpol@#1\endcsname
+      \expandafter\let\expandafter\POL at B\csname POLuserpol@#2\endcsname
+      \expandafter\POL at split\POL at A;\POL at degA\POL at polA
+      \expandafter\POL at split\POL at B;\POL at degB\POL at polB
+      \ifnum\POL at degA<\z@
+        \expandafter\xint_firstoftwo\else\expandafter\xint_secondoftwo
+      \fi
+        {\ifnum\POL at degB<\z@
+          \expandafter\xint_firstoftwo\else\expandafter\xint_secondoftwo
+        \fi
+          {\def\POL at result{-1.\empty{0/1[0]}}}%
+          {\xintAssignArray\POL at polB\to\POL at arrayB
+           \POL at normalize{B}%
+           \POL at gcd@exit BA}}%
+        {\ifnum\POL at degB<\z@
+          \expandafter\xint_firstoftwo\else\expandafter\xint_secondoftwo
+        \fi
+          {\xintAssignArray\POL at polA\to\POL at arrayA
+           \POL at normalize{A}%
+           \POL at gcd@exit AB}%
+          {\ifnum\POL at degA<\POL at degB\space
+             \let\POL at tmp\POL at B\let\POL at B\POL at A\let\POL at A\POL at tmp
+             \let\POL at tmp\POL at degB\let\POL at degB\POL at degA\let\POL at degA\POL at degB
+           \fi
+           \xintAssignArray\POL at polA\to\POL at arrayA
+           \xintAssignArray\POL at polB\to\POL at arrayB
+           \POL at gcd AB%
+           }}%
+    \expandafter
+    \endgroup
+    \expandafter\def\csname POLuserpol@#3\expandafter\endcsname
+        \expandafter{\POL at result}%
+    \POL at newpol{#3}%
+}%
+\def\POL at normalize#1{%
+    \expandafter\def\expandafter\POL at tmp\expandafter
+        {\csname POL at array#1\csname POL at array#10\endcsname\endcsname}%
+    \edef\POL at normalize@leading{\POL at tmp}%
+    \expandafter\def\POL at tmp{1/1[0]}%
+    \count@\csname POL at deg#1\endcsname\space
+    \xintloop
+    \ifnum\count@>\z@
+      \expandafter\edef\csname POL at array#1\the\count@\endcsname
+      {\xintIrr{\xintScalarDiv
+                   {\csname POL at array#1\the\count@\endcsname}%
+                   {\POL at normalize@leading}}[0]}%
+    \advance\count@\m at ne
+    \repeat
+}%                     
+\def\POL at gcd#1#2{%
+    \POL at normalize{#2}%
+    \edef\POL at degQ{\the\numexpr\csname POL at deg#1\endcsname
+                              -\csname POL at deg#2\endcsname}%
+    \count@\numexpr\csname POL at deg#1\endcsname+\@ne\relax
+    \count\tw@\numexpr\POL at degQ+\@ne\relax
+    \xintloop
+      \POL at gcd@getremainder at loopbody#1#2%
+    \ifnum\count\tw@>\z@
+    \repeat
+    \expandafter\def\csname POL at array#10\endcsname{1}%
+    \xintloop
+    \xintiiifZero{\csname POL at array#1\the\count@\endcsname}%
+      {\iftrue}%
+      {\iffalse}%
+    \advance\count@\m at ne
+    \repeat
+    \expandafter\edef\csname POL at deg#1\endcsname{\the\numexpr\count at -\@ne}%
+    \ifnum\count@<\@ne
+      \expandafter\POL at gcd@exit
+    \else
+      \expandafter\edef\csname POL at array#10\endcsname{\the\count@}%
+      \expandafter\POL at gcd
+    \fi{#2}{#1}%
+}%
+\def\POL at gcd@getremainder at loopbody#1#2{%
+  \edef\POL at gcd@ratio{\csname POL at array#1\the\count@\endcsname}%
+  \advance\count@\m at ne
+  \advance\count\tw@\m at ne
+  \count4 \count@
+  \count6 \csname POL at deg#2\endcsname\space
+  \xintloop
+  \ifnum\count6>\z@
+    \expandafter\edef\csname POL at array#1\the\count4\endcsname
+      {\xintScalarSub
+          {\csname POL at array#1\the\count4\endcsname}%
+          {\xintScalarMul
+            {\POL at gcd@ratio}%
+            {\csname POL at array#2\the\count6\endcsname}}}%
+    \advance\count4 \m at ne
+    \advance\count6 \m at ne
+  \repeat
+}%
+\def\POL at gcd@exit#1#2{%
+    \count@\numexpr\csname POL at deg#1\endcsname+\@ne\relax
+    \POL at resultfromarray #1%
+}%
+                 
+
+%% TODO: BEZOUT
+
+
+%% DIFFERENTIATION
+\def\POL at diff@loop at one #1/#2[#3]#4%
+  {\xintIrr{\xintiiMul{#4}{#1}/#2[0]}[#3]}%
+\def\POL at diff#1{\POL at diff@loop1.}%
+\def\POL at diff@loop#1.#2{%
+  \if\relax#2\expandafter\xint_gob_til_dot\fi
+  {\expandafter\POL at diff@loop at one\romannumeral0\xintraw{#2}{#1}}%
+  \expandafter\POL at 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 at iterindex{\the\numexpr#1\relax}%
+   \ifnum\POL at iterindex<\z@
+       \expandafter\@firstoftwo
+   \else
+       \expandafter\@secondoftwo
+   \fi
+   {\PolAntiDiff[-\POL at iterindex]}{\POL at Diff}%
+}%
+\def\POL at Diff{%
+   \ifcase\POL at iterindex\space
+      \expandafter\POL at Diff@no
+   \or\expandafter\POL at Diff@one
+   \else\xint_afterfi{\POL at Iterate\POL at Diff@one}%
+   \fi
+}%
+\def\POL at Diff@no #1#2{\PolLet{#2}{#1}}%
+\def\POL at Diff@one #1#2{%
+   \expandafter\expandafter\expandafter\POL at split
+      \csname POLuserpol@#1\endcsname;\POL at var@deg\POL at var@coeffs
+   \ifnum\POL at var@deg<\@ne
+      \@namedef{POLuserpol@#2}{-1.\empty{0/1[0]}}%
+   \else
+     \edef\POL at var@coeffs{\expandafter\POL at diff\POL at var@coeffs\relax}%
+     \expandafter\edef\csname POLuserpol@#2\endcsname
+        {\the\numexpr\POL at var@deg-\@ne.\noexpand\empty\POL at var@coeffs}%
+   \fi
+   \POL at newpol{#2}%
+}%
+% lazy way but allows to share with AntiDiff
+\def\POL at Iterate#1#2#3{%
+    \begingroup
+    \xintverbosefalse
+        #1{#2}{#3}%
+        \xintloop
+        \ifnum\POL at iterindex>\tw@
+          #1{#3}{#3}%
+          \edef\POL at iterindex{\the\numexpr\POL at 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 at antidiff@loop at one #1/#2[#3]#4%
+  {\xintIrr{#1/\xintiiMul{#4}{#2}[0]}[#3]}%
+\def\POL at antidiff{\POL at antidiff@loop1.}%
+\def\POL at antidiff@loop#1.#2{%
+  \if\relax#2\expandafter\xint_gob_til_dot\fi
+  {\expandafter\POL at antidiff@loop at one\romannumeral0\xintraw{#2}{#1}}%
+  \expandafter\POL at 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 at iterindex{\the\numexpr#1\relax}%
+   \ifnum\POL at iterindex<\z@
+       \expandafter\@firstoftwo
+   \else
+       \expandafter\@secondoftwo
+   \fi
+   {\PolDiff[-\POL at iterindex]}{\POL at AntiDiff}%
+}%
+\def\POL at AntiDiff{%
+   \ifcase\POL at iterindex\space
+      \expandafter\POL at AntiDiff@no
+   \or\expandafter\POL at AntiDiff@one
+   \else\xint_afterfi{\POL at Iterate\POL at AntiDiff@one}%
+   \fi
+}%
+\let\POL at AntiDiff@no\POL at Diff@no
+\def\POL at AntiDiff@one #1#2{%
+   \expandafter\expandafter\expandafter\POL at split
+      \csname POLuserpol@#1\endcsname;\POL at var@deg\POL at var@coeffs
+   \ifnum\POL at var@deg<\z@
+      \@namedef{POLuserpol@#2}{-1.\empty{0/1[0]}}%
+   \else
+     \edef\POL at var@coeffs{\expandafter\POL at antidiff\POL at var@coeffs\relax}%
+     \expandafter\edef\csname POLuserpol@#2\endcsname
+         {\the\numexpr\POL at var@deg+\@ne.\noexpand\empty{0/1[0]}\POL at var@coeffs}%
+   \fi
+   \POL at newpol{#2}%
+}%
+
+
+%% CORE ALGEBRA MACROS
+%% We do this non-expandably, but in a nestable way... this is the whole
+%% point because \xintdeffunc as used by \PolNewPol creates a big nested macro.
+%% The idea is to execute it with another meaning given to \xintAdd etc..,
+%% so that it operates on "polynomials". This is a mixture of expandable
+%% and non-expandable techniques.
+\def\POL at get#1#2#3{%
+    \global\POL at polfalse
+    \begingroup
+        \def\POL at result{#3}%
+        #3%
+        \expandafter
+    \endgroup
+    \expandafter\def\expandafter#1\expandafter{\POL at result}%
+    \unless\ifPOL at pol
+        % avoid expanding more than twice #3
+        \edef#1{#3}%
+        \xintiiifZero{#1}%
+            {\def#1{-1.\empty{0/1[0]}}}%
+            {\edef#1{0.\noexpand\empty{#1}}}%
+    \fi
+    #2%
+}%
+%% ADDITION
+\def\POL at add  {\POL at get\POL at A\POL at add@b}%
+\def\POL at add@b{\POL at get\POL at B\POL at add@c}%
+\def\POL at add@c{%
+    \global\POL at poltrue
+    \POL at ifZero\POL at A 
+        {\let\POL at result\POL at B}%
+        {\POL at ifZero\POL at B
+             {\let\POL at result\POL at A}%
+             {\POL@@add}}%
+}%
+\def\POL@@add{%
+  \expandafter\POL at split\POL at A;\POL at degA\POL at polA
+  \expandafter\POL at split\POL at B;\POL at degB\POL at polB
+  \ifnum\POL at degA>\POL at degB\relax
+    \xintAssignArray\POL at polA\to\POL at arrayA
+    \xintAssignArray\POL at polB\to\POL at arrayB
+  \else
+    \xintAssignArray\POL at polB\to\POL at arrayA
+    \xintAssignArray\POL at polA\to\POL at arrayB
+    \let\POL at tmp\POL at degB\let\POL at degB\POL at degA\let\POL at degA\POL at tmp
+  \fi
+  \count@\z@
+  \xintloop
+     \advance\count@\@ne
+     \expandafter\edef\csname POL at arrayA\the\count@\endcsname
+          {\xintScalarAdd{\@nameuse{POL at arrayA\the\count@}}%
+                         {\@nameuse{POL at arrayB\the\count@}}}%
+  \unless\ifnum\POL at degB<\count@
+  \repeat
+  \count@\@nameuse{POL at arrayA0} % 1+\POL at 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 at arrayA0 is never zero
+   \xintiiifZero{\@nameuse{POL at arrayA\the\count@}}%
+      {\iftrue}%
+      {\iffalse}%
+  \advance\count@\m at ne
+  \repeat
+  \POL at resultfromarray A% attention that \POL at arrayA0 not updated
+}%
+
+%% MULTIPLICATION
+\def\POL at mul  {\POL at get\POL at A\POL at mul@b}%
+\def\POL at mul@b{\POL at get\POL at B\POL at mul@c}%
+\def\POL at mul@c{%
+    \global\POL at poltrue
+    \POL at ifZero\POL at A 
+        {\def\POL at result{-1.\empty{0/1[0]}}}%
+        {\POL at ifZero\POL at B
+             {\def\POL at result{-1.\empty{0/1[0]}}}%
+             {\POL@@mul}}%
+}%
+\def\POL@@mul{%
+  \expandafter\POL at split\POL at A;\POL at degA\POL at polA
+  \expandafter\POL at split\POL at B;\POL at degB\POL at polB
+  \ifnum\POL at degA>\POL at degB\relax
+    \xintAssignArray\POL at polA\to\POL at arrayA
+    \xintAssignArray\POL at polB\to\POL at arrayB
+  \else
+    \xintAssignArray\POL at polB\to\POL at arrayA
+    \xintAssignArray\POL at polA\to\POL at arrayB
+    \let\POL at tmp\POL at degB
+    \let\POL at degB\POL at degA
+    \let\POL at degA\POL at tmp
+  \fi
+  \count@\z@
+  \xintloop
+    \POL@@mul at phaseIloopbody
+  \unless\ifnum\POL at degB<\count@
+  \repeat
+  \xintloop
+  \unless\ifnum\POL at degA<\count@ % car attention au cas de mêmes degrés
+    \POL@@mul at phaseIIloopbody
+  \repeat
+  \edef\POL at degC{\the\numexpr\POL at degA+\POL at degB}%
+  \xintloop
+  \unless\ifnum\POL at degC<\count@
+    \POL@@mul at phaseIIIloopbody
+  \repeat
+  %\count@\the\numexpr\POL at degC+\@ne\relax % never zero polynomial here
+  \POL at resultfromarray C%
+}%
+\def\POL@@mul at phaseIloopbody{%
+    \advance\count@\@ne
+    \def\POL at tmp{0[0]}%
+    \count\tw@\z@
+    \xintloop
+       \advance\count\tw@\@ne
+       \edef\POL at tmp{%
+         \xintScalarAdd
+           {\POL at tmp}%
+           {\xintScalarMul
+             {\@nameuse{POL at arrayA\the\count\tw@}}%
+             {\@nameuse{POL at arrayB\the\numexpr\count at +\@ne-\count\tw@}}%
+           }%
+          }%
+    \ifnum\count\tw@<\count@
+    \repeat
+    \expandafter\let\csname POL at arrayC\the\count@\endcsname\POL at tmp
+}%  
+\def\POL@@mul at phaseIIloopbody{%
+    \advance\count@\@ne
+    \def\POL at tmp{0[0]}%
+    \count\tw@\count@
+    \advance\count\tw at -\@nameuse{POL at arrayB0} %
+    \xintloop
+    \ifnum\count\tw@<\count@
+      \advance\count\tw@\@ne
+      \edef\POL at tmp{%
+        \xintScalarAdd
+          {\POL at tmp}%
+          {\xintScalarMul
+            {\@nameuse{POL at arrayA\the\count\tw@}}%
+            {\@nameuse{POL at arrayB\the\numexpr\count at +\@ne-\count\tw@}}%
+          }%
+         }%
+    \repeat 
+    \expandafter\let\csname POL at arrayC\the\count@\endcsname\POL at tmp
+}%
+\def\POL@@mul at phaseIIIloopbody{%
+    \advance\count@\@ne
+    \def\POL at tmp{0[0]}%
+    \count\tw@\count@
+    \advance\count\tw at -\@nameuse{POL at arrayB0} %
+    \xintloop
+      \advance\count\tw@\@ne
+      \edef\POL at tmp{%
+        \xintScalarAdd{\POL at tmp}%
+          {\xintScalarMul
+            {\@nameuse{POL at arrayA\the\count\tw@}}%
+            {\@nameuse{POL at arrayB\the\numexpr\count at +\@ne-\count\tw@}}%
+          }%
+         }%
+    \ifnum\@nameuse{POL at arrayA0}>\count\tw@
+    \repeat 
+    \expandafter\let\csname POL at arrayC\the\count@\endcsname\POL at tmp
+}%
+
+%% POWERS (SCALAR EXPONENT...)
+\def\POL at pow #1#2{%
+    \global\POL at polfalse
+    \begingroup
+        \def\POL at result{#1}%
+        #1%
+        \expandafter
+    \endgroup
+    \expandafter\def\expandafter\POL at A\expandafter{\POL at result}%
+    \unless\ifPOL at pol
+        \edef\POL at A{\xintScalarPow{#1}{#2}}% no error check
+        \xintiiifZero{\POL at A}%
+            {\def\POL at result{-1.\empty{0/1[0]}}}%
+            {\edef\POL at result{0.\noexpand\empty{\POL at A}}}%
+    \else
+      \edef\POL at B{\numexpr\xintNum{#2}\relax}% no check on exponent >= 0
+      \ifcase\POL at B
+        \def\POL at result{0.\empty{1/1[0]}}%
+      \or
+        \let\POL at result\POL at A
+      \else
+        \POL@@pow at check
+      \fi
+    \fi
+    \global\POL at poltrue
+}%
+\def\POL@@pow at check {%
+% no problem here with leftover tokens!
+% should I have used that I-don't-care technique more elsewhere?
+    \ifnum\@ne>\POL at A
+    % polynomial is a constant, must get rid of dot and \empty
+        \edef\POL at A{\expandafter\xintScalarPow\romannumeral`^^@%
+                    \expandafter\xint_gob_til_dot\POL at A{\POL at B}}%
+        \xintiiifZero{\POL at A}%
+            {\def\POL at result{-1.\empty{0/1[0]}}}%
+            {\edef\POL at result{0.\noexpand\empty{\POL at A}}}%
+    \else
+    \ifnum\@ne=\POL at A
+    % perhaps a constant times X, check constant term
+        \xintiiifZero
+        {\expandafter\xint_firstoftwo\romannumeral`^^@%
+         \expandafter\xint_gob_til_dot\POL at A}
+        {\edef\POL at result
+          {\the\POL at B.% here at least 2.
+           \noexpand\empty
+           \romannumeral\xintreplicate{\POL at B}{{0/1[0]}}%
+           {\xintScalarPow
+             {\expandafter\xint_secondoftwo\romannumeral`^^@%
+              \expandafter\xint_gob_til_dot\POL at A}%
+             {\POL at B}}}}%
+        {\POL@@pow}% not constant times X, use general recursion
+    \else
+        \POL@@pow% general recursion
+    \fi\fi
+}%
+\def\POL@@pow at recurse#1#2{%
+    \begingroup
+        #1%
+        \expandafter
+    \endgroup
+    \expandafter\def\expandafter\POL at A\expandafter{\POL at result}%
+    \edef\POL at B{\numexpr\xintNum{#2}\relax}%
+    \ifcase\POL at B
+        \POL at thisshouldneverhappen
+    \or
+        \let\POL at result\POL at A
+    \else
+        \expandafter\POL@@pow
+    \fi
+}%
+\def\POL@@pow {%
+    \let\POL at pow@exp\POL at B
+    \let\POL at B\POL at A
+    \POL@@mul
+    \let\POL at sqA\POL at result
+    \ifodd\POL at pow@exp\space
+       \expandafter\POL@@pow at odd
+          \the\numexpr(\POL at pow@exp+\@ne)/\tw at -\@ne\expandafter.%
+    \else 
+       \expandafter\POL@@pow at even
+          \the\numexpr(\POL at pow@exp+\@ne)/\tw at -\@ne\expandafter.%
+    \fi
+}%
+\def\POL@@pow at even#1.{%
+    \expandafter\POL@@pow at recurse\expandafter
+       {\expandafter\def\expandafter\POL at result\expandafter{\POL at sqA}}%
+       {#1}%
+}%
+\def\POL@@pow at odd#1.{%
+    \expandafter\POL@@pow at odd@i\expandafter{\POL at A}{#1}%
+}%
+\def\POL@@pow at odd@i #1#2{%
+    \expandafter\POL@@pow at recurse\expandafter
+       {\expandafter\def\expandafter\POL at result\expandafter{\POL at sqA}}%
+       {#2}%
+    \expandafter\POL at mul\expandafter
+        {\expandafter\def\expandafter\POL at result\expandafter
+         {\POL at result}\global\POL at poltrue}%
+        {\def\POL at result{#1}\global\POL at poltrue}%
+}%
+
+%% DIVISION
+%% no check on divisor being non-zero
+\def\POL at div  {\POL at get\POL at A\POL at div@b}%
+\def\POL at div@b{\POL at get\POL at B\POL at div@c}%
+\def\POL at div@c{%
+    \global\POL at poltrue
+    \expandafter\POL at split\POL at A;\POL at degA\POL at polA
+    \expandafter\POL at split\POL at B;\POL at degB\POL at polB
+    \ifnum\POL at degA<\POL at degB\space
+       \@namedef{POL at arrayQ1}{0/1[0]}%
+       \def\POL at degQ{-1}%
+    \else
+       \xintAssignArray\POL at polA\to\POL at arrayR
+       \xintAssignArray\POL at polB\to\POL at arrayB
+       \POL@@div
+    \fi
+    \count@\numexpr\POL at degQ+\@ne\relax
+    \POL at resultfromarray Q%
+}%
+\def\POL@@div{%
+    \xintAssignArray\POL at polA\to\POL at arrayR
+    \xintAssignArray\POL at polB\to\POL at arrayB
+    \edef\POL at B@leading{\csname POL at arrayB\the\numexpr\POL at degB+\@ne\endcsname}%
+    \edef\POL at degQ{\the\numexpr\POL at degA-\POL at degB}%
+    \count@\numexpr\POL at degA+\@ne\relax
+    \count\tw@\numexpr\POL at degQ+\@ne\relax
+    \xintloop
+      \POL@@div at loopbody
+    \ifnum\count\tw@>\z@
+    \repeat
+    %%\expandafter\def\csname POL at arrayR0\endcsname{1}%
+    \xintloop
+    \xintiiifZero{\csname POL at arrayR\the\count@\endcsname}%
+      {\iftrue}%
+      {\iffalse}%
+    \advance\count@\m at ne
+    \repeat
+    \edef\POL at degR{\the\numexpr\count at -\@ne}%
+}%
+\def\POL@@div at loopbody{%
+    \edef\POL@@div at ratio{%
+          \xintScalarDiv{\csname POL at arrayR\the\count@\endcsname}%
+                        {\POL at B@leading}}%
+    \expandafter\let\csname POL at arrayQ\the\count\tw@\endcsname
+          \POL@@div at ratio  
+    \advance\count@\m at ne
+    \advance\count\tw@\m at ne
+    \count4 \count@
+    \count6 \POL at degB\space
+    \xintloop
+    \ifnum\count6>\z@
+      \expandafter\edef\csname POL at arrayR\the\count4\endcsname
+        {\xintScalarSub
+            {\csname POL at arrayR\the\count4\endcsname}%
+            {\xintScalarMul
+              {\POL@@div at ratio}%
+              {\csname POL at arrayB\the\count6\endcsname}}}%
+      \advance\count4 \m at ne
+      \advance\count6 \m at ne
+    \repeat
+}%
+
+%% MINUS SIGN AS UNARY OPERATOR
+\def\POL at opp #1{%
+    \global\POL at polfalse
+    \begingroup
+        \def\POL at result{#1}%
+        #1%
+        \expandafter
+    \endgroup
+    \expandafter\def\expandafter\POL at A\expandafter{\POL at result}%
+    \unless\ifPOL at pol
+        \edef\POL at A{\xintScalarOpp{#1}}%
+        \xintiiifZero{\POL at A}%
+            {\def\POL at result{-1.\empty{0/1[0]}}}%
+            {\edef\POL at result{0.\noexpand\empty{\POL at A}}}%
+    \else
+      \edef\POL at B{0.\noexpand\empty{-1/1[0]}}%
+      \POL@@mul
+    \fi
+    \global\POL at poltrue
+}%
+
+
+%% EXPANDABLE MACROS
+\newcommand\PolEval{}%
+\def\PolEval#1#2\At#3{\romannumeral`^^@\xinttheexpr reduce(#1(#3))\relax}%
+%
+\newcommand\PolNthCoeff[2]{\romannumeral`^^@%
+    \expandafter\POL at 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 at 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 at degree\csname POLuserpol@#1\endcsname;}%
+\def\POL at degree #1.#2;{#1}%
+%
+\newcommand\PolToList[1]{\romannumeral`^^@\expandafter\expandafter\expandafter
+                         \xint_gob_til_dot\csname POLuserpol@#1\endcsname}%
+%
+\newcommand\PolToCSV[1]{\romannumeral0\xintlistwithsep{, }{\PolToList{#1}}}%
+
+
+\newif\ifpoltoexprall
+\newcommand\PolToExprCmd[1]{\xintPRaw{\xintRawWithZeros{#1}}}%
+\newcommand\PolToExprCmdWithSep[1]{\xintiiifSgn{#1}{}{+}{+}\PolToExprCmd{#1}}%
+\newcommand\PolToExpr[1]{\expandafter\expandafter\expandafter
+                      \POL at toexpr\csname POLuserpol@#1\endcsname\relax}%
+%
+\def\POL at toexpr#1.\empty{%
+    \ifnum#1<\z@
+       \PolToExprCmd{0/1[0]}\expandafter\@gobbletwo
+    \else
+       \expandafter\POL at toexpr@a
+    \fi}%
+%
+\def\POL at toexpr@a #1{\ifpoltoexprall\expandafter\POL at toexprall@b
+                         \else\expandafter\POL at toexpr@b
+                  \fi{#1}{}\PolToExprCmd0.}%
+%
+\def\POL at toexpr@b #1#2#3{%
+    \xintiiifZero{#1}%
+      {\expandafter\POL at toexpr@loop\expandafter#3}%
+      {#3{#1}#2\expandafter\POL at toexpr@loop\expandafter\PolToExprCmdWithSep}%
+    \expandafter\POL at toexpr@b\the\numexpr\@ne+%
+}%
+\def\POL at toexprall@b #1#2#3{%
+    #3{#1}#2%
+    \expandafter\POL at toexpr@loop\expandafter\PolToExprCmdWithSep
+    \expandafter\POL at toexprall@b\the\numexpr\@ne+%
+}%
+\def\POL at toexpr@loop#1#2#3.#4{%
+  \if\relax#4\expandafter\xint_gob_til_dot\fi #2{#4}{*x^#3}#1#3.%
+}%
+
+
+%% Patch of xintfrac.sty's \xintAdd: for a/b + c/d, use lcm(b,d)
+\RequirePackage{xintgcd}
+\def\POL_fadd_C #1#2#3%
+{%
+   \expandafter\POL_fadd_D
+      \romannumeral0\xintiigcd{#2}{#3}.%
+   {#2}{#3}{#1}%
+}%
+\def\POL_fadd_D #1.#2#3%
+{%
+    \expandafter\POL_fadd_E
+       \romannumeral0\xintiiquo{#3}{#1}.%
+       {\romannumeral0\xintiiquo{#2}{#1}}{#2}{#3}%
+}%
+\def\POL_fadd_E #1.#2#3#4#5%
+{%
+    \expandafter\POL_fadd_F\romannumeral0\xintiimul{#1}{#3}.{#2}%
+                               {\xintiiMul{#1}{#5}}%
+}%
+\def\POL_fadd_F #1.#2#3#4%
+{%
+    \expandafter\POL_fadd_G
+    \romannumeral0\xintiiadd{#3}{\xintiiMul{#2}{#4}}/#1%
+}%
+\def\POL_fadd_G #1{%
+\def\POL_fadd_G ##1{\if0##1\expandafter\XINT_fadd_iszero\fi#1##1}%
+}\POL_fadd_G{ }%
+
+\POL at restorecatcodes
+\endinput


Property changes on: trunk/Master/texmf-dist/tex/latex/polexpr/polexpr.sty
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: trunk/Master/tlpkg/bin/tlpkg-ctan-check
===================================================================
--- trunk/Master/tlpkg/bin/tlpkg-ctan-check	2018-01-12 18:35:28 UTC (rev 46290)
+++ trunk/Master/tlpkg/bin/tlpkg-ctan-check	2018-01-12 22:35:39 UTC (rev 46291)
@@ -493,7 +493,7 @@
     plain-doc plainpkg plari plantslabels plates
     platex platex-tools platexcheat play playfair plex plex-otf plipsum
     plnfss plstmary plweb pm-isomath pmgraph pmx pmxchords pnas2009
-    poemscol poetry poetrytex polski poltawski
+    poemscol poetry poetrytex polexpr polski poltawski
     polyglossia polynom polynomial
     polytable postcards poster-mac powerdot powerdot-FUBerlin
     ppr-prv pracjourn preprint prerex present presentations presentations-en

Modified: trunk/Master/tlpkg/tlpsrc/collection-mathscience.tlpsrc
===================================================================
--- trunk/Master/tlpkg/tlpsrc/collection-mathscience.tlpsrc	2018-01-12 18:35:28 UTC (rev 46290)
+++ trunk/Master/tlpkg/tlpsrc/collection-mathscience.tlpsrc	2018-01-12 22:35:39 UTC (rev 46291)
@@ -117,6 +117,7 @@
 depend perfectcut
 depend physics
 depend pm-isomath
+depend polexpr
 depend prftree
 depend proba
 depend prooftrees

Added: trunk/Master/tlpkg/tlpsrc/polexpr.tlpsrc
===================================================================


More information about the tex-live-commits mailing list