From 1b46f20416a9e8cc55188c0b4ad13cc91ace5aed Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Mon, 12 Apr 2021 20:04:33 +0000 Subject: polexpr (12apr21) git-svn-id: svn://tug.org/texlive/trunk@58854 c570f23f-e606-0410-a88d-b1316a301751 --- Master/texmf-dist/doc/generic/polexpr/README.md | 4 +- Master/texmf-dist/doc/generic/polexpr/polexpr.html | 2031 +++++++++++--------- 2 files changed, 1081 insertions(+), 954 deletions(-) (limited to 'Master/texmf-dist/doc/generic/polexpr') diff --git a/Master/texmf-dist/doc/generic/polexpr/README.md b/Master/texmf-dist/doc/generic/polexpr/README.md index b32b8f056df..1ea68b2df7e 100644 --- a/Master/texmf-dist/doc/generic/polexpr/README.md +++ b/Master/texmf-dist/doc/generic/polexpr/README.md @@ -83,8 +83,10 @@ Releases - 0.8 (2021/03/29) Complete refactoring of the package core for better integration with and enhancement of xintexpr 1.4. +- 0.8.1 (2021/04/12) + Bugfix: a typo broke the 0.8 ``diff1()`` and related functions. -Files of 0.8 release: +Files of 0.8.1 release: - polexpr.sty, polexprcore.tex, polexprexpr.tex, polexprsturm.tex, - README.md, diff --git a/Master/texmf-dist/doc/generic/polexpr/polexpr.html b/Master/texmf-dist/doc/generic/polexpr/polexpr.html index 81cd2b4b7c1..6b9881daef0 100644 --- a/Master/texmf-dist/doc/generic/polexpr/polexpr.html +++ b/Master/texmf-dist/doc/generic/polexpr/polexpr.html @@ -598,222 +598,230 @@ a { text-decoration: none; }

Package polexpr documentation

-

0.8 (2021/03/29)

+

0.8.1 (2021/04/12)

Contents

+ +
  • Examples of localization of roots

    +
  • +
  • Non-expandable macros

    -
  • -
  • \PolTypeset*{<pol. expr.>}

  • -
  • \PolDiff{polname_1}{polname_2}

  • -
  • \PolDiff[N]{polname_1}{polname_2}

  • -
  • \PolAntiDiff{polname_1}{polname_2}

  • -
  • \PolAntiDiff[N]{polname_1}{polname_2}

  • -
  • \PolDivide{polname_1}{polname_2}{polname_Q}{polname_R}

  • -
  • \PolQuo{polname_1}{polname_2}{polname_Q}

  • -
  • \PolRem{polname_1}{polname_2}{polname_R}

  • -
  • \PolGCD{polname_1}{polname_2}{polname_GCD}

  • -
  • Non-expandable macros related to the root localization routines

    +
  • \poldef polname(letter):= expression using the letter as indeterminate;

  • +
  • \PolDef[<letter>]{<polname>}{<expr. using the letter as indeterminate>}

  • +
  • \PolGenFloatVariant{<polname>}

  • +
  • \PolTypeset{<pol. expr.>}

  • -
  • \PolPrintIntervals*[varname]{sturmname}

    +
  • \PolTypeset*{<pol. expr.>}

  • +
  • Non-expandable macros related to the root localization routines

    +
  • +
  • \PolLet{<polname_2>}={<polname_1>}

  • +
  • \PolGlobalLet{<polname_2>}={<polname_1>}

  • +
  • \PolAssign{<polname>}\toarray\macro

  • +
  • \PolGet{<polname>}\fromarray\macro

  • +
  • \PolFromCSV{<polname>}{<csv>}

  • +
  • \PolMapCoeffs{\macro}{<polname>}

  • +
  • \PolReduceCoeffs{<polname>}

  • +
  • \PolReduceCoeffs*{<polname>}

  • +
  • \PolMakeMonic{<polname>}

  • +
  • \PolMakePrimitive{<polname>}

  • +
  • \PolDiff{<polname_1>}{<polname_2>}

  • +
  • \PolDiff[N]{<polname_1>}{<polname_2>}

  • +
  • \PolAntiDiff{<polname_1>}{<polname_2>}

  • +
  • \PolAntiDiff[N]{<polname_1>}{<polname_2>}

  • +
  • \PolDivide{<polname_1>}{<polname_2>}{<polname_Q>}{<polname_R>}

  • +
  • \PolQuo{<polname_1>}{<polname_2>}{<polname_Q>}

  • +
  • \PolRem{<polname_1>}{<polname_2>}{<polname_R>}

  • +
  • \PolGCD{<polname_1>}{<polname_2>}{<polname_GCD>}

  • + + +
  • Expandable macros

    -
  • -
  • \PolToExpr*{<pol. expr.>}

  • -
  • \PolToFloatExpr{<pol. expr.>}

    +
  • \PolToExpr{<pol. expr.>}

  • -
  • \PolToFloatExpr*{<pol. expr.>}

  • -
  • \PolToList{polname}

  • -
  • \PolToCSV{polname}

  • -
  • Expandable macros related to the root localization routines

    +
  • \PolToFloatExpr{<pol. expr.>}

    -
  • -
  • Expandable macros for use within execution of \PolPrintIntervals

    +
  • \PolToFloatExprOneTerm{<raw_coeff>}{<exponent>}

  • +
  • \PolToFloatExprCmd{<raw_coeff>}

  • + + +
  • \PolToExpr*{<pol. expr.>}

  • +
  • \PolToFloatExpr*{<pol. expr.>}

  • +
  • \PolNthCoeff{<polname>}{<index>}

  • +
  • \PolLeadingCoeff{<polname>}

  • +
  • \PolDegree{<polname>}

  • +
  • \PolIContent{<polname>}

  • +
  • \PolToList{<polname>}

  • +
  • \PolToCSV{<polname>}

  • +
  • \PolEval{<polname>}\AtExpr{<num. expr.>}

  • +
  • \PolEval{<polname>}\At{<value>}

  • +
  • \PolEvalReduced{<polname>}\AtExpr{<num. expr.>}

  • +
  • \PolEvalReduced{<polname>}\At{<value>}

  • +
  • \PolFloatEval{<polname>}\AtExpr{<num. expr.>}

  • +
  • \PolFloatEval{<polname>}\At{<value>}

  • +
  • Expandable macros related to the root localization routines

  • -
  • Booleans (with default setting as indicated)

    +
  • Booleans (with default setting as indicated)

  • -
  • Utilies

    +
  • Utilies

  • -
  • Technicalities

  • -
  • CHANGE LOG

  • -
  • Acknowledgments

  • +
  • Technicalities

  • +
  • CHANGE LOG

  • +
  • Acknowledgments

  • -

    Usage

    +

    Usage

    The package can be used with TeX based formats incorporating the e-TeX primitives. The \expanded primitive available generally since TeXLive 2019 is required.

    @@ -831,7 +839,7 @@ TeX macro format used if needed.

    -

    Abstract

    +

    Abstract

    The package provides a parser \poldef of algebraic polynomial expressions. As it is based on xintexpr the coefficients are allowed to be arbitrary rational numbers.

    @@ -849,7 +857,7 @@ computation of a greatest common divisor is now available directly in syntax.

    -

    Prerequisites

    +

    Prerequisites

    -

    Quick syntax overview

    -

    The syntax is:

    +

    Quick syntax overview

    +

    The syntax to define a new polynomial is:

    \poldef polname(x):= expression in variable x;
    +

    The package is focused on exact computations, so this expression will be +parsed by the services of xintexpr and accept arbitrarily big integers +or fractions.

    +

    If you are interested into numerical evaluations, for example for +plotting, it is advisable to use the \xintfloatexpr/\xintfloateval +context, as exact evaluations will quickly lead to manipulating numbers +with dozens of digits (when the number of digits exceeds five hundreds, +computation with xintexpr will become noticeably too slow, if many +evaluations need to be done). For the polynomial to be usable as a function in +floating point context, an extra step beyond \poldef is required: +see \PolGenFloatVariant.

    +

    As a rule, the functionalities such as getting the degree, or getting +one coefficient, or taking derivatives, etc..., i.e. anything which +handles the polynomial as an entity and not only as a numerical +function, are only available in the \poldef/\xintexpr/\xinteval +context. The \PolGenFloatVariant must be used each time the +polynomial gets modified or a new polynomial created out of it, if +continuing computations in \xintfloatexpr are to follow. But (see +xintexpr documentation) one can always use a sub-expression such as +\xintexpr deg(P)\relax as sub-component inside a +\xintfloatexpr/\xintfloateval.

    +

    Conversely if perhaps the coefficients of your polynomial have become +too gigantic and you would like to replace them with some approximation +to keep on working in \xinteval, not necessarily \xintfloateval, +see \PolMapCoeffs which can be used for example with \xintFloat +macro to make the float-rounding applied to the exact coefficients.

    -
  • The colon before the equality sign is optional and its catcode does -not matter.

  • -
  • The semi-colon at the end of the expression is mandatory. Its catcode -does not matter if \poldef is not used inside the argument of -another macro.

  • +
  • 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. Some +contexts (such as (pdf)LaTeX with babel+frenchb) modify its catcode. +If at top level, \poldef resets temporarily the semi-colon catcode +before fetching the expression, so is immune to this. There is also +naturally no problem either if \poldef is used in the replacement +text of some other macro which is defined at a time the ; has its +standard catcode, as is the case in LaTeX in the document preamble, +even with babel+french loaded.

    +

    The semi-colon intervenes in certain xintexpr syntax elements, within +parentheses. This (except if the inner semi-colons are hidden within +braces: {;}) will break \poldef which, contrarily to +xintexpr's \xintdefvar, does not balance parentheses when +fetching the semi-colon delimited polynomial expression.

    +
  • -

    There is an alternative syntax

    -
    \PolDef[optional letter]{polname}{expression in the letter}
    -

    Its optional first argument defaults to x.

    +

    Problems with the semi-colon are avoided via an alternative syntax:

    +
    \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.

    +

    \poldef f(x):= 1 - x + quo(x^5,1 - x + x^2);

    -
    \poldef f(x):= 1 - x + quo(x^5,1 - x + x^2);
    -

    defines polynomial f. The indeterminate x must be -only submitted to algebraic operations.

    -

    The quo() function (new at 0.8) computes the euclidean -division quotient.

    +
    \PolDef{f}{1 - x + quo(x^5,1 - x + x^2)}
    +

    Both parse the polynomial +expression, and convert it internally (currently) to the list +of its coefficients from the constant term to the highest degree +term.

    +

    The polynomial can then be used in further polynomial definitions or +serve as argument to package macros, or as a variable in various +functions which will be described later.

    Important

    -

    For backwards compatibility one can currently also use:

    +

    Euclidean quotient is mapped to the function quo() (as shown +in the example above), but +for backwards compatibility one can currently still use the / +infix operator:

    \poldef f(x):= 1 - x + x^5/(1 - x + x^2);

    Due to precedence rules the first operand is x^5, not of course 1-x+x^5.

    @@ -959,7 +1012,7 @@ to leave open this as a future possibility, the usage of quo() function. It is possible -that in a future major relase A/B with B a non-scalar will +that in a future major release A/B with B a non-scalar will raise an error. Or, who knows, rational functions will be implemented sometime during the next decades, and then A/B will naturally be the rational function.

    @@ -1009,6 +1062,10 @@ explicit (P+Q)*(1+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.

    @@ -1099,7 +1156,7 @@ polynomial variable but more generally any polynomial expression.

    -

    The polexpr 0.8 extensions to the \xintexpr syntax

    +

    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 @@ -1122,7 +1179,7 @@ which means it could then be accessible with syntax such as

    -

    Warning about unstability of the new syntax

    +

    Warning about unstability of the new syntax

    Warning

    Consider the entirety of this section as UNSTABLE and @@ -1139,7 +1196,7 @@ during the week devoted to development.

    -

    Infix operators +, -, *, /, **, ^

    +

    Infix operators +, -, *, /, **, ^

    As has been explained in the Quick syntax overview these infix operators have been made polynomial aware, not only in the @@ -1170,7 +1227,7 @@ powers.

    -

    Experimental infix operators //, /:

    +

    Experimental infix operators //, /:

    Here is the tentative behaviour of A//B according to types:

      @@ -1204,7 +1261,7 @@ about behaviour with pol2 a scalar.

    -

    Comparison operators <, >, <=, >=, ==, !=

    +

    Comparison operators <, >, <=, >=, ==, !=

    NOT YET IMPLEMENTED

    As the internal representation by xintfrac and xintexpr of @@ -1222,7 +1279,7 @@ following syntax:

    -

    pol(<nutple expression>)

    +

    pol(<nutple expression>)

    This converts a nutple [c0,c1,...,cN] into the polynomial variable having these coefficients. Attention that the square @@ -1255,8 +1312,27 @@ that we are actually referring to pre-declared variables in the sense of \xintdefvar.

    +
    +

    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)

    +
    +
    -

    \xinteval{<pol. expr.>}

    +

    \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]) @@ -1279,7 +1355,7 @@ This example can also be done as

    -

    evalp(<pol. expr.>, <pol. expr>)

    +

    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 @@ -1313,7 +1389,7 @@ though, as is amply demonstrated these days.

    -

    deg(<pol. expr.>)

    +

    deg(<pol. expr.>)

    Computes the degree.

    @@ -1326,7 +1402,7 @@ and deg(P)<=0
    -

    coeffs(<pol. expr.>)

    +

    coeffs(<pol. expr.>)

    Produces the nutple [c0,c1,...,cN] of coefficients. The highest degree coefficient is always non zero (except for the zero @@ -1339,27 +1415,44 @@ will be added to +

    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.>)

    +

    coeff(<pol. expr.>, <num. expr.>)

    -

    As expected. Produces zero if n is negative or higher than the -degree.

    +

    As expected. Produces zero if the numerical index is negative or +higher than the degree.

    -

    name and syntax 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.

    +

    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 +\PolNthCoeff{<polname>}{<index>} 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.

    -
    -

    lcoeff(<pol. expr.>)

    +
    +

    lc(<pol. expr.>)

    -

    The leading coefficient.

    +

    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.>)

    +

    monicpart(<pol. expr.>)

    Divides by the leading coefficient, except that monicpart(0)==0.

    @@ -1373,24 +1466,30 @@ efficiency of multiplication.

    -
    -

    icontent(<pol. expr.>)

    +
    +

    cont(<pol. expr.>)

    -

    The gcd of the (possibly fractional) 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.

    +

    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.

    -

    name unstable

    -

    Some hesitation with using content() rather.

    +

    name and syntax unstable

    +

    At 0.8 it was created as icontent() to match the legacy +macro \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.>)

    +

    primpart(<pol. expr.>)

    The quotient (except for the zero polynomial) by -icontent(<pol. expr.>). This is thus a polynomial with +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.

    @@ -1399,7 +1498,7 @@ into a power of ten exponent part, in the internal representation.

    -

    quorem(<pol. expr.>, <pol. expr.>)

    +

    quorem(<pol. expr.>, <pol. expr.>)

    Produces a nutple [Q,R] with Q the euclidean quotient and R the remainder.

    @@ -1410,14 +1509,14 @@ into a power of ten exponent part, in the internal representation.

    -

    quo(<pol. expr.>, <pol. expr.>)

    +

    quo(<pol. expr.>, <pol. expr.>)

    The euclidean quotient.

    The deprecated pol1/pol2 syntax computes the same polynomial.

    -

    rem(<pol. expr.>, <pol. expr.>)

    +

    rem(<pol. expr.>, <pol. expr.>)

    The euclidean remainder. If pol2 is a (non-zero) scalar, this is zero.

    @@ -1429,7 +1528,7 @@ even in that case.

    -

    prem(<pol. expr. 1>, <pol. expr. 2>)

    +

    prem(<pol. expr. 1>, <pol. expr. 2>)

    Produces a nutple [m, spR] where spR is the (special) pseudo Euclidean remainder. Its description is:

    @@ -1477,7 +1576,7 @@ remainder. This diverges from Maple's function with the same name.

    -

    divmod(<pol. expr. 1>, <pol. expr. 2>)

    +

    divmod(<pol. expr. 1>, <pol. expr. 2>)

    Overloads the scalar divmod() and associates it with the experimental // and /: as extended to the polynomial type.

    @@ -1490,7 +1589,7 @@ non constant polynomials, this is the same as quo
    -

    mod(<pol. expr. 1>, <pol. expr. 2>)

    +

    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.

    @@ -1500,7 +1599,7 @@ when the second argument pol2 is of degree
    -

    polgcd(<pol. expr. 1>, <pol. expr. 2>, ...)

    +

    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, @@ -1541,7 +1640,7 @@ polynomial, as one can always apply monicpart()

    -

    resultant(<pol. expr. 1>, <pol. expr. 2>)

    +

    resultant(<pol. expr. 1>, <pol. expr. 2>)

    The resultant.

    @@ -1550,7 +1649,7 @@ polynomial, as one can always apply monicpart()
    -

    disc(<pol. expr.>)

    +

    disc(<pol. expr.>)

    The discriminant.

    @@ -1559,7 +1658,7 @@ polynomial, as one can always apply monicpart()
    -

    polpowmod(<pol. expr. 1>, <num. expr.>, <pol. expr. 2>)

    +

    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.

    @@ -1595,7 +1694,7 @@ pol([1, 0, 0, 0, 5, 4, 0, 0, 0, 0, 6, 0, 0, 0, 0, 4, 5, 0, 0, 0, 1])
    -

    rdcoeffs(<pol. expr.>)

    +

    rdcoeffs(<pol. expr.>)

    This operates on the internal representation of the coefficients, reducing them to lowest terms.

    @@ -1605,7 +1704,7 @@ reducing them to lowest terms.

    -

    rdzcoeffs(<pol. expr.>)

    +

    rdzcoeffs(<pol. expr.>)

    This operates on the internal representation of the coefficients, reducing them to lowest terms then extracting from numerator @@ -1619,7 +1718,7 @@ computations.

    -

    diff1(<pol. expr.>)

    +

    diff1(<pol. expr.>)

    The first derivative.

    @@ -1630,7 +1729,7 @@ respect to a first variable.

    -

    diff2(<pol. expr.>)

    +

    diff2(<pol. expr.>)

    The second derivative.

    @@ -1641,7 +1740,7 @@ respect to a second variable.

    -

    diffn(<pol. expr. P>, <num. expr. n>)

    +

    diffn(<pol. expr. P>, <num. expr. n>)

    The nth derivative of P. For n<0 computes iterated primitives vanishing at the origin.

    @@ -1653,13 +1752,13 @@ vanishing at the origin.

    -

    antider(<pol. expr. P>)

    +

    antider(<pol. expr. P>)

    The primitive of P with no constant term. Same as diffn(P,-1).

    -

    intfrom(<pol. expr. P>, <pol. expr. c>)

    +

    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 @@ -1673,7 +1772,7 @@ maintaining this feature whose interest appears dubious.

    -

    integral(<pol. expr. P>, [<pol. expr. a>, <pol. expr. b>])

    +

    integral(<pol. expr. P>, [<pol. expr. a>, <pol. expr. b>])

    \int_a^b P(t)dt.

    The brackets here are not denoting an optional argument @@ -1692,7 +1791,7 @@ overhead to the pure scalar case ?

    -

    Examples of localization of roots

    +

    Examples of localization of roots

    Note

    As of 0.8, polexpr is usable with Plain TeX and not only with @@ -1701,6 +1800,19 @@ syntax which (at least at time of writing, March 2021) works in both.

    This is done in order for the examples to be easy to copy-paste to documents using either macro format.

    +

    This (slightly over-extended) section gives various examples of usage of +the package macros such as \PolToSturm, \PolSturmIsolateZeros +and \PolPrintIntervals for root localization, which exist since +release 0.4 (2018/02/16). The capacity to find all rational roots +exactly was added at 0.7.2 (2018/12/09).

    +

    The examples demonstrate that the package can find all real roots to +arbitrary precision, find the multiplicities of real roots, and find +exactly all rational roots.

    +

    Perhaps future releases will implement other approaches, which are known +to be generically computationally more efficient, at least in high +degrees, than the Sturm theorem based approach. This is not +immediate priority though (perhaps support of multivariate polynomials +would be more important feature; or localization of complex roots).

    • To make printed decimal numbers more enjoyable than via \xintSignedFrac (or \xintSignedFwOver with Plain):

      @@ -1715,8 +1827,21 @@ that one can also do:

    • For extra info in log file use \xintverbosetrue.

    +
    +

    Warning

    +

    Package macros related to root localization create (user-level) new +polynomials, or numeric variables, via a naming scheme which +postfixes a root name <sturmname> in various ways (see +\PolToSturm{<polname>}{<sturmname>} and +\PolSturmIsolateZeros{<sturmname>}). It is thus advisable to +keep the <sturmname> name-space separate from the one used to +name polynomial or scalar variables.

    +

    Regrettably all examples here use the condemnable +\PolToSturm{f}{f} practice which fuses the name-spaces. This can +lead to problems if one is not aware of the consequances.

    +
    -

    A typical example

    +

    A typical example

    In this example the polynomial is square-free.

    \poldef f(x) := x^7 - x^6 - 2x + 1;
     
    @@ -1756,9 +1881,9 @@ The more mathematically advanced among our dear readers will be able
     to give the exact value for $X_2$!
    -

    A degree four polynomial with nearby roots

    +

    A degree four polynomial with nearby roots

    Notice that this example is a bit outdated as 0.7 release has -added \PolSturmIsolateZeros**{sturmname} which would find exactly +added \PolSturmIsolateZeros**{<sturmname>} which would find exactly the roots. The steps here retain their interest when one is interested in finding isolating intervals for example to prepare some demonstration of dichotomy method.

    @@ -1782,7 +1907,7 @@ of dichotomy method.

    % of course finds here all roots exactly
    -

    The degree nine polynomial with 0.99, 0.999, 0.9999 as triple roots

    +

    The degree nine polynomial with 0.99, 0.999, 0.9999 as triple roots

    % define a user command (xinttools is loaded automatically by polexpr)
     \def\showmultiplicities#1{% #1 = "sturmname"
     \xintFor* ##1 in {\xintSeq{1}{\PolSturmNbOfIsolatedZeros{#1}}}\do{%
    @@ -1842,7 +1967,7 @@ The multiplicity is 1 for the root such that 0.9991447980 < x < 0.99914479
     The multiplicity is 1 for the root such that 0.9997663986 < x < 0.9997663987
    -

    A degree five polynomial with three rational roots

    +

    A degree five polynomial with three rational roots

    \poldef Q(x) :=  1581755751184441 x^5
                    -14907697165025339 x^4
                    +48415668972339336 x^3
    @@ -1874,7 +1999,7 @@ Z_2 = 3.14159265358979340254...
     Z_3 = 3.14159292035398230088...
    -

    A Mignotte type polynomial

    +

    A Mignotte type polynomial

    \PolDef{P}{x^10 - (10x-1)^2}%
     \PolTypeset{P}              % prints it in expanded form
     \PolToSturm{P}{P}           % we can use same prefix for Sturm chain
    @@ -1897,7 +2022,7 @@ $$\PolSturmIsolatedZeroLeft{P}{2}<Z_2<\PolSturmIsolatedZeroRight{P}{2}$$0.09999900004999650028 < Z_2 < 0.09999900004999650029
    -

    The Wilkinson polynomial

    +

    The Wilkinson polynomial

    See Wilkinson polynomial.

    %\xintverbosetrue % for the curious...
     
    @@ -1967,7 +2092,7 @@ Z_9 = 8.9172502485...
     Z_10 = 20.8469081014...
    -

    The second Wilkinson polynomial

    +

    The second Wilkinson polynomial

    \poldef f(x) := mul(x - 2^-i, i = 1..20);
     
     %\PolTypeset{f}
    @@ -2006,7 +2131,7 @@ fractions and they use \xintIrr before sto
     This may evolve in future.

    -

    The degree 41 polynomial with -2, -1.9, -1.8, ..., 0, 0.1, ..., 1.9, 2 as roots

    +

    The degree 41 polynomial with -2, -1.9, -1.8, ..., 0, 0.1, ..., 1.9, 2 as roots

    \PolDef{P}{mul((x-i*1e-1), i=-20..20)}% i/10 is same but less efficient

    In the defining expression we could have used i/10 but this gives less efficient internal form for the coefficients (the 10's end up @@ -2058,18 +2183,19 @@ optional argument keeping the same.

    -

    Roots of Chebyshev polynomials

    -
    \newcount\mycount
    -\poldef T_0(x) := 1;
    +

    Roots of Chebyshev polynomials

    +
    \poldef T_0(x) := 1;
     \poldef T_1(x) := x;
    -\mycount 2
    +\catcode`@ 11
    +\count@ 2
     \xintloop
    -  \poldef T_\the\mycount(x) :=
    -          2x*T_\the\numexpr\mycount-1(x)
    -           - T_\the\numexpr\mycount-2(x);
    -\ifnum\mycount<15
    -\advance\mycount 1
    +  \poldef T_\the\count@(x) :=
    +          2x*T_\the\numexpr\count@-1\relax
    +           - T_\the\numexpr\count@-2\relax;
    +\ifnum\count@<15
    +\advance\count@ 1
     \repeat
    +\catcode`@ 12
     
     $$T_{15} = \PolTypeset[X]{T_15}$$
     \PolToSturm{T_15}{T_15}
    @@ -2079,7 +2205,7 @@ $$T_{15} = \PolTypeset[X]{T_15}$$
     
    -

    Non-expandable macros

    +

    Non-expandable macros

    Note

    At 0.8 polexpr is usable with Plain TeX and not only with @@ -2088,24 +2214,24 @@ such as \renewcommand. Convert to TeX pri if testing with a non LaTeX macro format.

    -

    \poldef polname(letter):= expression using the letter as indeterminate;

    +

    \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, when used with argument the chosen polname. Of -course the expression can use other previously defined -polynomials.

    +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:

    -
    \poldef mypol(z) := add((-1)^i z^(2i+1)/(2i+1)!, i = 0..10);
    +

    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.

    Furthermore:

      -
    • a variable mypol is defined which can be used in \poldef +

    • 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 mypol() is defined which can be used in \poldef +

    • 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).

    • @@ -2118,13 +2244,12 @@ names as argument.

      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). -THIS MAY CHANGE

      +(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 mypol() is defined only for +

      The function polname() is defined only for \xintexpr/\xinteval context. It will be unknown to \xintfloateval.

      Worse, a @@ -2133,9 +2258,8 @@ 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 \PolGenFloatVariant{polname} to generate a function -usable in \xintfloateval. Such a function can only be -used with scalar input, see next warning.

      +

      See \PolGenFloatVariant{<polname>} to generate a function +usable in \xintfloateval.

      Attention!

      @@ -2145,13 +2269,12 @@ 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 \PolGenFloatVariant{polname} +via functions obtained from \PolGenFloatVariant{<polname>} 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.

      -

      THIS MAY CHANGE

      The original expression is lost after parsing, and in particular the package provides no way to typeset it (of course the package @@ -2159,111 +2282,35 @@ provides macros to typeset the computed polynomial). Typesetting the original expression has to be done manually, if needed.

    -
    -

    \PolDef[letter]{polname}{expression using the letter as indeterminate}

    +
    +

    \PolDef[<letter>]{<polname>}{<expr. using the letter as indeterminate>}

    Does the same as \poldef in an undelimited macro -format (thus avoiding potential problems with the catcode of the -semi-colon in presence of some packages.) In absence of the -[letter] optional argument, the variable is assumed to be x.

    +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{polname}

    +

    \PolGenFloatVariant{<polname>}

    -

    Makes the polynomial also usable in the \xintfloatexpr parser. -It will therein evaluates via an Horner scheme with coefficients -already pre-rounded to the float precision.

    +

    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 \PolToFloatExpr{<pol. expr.>}.

    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 as a -function.

    -
    -
    -
    -
    -

    \PolLet{polname_2}={polname_1}

    -
    -

    Makes a copy of the already defined polynomial polname_1 to a -new one polname_2. Same effect as -\PolDef{polname_2}{polname_1(x)} but with less overhead. The -= is optional.

    -
    -
    -
    -

    \PolGlobalLet{polname_2}={polname_1}

    -
    -

    Acts globally.

    -
    -
    -
    -

    \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.

    • -
    • 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 \PolNthCoeff{polname}{number}. The main difference is that -with \PolAssign, \macro is made a prefix to 1 + deg f -already defined (hidden to user) macros holding individually the -coefficients but \PolNthCoeff{polname}{number} does each time the job -to expandably recover the Nth coefficient, and due to -expandability can not store it in a macro for future usage (of course, -it can be an argument in an \edef.) The other difference -is the shift by one in indexing, mentioned above (negative -indices act the same in both.)

    -
    -
    -
    -

    \PolGet{polname}\fromarray\macro

    -
    -

    Does the converse operation to -\PolAssign{polname}\toarray\macro. Each individual -\macro{number} 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;.

    -
    -

    Note

    -

    Prior to 0.5, coefficients were not normalized via -\xintRaw for internal storage.

    -
    -
    -
    -
    -

    \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 \PolToCSV.

    -
    -

    Note

    -

    Prior to 0.5, coefficients were not normalized via -\xintRaw for internal storage.

    +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{<pol. expr.>}

    +

    \PolTypeset{<pol. expr.>}

    Typesets in descending powers, switching to math mode if in text mode, after evaluating the polynomial expression:

    @@ -2280,23 +2327,37 @@ can be re-defined for customization. Their default definitions are expandable, but this is not a requirement.

    -

    \PolTypesetCmd{raw_coeff}

    +

    \PolTypesetCmd{<raw_coeff>}

    -

    Checks if the coefficient is 1 or -1 and then skips printing -the 1, except for the constant term. Also it sets conditional -\PolIfCoeffIsPlusOrMinusOne{A}{B}.

    +

    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 +\PolIfCoeffIsPlusOrMinusOne{T}{F}.

    The actual printing of the coefficients, when not equal to plus or -minus one is handled by \PolTypesetOne{raw_coeff}.

    +minus one, is handled by \PolTypesetOne{<raw_coeff>}.

    +
    +

    \PolIfCoeffIsPlusOrMinusOne{T}{F}

    +
    +

    This macro is a priori undefined.

    +

    It is defined via the default \PolTypesetCmd{<raw_coeff>} 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{raw_coeff}

    +

    \PolTypesetOne{<raw_coeff>}

    Defaults to \xintSignedFrac (LaTeX) or \xintSignedFwOver -(else). But these xintfrac very old legacy macros are a bit -annoyin as they insist in exhibiting a power of ten rather than +(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 things such as:

    +

    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}}}
    @@ -2305,7 +2366,7 @@ using simpler decimal notation.

    -

    \PolTypesetMonomialCmd

    +

    \PolTypesetMonomialCmd

    This decides how a monomial (in variable \PolVar and with exponent \PolIndex) is to be printed. The default does nothing @@ -2316,231 +2377,138 @@ for the constant term, \PolVar for the fir

    -

    \PolTypesetCmdPrefix{raw_coeff}

    +

    \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 \xintSignedFrac (or \xintSignedFwOver) used by -\PolTypesetCmd{raw_coeff} will put the - sign in front of +\PolTypesetCmd{<raw_coeff>} 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*{<pol. expr.>}

    +

    \PolTypeset*{<pol. expr.>}

    -

    Typesets in ascending powers. Use e.g. [h] optional argument -(after the *) to use letter h rather than x.

    +

    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.

    -
    -

    \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[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{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[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{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{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{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{polname_1}{polname_2}{polname_GCD}

    -
    -

    This sets polname_GCD to be the (monic) GCD of the two first -polynomials. It is a unitary polynomial except if both polname_1 -and polname_2 vanish, then polname_GCD is the zero -polynomial.

    -
    -
    +

    The start of the decimal expansion of the <index>-th root is given by +\PolSturmIsolatedZeroLeft{<sturmname>}{<index>} if the root is positive, and by +PolSturmIsolatedZeroRight{<sturmname>}{<index>} 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 -\PolSturmNbOfIsolatedZeros{sturmname}.

    +\PolSturmNbOfIsolatedZeros{<sturmname>}.

    Furthermore -\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualTo{value} and -\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualToExpr{expression}. +\PolSturmNbOfRootsOf{<sturmname>}\LessThanOrEqualTo{<value>} and +\PolSturmNbOfRootsOf{<sturmname>}\LessThanOrEqualToExpr{<num. expr.>}. 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 \PolRefineInterval*{<sturmname>}{<index>} or +other localization improving macros.

    Note

    The current polexpr implementation defines the xintexpr variables -and xinttools arrays described above with global scpe. On the -other hand the Sturm sequence polynomials do obey the current scope.

    +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

    -

    As all computations are done exactly there can be no errors... -apart those due to bad coding by author. The results are exact +

    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 @@ -2629,35 +2601,41 @@ are studied in numerical mathematics.

    -

    \PolSturmIsolateZeros*{sturmname}

    +

    \PolSturmIsolateZeros*{<sturmname>}

    -

    The macro does the same as \PolSturmIsolateZeros{sturmname} and +

    The macro does the same as \PolSturmIsolateZeros{<sturmname>} and then in addition it does the extra work to determine all -multiplicities (of the real roots): -after executing this macro, -\PolSturmIsolatedZeroMultiplicity{sturmname}{index} will expand +multiplicities of the real roots.

    +

    After execution, +\PolSturmIsolatedZeroMultiplicity{<sturmname>}{<index>} 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 f, xintexpr -variables fM_1, fM_2... hold the multiplicities thus +

    Furthermore, if for example the <sturmname> is S, xintexpr +variables SM_1, SM_2... hold the multiplicities thus computed.

    Note

    -

    It is not necessary to have executed the PolToSturm* starred -variant, as the non-starred variant keeps internally the memory of the -original GCD (and even of the full non-normalized original Sturm -chain), even though it does not make the declarations as user-level -genuine polynomials.

    +

    Somewhat counter-intuitively, it is not necessary to have +executed the \PolToSturm* starred variant: during its +execution, \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 for an example.

    +
    -

    \PolSturmIsolateZeros**{sturmname}

    +

    \PolSturmIsolateZeros**{<sturmname>}

    -

    The macro does the same as \PolSturmIsolateZeros*{sturmname} and +

    The macro does the same as \PolSturmIsolateZeros*{<sturmname>} and in addition it does the extra work to determine all the rational roots.

    @@ -2670,7 +2648,7 @@ to match the (square-free) sturmname_0 fro roots have been removed (see \polexprsetup for customizing this name). The number of distinct rational roots is thus the difference between the degrees of these two polynomials (see also -\PolSturmNbOfRationalRoots{sturmname}).

    +\PolSturmNbOfRationalRoots{<sturmname>}).

    And sturmname_norr is sturmname_0_ from which all rational roots have been removed (see \polexprsetup), i.e. it contains the irrational roots of the original polynomial, with the same @@ -2678,23 +2656,17 @@ multiplicities.

    See A degree five polynomial with three rational roots for an example.

    -
    - +
    -

    \PolSturmIsolateZerosAndFindRationalRoots{sturmname}

    +

    \PolSturmIsolateZerosAndFindRationalRoots{<sturmname>}

    -

    This works exactly like \PolSturmIsolateZeros**{sturmname} +

    This works exactly like \PolSturmIsolateZeros**{<sturmname>} (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.

    @@ -2708,11 +2680,11 @@ their multiplicities at the same time.

    This macro does not define xintexpr variables sturmnameM_1, sturmnameM_2, ... holding the multiplicities and it leaves the multiplicity array (whose accessor -is \PolSturmIsolatedZeroMultiplicity{sturmname}{index}) into +is \PolSturmIsolatedZeroMultiplicity{<sturmname>}{<index>}) into a broken state, as all non-rational roots will supposedly have multiplicity one. This means that the output of -\PolPrintIntervals* for example will be -erroneous for the intervals with irrational roots.

    +\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 @@ -2722,44 +2694,43 @@ rational root anyhow).

    -

    \PolRefineInterval*{sturmname}{index}

    +

    \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. This means that the kth root is then +the original interval. As a consequence, the kth root is then strictly separated from the other roots.

    -

    \PolRefineInterval[N]{sturmname}{index}

    +

    \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{sturmname}{index}{E}

    +
    +

    \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 kth root will then be known exactly.

    -
    -

    \PolEnsureIntervalLengths{sturmname}{E}

    +
    +

    \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 (length will be shorter -than 10^E in output only if it did not change or became zero.)

    +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.

    -

    \PolPrintIntervals[varname]{sturmname}

    +

    \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 @@ -2780,7 +2751,7 @@ primitives.

    See next macros which govern its output.

    -

    \PolPrintIntervalsNoRealRoots

    +

    \PolPrintIntervalsNoRealRoots

    Executed in place of an array environment, when there are no real roots. Default definition:

    @@ -2788,21 +2759,21 @@ real roots. Default definition:

    -

    \PolPrintIntervalsBeginEnv

    +

    \PolPrintIntervalsBeginEnv

    Default definition:

    \newcommand\PolPrintIntervalsBeginEnv{\[\begin{array}{rcccl}}
    -

    \PolPrintIntervalsEndEnv

    +

    \PolPrintIntervalsEndEnv

    Default definition:

    \newcommand\PolPrintIntervalsEndEnv{\end{array}\]}
    -

    \PolPrintIntervalsKnownRoot

    +

    \PolPrintIntervalsKnownRoot

    Default definition:

    \newcommand\PolPrintIntervalsKnownRoot{%
    @@ -2812,7 +2783,7 @@ real roots. Default definition:

    -

    \PolPrintIntervalsUnknownRoot

    +

    \PolPrintIntervalsUnknownRoot

    Default definition:

    \newcommand\PolPrintIntervalsUnknownRoot{%
    @@ -2823,21 +2794,21 @@ real roots. Default definition:

    -

    \PolPrintIntervalsPrintExactZero

    +

    \PolPrintIntervalsPrintExactZero

    Default definition:

    \newcommand\PolPrintIntervalsPrintExactZero{\PolPrintIntervalsTheLeftEndPoint}
    -

    \PolPrintIntervalsPrintLeftEndPoint

    +

    \PolPrintIntervalsPrintLeftEndPoint

    Default definition:

    \newcommand\PolPrintIntervalsPrintLeftEndPoint{\PolPrintIntervalsTheLeftEndPoint}
    -

    \PolPrintIntervalsPrintRightEndPoint

    +

    \PolPrintIntervalsPrintRightEndPoint

    Default definition is:

    \newcommand\PolPrintIntervalsPrintRightEndPoint{\PolPrintIntervalsTheRightEndPoint}
    @@ -2845,7 +2816,7 @@ real roots. Default definition:

    -

    \PolPrintIntervals*[varname]{sturmname}

    +

    \PolPrintIntervals*[<varname>]{<sturmname>}

    This starred variant produces an alternative output (which displays the root multiplicity), and is provided as an @@ -2862,26 +2833,123 @@ definition:

    Multiplicities are printed using this auxiliary macro:

    -

    \PolPrintIntervalsPrintMultiplicity

    +

    \PolPrintIntervalsPrintMultiplicity

    whose default definition is:

    \newcommand\PolPrintIntervalsPrintMultiplicity{(\mbox{mult. }\PolPrintIntervalsTheMultiplicity)}
    +
    +

    \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{\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 +\PolSturmNbOfRootsOf{<sturmname>}\LessThanOrEqualTo{<value>}, +which however requires prior execution of \PolSturmIsolateZeros.

    +

    See also the expandable +\PolSturmNbWithMultOfRootsOf{<sturmname>}\LessThanOrEqualTo{<value>} +which requires prior execution of +\PolSturmIsolateZeros*.

    +
    +
    +
    +
    +

    \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.

    +
    +
    + +
    +

    \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 \PolNthCoeff{<polname>}{<index>}.

    +
    +
    +
    +

    \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;.

    +
    +
    +
    +

    \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 \PolToCSV{<polname>}.

    +
    -

    \PolMapCoeffs{\macro}{polname}

    +

    \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 replacement text of -\macro, \index expands to the coefficient index (which is -defined to be zero for the constant term).

    -

    Notice that \macro will have to handle inputs of the shape -A/B[N] (xintfrac internal notation). This means that it probably -will have to be expressed in terms of macros from xintfrac package.

    +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 @@ -2889,175 +2957,132 @@ will have to be expressed in terms of macros from

    -

    \PolReduceCoeffs{polname}

    +

    \PolReduceCoeffs{<polname>}

    -

    About the same as \PolMapCoeffs{\xintIrr}{polname} (but -maintaining a [0] postfix for speedier xintfrac parsing when -polynomial function is used for computations.) This is a -one-argument macro, working 'in-place'.

    +

    Reduces the internal representations of the coefficients to +their lowest terms.

    -

    \PolReduceCoeffs*{polname}

    -
    -

    This starred variant leaves un-touched the decimal exponent in the -internal representation of the fractional coefficients, i.e. if a -coefficient is internally A/B[N], then A/B is reduced to -smallest terms, but the 10^N part is kept as is. Note: if the -polynomial is freshly defined directly via \PolFromCSV its coefficients might still be internally in some -format like 1.5e7; the macro will anyhow always first do the -needed conversion to strict format A/B[N].

    +

    \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 -\PolReduceCoeffs{polname}: as the numerators and denominators -remain smaller, this proves very beneficial in favorable cases -(especially when the coefficients are decimal numbers) to the -expansion speed of the xintfrac macros used internally by -\PolEval.

    +\PolReduceCoeffs{<polname>}: as the numerators and denominators +remain generally smaller.

    -

    \PolMakeMonic{polname}

    +

    \PolMakeMonic{<polname>}

    Divides by the leading coefficient. It is recommended to execute -\PolReduceCoeffs*{polname} immediately afterwards. This is not -done automatically, due to the case the original polynomial had integer -coefficients and we want to keep the leading one as common -denominator.

    +\PolReduceCoeffs*{<polname>} 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{polname}

    +

    \PolMakePrimitive{<polname>}

    -

    Divides by the integer content see (\PolIContent). This thus produces a polynomial with integer +

    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.

    -
    -
    -

    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.

    -
    -

    All these macros expand completely in two steps except \PolToExpr -and \PolToFloatExpr (and their auxiliaries) which need a -\write, \edef or a \csname...\endcsname context.

    -
    -

    \PolEval{polname}\AtExpr{numerical expression}

    -
    -

    It boils down to -\xinttheexpr polname(numerical expression)\relax.

    -
    -
    -
    -

    \PolEval{polname}\At{fraction}

    +
    +

    \PolDiff{<polname_1>}{<polname_2>}

    -

    Evaluates the polynomial at value fraction which must be in (or -expand to) a format acceptable to the xintfrac macros.

    +

    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.)

    -
    -

    \PolEvalReduced{polname}\AtExpr{numerical expression}

    +
    +

    \PolDiff[N]{<polname_1>}{<polname_2>}

    -

    Boils down to \xinttheexpr reduce(polname(numerical expression))\relax.

    +

    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.

    -
    -

    \PolEvalReduced{polname}\At{fraction}

    +
    +

    \PolAntiDiff{<polname_1>}{<polname_2>}

    -

    Evaluates the polynomial at value fraction which must be in (or -expand to) a format acceptable to the xintfrac macros, and produce -an irreducible fraction.

    +

    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.)

    -
    -

    \PolFloatEval{polname}\AtExpr{numerical expression}

    +
    +

    \PolAntiDiff[N]{<polname_1>}{<polname_2>}

    -

    Boils down to \xintthefloatexpr polname(numerical expression)\relax.

    -

    This is done via a Horner Scheme (see \poldef and -\PolGenFloatVariant{polname}), with already rounded -coefficients. 4 To use the exact coefficients with exactly -executed additions and multiplications, just insert it in the float -expression as in this example: 5

    -
    \xintthefloatexpr 3.27*\xintexpr f(2.53)\relax^2\relax
    -

    The f(2.53) is exactly computed then rounded at the time of -getting raised to the power 2. Moving the ^2 inside, that -operation would also be treated exactly.

    -
    -
    4
    -

    Anyway each floating point operation starts by rounding its -operands to the floating point precision.

    -
    -
    5
    -

    The \xintexpr here could be \xinttheexpr but that -would be less efficient. Cf. xintexpr documentation about -nested expressions.

    -
    -
    +

    This sets polname_2 to the result of N successive integrations on +polname_1. With negative N, it switches to using \PolDiff.

    -
    -

    \PolFloatEval{polname}\At{fraction}

    +
    +

    \PolDivide{<polname_1>}{<polname_2>}{<polname_Q>}{<polname_R>}

    -

    Evaluates the polynomial at value fraction which must be in (or -expand to) a format acceptable to the xintfrac macros, and produces -a floating point number.

    +

    This sets polname_Q and polname_R to be the quotient and +remainder in the Euclidean division of polname_1 by +polname_2.

    -
    -

    \PolIfCoeffIsPlusOrMinusOne{A}{B}

    +
    +

    \PolQuo{<polname_1>}{<polname_2>}{<polname_Q>}

    -

    This macro is a priori undefined.

    -

    It is defined via the default \PolTypesetCmd{raw_coeff} 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 A if the coefficient has been found to be -plus or minus one, and B if not.

    +

    This sets polname_Q to be the quotient in the Euclidean division +of polname_1 by polname_2.

    -
    -

    \PolLeadingCoeff{polname}

    +
    +

    \PolRem{<polname_1>}{<polname_2>}{<polname_R>}

    -

    Expands to the leading coefficient.

    +

    This sets polname_R to be the remainder in the Euclidean division +of polname_1 by polname_2.

    -
    -

    \PolNthCoeff{polname}{number}

    +
    +

    \PolGCD{<polname_1>}{<polname_2>}{<polname_GCD>}

    -

    It expands to the raw N-th coefficient (0/1[0] if the index -number is out of range). With N=-1, -2, ... expands to the -leading coefficients.

    +

    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.

    -
    -

    \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{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.

    -
    +
    +

    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{<pol. expr.>}

    +

    \PolToExpr{<pol. expr.>}

    -

    Produces expandably 6 the string coeff_N*x^N+..., i.e. the +

    Produces expandably 4 the string coeff_N*x^N+..., i.e. the polynomial is using descending powers.

    -
    6
    +
    4

    requires exhaustive expansion, for example as triggered by \write or \edef.

    @@ -3096,14 +3121,14 @@ 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 input.

    -

    \PolToExprInVar

    +

    \PolToExprInVar

    Defaults to x: the letter used as the polynomial indeterminate.

    Recall that declared polynomials are more efficiently used in @@ -3113,14 +3138,14 @@ 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.

    @@ -3128,7 +3153,7 @@ expand to ** for Python compatible output
    -

    \PolToExprCmd{raw_coeff}

    +

    \PolToExprCmd{<raw_coeff>}

    Defaults to \xintPRaw{\xintRawWithZeros{#1}}.

    This means that the coefficient value is printed-out as a fraction @@ -3146,8 +3171,8 @@ so for example 23.007/2 or -

    \PolToExprOneTerm{raw_coeff}{number}

    +
    +

    \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.

    @@ -3156,14 +3181,14 @@ produces the corresponding term in output, such as \PolToExprCaret.

    -
    -

    \PolToExprOneTermStyleA{raw_coeff}{number}

    +
    +

    \PolToExprOneTermStyleA{<raw_coeff>}{<exponent>}

    This holds the default package meaning of \PolToExprOneTerm.

    -
    -

    \PolToExprOneTermStyleB{raw_coeff}{number}

    +
    +

    \PolToExprOneTermStyleB{<raw_coeff>}{<exponent>}

    This holds an alternative meaning, which puts the fractional part of a coefficient after the monomial, i.e. like this:

    @@ -3176,34 +3201,26 @@ To revert to the package default behaviour, issue
    -

    \PolToExprTermPrefix{raw_coeff}

    +

    \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 \PolToExprCmd{raw_coeff} which in case of a +the default for \PolToExprCmd{<raw_coeff>} which in case of a positive coefficient does not output an explicit + prefix.

    -
    -

    \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 -\PolToExpr{<pol. expr.>}.

    -
    -
    -

    \PolToFloatExpr{<pol. expr.>}

    +

    \PolToFloatExpr{<pol. expr.>}

    -

    Similar to \PolToExpr{<pol. expr.>} but using \PolToFloatExprCmd which by default rounds and +

    Similar to \PolToExpr{<pol. expr.>} but using +\PolToFloatExprCmd{<raw_coeff>} which by default rounds and converts the coefficients to floating point format.

    Note

    -

    This is unrelated to \PolGenFloatVariant{polname}: -\PolToFloatExprCmd{raw_coeff} operates on the exact +

    This is unrelated to \PolGenFloatVariant{<polname>}: +\PolToFloatExprCmd{<raw_coeff>} 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 @@ -3211,15 +3228,15 @@ in between).

    Extended at 0.8 to accept general expressions as input.

    -
    -

    \PolToFloatExprOneTerm{raw_coeff}{number}

    +
    +

    \PolToFloatExprOneTerm{<raw_coeff>}{<exponent>}

    -

    Similar to \PolToExprOneTerm. But does not treat +

    Similar to \PolToExprOneTerm{<raw_coeff>}{<exponent>}. But does not treat especially coefficients equal to plus or minus one.

    -

    \PolToFloatExprCmd{raw_coeff}

    +

    \PolToFloatExprCmd{<raw_coeff>}

    The one-argument macro used by \PolToFloatExprOneTerm. It defaults to \xintFloat{#1}.

    @@ -3239,15 +3256,57 @@ in xintfrac raw format.

    -
    -

    \PolToFloatExpr*{<pol. expr.>}

    +
    +

    \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 +\PolToExpr{<pol. expr.>}.

    +
    +
    +
    +

    \PolToFloatExpr*{<pol. expr.>}

    Ascending powers.

    Extended at 0.8 to accept general expressions as input.

    +
    +

    \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{<polname>}

    +
    +

    Expands to the leading coefficient.

    +
    +
    +
    +

    \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{<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.

    +
    +
    -

    \PolToList{polname}

    +

    \PolToList{<polname>}

    Expands to {coeff_0}{coeff_1}...{coeff_N} with N = degree, and coeff_N the leading coefficient @@ -3256,77 +3315,128 @@ empty output.)

    -

    \PolToCSV{polname}

    +

    \PolToCSV{<polname>}

    Expands to coeff_0, coeff_1, coeff_2, ....., coeff_N, starting with constant term and ending with leading coefficient. Converse -to \PolFromCSV.

    +to \PolFromCSV{<polname>}{<csv>}.

    +
    +
    +
    +

    \PolEval{<polname>}\AtExpr{<num. expr.>}

    +
    +

    Same output as +\xinteval{polname(numerical expression)}.

    +
    +
    +
    +

    \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.

    +
    +
    +
    +

    \PolEvalReduced{<polname>}\AtExpr{<num. expr.>}

    +
    +

    Same output as \xinteval{reduce(polname(numerical expression))}.

    +
    +
    +
    +

    \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.

    +
    +
    +
    +

    \PolFloatEval{<polname>}\AtExpr{<num. expr.>}

    +
    +

    Same output as \xintfloateval{polname(numerical expression)}.

    +
    +

    Attention!

    +

    \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: 5

    +
    \xintfloateval{3.27*\xintexpr f(2.53)\relax^2}
    +
    +
    5
    +

    Cf. xintexpr documentation about nested expressions.

    +
    +
    +
    +
    +
    +

    \PolFloatEval{<polname>}\At{<value>}

    +
    +

    Evaluates the polynomial at the value which must be in (or expand +to) a format acceptable to the xintfrac macros.