summaryrefslogtreecommitdiff
path: root/macros/generic/polexpr/polexpr-ref.rst.txt
diff options
context:
space:
mode:
Diffstat (limited to 'macros/generic/polexpr/polexpr-ref.rst.txt')
-rw-r--r--macros/generic/polexpr/polexpr-ref.rst.txt3184
1 files changed, 3184 insertions, 0 deletions
diff --git a/macros/generic/polexpr/polexpr-ref.rst.txt b/macros/generic/polexpr/polexpr-ref.rst.txt
new file mode 100644
index 0000000000..028e68626f
--- /dev/null
+++ b/macros/generic/polexpr/polexpr-ref.rst.txt
@@ -0,0 +1,3184 @@
+.. comment: -*- fill-column: 72; mode: rst -*-
+
+===================
+ polexpr reference
+===================
+
+.. _quick:
+
+Syntax overview via examples
+----------------------------
+
+The syntax to define a new polynomial is::
+
+ \poldef polname(x):= expression in variable x;
+
+..
+
+The expression will be parsed by the services of xintexpr_, with some
+polynomial aware functions added to its syntax; they are described in
+detail :ref:`below <polexpr08>`. The parser accepts and will handle
+exactly arbitrarily big integers or fractions.
+
+.. note::
+
+ xintexpr_ does not automatically reduce fractions to lowest terms,
+ and, so far (but this may change in future) neither does :ref:`\\poldef
+ <poldef;>`.
+ See :ref:`rdcoeffs() <rdcoeffs>` and the macro
+ :ref:`\\PolReduceCoeffs <PolReduceCoeffs>`.
+
+
+- In place of ``x`` an arbitrary *dummy variable* is authorized,
+ i.e. per default one ``a, .., z, A, .., Z`` (more letters can be declared
+ under Unicode engines).
+
+- ``polname`` consists of *letters*, *digits*, and also the ``_`` and
+ ``'`` characters are allowed. The polynomial name **must** start with
+ a letter: do not use the underscore ``_`` as *first character* of a
+ polynomial name (even if of catcode letter). No warning is emitted
+ but dire consequences will ensue. The ``@`` is also allowed
+ (independently of its catcode "letter" or "other", which does not
+ matter). It is recommended to avoid using it as first character,
+ except for temporary polynomial variables.
+
+- The colon before the equality sign is optional and its (reasonable)
+ catcode does not matter.
+
+- The semi-colon at the end of the expression is mandatory. It is not
+ allowed to arise from expansion (despite the fact that the expression
+ itself will be parsed using only expansion), it must be "visible"
+ immediately.
+
+There are some potential problems (refer to the Technicalities_ section at
+bottom of this page) with the semi-colon as expression terminator, so an
+alternative syntax is provided, which avoids it altogether::
+
+ \PolDef[optional letter]{<polname>}{<expr. using letter as indeterminate>}
+
+The ``\PolDef`` optional first argument defaults to ``x`` and must be
+used as the indeterminate in the expression.
+
+Examples:
+
+``\poldef f(x):= 1 - x + quo(x^5,1 - x + x^2);``
+
+``\PolDef{f}{1 - x + quo(x^5,1 - x + x^2)}``
+ Both parse the polynomial
+ expression, and they create internally macros serving to
+ incarnate the polynomial, its coefficients, and the associated
+ polynomial function.
+
+ The polynomial can then be used in further polynomial definitions,
+ be served as argument to package macros, or appear as a variable in
+ various functions `described later <polexpr08_>`_.
+
+ .. warning::
+
+ Both the function ``quo()`` (as shown in the example above), and
+ the infix operator ``/`` are mapped to the Euclidean quotient.
+
+ This usage of ``/`` to stand for the Euclidean quotient is
+ **deprecated** and reserved for a (somewhat improbable) possible
+ extension of the package to handle rational functions as well.
+
+ .. _warningtacit:
+
+ .. attention::
+
+ Tacit multiplication rules let the parser when encountering
+ ``1/2 x^2`` skip the space and thus handle it as ``1/(2*x^2)``.
+ But then it gives zero, because `/` stands for the Euclidean
+ quotient operation here.
+
+ Thus one must use ``(1/2)x^2`` or ``1/2*x^2`` or
+ ``(1/2)*x^2`` for disambiguation: ``x - 1/2*x^2 + 1/3*x^3...``. It is
+ simpler to move the denominator to the right: ``x - x^2/2 +
+ x^3/3 - ...``.
+
+ It is worth noting that ``1/2(x-1)(x-2)`` suffers the same issue:
+ xintexpr_\ 's tacit multiplication always "ties more", hence this
+ gets interpreted as ``1/(2*(x-1)*(x-2))`` not as
+ ``(1/2)*(x-1)*(x-2)`` and then gives zero by
+ polynomial division. Thus, in such cases, use one of
+ ``(1/2)(x-1)(x-2)``, ``1/2*(x-1)(x-2)`` or ``(x-1)(x-2)/2``.
+
+ ``\poldef P(x):=...;`` defines ``P`` as a *polynomial function*,
+ which can be used inside ``\xinteval``, as::
+
+ \xinteval{P(3 + 7 + 11)}
+
+ or even as::
+
+ \xinteval{P(Q1 + Q2 + Q3)}
+
+ where ``Q1``, ``Q2``, ``Q3`` are polynomials. The evaluation result,
+ if not a scalar, will then be printed as ``pol([c0,c1,...])`` which
+ stands for a polynomial variable having the listed coefficients; see
+ :ref:`pol() <pol>`.
+
+ Indeed, as seen above with ``Q1``, the symbol ``P`` also stands for
+ a *variable of polynomial type*, which serves as argument to
+ polynomial specific functions such as :ref:`deg() <deg>` or
+ :ref:`polgcd() <polgcd>`, or as argument to other polynomials (as
+ above), or even simply stands for its own in algebraic expressions
+ such as::
+
+ \poldef Q(z):= P^2 + z^10;
+
+ Notice that in the above, the ``(z)`` part is mandatory, as it informs
+ ``\poldef`` of the letter used for the indeterminate. In the above
+ ``P(z)^2`` would give the same as ``P^2`` but the latter is slightly
+ more efficient.
+
+ One needs to acquire a good understanding of when the symbol ``P``
+ will stand for a function and when it will stand for a variable.
+
+ - If ``P`` and
+ ``Q`` are both declared polynomials then::
+
+ (P+Q)(3)% <--- attention, does (P+Q)*3, not P(3)+Q(3)
+
+ is currently evaluated as ``(P+Q)*3``, because ``P+Q`` is not
+ known as a *function*, but *only as a variable of polynomial
+ type*. Note that :ref:`evalp(P+Q,3) <evalp>` gives as expected
+ the same as ``P(3)+Q(3)``.
+
+ - Also::
+
+ (P)(3)% <--- attention, does P*3, not P(3)
+
+ will compute ``P*3``, because one can not in current xintexpr_ syntax
+ enclose a function name in parentheses: consequently it is the variable
+ which is used here.
+
+ There is a *meager possibility* that in future some internal changes
+ to xintexpr_ would let ``(P)(3)`` actually compute ``P(3)`` and
+ ``(P+Q)(3)`` compute ``P(3) + Q(3)``, but note that ``(P)(P)`` will
+ then do ``P(P)`` and not ``P*P``, the latter, current
+ interpretation, looking more intuitive. Anyway, do not rely too
+ extensively on tacit ``*`` and use explicit ``(P+Q)*(1+2)`` if this
+ is what is intended.
+
+
+``\PolLet{g}={f}``
+ saves a copy of ``f`` under name ``g``. Also usable without ``=``.
+
+ Has exactly the same effect as ``\poldef g(x):=f;`` or ``\poldef
+ g(w):=f(w);``\ .
+
+``\poldef f(z):= f^2;``
+ redefines ``f`` in terms of itself. Prior to ``0.8`` one needed
+ the right hand side to be ``f(z)^2``. Also, now ``sqr(f)`` is
+ possible (also ``sqr(f(x))`` but not ``sqr(f)(x)``).
+
+ It may look strange that an indeterminate variable is used on
+ left-hand-side even though it may be absent of right-hand-side, as
+ it seems to define ``f`` always as a polynomial function.
+
+ This is a legacy of pre-``0.8`` context.
+
+ .. important::
+
+ Note that ``f^2(z)`` or ``sqr(f)(z)`` will give a logical but
+ perhaps unexpected result: first ``f^2`` is computed, then the
+ opening parenthesis is seen which inserts a tacit multiplication
+ ``*``, so in the end it is as if the input had been ``f^2 * z``.
+ Although ``f`` is both a variable and a function, ``f^2`` is
+ computed as a polynomial *variable* and ceases being a function.
+
+``\poldef f(T):= f(f);``
+ again modifies ``f``. Here it is used both as variable and as
+ a function. Prior to ``0.8`` it needed to be ``f(f(T))``.
+
+``\poldef k(z):= f-g(g^2)^2;``
+ if everybody followed, this should now define the zero polynomial...
+ And ``f-sqr(g(sqr(g)))`` computes the same thing.
+
+ We can check this in a typeset document like this::
+
+ \poldef f(x):= 1 - x + quo(x^5,1 - x + x^2);%
+ \PolLet{g}={f}%
+ \poldef f(z):= f^2;%
+ \poldef f(T):= f(f);%
+ \poldef k(w):= f-sqr(g(sqr(g)));%
+ $$f(x) = \vcenter{\hsize10cm \PolTypeset{f}} $$
+ $$g(z) = \PolTypeset{g} $$
+ $$k(z) = \PolTypeset{k} $$
+ \immediate\write128{f(x)=\PolToExpr{f}}% ah, here we see it also
+
+``\poldef f'(x):= diff1(f);``
+ (new at ``0.8``)
+
+``\PolDiff{f}{f'}``
+ Both set ``f'`` (or any other chosen name) to the derivative
+ of ``f``.
+
+ .. important::
+
+ This is not done automatically. If some new definition needs to use
+ the derivative of some available polynomial, that derivative
+ polynomial must have been previously defined: something such as
+ ``f'(3)^2`` will not work without a prior definition of ``f'``.
+
+ But one can now use ``diff1(f)`` for on-the-spot construction with no
+ permanent declaration, so here ``evalp(diff1(f),3)^2``. And
+ ``diff1(f)^2`` is same as ``f'^2``, assuming here ``f'`` was declared
+ to be the derived polynomial.
+
+ Notice that the name ``diff1()`` is experimental and may change. Use
+ ``\PolDiff{f}{f'}`` as the stable interface.
+
+``\PolTypeset{P}``
+ Typesets (switching to math mode if in text mode)::
+
+ \poldef f(x):=(3+x)^5;%
+ \PolDiff{f}{f'}\PolDiff{f'}{f''}\PolDiff{f''}{f'''}%
+ $$f(z) = \PolTypeset[z]{f} $$
+ $$f'(z) = \PolTypeset[z]{f'} $$
+ $$f''(z) = \PolTypeset[z]{f''} $$
+ $$f'''(z)= \PolTypeset[z]{f'''} $$
+
+ See `its documentation <PolTypeset_>`_ for the configurability
+ via macros.
+
+ Since ``0.8`` `\\PolTypeset <PolTypeset_>`_ accepts directly an
+ expression, it does not have to be a pre-declared polynomial name::
+
+ \PolTypeset{mul(x-i,i=1..5)}
+
+``\PolToExpr{P}``
+ Expandably (contrarily to `\\PolTypeset <PolTypeset_>`_)
+ produces ``c_n*x^n + ... + c_0`` starting from the leading
+ coefficient. The ``+`` signs are omitted if followed by negative
+ coefficients.
+
+ This is useful for console or file output. This syntax is Maple and
+ PSTricks ``\psplot[algebraic]`` compatible; and also it is
+ compatible with ``\poldef`` input syntax, of course. See
+ `\\PolToExprCaret`_ for configuration of the ``^``, for example to
+ use rather ``**`` for Python syntax compliance.
+
+ Changed at ``0.8``: the ``^`` in output is by default of catcode 12
+ so in a draft document one can use ``\PolToExpr{P}`` inside the
+ typesetting flow (without requiring math mode, where the ``*`` would
+ be funny and ``^12`` would only put the ``1`` as exponent anyhow;
+ but arguably in text mode the ``+`` and ``-`` are not satisfactory
+ for math, except sometimes in monospace typeface, and anyhow TeX is
+ unable to break the expression across lines, barring special help).
+
+ See :ref:`\\PolToExpr{\<pol. expr.\>} <PolToExpr>` and related macros for customization.
+
+ Extended at ``0.8`` to accept as argument not only the name of a
+ polynomial variable but more generally any polynomial expression.
+
+
+Using defined polynomials in floating point context
+---------------------------------------------------
+
+Exact manipulations with fractional coefficients may quickly lead to
+very large denominators. For numerical evaluations, it is advisable
+to a use a floating point context. But for the polynomial to be
+usable as a function in floating point context, an extra step beyond
+``\poldef`` is required: see `\\PolGenFloatVariant`_. Then the
+``\xintfloateval`` macro from xintexpr_ will recognize the polynomial
+as a genuine function (with already float-rounded coefficients, and
+using a Horner scheme).
+
+But `\\PolGenFloatVariant`_ must be used each time the polynomial gets
+redefined or a new polynomial is created out of it. Functions such as
+for example :ref:`deg() <deg>` which handle the polynomial as an entity
+are only available within the ``\poldef`` and ``\xinteval`` (or
+``\xintexpr``) parsers. Inside ``\xintfloateval`` a polynomial can only
+serve as a numerical function (and only after declaration via
+`\\PolGenFloatVariant`_), and not as a variable.
+
+In some cases one may wish to replace a polynomial having acquired
+very big fractional coefficients with a new one whose coefficients
+have been float-rounded. See :ref:`\\PolMapCoeffs <PolMapCoeffs>`
+which can be used for example with the ``\xintFloat`` macro from the
+xintfrac_ package to achieve this.
+
+
+.. _polexpr08:
+
+The polexpr ``0.8`` extensions to the ``\xintexpr`` syntax
+----------------------------------------------------------
+
+All the syntax elements described in this section can be used in the
+``\xintexpr/\xinteval`` context (where polynomials can be obtained from
+the ``pol([])`` constructor, once polexpr is loaded): their usage is
+not limited to only ``\poldef`` context.
+
+.. note::
+
+ If a variable ``myPol`` defined via ``\xintdefvar`` turns out
+ to be a polynomial, the difference with those declared via ``\poldef``
+ will be:
+
+ 1. ``myPol`` is not usable as *function*, but only as a variable.
+ Attention that ``f(x)`` if ``f`` is only a variable (even a
+ polynomial one) will actually compute ``f * x``.
+
+ 2. ``myPol`` is not known to the polexpr package, hence for example the
+ macros to achieve localization of its roots are unavailable.
+
+ In a parallel universe I perhaps have implemented this expandably
+ which means it could then be accessible with syntax such as
+ ``rightmostroot(pol([42,1,34,2,-8,1]))`` but...
+
+
+Warning about unstability of the new syntax
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. warning::
+
+ Consider the entirety of this section as **UNSTABLE** and
+ **EXPERIMENTAL** (except perhaps regarding ``+``, ``-`` and ``*``).
+
+ And this applies even to items not explicitly flagged with one of
+ **unstable**, **Unstable**, or **UNSTABLE** which only reflect that
+ documentation was written over a period of time exceeding one minute,
+ enough for the author mood changes to kick in.
+
+ It is hard to find good names at the start of a life-long extension
+ program of functionalities, and perhaps in future it will be
+ preferred to rename everything or give to some functions other
+ meanings. Such quasi-complete renamings happened already a few times
+ during the week devoted to development.
+
+
+Infix operators ``+, -, *, /, **, ^``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ As has been explained in the `Syntax overview via examples`_
+ section these infix operators have been made polynomial aware, not
+ only in the ``\poldef`` context, but generally in any
+ ``\xintexpr/\xinteval`` context, inclusive of ``\xintdeffunc``.
+
+ Conversely functions declared via ``\xintdeffunc`` and making use of
+ these operators will automatically be able to accept polynomials
+ declared from ``\poldef`` as variables.
+
+ Usage of ``/`` for euclidean division of polynomials is **deprecated**.
+ Only in case of a scalar denominator is it to be considered stable.
+ Please use rather ``quo()``.
+
+Experimental infix operators ``//, /:``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Here is the tentative behaviour of ``A//B`` according to types:
+
+ - ``A`` non scalar and ``B`` non scalar: euclidean quotient,
+
+ - ``A`` scalar and ``B`` scalar: floored division,
+
+ - ``A`` scalar and ``B`` non scalar: produces zero,
+
+ - ``A`` non scalar and ``B`` scalar: coefficient per
+ coefficient floored division.
+
+ This is an **experimental** overloading of the ``//`` and ``/:``
+ from ``\xintexpr``.
+
+ The behaviour in the last case, but not only, is to be considerd
+ **unstable**. The alternative would be for ``A//B`` with ``B``
+ scalar to act as ``quo(A,B)``. But, we have currently chosen to let
+ ``//B`` for a scalar ``B`` act coefficient-wise on the numerator.
+ Beware that it thus means it can be employed with the idea of doing
+ euclidean division only by checking that ``B`` is non-scalar.
+
+ The ``/:`` operator provides the associated remainder so always
+ ``A`` is reconstructed from ``(A//B)*B + A/:B``.
+
+ If ``:`` is active character use ``/\string:`` (it is safer to use
+ ``/\string :`` if it is not known if ``:`` has catcode other, letter,
+ or is active, but note that ``/:`` is fine and needs no precaution if
+ ``:`` has catcode letter, it is only an active ``:`` which is
+ problematic, like for all other characters possibly used in an
+ expression).
+
+ **UNSTABLE**
+
+ As explained above, there are (among other things) hesitations
+ about behaviour with ``pol2`` a scalar.
+
+Comparison operators ``<, >, <=, >=, ==, !=``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ **NOT YET IMPLEMENTED**
+
+ As the internal representation by xintfrac_ and xintexpr_ of
+ fractions does not currently require them to be in reduced terms,
+ such operations would be a bit costly as they could not benefit from
+ the ``\pdfstrcmp`` engine primitive. In fact xintexpr_ does not use
+ it yet anywhere, even for normalized pure integers, although it could
+ speed up signifcantly certain aspects of core arithmetic.
+
+ Equality of polynomials can currently be tested by computing the
+ difference, which is a bit costly. And of course the ``deg()``
+ function allows comparing degrees. In this context note the
+ following syntax::
+
+ (deg(Q)) ?? { zero } { non-zero scalar } { non-scalar }
+
+ for branching.
+
+
+.. _pol:
+
+``pol(<nutple expression>)``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ This converts a nutple ``[c0,c1,...,cN]`` into the polynomial
+ variable having these coefficients. Attention that the square
+ brackets are **mandatory**, except of course if the argument is
+ actually an expression producing such a "nutple".
+
+ Currently, this process will not normalize the coefficients (such
+ as reducing to lowest terms), it only trims out the leading zero
+ coefficients.
+
+ Inside ``\xintexpr``, this is the only (allowed) way to create ex
+ nihilo a polynomial variable; inside ``\poldef`` it is an alternative
+ input syntax which is more efficient than the input ``c0 + c1 * x + c2 *
+ x^2 + ...``.
+
+.. important::
+
+ Whenever an expression with polynomials collapses to a constant, it
+ becomes a scalar. There is currently no distinction during the
+ parsing of expressions by ``\poldef``
+ or ``\xintexpr`` between constant polynomial variables and scalar
+ variables.
+
+ Naturally, ``\poldef`` can be used to declare a constant polynomial
+ ``P``, then ``P`` can also be used as function having a value
+ independent of argument, but as a variable, it is non-distinguishable
+ from a scalar (of course functions such as ``deg()`` tacitly
+ consider scalars to be constant polynomials).
+
+ Notice that we tend to use the vocable "variable" to refer to
+ arbitrary expressions used as function arguments, without implying
+ that we are actually referring to pre-declared variables in the sense
+ of ``\xintdefvar``.
+
+.. _lpol:
+
+``lpol(<nutple expression>)``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ This converts a nutple ``[cN,...,c1,c0]`` into the polynomial
+ variable having these coefficients, with leading coefficients coming
+ first in the input. Attention that the square brackets are
+ **mandatory**, except of course if the argument is actually an
+ expression producing such a "nutple".
+
+ Currently, this process will not normalize the coefficients (such
+ as reducing to lowest terms), it only trims out the leading zero
+ coefficients.
+
+ **NAME UNSTABLE**
+
+ It can be used in ``\poldef`` as an alternative input syntax, which
+ is more efficient than using the algebraic notation with monomials.
+
+ (new with ``0.8.1``, an empty nutple will cause breakage)
+
+.. _xintevalpolexpr:
+
+``\xinteval{<pol. expr.>}``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ This is documented here for lack of a better place: it evaluates the
+ polynomial expression then outputs the "string" ``pol([c0, c1, ..., cN])``
+ if the degree ``N`` is at least one (and the usual scalar output else).
+
+ The "pol" word uses letter catcodes, which is actually mandatory for
+ this output to be usable as input, but it does not make sense to use
+ this inside ``\poldef`` or ``\xintexpr`` at it means basically
+ executing ``pol(coeffs(..expression..))`` which is but a convoluted
+ way to obtain the same result as ``(..expression..)`` (the
+ parentheses delimiting the polynomial expression).
+
+ For example, ``\xinteval{(1+pol([0,1]))^10}`` expands (in two steps)
+ to::
+
+ pol([1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1])
+
+ You do need loading polexpr for this, else of course ``pol([])``
+ remains unknown to ``\xinteval{}`` as well as the polynomial algebra !
+ This example can also be done as
+ ``\xinteval{subs((1+x)^10,x=pol([0,1]))}``.
+
+ I hesitated using as output the polynomial notation as produced by
+ `\\PolToExpr{} <poltoexpr_>`_, but finally opted for this.
+
+.. _evalp:
+
+``evalp(<pol. expr.>, <pol. expr>)``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Evaluates the first argument as a polynomial function of the
+ second. Usually the second argument will be scalar, but this is not
+ required::
+
+ \poldef K(x):= evalp(-3x^3-5x+1,-27x^4+5x-2);
+
+ If the first argument is an already declared polynomial ``P``, use
+ rather the functional form ``P()`` (which can accept a numerical as
+ well as polynomial argument) as it is more efficient.
+
+ One can also use ``subs()`` syntax [#]_ (see xintexpr_ documentation)::
+
+ \poldef K(x):= subs(-3y^3-5y+1, y = -27x^4+5x-2);
+
+ but the ``evalp()`` will use a Horner evaluation scheme which is
+ usually more efficient.
+
+ .. [#] by the way Maple uses the opposite, hence wrong, order
+ ``subs(x=..., P)`` but was written before computer science
+ reached the xintexpr_ heights. However it makes validating
+ Maple results by polexpr sometimes cumbersome, but perhaps
+ they will update it at some point.
+
+ ..
+
+ **name unstable**
+
+ ``poleval``? ``evalpol``? ``peval``? ``evalp``? ``value``?
+ ``eval``? ``evalat``? ``eval1at2``? ``evalat2nd``?
+
+ Life is so complicated when one asks questions. Not everybody does,
+ though, as is amply demonstrated these days.
+
+ **syntax unstable**
+
+ I am hesitating about permuting the order of the arguments.
+
+.. _deg:
+
+``deg(<pol. expr.>)``
+~~~~~~~~~~~~~~~~~~~~~
+
+ Computes the degree.
+
+.. important::
+
+ As ``\xintexpr`` does not yet support infinities, the degree of
+ the zero polynomial is ``-1``. Beware that this breaks additivity
+ of degrees, but ``deg(P)<0`` correctly detects the zero polynomial,
+ and ``deg(P)<=0`` detects scalars.
+
+``coeffs(<pol. expr.>)``
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Produces the nutple ``[c0,c1,...,cN]`` of coefficients. The highest
+ degree coefficient is always non zero (except for the zero
+ polynomial...).
+
+ **name unstable**
+
+ I am considering in particular using ``polcoeffs()`` to avoid
+ having to overload ``coeffs()`` in future when matrix type
+ will be added to xintexpr_.
+
+.. _lcoeffs:
+
+``lcoeffs(<pol. expr.>)``
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Produces the nutple ``[cN,....,c1,c0]`` of coefficients, starting
+ with the highest degree coefficient.
+
+ (new with ``0.8.1``)
+
+``coeff(<pol. expr.>, <num. expr.>)``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ As expected. Produces zero if the numerical index is negative or
+ higher than the degree.
+
+ **name, syntax and output unstable**
+
+ I am hesitating with ``coeff(n,pol)`` syntax and also perhaps using
+ ``polcoeff()`` in order to avoid having to overload ``coeff()``
+ when matrix type will be added to xintexpr_.
+
+ The current behaviour is at odds with legacy
+ :ref:`\\PolNthCoeff{\<polname\>}{\<index\>} <PolNthCoeff>` regarding negative indices.
+ Accessing leading or sub-leading coefficients can be done with
+ other syntax, see `lc(<pol. expr.>)`_, and in some contexts it
+ is useful to be able to rely on the fact that coefficients with
+ negative indices do vanish, so I am for time being maintaining this.
+
+.. _lc:
+
+``lc(<pol. expr.>)``
+~~~~~~~~~~~~~~~~~~~~
+
+ The leading coefficient. The same result can be obtained from
+ ``coeffs(pol)[-1]``, which shows also how to generalize to access
+ sub-leading coefficients. See the xintexpr_ documentation for
+ Python-like indexing syntax.
+
+``monicpart(<pol. expr.>)``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Divides by the leading coefficient, except that ``monicpart(0)==0``.
+
+ **unstable**
+
+ Currently the coefficients are reduced to lowest terms (contrarily
+ to legacy behaviour of `\\PolMakeMonic <polmakemonic_>`_), and
+ additionally the xintfrac_ ``\xintREZ`` macro is applied which
+ extracts powers of ten from numerator or denominator and stores
+ them internally separately. This is generally beneficial to
+ efficiency of multiplication.
+
+.. _cont:
+
+``cont(<pol. expr.>)``
+~~~~~~~~~~~~~~~~~~~~~~
+
+ The (fractional) greatest common divisor of the polynomial
+ coefficients. It is always produced as an irreducible (non-negative)
+ fraction. According to Gauss theorem the content of a product is the
+ product of the contents.
+
+ .. commentaire 8 avril 2021
+
+ surprenamment après avoir utilisé `\\PolIContent <PolIContent_>`_
+ une fois on peut utiliser `\\PolIContent`_ directement.
+
+ avec docutils 0.16
+
+ ..
+
+ **name and syntax unstable**
+
+ At ``0.8`` it was created as ``icontent()`` to match the legacy
+ macro `\\PolIContent <PolIContent_>`_, whose name in 2018 was
+ chosen in relation to Maple's function ``icontent()``, possibly
+ because at that time I had not seen that Maple also had a
+ ``content()`` function. Name changed at ``0.8.1``.
+
+ It will change syntax if in future multivariate polynomials are
+ supported, and ``icontent()`` will then make a come-back.
+
+``primpart(<pol. expr.>)``
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ The quotient (except for the zero polynomial) by
+ ``cont(<pol. expr.>)``. This is thus a polynomial with
+ integer coefficients having ``1`` as greatest common divisor. The
+ sign of the leading coefficient is the same as in the original.
+
+ And ``primpart(0)==0``.
+
+ The trailing zeros of the integer coefficients are extracted
+ into a power of ten exponent part, in the internal representation.
+
+``quorem(<pol. expr.>, <pol. expr.>)``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Produces a nutple ``[Q,R]`` with ``Q`` the euclidean quotient and
+ ``R`` the remainder.
+
+ **name unstable**
+
+ ``poldiv()``?
+
+``quo(<pol. expr.>, <pol. expr.>)``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ The euclidean quotient.
+
+ The deprecated ``pol1/pol2`` syntax computes the same polynomial.
+
+``rem(<pol. expr.>, <pol. expr.>)``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ The euclidean remainder. If ``pol2`` is a (non-zero) scalar, this is
+ zero.
+
+ There is no infix operator associated to this, for lack of evident
+ notation. Please advise.
+
+ ``/:`` can be used if one is certain that ``pol2`` is of
+ degree at least one. But read the warning about it being unstable
+ even in that case.
+
+.. not implemented
+
+ ``spquorem(pol1,pol2)``
+ ~~~~~~~~~~~~~~~~~~~~~~~
+
+ Produces a tuple ``[Q,R]`` with the pseudo-quotient and
+ pseudo-remainder. See `prem(pol1, pol2) <prem_>`_ for
+ their definitions.
+
+ **NOT IMPLEMENTED**
+
+ I am hesitating returning rather the nutple ``[b^f, Q, R]`` or
+ ``[f, Q, R]``. Note that the number of non-zero coefficients of
+ a polynomial ``P`` can be computed as ``add(?(c),c=coeffs(P))``,
+ and in this context I am hesitating abstracting a function to
+ provide this [#]_. The usual problem is that I don't know how to
+ name the function.
+
+ I am also hesitating providing rather a function returning only
+ ``f`` and ``R``, not ``Q``, which for modular computations we don't
+ need to carry along.
+
+ .. [#] one can embed ``\xintiiexpr add(?(c),c=coeffs(P))\relax``
+ inside ``\xintexpr`` and it will be more efficient for long
+ polynomials, but naturally a core implementation using a
+ single ``\numexpr`` would be quite more efficient still.
+
+.. _prem:
+
+``prem(<pol. expr. 1>, <pol. expr. 2>)``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Produces a nutple ``[m, spR]`` where ``spR`` is the (special) pseudo
+ Euclidean remainder. Its description is:
+
+ - the standard euclidean remainder ``R`` is ``spR/m``
+
+ - ``m = b^f`` with ``b`` equal to the **absolute value** of the
+ leading coefficient of ``pol2``,
+
+ - ``f`` is the number of non-zero coefficients in the euclidean
+ quotient, if ``deg(pol2)>0`` (even if the remainder vanishes).
+
+ If ``pol2`` is a scalar however, the function outputs ``[1,0]``.
+
+ With these definitions one can show that if both ``pol1`` and
+ ``pol2`` have integer coefficients, then this is also the case of
+ ``spR``, which makes its interest (and also ``m*Q`` has integer
+ coefficients, with ``Q`` the euclidean quotient, if ``deg(pol2)>0``).
+ Also, ``prem()`` is computed faster than ``rem()`` for such integer
+ coefficients polynomials.
+
+ .. hint::
+
+ If you want the euclidean quotient ``R`` evaluated via ``spR/m``
+ (which may be faster, even with non integer coefficients) use
+ ``subs(last(x)/first(x),x=prem(P,Q))`` syntax as it avoids
+ computing ``prem(P,Q)`` twice. This does the trick both in
+ ``\poldef`` or in ``\xintdefvar``.
+
+ However, as is explained in the xintexpr_ documentation, using
+ such syntax in an ``\xintdeffunc`` is (a.t.t.o.w) illusory, due to
+ technicalities of how ``subs()`` gets converted into nested
+ expandable macros. One needs an auxiliary function like this::
+
+ \xintdeffunc lastoverfirst(x):=last(x)/first(x);
+ \xintdeffunc myR(x)=lastoverfirst(prem(x));
+
+ Then, ``myR(pol1,pol2)`` will evaluate ``prem(pol1,pol2)`` only
+ once and compute a polynomial identical to the euclidean
+ remainder (internal representations of coefficients may differ).
+
+ In this case of integer coefficients polynomials, the polexpr
+ internal representation of the integer coefficients in the pseudo
+ remainder will be with unit denominators only if that was already the
+ case for those of ``pol1`` and ``pol2`` (no automatic reduction to
+ lowest terms is made prior or after computation).
+
+ Pay attention here that ``b`` is the **absolute value** of the
+ leading coefficient of ``pol2``. Thus the coefficients of the
+ pseudo-remainder have the same signs as those of the standard
+ remainder. This diverges from Maple's function with the same name.
+
+
+``divmod(<pol. expr. 1>, <pol. expr. 2>)``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Overloads the scalar ``divmod()`` and associates it with the
+ experimental ``//`` and ``/:`` as extended to the polynomial type.
+
+ In particular when both ``pol1`` and ``pol2`` are scalars, this is
+ the usual ``divmod()`` (as in Python) and for ``pol1`` and ``pol2``
+ non constant polynomials, this is the same as ``quorem()``.
+
+ **Highly unstable** overloading of ``\xinteval``\ 's ``divmod()``.
+
+``mod(<pol. expr. 1>, <pol. expr. 2>)``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ The ``R`` of the ``divmod()`` output. Same as ``R`` of ``quorem()``
+ when the second argument ``pol2`` is of degree at least one.
+
+ **Highly unstable** overloading of ``\xinteval``\ 's ``mod()``.
+
+``polgcd(<pol. expr. 1>, <pol. expr. 2>, ...)``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Evaluates to the greatest common polynomial divisor of all the
+ polynomial inputs. The output is a **primitive** (in particular,
+ with integer coefficients) polynomial. It is zero if and only if all
+ inputs vanish.
+
+ Attention, there must be either at least two polynomial variables, or
+ alternatively, only one argument which then must be a bracketed list
+ or some expression or variable evaluating to such a "nutple" whose
+ items are polynomials (see the documentation of the scalar ``gcd()``
+ in xintexpr_).
+
+ The two variable case could (and was, during development) have been
+ defined at user level like this::
+
+ \xintdeffunc polgcd_(P,Q):=
+ (deg(Q))??{P}{1}{polgcd_(Q,primpart(last(prem(P,Q))))};
+ \xintdeffunc polgcd(P,Q):=polgcd_(primpart(P),primpart(Q));%
+
+ This is basically what is done internally for two polynomials, up
+ to some internal optimizations.
+
+ **UNSTABLE**
+
+ I hesitate between returning a *primitive* or a *monic* polynomial.
+ Maple returns a primitive polynomial if all inputs [#]_ have integer
+ coefficients, else it returns a monic polynomial, but this is
+ complicated technically for us to add such a check and would add
+ serious overhead.
+
+ Internally, computations are done using primitive
+ integer-coefficients polynomials (as can be seen in the function
+ template above). So I decided finally to output a primitive
+ polynomial, as one can always apply ``monicpart()`` to it.
+
+ Attention that this is at odds with behaviour of the legacy
+ `\\PolGCD <PolGCD_>`_ (non expandable) macro.
+
+ .. [#] actually, only two polynomial arguments are allowed by Maple's
+ ``gcd()`` as far as I know.
+
+``resultant(<pol. expr. 1>, <pol. expr. 2>)``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ The resultant.
+
+ **NOT YET IMPLEMENTED**
+
+``disc(<pol. expr.>)``
+~~~~~~~~~~~~~~~~~~~~~~
+
+ The discriminant.
+
+ **NOT YET IMPLEMENTED**
+
+``polpowmod(<pol. expr. 1>, <num. expr.>, <pol. expr. 2>)``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Modular exponentiation: ``mod(pol1^N, pol2)`` in a more efficient
+ manner than first computing ``pol1^N`` then reducing modulo ``pol2``.
+
+ Attention that this is using the ``mod()`` operation, whose current
+ experimental status is as follows:
+
+ - if ``deg(pol2)>0``, the euclidean remainder operation,
+ - if ``pol2`` is a scalar, coefficient-wise reduction modulo ``pol2``.
+
+
+ **UNSTABLE**
+
+ This is currently implemented at high level via ``\xintdeffunc`` and
+ recursive definitions, which were copied over from a scalar example
+ in the xintexpr_ manual::
+
+ \xintdeffunc polpowmod_(P, m, Q) :=
+ isone(m)?
+ % m=1: return P modulo Q
+ { mod(P,Q) }
+ % m > 1: test if odd or even and do recursive call
+ { odd(m)? { mod(P*sqr(polpowmod_(P, m//2, Q)), Q) }
+ { mod( sqr(polpowmod_(P, m//2, Q)), Q) }
+ }
+ ;%
+ \xintdeffunc polpowmod(P, m, Q) := (m)?{polpowmod_(P, m, Q)}{1};%
+
+ Negative exponents are not currently implemented.
+
+ For example::
+
+ \xinteval{subs(polpowmod(1+x,100,x^7),x=pol([0,1]))}
+ \xinteval{subs(polpowmod(1+x,20,10), x=pol([0,1]))}
+
+ produce respectively::
+
+ pol([1, 100, 4950, 161700, 3921225, 75287520, 1192052400])
+ pol([1, 0, 0, 0, 5, 4, 0, 0, 0, 0, 6, 0, 0, 0, 0, 4, 5, 0, 0, 0, 1])
+
+.. perte de temps terrible pourquoi j'écris cela
+ When ``pol2`` is as scalar then the degrees of the modular powers
+ ``mod(pol1^N, pol2)`` will in general increase linearly in ``N``
+ hence become big. But one can play with modifying the above
+ template and nesting two ``mod()``, one with an integer modulus,
+ say ``7``, and the other the a monic integer coefficients
+ polynomial such as ``Q = x^2+1``. Then an integer coefficients
+ polynomial ``P`` will have an integer coefficient remainder modulo
+ ``Q``, and
+
+.. _rdcoeffs:
+
+``rdcoeffs(<pol. expr.>)``
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ This operates on the internal representation of the coefficients,
+ reducing them to lowest terms.
+
+ **name HIGHLY undecided**
+
+``rdzcoeffs(<pol. expr.>)``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ This operates on the internal representation of the coefficients,
+ reducing them to lowest terms then extracting from numerator
+ or denominator the maximal power of ten to store as a decimal
+ exponent.
+
+ This is sometimes favourable to more efficient polynomial algebra
+ computations.
+
+ **name HIGHLY undecided**
+
+``diff1(<pol. expr.>)``
+~~~~~~~~~~~~~~~~~~~~~~~
+
+ The first derivative.
+
+ **name UNSTABLE**
+
+ This name may be used in future to be the partial derivative with
+ respect to a first variable.
+
+``diff2(<pol. expr.>)``
+~~~~~~~~~~~~~~~~~~~~~~~
+
+ The second derivative.
+
+ **name UNSTABLE**
+
+ This name may be used in future to be the partial derivative with
+ respect to a second variable.
+
+
+``diffn(<pol. expr. P>, <num. expr. n>)``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ The ``n``\ th derivative of ``P``. For ``n<0`` computes iterated primitives
+ vanishing at the origin.
+
+ The coefficients are not reduced to lowest terms.
+
+ **name and syntax UNSTABLE**
+
+ I am also considering reversing the order of the arguments.
+
+``antider(<pol. expr. P>)``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ The primitive of ``P`` with no constant term. Same as ``diffn(P,-1)``.
+
+``intfrom(<pol. expr. P>, <pol. expr. c>)``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ The primitive of ``P`` vanishing at ``c``, i.e. ``\int_c^x P(t)dt``.
+
+ Also ``c`` can be a polynomial... so if ``c`` is monomial ``x``
+ this will give zero!
+
+ **UNSTABLE**
+
+ Allowing general polynomial variable for ``c`` adds a bit of
+ overhead to the case of a pure scalar. So I am hesitating
+ maintaining this feature whose interest appears dubious.
+
+ .. attention::
+
+ As the two arguments are both allowed to be polynomials, if by
+ inadvertance one exchanges the two, there is no error but the
+ meaning of ``intfrom(c,P)`` is completely otherwise, as it
+ produces ``c*(x - P)`` if ``c`` is a scalar::
+
+ >>> &pol
+ pol mode (i.e. function definitions use \poldef)
+ >>> P(x):=1+x^2;
+ P = x^2+1
+ --> &GenFloat(P) lets P become usable as function in fp mode
+ --> &ROOTS(P) (resp. &ROOTS(P,N)) finds all rational roots exactly and
+ all irrational roots with at least 10 (resp. N) fractional digits
+ >>> intfrom(P,1);
+ @_1 pol([-4/3, 1, 0, 1/3])
+ >>> intfrom(1,P);
+ @_2 pol([-1, 1, -1])
+ >>> &bye
+
+
+
+.. grosse hésitation ici
+
+ ``intto(<pol. expr. P>, <pol. expr. c>)``
+ -----------------------------------------
+
+ ``\int_x^c P(t)dt``.
+
+ c'est l'opposé du précédent
+
+ mais le nom pourrait faire penser à \int_0^x plutôt
+
+``integral(<pol. expr. P>, [<pol. expr. a>, <pol. expr. b>])``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ ``\int_a^b P(t)dt``.
+
+ .. warning::
+
+ The brackets here are not denoting an optional argument but a
+ *mandatory* nutple argument ``[a, b]`` with *two items*. No real
+ recoverable-from error check is done on the input syntax. The
+ input can be an xintexpr_ variable which happens to be a nutple
+ with two items, or any expression which evaluates to such a
+ nutple.
+
+ ``a`` and ``b`` are not restricted to be scalars, they are allowed to
+ be themselves polynomial variables or even polynomial expressions.
+
+ To compute ``\int_{x-1}^x P(t)dt`` it is more efficient to use
+ ``intfrom(x-1)``.
+
+ Similary to compute ``\int_x^{x+1} P(t)dt``, use ``-intfrom(x+1)``.
+
+ **UNSTABLE**
+
+ Am I right to allow general polynomials ``a`` and ``b`` hence add
+ overhead to the pure scalar case ?
+
+
+
+Non-expandable macros
+---------------------
+
+.. note::
+
+ At ``0.8`` ``polexpr`` is usable with Plain TeX and not only with
+ LaTeX. Some examples given in this section may be using LaTeX syntax
+ such as ``\renewcommand``.
+
+.. _poldef;:
+
+``\poldef polname(letter):= expression using the letter as indeterminate;``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ This evaluates the *polynomial expression* and stores the
+ coefficients in a private structure accessible later via other
+ package macros, used with argument ``polname``. Of course the
+ *expression* can make use of previously defined polynomials.
+
+ Polynomial names must start with a letter and are constituted of
+ letters, digits, underscores and the right tick ``'``.
+
+ The whole xintexpr_ syntax is authorized, as long as the final
+ result is of polynomial type::
+
+ \poldef polname(z) := add((-1)^i z^(2i+1)/(2i+1)!, i = 0..10);
+
+ With fractional coefficients, beware the `tacit multiplication issue
+ <warningtacit_>`_.
+
+ Furthermore:
+
+ - a variable ``polname`` is defined which can be used in ``\poldef``
+ as well as in ``\xinteval`` for algebraic computations or as
+ argument to polynomial aware functions,
+
+ - a function ``polname()`` is defined which can be used in ``\poldef``
+ as well as in ``\xinteval``. It accepts there as argument scalars
+ and also other polynomials (via their names, thanks to previous
+ item).
+
+ Notice that any function defined via ``\xintdeffunc`` and using
+ only algebraic operations (and ople indexing or slicing operations)
+ should work fine in ``\xintexpr/\xinteval`` with such polynomial
+ names as argument.
+
+ In the case of a constant polynomial, the xintexpr_ variable (not the
+ internal data structure on which the package macros operate)
+ associated to it is indistinguishable from a scalar, it is actually
+ a scalar and has lost all traces from its origins as a polynomial
+ (so for example can be used as argument to the ``cos()`` function).
+
+ The *function* on the other hand remains a one-argument function,
+ which simply has a constant value.
+
+ .. attention::
+
+ The function ``polname()`` is defined **only** for
+ ``\xintexpr/\xinteval``
+ context. It will be unknown to ``\xintfloateval``.
+
+ Worse, a
+ previously existing floating point function of the same name will
+ be let undefined again, to avoid hard to debug mismatches between
+ exact and floating point polynomials. This also applies when the
+ polynomial is produced not via ``\poldef`` or ``\PolDef`` but
+ as result of usage of the other package macros.
+
+ See :ref:`\\PolGenFloatVariant{\<polname\>} <PolGenFloatVariant>` to generate a **function**
+ usable in ``\xintfloateval``.
+
+ .. attention::
+
+ Using the **variable** ``mypol`` inside ``\xintfloateval`` will
+ generate low-level errors because the infix operators there are
+ not polynomial-aware, and the polynomial specific functions such
+ as ``deg()`` are only defined for usage inside ``\xintexpr``.
+
+ In short, currently polynomials defined via ``polexpr`` can
+ be used in floating point context only for numerical evaluations,
+ via **functions** obtained from :ref:`\\PolGenFloatVariant{\<polname\>} <PolGenFloatVariant>`
+ usage.
+
+ Changes to the original polynomial via package macros are not
+ automatically mapped to the numerical floating point evaluator
+ which must be manually updated as necessary when the original
+ rational coefficient polynomial is modified.
+
+ The original expression is lost after parsing, and in particular the
+ package provides no way to typeset it (of course the package
+ provides macros to typeset the computed polynomial). Typesetting
+ the original expression has to be done manually, if needed.
+
+.. _PolDef:
+
+``\PolDef[<letter>]{<polname>}{<expr. using the letter as indeterminate>}``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Does the same as `\\poldef <poldef;_>`_ in an undelimited macro
+ format, the main interest is to avoid potential problems with the
+ catcode of the semi-colon in presence of some packages. In absence
+ of a ``[<letter>]`` optional argument, the variable is assumed to be
+ ``x``.
+
+
+.. _PolGenFloatVariant:
+
+``\PolGenFloatVariant{}``
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolGenFloatVariant{<polname>}``
+
+ Makes the polynomial also usable in the
+ ``\xintfloatexpr/\xintfloateval`` parser. It will therein evaluates
+ via an Horner scheme using polynomial coefficients already
+ pre-rounded to the float precision.
+
+ See also :ref:`\\PolToFloatExpr{\<pol. expr.\>} <PolToFloatExpr>`.
+
+ .. attention::
+
+ Any operation, for example generating the derivative polynomial,
+ or dividing two polynomials or using the ``\PolLet``, must be
+ followed by explicit usage of ``\PolGenFloatVariant{<polname>}`` if
+ the new polynomial is to be used in ``\xintfloateval``.
+
+.. _PolTypeset:
+
+``\PolTypeset{}``
+~~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolTypeset{<pol. expr.>}``
+
+ Typesets in descending powers, switching to math mode if in text
+ mode, after evaluating the polynomial expression::
+
+ \PolTypeset{mul(x-i,i=1..5)}% possible since polexpr 0.8
+
+ The letter used in the input expression is by default ``x``,
+ but can be modified by a redefinition of `\\PolToExprInVar`_.
+
+ It uses also by default the letter ``x`` on output but this one can
+ be changed via an optional argument::
+
+ \PolTypeset[z]{polname or polynomial expression}
+
+ By default zero coefficients are skipped (use ``\poltypesetalltrue``
+ to get all of them in output).
+
+ The following macros (whose meanings will be found in the package code)
+ can be re-defined for customization. Their default definitions are
+ expandable, but this is not a requirement.
+
+.. _PolTypesetCmd:
+
+``\PolTypesetCmd{}``
+^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolTypesetCmd{<raw_coeff>}``
+
+ Its package definition checks if the coefficient is ``1`` or ``-1``
+ and then skips printing the ``1``, except for the coefficient of
+ degree zero. Also it sets the conditional deciding behaviour of
+ :ref:`\\PolIfCoeffIsPlusOrMinusOne{T}{F} <PolIfCoeffIsPlusOrMinusOne>`.
+
+ The actual printing of the coefficients, when not equal to plus or
+ minus one, is handled by :ref:`\\PolTypesetOne{\<raw_coeff\>} <PolTypesetOne>`.
+
+.. _PolIfCoeffIsPlusOrMinusOne:
+
+``\PolIfCoeffIsPlusOrMinusOne{}{}``
+***********************************
+
+Syntax: ``\PolIfCoeffIsPlusOrMinusOne{T}{F}``
+
+ This macro is a priori undefined.
+
+ It is defined via the default :ref:`\\PolTypesetCmd{\<raw_coeff\>} <PolTypesetCmd>` to be
+ used if needed in the execution of `\\PolTypesetMonomialCmd`_,
+ e.g. to insert a ``\cdot`` in front of ``\PolVar^{\PolIndex}`` if
+ the coefficient is not plus or minus one.
+
+ The macro will execute ``T`` if the coefficient has been found to be
+ plus or minus one, and ``F`` if not. It chooses expandably between
+ ``T`` and ``F``.
+
+.. _PolTypesetOne:
+
+``\PolTypesetOne{}``
+^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolTypesetOne{<raw_coeff>}``
+
+ Defaults to ``\xintTeXsignedFrac`` (LaTeX) or ``\xintTeXsignedOver``
+ (else). But these xintfrac_ old legacy macros are a bit
+ annoying as they insist in exhibiting a power of ten rather than
+ using simpler decimal notation.
+
+ As alternative, one can do definitions such as::
+
+ \def\PolTypesetOne#1{\xintDecToString{\xintREZ{#1}}}
+ % or with LaTeX+siunitx for example
+ \renewcommand\PolTypesetOne[1]{\num{\xintPFloat[5]{#1}}}
+ % (as \num of siunitx understands floating point notation)
+ \renewcommand\PolTypesetOne[1]{\num{\xintRound{4}{#1}}}
+
+.. _PolTypesetMonomialCmd:
+
+``\PolTypesetMonomialCmd``
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ This decides how a monomial (in variable ``\PolVar`` and with
+ exponent ``\PolIndex``) is to be printed. The default does nothing
+ for the constant term, ``\PolVar`` for the first degree and
+ ``\PolVar^{\PolIndex}`` for higher degrees monomials. Beware that
+ ``\PolIndex`` expands to digit tokens and needs termination in
+ ``\ifnum`` tests.
+
+.. _PolTypesetCmdPrefix:
+
+``\PolTypesetCmdPrefix{}``
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolTypesetCmdPrefix{<raw_coeff>}``
+
+ Expands to a ``+`` if the ``raw_coeff`` is zero or positive, and to
+ nothing if ``raw_coeff`` is negative, as in latter case the
+ ``\xintTeXsignedFrac`` (or ``\xintTeXsignedOver``) used by
+ :ref:`\\PolTypesetCmd{\<raw_coeff\>} <PolTypesetCmd>` will put the ``-`` sign in front of
+ the fraction (if it is a fraction) and this will thus serve as
+ separator in the typeset formula. Not used for the first term.
+
+
+.. _PolTypeset*:
+
+``\PolTypeset*{}``
+~~~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolTypeset*{<pol. expr.>}``
+
+ Typesets in ascending powers. Use ``[<letter>]`` optional argument
+ (after the ``*``) to use another letter than ``x``.
+
+ Extended at ``0.8`` to accept general expressions and not only
+ polynomial names. Redefine `\\PolToExprInVar`_ to use in the
+ expression another letter than default ``x``.
+
+
+.. _PolLet:
+
+``\PolLet{}={}``
+~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolLet{<polname_2>}={<polname_1>}``
+
+ Makes a copy of the already defined polynomial ``polname_1`` to a
+ new one ``polname_2``. This has the same effect as
+ ``\PolDef{<polname_2>}{<polname_1>(x)}`` or (better)
+ ``\PolDef{<polname_2>}{<polname_1>}`` but with less overhead. The
+ ``=`` is optional.
+
+.. _PolGlobalLet:
+
+``\PolGlobalLet{}={}``
+~~~~~~~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolGlobalLet{<polname_2>}={<polname_1>}``
+
+ Acts globally.
+
+.. _PolAssign:
+
+``\PolAssign{}\toarray{}``
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolAssign{<polname>}\toarray{<\macro>}``
+
+ Defines a one-argument expandable macro ``\macro{#1}`` which expands
+ to the (raw) #1th polynomial coefficient.
+
+ - Attention, coefficients here are indexed starting at 1. This is
+ an unfortunate legacy situation related to the original indexing
+ convention in xinttools_ arrays.
+
+ - With #1=-1, -2, ..., ``\macro{#1}`` returns leading coefficients.
+
+ - With #1=0, returns the number of coefficients, i.e. ``1 + deg f``
+ for non-zero polynomials.
+
+ - Out-of-range #1's return ``0/1[0]``.
+
+ See also :ref:`\\PolNthCoeff{\<polname\>}{\<index\>} <PolNthCoeff>`.
+
+.. _PolGet:
+
+``\PolGet{}\fromarray{}``
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolGet{<polname>}\fromarray{<\macro>}``
+
+ Does the converse operation to
+ ``\PolAssign{<polname>}\toarray\macro``. Each individual
+ ``\macro{<value>}`` gets expanded in an ``\edef`` and then normalized
+ via xintfrac_\ 's macro ``\xintRaw``.
+
+ The leading zeros 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;``.
+
+ .. vieux commentaire
+
+ Prior to ``0.5``, coefficients were not normalized via
+ ``\xintRaw`` for internal storage.
+
+.. _PolFromCSV:
+
+``\PolFromCSV{}{}``
+~~~~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolFromCSV{<polname>}{<csv>}``
+
+ Defines a polynomial directly from the comma separated list of values
+ (or a macro expanding to such a list) of its coefficients, the *first
+ item* gives the constant term, the *last item* gives the leading
+ coefficient, except if zero, then it is dropped (iteratively). List
+ items are each expanded in an ``\edef`` and then put into normalized
+ form via xintfrac_\ 's macro ``\xintRaw``.
+
+ As leading zero coefficients are removed::
+
+ \PolFromCSV{f}{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+
+ defines the zero polynomial, which holds only one coefficient.
+
+ See also expandable macro :ref:`\\PolToCSV{\<polname\>} <PolToCSV>`.
+
+ .. vieux commentaire
+
+ Prior to ``0.5``, coefficients were not normalized via
+ ``\xintRaw`` for internal storage.
+
+
+.. _PolMapCoeffs:
+
+``\PolMapCoeffs{}{}``
+~~~~~~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolMapCoeffs{\macro}{<polname>}``
+
+ It modifies ('in-place': original coefficients get lost) 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 the replacement text of ``\macro``, ``\index`` expands to the
+ coefficient index (starting at zero for the constant term).
+
+ Notice that ``\macro`` will have to handle inputs in the xintfrac_
+ internal format. This means that it probably will have to be
+ expressed in terms of macros from the xintfrac_ package.
+
+ Example::
+
+ \def\foo#1{\xintMul{#1}{\the\numexpr\index*\index\relax}}
+
+ (or with ``\xintSqr{\index}``) to replace ``n``-th coefficient
+ ``f_n`` by ``f_n*n^2``.
+
+.. _PolReduceCoeffs:
+
+``\PolReduceCoeffs{}``
+~~~~~~~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolReduceCoeffs{<polname>}``
+
+ Reduces the internal representations of the coefficients to
+ their lowest terms.
+
+.. _PolReduceCoeffs*:
+
+``\PolReduceCoeffs*{}``
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolReduceCoeffs*{<polname>}``
+
+ Reduces the internal representations of the coefficients to their
+ lowest terms, but ignoring a possible separated "power of ten part".
+
+ For example, xintfrac_ stores an ``30e2/50`` input as ``30/50`` with
+ a separate ``10^2`` part. This will thus get replaced by ``3e^2/5``
+ (or rather whatever xintfrac_ uses for internal representation), and
+ not by ``60`` as would result from complete reduction.
+
+ Evaluations with polynomials treated by this can be much faster than
+ with those handled by the non-starred variant
+ :ref:`\\PolReduceCoeffs{\<polname\>} <PolReduceCoeffs>`: as the numerators and denominators
+ remain generally smaller.
+
+.. _PolMakeMonic:
+
+``\PolMakeMonic{}``
+~~~~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolMakeMonic{<polname>}``
+
+ Divides by the leading coefficient. It is recommended to execute
+ :ref:`\\PolReduceCoeffs*{\<polname\>} <PolReduceCoeffs*>` immediately afterwards. This is not
+ done automatically, in case the original polynomial had integer
+ coefficients and the user wants to keep the leading one as common
+ denominator for typesetting purposes.
+
+.. _PolMakePrimitive:
+
+``\PolMakePrimitive{}``
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolMakePrimitive{<polname>}``
+
+ Divides by the integer content see (`\\PolIContent`_).
+ This thus produces a polynomial with integer
+ coefficients having no common factor. The sign of the leading
+ coefficient is not modified.
+
+.. _PolDiff:
+
+``\PolDiff{}{}``
+~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolDiff{<polname_1>}{<polname_2>}``
+
+ This sets ``polname_2`` to the first derivative of ``polname_1``. It
+ is allowed to issue ``\PolDiff{f}{f}``, effectively replacing ``f``
+ by ``f'``.
+
+ Coefficients of the result ``polname_2`` are irreducible fractions
+ (see `Technicalities`_ for the whole story.)
+
+.. _PolDiff[]:
+
+``\PolDiff[]{}{}``
+~~~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolDiff[N]{<polname_1>}{<polname_2>}``
+
+ This sets ``polname_2`` to the ``N``-th derivative of ``polname_1``.
+ Identical arguments is allowed. With ``N=0``, same effect as
+ ``\PolLet{<polname_2>}={<polname_1>}``. With negative ``N``, switches to
+ using ``\PolAntiDiff``.
+
+.. _PolAntiDiff:
+
+``\PolAntiDiff{}{}``
+~~~~~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolAntiDiff{<polname_1>}{<polname_2>}``
+
+ This sets ``polname_2`` to the primitive of ``polname_1`` vanishing
+ at zero.
+
+ Coefficients of the result ``polname_2`` are irreducible fractions
+ (see `Technicalities`_ for the whole story.)
+
+.. _PolAntiDiff[]:
+
+``\PolAntiDiff[]{}{}``
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolAntiDiff[N]{<polname_1>}{<polname_2>}``
+
+ This sets ``polname_2`` to the result of ``N`` successive integrations on
+ ``polname_1``. With negative ``N``, it switches to using ``\PolDiff``.
+
+.. _PolDivide:
+
+``\PolDivide{}{}{}{}``
+~~~~~~~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolDivide{<polname_1>}{<polname_2>}{<polname_Q>}{<polname_R>}``
+
+ This sets ``polname_Q`` and ``polname_R`` to be the quotient and
+ remainder in the Euclidean division of ``polname_1`` by
+ ``polname_2``.
+
+.. _PolQuo:
+
+``\PolQuo{}{}{}``
+~~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolQuo{<polname_1>}{<polname_2>}{<polname_Q>}``
+
+ This sets ``polname_Q`` to be the quotient in the Euclidean division
+ of ``polname_1`` by ``polname_2``.
+
+.. _PolRem:
+
+``\PolRem{}{}{}``
+~~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolRem{<polname_1>}{<polname_2>}{<polname_R>}``
+
+ This sets ``polname_R`` to be the remainder in the Euclidean division
+ of ``polname_1`` by ``polname_2``.
+
+.. _PolGCD:
+
+``\PolGCD{}{}{}``
+~~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolGCD{<polname_1>}{<polname_2>}{<polname_GCD>}``
+
+ This sets ``polname_GCD`` to be the (monic) GCD of ``polname_1``
+ and ``polname_2``. It is a unitary polynomial except if both
+ ``polname_1`` and ``polname_2`` vanish, then ``polname_GCD`` is the
+ zero polynomial.
+
+.. ``\PolIGCD{<polname_1>}{<polname_2>}{polname_iGCD}``
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ **NOT YET**
+
+ This **assumes** that the two polynomials have integer coefficients.
+ It then computes the greatest common divisor in the integer
+ polynomial ring, normalized to have a positive leading coefficient
+ (if the inputs are not both zero).
+
+
+Root localization routines via the `Sturm Theorem`_
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+As :ref:`\\PolToSturm{\<polname\>}{\<sturmname\>} <PolToSturm>` and
+:ref:`\\PolSturmIsolateZeros{\<sturmname\>} <PolSturmIsolateZeros>` and variants declare
+additional polynomial or scalar variables with names based on ``<sturmname>`` as
+prefix, it is advisable to keep the ``<sturmname>`` namespace separate from
+the one applying to ``\xintexpr`` variables generally, or to polynomials.
+
+.. _PolToSturm:
+
+``\PolToSturm{}{}``
+^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolToSturm{<polname>}{<sturmname>}``
+
+ With ``<polname>`` being for example ``P``, and ``<sturmname>`` being
+ for example ``S``, the macro starts by computing the derivative
+ ``P'``, then computes the opposite of the remainder in the euclidean
+ division of ``P`` by ``P'``, then the opposite of the remainder in
+ the euclidean division of ``P'`` by the first obtained polynomial,
+ etc... Up to signs following the ``--++--++...`` pattern, these are
+ the same remainders as in the Euclide algorithm applied to the
+ computation of the GCD of ``P`` and ``P'``.
+
+ The precise process differs from the above description: the
+ algorithm first sets ``S_0_`` to be the *primitive part* of ``P``
+ and ``S_1_`` to be the *primitive part* of ``P'`` (see
+ :ref:`\\PolIContent{\<polname\>} <PolIContent>`), then at each step
+ the remainder is made primitive and stored for internal reference as
+ ``S_k_``, so only integer-coefficients polynomials are manipulated.
+
+ .. warning::
+
+ This exact procedure will perhaps in future be replaced by a
+ *sub-resultant algorithm*, which may bring some speed gain in
+ obtaining a pseudo-Sturm sequence, but some experimenting is
+ needed, in the context of realistically realizable computations
+ by the package; primitive polynomials although a bit costly
+ have the smallest coefficients hence are the best for the kind of
+ computations done for root localization, after having computed a
+ Sturm sequence.
+
+ The last non-zero primitivized remainder ``S_N_`` is, up to sign,
+ the primitive part of the GCD of ``P`` and ``P'``. Its roots (real
+ and complex) are the multiple roots of the original ``P``. The
+ original ``P`` was "square-free" (i\.e\. did not have multiple real
+ or complex roots) if and only if ``S_N_`` is a constant, which is
+ then ``+1`` or ``-1`` (its value before primitivization is lost).
+
+ The macro then divides each ``S_k_`` by ``S_N_`` and declares the
+ quotients ``S_k`` as user polynomials for future use. By Gauss
+ theorem about the contents of integer-coefficients polynomials,
+ these ``S_k`` also are primitive integer-coefficients polynomials.
+
+ This step will be referred to as *normalization*, and in this
+ documentation the obtained polynomials are said to constitute the
+ "Sturm chain" (or "Sturm sequence"), i.e. by convention the "Sturm
+ chain polynomials" are square-free and primitive. The possibly
+ non-square-free ones are referred to as *non-normalized*.
+
+ As an exception to the rule, if the original ``P`` was "square-free"
+ (i\.e\. did not have multiple real or complex roots) then
+ normalization is skipped (in that case ``S_N_`` is either ``+1`` or
+ ``-1``), so ``S_0_`` is exactly the primitive part of starting
+ polynomial ``P``, in the "square-free" case.
+
+ The next logical step is to execute `\\PolSturmIsolateZeros{S}
+ <PolSturmIsolateZeros_>`_ or one of its variants. Be careful not to
+ use the names ``sturmname_0``, ``sturmname_1``, etc... for defining
+ other polynomials after having done
+ ``\PolToSturm{<polname>}{<sturmname>}`` and before executing
+ ``\PolSturmIsolateZeros{<sturmname>}`` or its variants else the
+ latter will behave erroneously.
+
+ .. note::
+
+ The declaration of the ``S_k``\ 's will overwrite
+ with no warning previously declared polynomials with identical
+ names ``S_k``. This is original reason why the macro expects two
+ names: ``<polname>`` and ``<sturmname>``.
+
+ It is allowed to use the polynomial name ``P`` as Sturm chain
+ name ``S``: ``\PolToSturm{f}(f}``, but of course fusing the
+ namespaces is slightly dangerous. And, also `\\PolSturmIsolateZeros
+ <PolSturmIsolateZeros_>`_ creates variables sharing
+ the ``<sturmname>`` prefix, which must be taken into account to
+ avoid name clashes.
+
+ .. warning::
+
+ The reason why the ``S_k``\ 's are declared as polynomials is
+ that the associated polynomial functions are needed to compute
+ the sign changes in the Sturm sequence evaluated at a given
+ location, as this is the basis mechanism of `\\PolSturmIsolateZeros
+ <PolSturmIsolateZeros_>`_ (on the basis of the `Sturm theorem`_).
+
+ It is possible that in future the package will only internally
+ construct such polynomial functions and only the starred variant
+ will make the normalized (i.e. square-free) Sturm sequence public.
+
+ The integer ``N`` giving the length of the Sturm chain ``S_0``,
+ ``S_1``, ..., ``S_N`` is available as
+ :ref:`\\PolSturmChainLength{\<sturmname\>} <PolSturmChainLength>`. If all roots of original ``P``
+ are real, then ``N`` is both the number of distinct real roots and
+ the degree of ``S_0``. In the case of existence of complex roots,
+ the number of distinct real roots is at most ``N`` and ``N`` is at
+ most the degree of ``S_0``.
+
+.. _PolToSturm*:
+
+``\PolToSturm*{}{}``
+^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolToSturm*{<polname>}{<sturmname>}``
+
+ Does the same as `un-starred version <PolToSturm_>`_ and additionally it
+ keeps for user usage the memory of the *un-normalized* (but still
+ made primitive) Sturm chain
+ polynomials ``sturmname_k_``, ``k=0,1, ..., N``, with
+ ``N`` being :ref:`\\PolSturmChainLength{\<sturmname\>} <PolSturmChainLength>`.
+
+ .. comment
+
+ The square-free part of ``<polname>`` is ``sturmname_0``, and their
+ quotient is the polynomial with name
+ ``sturmname_\PolSturmChainLength{<sturmname>}_``. It thus easy to
+ set-up a loop iteratively computing the latter until the last one
+ is a constant, thus obtaining the decomposition of an ``f`` as
+ a product ``c f_1 f_2 f_3 ...`` of a constant and square-free (primitive)
+ polynomials, where each ``f_i`` divides its predecessor.
+
+.. _PolSturmIsolateZeros:
+
+``\PolSturmIsolateZeros{}``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolSturmIsolateZeros{<sturmname>}``
+
+ The macro locates, using the `Sturm Theorem`_, as many disjoint
+ intervals as there are distinct real roots.
+
+ .. important::
+
+ The Sturm chain must have been produced by an earlier
+ :ref:`\\PolToSturm{\<polname\>}{\<sturmname\>} <PolToSturm>`.
+
+ After its execution they are two types of such intervals (stored in
+ memory and accessible via macros or xintexpr_ variables, see below):
+
+ - singleton ``{a}``: then ``a`` is a root, (necessarily a decimal
+ number, but not all such decimal numbers are exactly identified yet).
+
+ - open intervals ``(a,b)``: then there is exactly one root ``z``
+ such that ``a < z < b``, and the end points are guaranteed to not
+ be roots.
+
+ The interval boundaries are decimal numbers, originating
+ in iterated decimal subdivision from initial intervals
+ ``(-10^E, 0)`` and ``(0, 10^E)`` with ``E`` chosen initially large
+ enough so that all roots are enclosed; if zero is a root it is always
+ identified as such. The non-singleton intervals are of the
+ type ``(a/10^f, (a+1)/10^f)`` with ``a`` an integer, which is
+ neither ``0`` nor ``-1``. Hence either ``a`` and ``a+1`` are both positive
+ or they are both negative.
+
+ One does not *a priori* know what will be the lengths of these
+ intervals (except that they are always powers of ten), they
+ vary depending on how many digits two successive roots have in
+ common in their respective decimal expansions.
+
+ .. important::
+
+ If some two consecutive intervals share an end-point, no
+ information is yet gained about the separation between the two
+ roots which could at this stage be arbitrarily small.
+
+ See :ref:`\\PolRefineInterval*{\<sturmname\>}{\<index\>} <PolRefineInterval*>` which addresses
+ this issue.
+
+ .. This procedure is covariant
+ with the independent variable ``x`` becoming ``-x``.
+ Hmm, pas sûr et trop fatigué
+
+ Let us suppose ``<sturmname>`` is ``S``.
+
+ The interval boundaries (and exactly found roots) are made available
+ for future computations in ``\xintexpr/xinteval`` or ``\poldef`` as
+ variables ``SL_1``, ``SL_2``, etc..., for the left end-points and
+ ``SR_1``, ``SR_2``, ..., for the right end-points.
+
+ Additionally, xintexpr_ variable ``SZ_1_isknown`` will have value
+ ``1`` if the root in the first interval is known, and ``0``
+ otherwise. And similarly for the other intervals.
+
+ .. important::
+
+ The variable declarations are done with no check of existence of
+ previously existing variables with identical names.
+
+ Also, macros :ref:`\\PolSturmIsolatedZeroLeft{\<sturmname\>}{\<index\>} <PolSturmIsolatedZeroLeft>` and
+ :ref:`\\PolSturmIsolatedZeroRight{\<sturmname\>}{\<index\>} <PolSturmIsolatedZeroRight>` are provided which
+ expand to these same values, written in decimal notation (i.e.
+ pre-processed by `\\PolDecToString <PolDecToString_>`_.) And there
+ is also :ref:`\\PolSturmIfZeroExactlyKnown{\<sturmname\>}{\<index\>}{T}{F} <PolSturmIfZeroExactlyKnown>`.
+
+ .. important::
+
+ Trailing zeroes in the stored decimal numbers accessible via the
+ macros are significant: they are also present in the decimal
+ expansion of the exact root, so as to be able for example to
+ print out bounds of real roots with as many digits as is
+ significant, even if the digits are zeros.
+
+ The start of the decimal expansion of the ``<index>``-th root is given by
+ `\\PolSturmIsolatedZeroLeft{<sturmname>}{<index>}
+ <PolSturmIsolatedZeroLeft_>`_ if the root is positive, and by
+ `\PolSturmIsolatedZeroRight{<sturmname>}{<index>}
+ <PolSturmIsolatedZeroRight_>`_ if the root is neagtive. These two
+ decimal numbers are either both zero or both of the same sign.
+
+ The number of distinct roots is obtainable expandably as
+ :ref:`\\PolSturmNbOfIsolatedZeros{\<sturmname\>} <PolSturmNbOfIsolatedZeros>`.
+
+ Furthermore
+ :ref:`\\PolSturmNbOfRootsOf{\<sturmname\>}\\LessThanOrEqualTo{\<value\>} <PolSturmNbOfRootsOfLessThanOrEqualTo>` and
+ :ref:`\\PolSturmNbOfRootsOf{\<sturmname\>}\\LessThanOrEqualToExpr{\<num. expr.\>} <PolSturmNbOfRootsOfLessThanOrEqualToExpr>`.
+ will expandably compute respectively the number of real roots at
+ most equal to ``value`` or ``expression``, and the same but with
+ multiplicities.
+
+ These variables and macros are automatically updated in case of
+ subsequent usage of :ref:`\\PolRefineInterval*{\<sturmname\>}{\<index\>} <PolRefineInterval*>` or
+ other localization improving macros.
+
+ .. note::
+
+ The current polexpr implementation defines the xintexpr_ variables
+ and xinttools_ arrays as described above with global scope. On the
+ other hand the Sturm sequence polynomials obey the current scope.
+
+ This is perhaps a bit inconsistent and may change in future.
+
+ .. note::
+
+ The results are exact
+ bounds for the mathematically exact real roots.
+
+ Future releases will perhaps also provide macros based on Newton
+ or Regula Falsi methods. Exact computations with such methods
+ lead however quickly to very big fractions, and this forces usage
+ of some rounding scheme for the abscissas if computation times
+ are to remain reasonable. This raises issues of its own, which
+ are studied in numerical mathematics.
+
+.. _PolSturmIsolateZeros*:
+
+``\PolSturmIsolateZeros*{}``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolSturmIsolateZeros*{<sturmname>}``
+
+ The macro does the same as :ref:`\\PolSturmIsolateZeros{\<sturmname\>} <PolSturmIsolateZeros>` and
+ then in addition it does the extra work to determine all
+ multiplicities of the real roots.
+
+ After execution,
+ :ref:`\\PolSturmIsolatedZeroMultiplicity{\<sturmname\>}{\<index\>} <PolSturmIsolatedZeroMultiplicity>` expands
+ to the multiplicity of the root located in the ``index``\ -th
+ interval (intervals are enumerated from left to right, with index
+ starting at ``1``).
+
+ Furthermore, if for example the ``<sturmname>`` is ``S``, xintexpr_
+ variables ``SM_1``, ``SM_2``... hold the multiplicities thus
+ computed.
+
+ .. note::
+
+ Somewhat counter-intuitively, it is not necessary to have
+ executed the :ref:`\\PolToSturm* <PolToSturm*>`
+ starred variant: during its
+ execution, :ref:`\\PolToSturm <PolToSturm>`,
+ even though it does not declare the
+ non-square-free Sturm chain polynomials as user-level genuine
+ polynomials, stores their data in private macros.
+
+ See ``The degree nine polynomial with 0.99, 0.999, 0.9999 as triple
+ roots`` example in ``polexpr-examples.pdf``.
+
+.. _PolSturmIsolateZerosAndGetMultiplicities:
+
+``\PolSturmIsolateZerosAndGetMultiplicities{}``
+***********************************************
+
+Syntax: ``\PolSturmIsolateZerosAndGetMultiplicities{<sturmname>}``
+
+ This is another name for :ref:`\\PolSturmIsolateZeros*{\<sturmname\>} <PolSturmIsolateZeros*>`.
+
+.. _PolSturmIsolateZeros**:
+
+``\PolSturmIsolateZeros**{}``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolSturmIsolateZeros**{<sturmname>}``
+
+ The macro does the same as :ref:`\\PolSturmIsolateZeros*{\<sturmname\>} <PolSturmIsolateZeros*>` and
+ in addition it does the extra work to determine all the *rational*
+ roots.
+
+ .. note::
+
+ After execution of this macro, a root is "known" if and only if
+ it is rational.
+
+ Furthermore, primitive polynomial ``sturmname_sqf_norr`` is created
+ to match the (square-free) ``sturmname_0`` from which all rational
+ roots have been removed. The number of distinct rational roots is
+ thus the difference between the degrees of these two polynomials
+ (see also :ref:`\\PolSturmNbOfRationalRoots{\<sturmname\>}
+ <PolSturmNbOfRationalRoots>`).
+
+ And ``sturmname_norr`` is ``sturmname_0_`` from which all rational
+ roots have been removed, i.e. it contains the irrational roots of
+ the original polynomial, with the same multiplicities.
+
+ See ``A degree five polynomial with three rational
+ roots`` in ``polexpr-examples.pdf``.
+
+.. _PolSturmIsolateZerosGetMultiplicitiesAndRationalRoots:
+
+``\PolSturmIsolateZerosGetMultiplicitiesAndRationalRoots``
+**********************************************************
+
+Syntax: ``\PolSturmIsolateZerosGetMultiplicitiesAndRationalRoots``
+
+ This is another name for :ref:`\\PolSturmIsolateZeros**{\<sturmname\>} <PolSturmIsolateZeros**>`.
+
+.. _PolSturmIsolateZerosAndFindRationalRoots:
+
+``\PolSturmIsolateZerosAndFindRationalRoots{}``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolSturmIsolateZerosAndFindRationalRoots{<sturmname>}``
+
+ This works exactly like :ref:`\\PolSturmIsolateZeros**{\<sturmname\>} <PolSturmIsolateZeros**>`
+ (inclusive of declaring the polynomials ``sturmname_sqf_norr`` and
+ ``sturmname_norr`` with no rational roots) except that it does *not*
+ compute the multiplicities of the *non-rational* roots.
+
+ .. note::
+
+ There is no macro to find the rational roots but not compute
+ their multiplicities at the same time.
+
+ .. attention::
+
+ This macro does *not* define xintexpr_ variables
+ ``sturmnameM_1``, ``sturmnameM_2``, ... holding the
+ multiplicities and it leaves the multiplicity array (whose accessor
+ is :ref:`\\PolSturmIsolatedZeroMultiplicity{\<sturmname\>}{\<index\>} <PolSturmIsolatedZeroMultiplicity>`) into
+ a broken state, as all non-rational roots will supposedly have
+ multiplicity one. This means that the output of
+ `\\PolPrintIntervals* <PolPrintIntervals*_>`_ will be
+ erroneous regarding the multiplicities of irrational roots.
+
+ I decided to document it because finding multiplicities of the
+ non rational roots is somewhat costly, and one may be interested
+ only into finding the rational roots (of course random
+ polynomials with integer coefficients will not have *any*
+ rational root anyhow).
+
+
+.. _PolRefineInterval*:
+
+``\PolRefineInterval*{}{}``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolRefineInterval*{<sturmname>}{<index>}``
+
+ The ``index``\ -th interval (starting indexing at one) is further
+ subdivided as many times as is necessary in order for the newer
+ interval to have both its end-points distinct from the end-points of
+ the original interval. As a consequence, the ``k``\ th root is then
+ strictly separated from the other roots.
+
+.. _PolRefineInterval[]:
+
+``\PolRefineInterval[]{}{}``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolRefineInterval[N]{<sturmname>}{<index>}``
+
+ The ``index``\ -th interval (starting count at one) is further
+ subdivided once, reducing its length by a factor of 10. This is done
+ ``N`` times if the optional argument ``[N]`` is present.
+
+.. _PolEnsureIntervalLength:
+
+``\PolEnsureIntervalLength{}{}{}``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolEnsureIntervalLength{<sturmname>}{<index>}{<exponent>}``
+
+ The ``index``\ -th interval is subdivided until its length becomes at
+ most ``10^E``. This means (for ``E<0``) that the first ``-E`` digits
+ after decimal mark of the ``k``\ th root will then be known exactly.
+
+.. _PolEnsureIntervalLengths:
+
+``\PolEnsureIntervalLengths{}{}``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolEnsureIntervalLengths{<sturmname>}{<exponent>}``
+
+ The intervals as obtained from ``\PolSturmIsolateZeros`` are (if
+ necessary) subdivided further by (base 10) dichotomy in order for
+ each of them to have length at most ``10^E``.
+
+ This means that decimal expansions of all roots will be known with
+ ``-E`` digits (for ``E<0``) after decimal mark.
+
+.. _PolSetToSturmChainSignChangesAt:
+
+``\PolSetToSturmChainSignChangesAt{}{}{}``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolSetToSturmChainSignChangesAt{\foo}{<sturmname>}{<value>}``
+
+ Sets macro ``\foo`` to store the number of sign changes in the
+ already computed normalized Sturm chain with name prefix
+ ``<sturmname>``, at location ``<value>`` (which must be in format as
+ acceptable by the xintfrac_ macros.)
+
+ The definition is made with global scope. For local scope, use
+ ``[\empty]`` as extra optional argument.
+
+ One can use this immediately after creation of the Sturm chain.
+
+.. _PolSetToNbOfZerosWithin:
+
+``\PolSetToNbOfZerosWithin{}{}{}{}``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolSetToNbOfZerosWithin{\foo}{<sturmname>}{<value_left>}{<value_right>}``
+
+ Sets, assuming the normalized Sturm chain has been already computed,
+ macro ``\foo`` to store the number of roots of ``sturmname_0`` in
+ the interval ``(value_left, value_right]``. The macro first
+ re-orders end-points if necessary for ``value_left <= value_right``
+ to hold.
+
+ In accordance to `Sturm Theorem`_ this is computed as the difference
+ between the number of sign changes of the Sturm chain at ``value_right``
+ and the one at ``value_left``.
+
+ The definition is made with global scope. For local scope, use
+ ``[\empty]`` as extra optional argument.
+
+ One can use this immediately after creation of a Sturm chain.
+
+ See also the expandable
+ :ref:`\\PolSturmNbOfRootsOf{\<sturmname\>}\\LessThanOrEqualTo{value} <PolSturmNbOfRootsOfLessThanOrEqualTo>`,
+ which however requires prior execution of `\\PolSturmIsolateZeros
+ <PolSturmIsolateZeros_>`_.
+
+ See also the expandable
+ :ref:`\\PolSturmNbWithMultOfRootsOf{\<sturmname\>}\\LessThanOrEqualTo{value} <PolSturmNbWithMultOfRootsOfLessThanOrEqualTo>`
+ which requires prior execution of
+ `\\PolSturmIsolateZeros* <PolSturmIsolateZeros*_>`_.
+
+.. _PolPrintIntervals:
+
+Displaying the found roots: ``\PolPrintIntervals[<varname>]{}``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolPrintIntervals[<varname>]{<sturmname>}``
+
+ This is a convenience macro which prints the bounds for the roots
+ ``Z_1``, ``Z_2``, ... (the optional argument ``varname`` allows to
+ specify a replacement for the default ``Z``). This will be done (by
+ default) in a
+ math mode ``array``, one interval per row, and pattern ``rcccl``,
+ where the second and fourth column hold the ``<`` sign, except when
+ the interval reduces to a singleton, which means the root is known
+ exactly.
+
+ .. note::
+
+ The explanations here and in this section are for LaTeX. With
+ other TeX macro formats, the LaTeX syntax such as for example
+ ``\begin{array}{rcccl}`` which appears in the documentation here
+ is actually replaced with quasi-equivalent direct use of TeX
+ primitives.
+
+ The next macros which govern its output.
+
+.. _PolPrintIntervalsNoRealRoots:
+
+``\PolPrintIntervalsNoRealRoots``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ Executed in place of an ``array`` environment, when there are no
+ real roots. Default definition::
+
+ \newcommand\PolPrintIntervalsNoRealRoots{}
+
+.. _PolPrintIntervalsBeginEnv:
+
+``\PolPrintIntervalsBeginEnv``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ Default definition (given here for LaTeX, Plain has a variant)::
+
+ \newcommand\PolPrintIntervalsBeginEnv{\[\begin{array}{rcccl}}
+
+ A simpler ``center`` environment provides a straightforward way to
+ obtain a display allowing pagebreaks. Of course redefinitions must
+ at any rate be kept in sync with `\\PolPrintIntervalsKnownRoot`_ and
+ `\\PolPrintIntervalsUnknownRoot`_.
+
+ Prior to ``0.8.6`` it was not possible to use here for example
+ ``\begin{align}`` due to the latter executing twice in contents.
+
+
+.. _PolPrintIntervalsEndEnv:
+
+``\PolPrintIntervalsEndEnv``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ Default definition::
+
+ \newcommand\PolPrintIntervalsEndEnv{\end{array}\]}
+
+.. _PolPrintIntervalsRowSeparator:
+
+``\PolPrintIntervalsRowSeparator``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ Expands by default to ``\\`` with LaTeX and to ``\cr`` with Plain
+
+ Added at ``0.8.6``.
+
+.. _PolPrintIntervalsKnownRoot:
+
+``\PolPrintIntervalsKnownRoot``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ Default definition::
+
+ \newcommand\PolPrintIntervalsKnownRoot{%
+ &&\PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}%
+ &=&\PolPrintIntervalsPrintExactZero
+ }
+
+.. _PolPrintIntervalsUnknownRoot:
+
+``\PolPrintIntervalsUnknownRoot``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ Default definition::
+
+ \newcommand\PolPrintIntervalsUnknownRoot{%
+ \PolPrintIntervalsPrintLeftEndPoint&<&%
+ \PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}&<&%
+ \PolPrintIntervalsPrintRightEndPoint
+ }
+
+
+.. _PolPrintIntervalsPrintExactZero:
+
+``\PolPrintIntervalsPrintExactZero``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ Default definition::
+
+ \newcommand\PolPrintIntervalsPrintExactZero{\PolPrintIntervalsTheLeftEndPoint}
+
+
+.. _PolPrintIntervalsPrintLeftEndPoint:
+
+``\PolPrintIntervalsPrintLeftEndPoint``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ Default definition::
+
+ \newcommand\PolPrintIntervalsPrintLeftEndPoint{\PolPrintIntervalsTheLeftEndPoint}
+
+.. _PolPrintIntervalsPrintRightEndPoint:
+
+``\PolPrintIntervalsPrintRightEndPoint``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ Default definition is::
+
+ \newcommand\PolPrintIntervalsPrintRightEndPoint{\PolPrintIntervalsTheRightEndPoint}
+
+.. _PolPrintIntervals*:
+
+``\PolPrintIntervals*[<varname>]{}``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolPrintIntervals*[<varname>]{<sturmname>}``
+
+ This starred variant produces an alternative output (which
+ displays the root multiplicity), and is provided as an
+ example of customization.
+
+ As replacement for `\\PolPrintIntervalsKnownRoot`_,
+ `\\PolPrintIntervalsPrintExactZero`_,
+ `\\PolPrintIntervalsUnknownRoot`_ it uses its own
+ ``\POL@@PrintIntervals...`` macros. We only reproduce here one
+ definition::
+
+ \newcommand\POL@@PrintIntervalsPrintExactZero{%
+ \displaystyle
+ \xintTeXsignedFrac{\PolPrintIntervalsTheLeftEndPoint}%
+ }%
+
+ Multiplicities are printed using this auxiliary macro:
+
+.. _PolPrintIntervalsPrintMultiplicity:
+
+``\PolPrintIntervalsPrintMultiplicity``
+***************************************
+
+ whose default definition is::
+
+ \newcommand\PolPrintIntervalsPrintMultiplicity{(\mbox{mult. }\PolPrintIntervalsTheMultiplicity)}
+
+
+Expandable macros
+-----------------
+
+.. note::
+
+ At ``0.8`` ``polexpr`` is usable with Plain TeX and not only with
+ LaTeX. Some examples given in this section may be using LaTeX syntax
+ such as ``\renewcommand``. Convert to TeX primitives as appropriate
+ if testing with a non LaTeX macro format.
+
+These macros expand completely in two steps except ``\PolToExpr`` and
+``\PolToFloatExpr`` which need a ``\write``, ``\edef`` or a
+``\csname...\endcsname`` context.
+
+.. _PolToExpr:
+
+``\PolToExpr{}``
+~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolToExpr{<pol. expr.>}``
+
+ Produces expandably [#]_ the string ``coeff_N*x^N+...``, i.e. the
+ polynomial is using descending powers.
+
+ .. [#] requires exhaustive expansion, for example as triggered by
+ ``\write`` or ``\edef``.
+
+ Since ``0.8`` the input is not restricted to be a polynomial name but
+ is allowed to be an arbitrary expression. Then ``x`` is expected as
+ indeterminate but this can be customized via `\\PolToExprInVar`_.
+
+ The output uses the letter ``x`` by default, this is customizable
+ via `\\PolToExprVar`_. The default output is compatible both with
+
+ - the Maple's input format,
+
+ - and the PSTricks ``\psplot[algebraic]`` input format.
+
+ Attention that it is not compatible with Python, see further
+ `\\PolToExprCaret`_ in this context.
+
+ The following applies:
+
+ - vanishing coefficients are skipped (issue ``\poltoexpralltrue`` to
+ override this and produce output such as ``x^3+0*x^2+0*x^1+0``),
+
+ - negative coefficients are not prefixed by a ``+`` sign (else,
+ Maple would not be happy),
+
+ - coefficients numerically equal to ``1`` (or ``-1``) are present
+ only via their sign,
+
+ - the letter ``x`` is used and the degree one monomial is output as
+ ``x``, not as ``x^1``.
+
+ - (``0.8``) the caret ``^`` is of catcode 12. This means that one
+ can for convenience typeset in regular text mode, for example
+ using ``\texttt`` (in LaTeX). But TeX will not know how to break
+ the expression across end-of-lines anyhow. Formerly ``^`` was
+ suitable for math mode but as the exponent is not braced this
+ worked only for polynomials of degrees at most 9. Anyhow this
+ is not supposed to be a typesetting macro.
+
+ Complete customization is possible, see the next macros. Any user
+ redefinition must maintain the expandability property.
+
+.. _PolToExprVar:
+
+``\PolToExprVar``
+^^^^^^^^^^^^^^^^^
+
+ Defaults to ``x``. The letter used in the macro output.
+
+
+.. _PolToExprInVar:
+
+``\PolToExprInVar``
+^^^^^^^^^^^^^^^^^^^
+
+ Defaults to ``x``: the letter used as the polynomial indeterminate
+ in the macro input.
+
+ Recall that declared polynomials are more efficiently used in
+ algebraic expressions without the ``(x)``, i.e. ``P*Q`` is better
+ than ``P(x)*Q(x)``. Thus the input, even if an expression, does not
+ have to contain any ``x``.
+
+ (new with ``0.8``)
+
+.. _PolToExprTimes:
+
+``\PolToExprTimes``
+^^^^^^^^^^^^^^^^^^^
+
+ Defaults to ``*``.
+
+.. _PolToExprCaret:
+
+``\PolToExprCaret``
+^^^^^^^^^^^^^^^^^^^
+
+ Defaults to ``^`` of catcode 12. Set it to
+ expand to ``**`` for Python compatible output.
+
+ (new with ``0.8``)
+
+.. _PolToExprCmd:
+
+``\PolToExprCmd{}``
+^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolToExprCmd{<raw_coeff>}``
+
+ Defaults to ``\xintPRaw{\xintRawWithZeros{#1}}``.
+
+ This means that the coefficient value is printed-out as a fraction
+ ``a/b``, skipping the ``/b`` part if ``b`` turns out to be one.
+
+ Configure it to be ``\xintPRaw{\xintIrr{#1}}`` if the fractions
+ must be in irreducible terms.
+
+ An alternative is ``\xintDecToString{\xintREZ{#1}}`` which uses
+ integer or decimal fixed point format such as ``23.0071`` if the
+ internal representation of the number only has a power of ten as
+ denominator (the effect of ``\xintREZ`` here is to remove trailing
+ decimal zeros). The behaviour of ``\xintDecToString`` is not yet
+ stable for other cases, and for example at time of writing no
+ attempt is made to identify inputs having a finite decimal expansion
+ so for example ``23.007/2`` or ``23.007/25`` can appear in output
+ and not their finite decimal expansion with no denominator.
+
+.. _PolToExprOneTerm:
+
+``\PolToExprOneTerm{}{}``
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolToExprOneTerm{<raw_coeff>}{<exponent>}``
+
+ This is the macro which from the coefficient and the exponent
+ produces the corresponding term in output, such as ``2/3*x^7``.
+
+ For its default definition, see the source code. It uses
+ `\\PolToExprCmd <PolToExprCmd_>`_, `\\PolToExprTimes
+ <PolToExprTimes_>`_, `\\PolToExprVar <PolToExprVar_>`_ and
+ `\\PolToExprCaret`_.
+
+.. _PolToExprOneTermStyleA:
+
+``\PolToExprOneTermStyleA{}{}``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolToExprOneTermStyleA{<raw_coeff>}{<exponent>}``
+
+ This holds the default package meaning of ``\PolToExprOneTerm``.
+
+.. _PolToExprOneTermStyleB:
+
+``\PolToExprOneTermStyleB{}{}``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolToExprOneTermStyleB{<raw_coeff>}{<exponent>}``
+
+ This holds an alternative meaning, which puts the fractional part of
+ a coefficient after the monomial, i.e. like this::
+
+ 2*x^11/3+3*x^8/7-x^5-x^4/4-x^3-x^2/2-2*x+1
+
+ `\\PolToExprCmd <PolToExprCmd_>`_ isn't used at all in this style. But
+ `\\PolToExprTimes <PolToExprTimes_>`_, `\\PolToExprVar
+ <PolToExprVar_>`_ and `\\PolToExprCaret`_ are obeyed.
+
+ To activate it use ``\let\PolToExprOneTerm\PolToExprOneTermStyleB``.
+ To revert to the package default behaviour, issue
+ ``\let\PolToExprOneTerm\PolToExprOneTermStyleA``.
+
+.. _PolToExprTermPrefix:
+
+``\PolToExprTermPrefix{}``
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolToExprTermPrefix{<raw_coeff>}``
+
+ It receives as argument the coefficient. Its default behaviour is
+ to produce a ``+`` if the coefficient is positive, which will thus
+ serve to separate the monomials in the output. This is to match
+ the default for :ref:`\\PolToExprCmd{\<raw_coeff\>} <PolToExprCmd>` which in case of a
+ positive coefficient does not output an explicit ``+`` prefix.
+
+.. _PolToFloatExpr:
+
+``\PolToFloatExpr{}``
+~~~~~~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolToFloatExpr{<pol. expr.>}``
+
+ Similar to :ref:`\\PolToExpr{\<pol. expr.\>} <PolToExpr>` but using
+ :ref:`\\PolToFloatExprCmd{\<raw_coeff\>} <PolToFloatExprCmd>` which by default rounds and
+ converts the coefficients to floating point format.
+
+ .. note::
+
+ This is unrelated to :ref:`\\PolGenFloatVariant{\<polname\>} <PolGenFloatVariant>`:
+ :ref:`\\PolToFloatExprCmd{\<raw_coeff\>} <PolToFloatExprCmd>` operates on the *exact*
+ coefficients anew (and may thus produce something else than
+ the coefficients of the polynomial function acting
+ in ``\xintfloateval`` if the floating point precision was changed
+ in between).
+
+ Extended at ``0.8`` to accept general expressions as input.
+
+.. _PolToFloatExprOneTerm:
+
+``\PolToFloatExprOneTerm{}{}``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolToFloatExprOneTerm{<raw_coeff>}{<exponent>}``
+
+ Similar to :ref:`\\PolToExprOneTerm{\<raw_coeff\>}{\<exponent\>} <PolToExprOneTerm>`. But does not treat
+ especially coefficients equal to plus or minus one.
+
+.. _PolToFloatExprCmd:
+
+``\PolToFloatExprCmd{}``
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolToFloatExprCmd{<raw_coeff>}``
+
+ The one-argument macro used by ``\PolToFloatExprOneTerm``.
+ It defaults to ``\xintPFloat{#1}``, which trims trailing
+ zeroes.
+
+ *changed at 0.8.2* Formerly it was using ``\xintFloat``.
+
+.. _PolToExpr*:
+
+``\PolToExpr*{}``
+~~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolToExpr*{<pol. expr.>}``
+
+ Ascending powers: ``coeff_0+coeff_1*x+coeff_2*x^2+...``.
+
+ Extended at ``0.8`` to accept general expressions as input.
+
+ Customizable with the same macros as for
+ :ref:`\\PolToExpr{\<pol. expr.\>} <PolToExpr>`.
+
+.. _PolToFloatExpr*:
+
+``\PolToFloatExpr*{}``
+~~~~~~~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolToFloatExpr*{<pol. expr.>}``
+
+ Ascending powers.
+
+ Extended at ``0.8`` to accept general expressions as input.
+
+.. _PolNthCoeff:
+
+``\PolNthCoeff{}{}``
+~~~~~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolNthCoeff{<polname>}{<index>}``
+
+ It expands to the raw ``N``-th coefficient (``N=0`` corresponds to
+ the constant coefficient). If ``N`` is out of range, zero (in its
+ default xintfrac_ format ``0/1[0]``) is returned.
+
+ Negative indices ``N=-1``, ``-2``, ... return the leading
+ coefficient, sub-leading coefficient, ..., and finally ``0/1[0]``
+ for ``N<-1-degree``.
+
+.. _PolLeadingCoeff:
+
+``\PolLeadingCoeff{}``
+~~~~~~~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolLeadingCoeff{<polname>}``
+
+ Expands to the leading coefficient.
+
+.. _PolDegree:
+
+``\PolDegree{}``
+~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolDegree{<polname>}``
+
+ It expands to the degree. This is ``-1`` if zero polynomial but this
+ may change in future. Should it then expand to ``-\infty`` ?
+
+.. _PolIContent:
+
+``\PolIContent{}``
+~~~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolIContent{<polname>}``
+
+ It expands to the contents of the polynomial, i.e. to the positive
+ fraction such that dividing by this fraction produces a polynomial
+ with integer coefficients having no common prime divisor.
+
+ See `\\PolMakePrimitive <PolMakePrimitive_>`_.
+
+.. _PolToList:
+
+``\PolToList{}``
+~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolToList{<polname>}``
+
+ Expands to ``{coeff_0}{coeff_1}...{coeff_N}`` with ``N`` = degree, and
+ ``coeff_N`` the leading coefficient
+ (the zero polynomial does give ``{0/1[0]}`` and not an
+ empty output.)
+
+.. _PolToCSV:
+
+``\PolToCSV{}``
+~~~~~~~~~~~~~~~
+
+Syntax: ``\PolToCSV{<polname>}``
+
+ Expands to ``coeff_0, coeff_1, coeff_2, ....., coeff_N``, starting
+ with constant term and ending with leading coefficient. Converse
+ to :ref:`\\PolFromCSV{\<polname\>}{\<csv\>} <PolFromCSV>`.
+
+
+.. _PolEvalAtExpr:
+
+``\PolEval{}\AtExpr{}``
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolEval{<polname>}\AtExpr{<num. expr.>}``
+
+ Same output as
+ ``\xinteval{polname(numerical expression)}``.
+
+.. _PolEvalAt:
+
+``\PolEval{}\At{}``
+~~~~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolEval{<polname>}\At{<value>}``
+
+ Evaluates the polynomial at the given value which must be in (or
+ expand to) a format acceptable to the xintfrac_ macros.
+
+.. _PolEvalReducedAtExpr:
+
+``\PolEvalReduced{}\AtExpr{}``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolEvalReduced{<polname>}\AtExpr{<num. expr.>}``
+
+ Same output as ``\xinteval{reduce(polname(numerical expression))}``.
+
+.. _PolEvalReducedAt:
+
+``\PolEvalReduced{}\At{}``
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolEvalReduced{<polname>}\At{<value>}``
+
+ Evaluates the polynomial at the value which must be in (or expand
+ to) a format acceptable to the xintfrac_ macros, and outputs an
+ irreducible fraction.
+
+.. _PolFloatEvalAtExpr:
+
+``\PolFloatEval{}\AtExpr{}``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolFloatEval{<polname>}\AtExpr{<num. expr.>}``
+
+ Same output as ``\xintfloateval{polname(numerical expression)}``.
+
+ .. attention::
+
+ `\\PolGenFloatVariant <PolGenFloatVariant_>`_ must have
+ been issued before.
+
+ To use the *exact coefficients* with *exactly executed* additions
+ and multiplications and do the rounding only as the final last step,
+ the following syntax can be used: [#]_
+
+ ::
+
+ \xintfloateval{3.27*\xintexpr f(2.53)\relax^2}
+
+
+ .. [#] Cf. xintexpr_ documentation about nested expressions.
+
+.. _PolFloatEvalAt:
+
+``\PolFloatEval{}\At{}``
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolFloatEval{<polname>}\At{<value>}``
+
+ Evaluates the polynomial at the value which must be in (or expand
+ to) a format acceptable to the xintfrac_ macros.
+
+
+Expandable macros in relation to root localization via `Sturm Theorem`_
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. _PolSturmChainLength:
+
+``\PolSturmChainLength{}``
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolSturmChainLength{<sturmname>}``
+
+ Returns the integer ``N`` such that ``sturmname_N`` is the last one
+ in the Sturm chain ``sturmname_0``, ``sturmname_1``, ...
+
+ See :ref:`\\PolToSturm{\<polname\>}{\<sturmname\>} <PolToSturm>`.
+
+.. _PolSturmIfZeroExactlyKnown:
+
+``\PolSturmIfZeroExactlyKnown{}{}{}{}``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolSturmIfZeroExactlyKnown{<sturmname>}{<index>}{T}{F}``
+
+ Executes ``T`` if the ``index``\ -th interval reduces to a singleton,
+ i.e. the root is known exactly, else ``F``.
+
+ .. vieux commentaire
+
+ ``index`` is allowed to be something like ``1+2*3`` as it is fed
+ to ``\the\numexpr...\relax``.
+
+.. _PolSturmIsolatedZeroLeft:
+
+``\PolSturmIsolatedZeroLeft{}{}``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolSturmIsolatedZeroLeft{<sturmname>}{<index>}``
+
+ Expands to the left end-point for the ``index``\ -th interval, as
+ computed by some earlier :ref:`\\PolSturmIsolateZeros{\<sturmname\>} <PolSturmIsolateZeros>`.
+
+ .. note::
+
+ Execution of this macro after some
+ `\\PolRefineInterval{<sturmname>}{<index>} <PolRefineInterval[]_>`_
+ will take into account the now known tighter bounds.
+
+ The value is pre-formatted using `\\PolDecTostring
+ <PolDecToString_>`_.
+
+.. _PolSturmIsolatedZeroRight:
+
+``\PolSturmIsolatedZeroRight{}{}``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolSturmIsolatedZeroRight{<sturmname>}{<index>}``
+
+ Expands to the right end-point for the ``index``\ -th interval as
+ computed by some earlier :ref:`\\PolSturmIsolateZeros{\<sturmname\>} <PolSturmIsolateZeros>` and
+ possibly refined afterwards.
+
+ The value is pre-formatted using `\\PolDecTostring
+ <PolDecToString_>`_.
+
+.. _PolSturmIsolatedZeroMultiplicity:
+
+``\PolSturmIsolatedZeroMultiplicity{}{}``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolSturmIsolatedZeroMultiplicity{<sturmname>}{<index>}``
+
+ Expands to the multiplicity of the unique root contained in the
+ ``index``\ -th interval.
+
+ .. attention::
+
+ A prior execution of :ref:`\\PolSturmIsolateZeros*{\<sturmname\>} <PolSturmIsolateZeros*>` is mandatory.
+
+ See ``The degree nine polynomial with 0.99, 0.999, 0.9999 as triple
+ roots`` in ``polexpr-examples.pdf``.
+
+.. _PolSturmNbOfIsolatedZeros:
+
+``\PolSturmNbOfIsolatedZeros{}``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolSturmNbOfIsolatedZeros{<sturmname>}``
+
+ Expands to the number of real roots of the polynomial
+ ``<sturmname>_0``, i.e. the number of distinct real roots of the
+ polynomial originally used to create the Sturm chain via
+ :ref:`\\PolToSturm{\<polname\>}{\<sturmname\>} <PolToSturm>`.
+
+.. warning::
+
+ The next few macros counting roots, with or without multiplicities,
+ less than or equal to some value, are under evaluation and may be
+ removed from the package if their utility is judged to be not high
+ enough. They can be re-coded at user level on the basis of the other
+ documented package macros anyway.
+
+.. _PolSturmNbOfRootsOfLessThanOrEqualTo:
+
+``\PolSturmNbOfRootsOf{}\LessThanOrEqualTo{}``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolSturmNbOfRootsOf{<sturmname>}\LessThanOrEqualTo{<value>}``
+
+ Expands to the number of distinct roots (of the polynomial used to
+ create the Sturm chain) less than or equal to the ``value`` (i.e. a
+ number of fraction recognizable by the xintfrac_ macros).
+
+ .. attention::
+
+ :ref:`\\PolSturmIsolateZeros{\<sturmname\>} <PolSturmIsolateZeros>` must have been executed
+ beforehand.
+
+ And the argument is a ``<sturmname>``, not a ``<polname>`` (this is
+ why the macro contains Sturm in its name), simply to be reminded
+ of the above constraint.
+
+.. _PolSturmNbOfRootsOfLessThanOrEqualToExpr:
+
+``\PolSturmNbOfRootsOf{}\LessThanOrEqualToExpr{}``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolSturmNbOfRootsOf{<sturmname>}\LessThanOrEqualToExpr{<num. expr.>}``
+
+ Expands to the number of distinct roots (of the polynomial
+ used to create the Sturm chain) which are less than or equal to the
+ given numerical expression.
+
+ .. attention::
+
+ :ref:`\\PolSturmIsolateZeros{\<sturmname\>} <PolSturmIsolateZeros>` must have been executed
+ beforehand.
+
+.. _PolSturmNbWithMultOfRootsOfLessThanOrEqualTo:
+
+``\PolSturmNbWithMultOfRootsOf{}\LessThanOrEqualTo{}``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolSturmNbWithMultOfRootsOf{<sturmname>}\LessThanOrEqualTo{<value>}``
+
+ Expands to the number counted with multiplicities of the roots (of
+ the polynomial used to create the Sturm chain) which are less than
+ or equal to the given ``value``.
+
+ .. attention::
+
+ :ref:`\\PolSturmIsolateZeros*{\<sturmname\>} <PolSturmIsolateZeros*>` (or the double starred
+ variant) must have been executed beforehand.
+
+.. _PolSturmNbWithMultOfRootsOfLessThanOrEqualToExpr:
+
+``\PolSturmNbWithMultOfRootsOf{}\LessThanOrEqualToExpr{}``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolSturmNbWithMultOfRootsOf{<sturmname>}\LessThanOrEqualToExpr{<num. expr.>}``
+
+ Expands to the total number of roots (counted with multiplicities)
+ which are less than or equal to the given ``expression``.
+
+ .. attention::
+
+ :ref:`\\PolSturmIsolateZeros*{\<sturmname\>} <PolSturmIsolateZeros*>` (or the double starred
+ variant) must have been executed beforehand.
+
+.. _PolSturmNbOfRationalRoots:
+
+``\PolSturmNbOfRationalRoots{}``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolSturmNbOfRationalRoots{<sturmname>}``
+
+ Expands to the number of rational roots (without multiplicities).
+
+ .. attention::
+
+ :ref:`\\PolSturmIsolateZeros**{\<sturmname\>} <PolSturmIsolateZeros**>` must have been executed
+ beforehand.
+
+.. _PolSturmNbOfRationalRootsWithMultiplicities:
+
+``\PolSturmNbOfRationalRootsWithMultiplicities{}``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolSturmNbOfRationalRootsWithMultiplicities{<sturmname>}``
+
+ Expands to the number of rational roots (counted with multiplicities).
+
+ .. attention::
+
+ :ref:`\\PolSturmIsolateZeros**{\<sturmname\>} <PolSturmIsolateZeros**>` must have been executed
+ beforehand.
+
+.. _PolSturmRationalRoot:
+
+``\PolSturmRationalRoot{}{}``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolSturmRationalRoot{<sturmname>}{<k>}``
+
+ Expands to the k-th rational root. They are enumerated from left to
+ right starting at index value ``1``.
+
+ .. attention::
+
+ :ref:`\\PolSturmIsolateZeros**{\<sturmname\>} <PolSturmIsolateZeros**>` must have been executed
+ beforehand.
+
+.. _PolSturmRationalRootIndex:
+
+``\PolSturmRationalRootIndex{}{}``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolSturmRationalRootIndex{<sturmname>}{<k>}``
+
+ Expands to the index of the ``k``\ th rational root as part of the
+ ordered real roots (counted without multiplicities). So
+ :ref:`\\PolSturmRationalRoot{\<sturmname\>}{\<k\>} <PolSturmRationalRoot>` is equivalent to
+ this nested call::
+
+ \PolSturmIsolatedZeroLeft{<sturmname>}{\PolSturmRationalRootIndex{<sturmname>}{<k>}}
+
+ .. attention::
+
+ :ref:`\\PolSturmIsolateZeros**{\<sturmname\>} <PolSturmIsolateZeros**>` must have been executed
+ beforehand.
+
+.. _PolSturmRationalRootMultiplicity:
+
+``\PolSturmRationalRootMultiplicity{}{}``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolSturmRationalRootMultiplicity{<sturmname>}{<k>}``
+
+ Expands to the multiplicity of the ``k``\ th rational root.
+
+ .. attention::
+
+ :ref:`\\PolSturmIsolateZeros**{\<sturmname\>} <PolSturmIsolateZeros**>` must have been executed
+ beforehand.
+
+.. _PolIntervalWidth:
+
+``\PolIntervalWidth{}{}``
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax: ``\PolIntervalWidth{<sturmname>}{<index>}``
+
+ The ``10^E`` width of the current ``index``\ -th root localization
+ interval. Output is in xintfrac_ raw ``1/1[E]`` format (if not zero).
+
+ .. renommer cela en \PolSturmIntervalWidth ?
+
+Expandable macros for use within execution of ``\PolPrintIntervals``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+These macros are for usage within custom user redefinitions of
+`\\PolPrintIntervalsKnownRoot`_, `\\PolPrintIntervalsUnknownRoot`_, or
+in redefinitions of `\PolPrintIntervalsPrintExactZero`_ (used in the
+default for the former) and of `\\PolPrintIntervalsPrintLeftEndPoint`_,
+`\\PolPrintIntervalsPrintRightEndPoint`_ (used in the default for the
+latter).
+
+.. vieux commentaire
+
+ Some macros formerly mentioned here got removed at 0.7:
+ ``\PolPrintIntervalsTheEndPoint``,
+ ``\PolIfEndPointIsPositive{T}{F}``,
+ ``\PolIfEndPointIsNegative{T}{F}``,
+ ``\PolIfEndPointIsZero{T}{F}``.
+
+.. _PolPrintIntervalsTheVar:
+
+``\PolPrintIntervalsTheVar``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ Expands to the name (default ``Z``) used for representing the roots,
+ which was passed as optional argument ``varname`` to
+ :ref:`\\PolPrintIntervals[varname]{\<sturmname\>} <PolPrintIntervals>`.
+
+.. _PolPrintIntervalsTheIndex:
+
+``\PolPrintIntervalsTheIndex``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ Expands to the index of the considered interval (indexing starting
+ at 1 for the leftmost interval).
+
+.. _PolPrintIntervalsTheSturmName:
+
+``\PolPrintIntervalsTheSturmName``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ Expands to the argument which was passed as ``<sturmname>`` to
+ :ref:`\\PolPrintIntervals[varname]{\<sturmname\>} <PolPrintIntervals>`.
+
+.. _PolPrintIntervalsTheLeftEndPoint:
+
+``\PolPrintIntervalsTheLeftEndPoint``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ The left end point of the interval, as would be produced by
+ `\\PolSturmIsolatedZeroLeft <PolSturmIsolatedZeroLeft_>`_ if it was
+ used with arguments the Sturm chain name and interval index returned
+ by `\\PolPrintIntervalsTheSturmName`_ and
+ `\\PolPrintIntervalsTheIndex`_.
+
+.. _PolPrintIntervalsTheRightEndPoint:
+
+``\PolPrintIntervalsTheRightEndPoint``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ The right end point of the interval, as would be produced by
+ `\\\PolSturmIsolatedZeroRight <PolSturmIsolatedZeroRight_>`_ for
+ this Sturm chain name and index.
+
+.. _PolPrintIntervalsTheMultiplicity:
+
+``\PolPrintIntervalsTheMultiplicity``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ The multiplicity of the unique root within the interval of index
+ `\\PolPrintIntervalsTheIndex`_. Makes sense only if the starred (or
+ double-starred) variant of `\\PolSturmIsolateZeros
+ <PolSturmIsolateZeros_>`_ was used earlier.
+
+
+TeX Booleans (with names enacting their defaults)
+-------------------------------------------------
+
+.. _xintverbosefalse:
+
+``\xintverbosefalse``
+~~~~~~~~~~~~~~~~~~~~~
+
+ This is actually an xintexpr_ configuration. Setting it to
+ ``true`` triggers the writing of information to the log when new
+ polynomial or scalar variables are defined.
+
+ .. caution::
+
+ The macro and variable meanings as written to the log are to be
+ considered unstable and undocumented internal structures.
+
+.. _polnewpolverbosefalse:
+
+``\polnewpolverbosefalse``
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ When ``\poldef`` is used, both a variable and a function are
+ defined. The default ``\polnewpolverbosefalse`` setting suppresses
+ the print-out to the log and terminal of the function macro meaning,
+ as it only duplicates the information contained in the variable
+ which is already printed out to the log and terminal.
+
+ However :ref:`\\PolGenFloatVariant{\<polname\>} <PolGenFloatVariant>`
+ does still print out the information relative to the polynomial
+ function it defines for use in ``\xintfloateval{}`` as there is no
+ float polynomial variable, only the
+
+ function, and it is the only way to see its rounded coefficients
+ (``\xintverbosefalse`` suppresses also that info).
+
+ If set to ``true``, it overrides in both cases
+ ``\xintverbosefalse``. The setting only affects polynomial
+ declarations. Scalar variables such as those holding information on
+ roots obey only the ``\xintverbose...`` setting.
+
+ (new with ``0.8``)
+
+.. _poltypesetallfalse:
+
+``\poltypesetallfalse``
+~~~~~~~~~~~~~~~~~~~~~~~
+
+ If ``true``, `\\PolTypeset <PolTypeset_>`_ will also typeset the vanishing
+ coefficients.
+
+
+.. _poltoexprallfalse:
+
+``\poltoexprallfalse``
+~~~~~~~~~~~~~~~~~~~~~~
+
+ If ``true``, :ref:`\\PolToExpr{\<pol. expr.\>} <PolToExpr>` and
+ :ref:`\\PolToFloatExpr{\<pol. expr.\>} <PolToFloatExpr>` will also
+ include the vanishing coefficients in their outputs.
+
+
+Utilities
+---------
+
+.. _PolDecToString:
+
+``\PolDecToString{}``
+~~~~~~~~~~~~~~~~~~~~~
+
+Syntax: ``\PolDecToString{decimal number}``
+
+ This is a utility macro to print decimal numbers. It is an alias
+ for ``\xintDecToString``.
+
+.. vieux commentaire
+
+ It has been
+ backported to xintfrac_ (release ``1.3`` of ``2018/03/01``) under
+ the name ``\xintDecToString``, and the ``polexpr`` macro is simply
+ now an alias to it.
+
+..
+
+ For example
+ ``\PolDecToString{123.456e-8}`` will expand to ``0.00000123456``
+ and ``\PolDecToString{123.450e-8}`` to ``0.00000123450`` which
+ illustrates that trailing zeros are not trimmed.
+
+ To trim trailing zeroes, one can use
+ ``\PolDecToString{\xintREZ{#1}}``.
+
+ Attention that a.t.t.o.w. if the argument is for example ``1/5``, the
+ macro does not identify that this is in fact a number with a finite
+ decimal expansion and it outputs ``1/5``. See current xintfrac_
+ documentation.
+
+.. vieux commentaire
+
+ The precise behaviour of this macro may evolve in future releases of
+ xintexpr_.
+
+..
+
+
+.. _polexprsetup:
+
+``\polexprsetup{key=val,...}``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Serves to customize the package. Currently only two keys are
+ recognized:
+
+ - ``norr``: the postfix that :ref:`\\PolSturmIsolateZeros**{\<sturmname\>} <PolSturmIsolateZeros**>`
+ should append to ``<sturmname>`` to declare the primitive polynomial
+ obtained from original one after removal of all rational roots.
+ The default value is ``_norr`` (standing for “no rational roots”).
+
+ - ``sqfnorr``: the postfix that :ref:`\\PolSturmIsolateZeros**{\<sturmname\>} <PolSturmIsolateZeros**>`
+ should append to ``<sturmname>`` to declare the primitive polynomial
+ obtained from original one after removal of all rational roots and
+ suppression of all multiplicities.
+ The default value is ``_sqf_norr`` (standing for “square-free with
+ no rational roots”).
+
+ The package executes ``\polexprsetup{norr=_norr,
+ sqfnorr=_sqf_norr}`` as default.
+
+
+Technicalities
+--------------
+
+
+- The ``@`` is allowed in the name of a polynomial (independently of
+ whether it is of catcode letter or other.) This has always been the
+ case, but was not documented by polexpr prior to ``0.8``, as the
+ author has never found the time to provide some official guidelines on
+ how to name temporary variables and the ``@`` is used already as such
+ internally; time has still not yet been found to review the situation
+ but it seems reasonable to recommend at any rate to restrict usage of
+ ``@`` to scratch variables of defined macros and to avoid using it to
+ name document variable.
+
+- Catcodes are set temporarily by `\\poldef <poldef;_>`_ macro to safe
+ values prior to grab the polynomial expression up to the terminator
+ ``;``, and also by `\\PolDef <PolDef_>`_ prior to grab the
+ brace-enclosed polynomial expression. This gives a layer of
+ protection in case some package (for example the ``babel-french`` module)
+ has made some characters active. It will fail though if the whole
+ thing is located inside some definition of a macro done at a time the
+ characters are active.
+
+- ..
+
+ .. attention::
+
+ Contrarily to ``\xintdefvar`` and ``\xintdeffunc`` from xintexpr_,
+ ``\poldef`` uses a naive delimited macro to fetch up to the
+ expression terminator ``";"``, hence it will be fooled if some
+ ``;`` is used inside the expression (which is possible as it
+ appears in some xintexpr_ constructs). Work-around is to use curly
+ braces around the inner semi-colons, or simpler to use
+ ``\PolDef``.
+
+- As a consequence of xintfrac_ addition and subtraction always using
+ least common multiples for the denominators, user-chosen common
+ denominators (currently) survive additions and multiplications. For
+ example, this::
+
+ \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*Q;
+
+ gives internally 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. Notice though that
+ ``\PolToExpr{PQ}`` outputs the ``6/6*x^3`` as ``x^3`` because (by
+ default) it recognizes and filters out coefficients equal to one or
+ minus one. One can use for example
+ ``\PolToCSV{PQ}`` to see the internally stored coefficients.
+
+ .. vieux commentaire
+
+ prior to ``0.4.1``, ``polexpr`` used to temporarily patch
+ during the parsing of polynomials the xintfrac_ macros. This
+ patch was backported to xintexpr_ at release ``1.3``.
+
+- :ref:`\\PolDiff{\<polname_1\>}{\<polname_2\>} <PolDiff>` always applies ``\xintPIrr`` to the
+ resulting coefficients, which means that fractions are reduced to
+ lowest terms but ignoring an already separated *power of ten* part ``[N]``
+ present in the internal representation. This is tentative and may change.
+
+ Same remark for :ref:`\\PolAntiDiff{\<polname_1\>}{\<polname_2\>} <PolAntiDiff>`.
+
+- Currently, the package stores all coefficients from index ``0`` to
+ index equal to the polynomial degree inside a single macro, as a list.
+ This data structure is obviously very inefficient for polynomials of
+ high degree and few coefficients (as an example with ``\poldef
+ f(x):=x^1000 + x^500;`` the subsequent definition ``\poldef g(x):=
+ f(x)^2;`` will do of the order of 1,000,000 multiplications and
+ additions involvings only zeroes... which does take time). This
+ may change in the future.
+
+- As is to be expected internal structures of the package are barely
+ documented and unstable. Don't use them.
+
+
+.. _xinttools:
+.. _xintfrac:
+.. _xint: https://www.ctan.org/pkg/xint
+
+.. _xintexpr: https://www.ctan.org/pkg/xintexpr
+
+.. _xintsession: https://www.ctan.org/pkg/xintsession
+
+.. _Wilkinson polynomial: https://en.wikipedia.org/wiki/Wilkinson%27s_polynomial
+
+.. _Sturm algorithm:
+.. _Sturm Theorem: https://en.wikipedia.org/wiki/Sturm%27s_theorem
+
+.. _DocUtils: http://docutils.sourceforge.net/docs/index.html
+
+
+.. Local variables:
+.. sentence-end-double-space: t;
+.. End: