summaryrefslogtreecommitdiff
path: root/macros/generic
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2021-03-30 03:00:56 +0000
committerNorbert Preining <norbert@preining.info>2021-03-30 03:00:56 +0000
commit93809c868bf15852ddc7b50542713131a5d8c05f (patch)
tree3c741be9d43fdee2f3ecdb17d463deb188d881a8 /macros/generic
parent3c5dd0d2f091e5e866af1de0327171b253ec9178 (diff)
CTAN sync 202103300300
Diffstat (limited to 'macros/generic')
-rw-r--r--macros/generic/polexpr/README.md123
-rw-r--r--macros/generic/polexpr/polexpr.html4086
-rw-r--r--macros/generic/polexpr/polexpr.sty1057
-rw-r--r--macros/generic/polexpr/polexprcore.tex1366
-rw-r--r--macros/generic/polexpr/polexprexpr.tex179
-rw-r--r--macros/generic/polexpr/polexprsturm.tex1775
-rw-r--r--macros/generic/xint/CHANGES.html177
-rw-r--r--macros/generic/xint/README.md8
-rw-r--r--macros/generic/xint/sourcexint.pdfbin1026778 -> 1031328 bytes
-rw-r--r--macros/generic/xint/xint.dtx852
-rw-r--r--macros/generic/xint/xint.pdfbin1006708 -> 1012827 bytes
11 files changed, 9235 insertions, 388 deletions
diff --git a/macros/generic/polexpr/README.md b/macros/generic/polexpr/README.md
new file mode 100644
index 0000000000..b32b8f056d
--- /dev/null
+++ b/macros/generic/polexpr/README.md
@@ -0,0 +1,123 @@
+Package polexpr README
+======================
+
+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.
+
+ \input polexpr.sty
+
+with Plain or other non-LaTeX macro formats, or:
+
+ \usepackage{polexpr}
+
+with the LaTeX macro format.
+
+The package currently requires xintexpr.sty `1.4d` or later.
+
+Abstract
+--------
+
+The package provides a parser `\poldef` of algebraic polynomial
+expressions. As it is based on
+[xintexpr](http://www.ctan.org/pkg/xint)
+the coefficients are allowed to be arbitrary rational numbers.
+
+Once defined, a polynomial is usable by its name either as a numerical
+function in `\xintexpr/\xinteval`, or for additional polynomial
+definitions, or as argument to the package macros. The localization of
+real roots to arbitrary precision as well as the determination of all
+rational roots is implemented via such macros.
+
+Since release `0.8`, polexpr extends the
+[xintexpr](http://www.ctan.org/pkg/xint) syntax to recognize
+polynomials as a new variable type (and not only as functions).
+Functionality which previously was implemented via macros such as the
+computation of a greatest common divisor is now available directly in
+`\xintexpr`, `\xinteval` or `\poldef` via infix or functional syntax.
+
+Releases
+--------
+
+- 0.1 (2018/01/11)
+ Initial release (files README, polexpr.sty).
+- 0.2 (2018/01/14)
+ Documentation moved to polexpr.{txt,html}.
+- 0.3 (2018/01/17)
+ Make polynomials known to `\xintfloatexpr` and improve
+ documentation.
+- 0.3.1 (2018/01/18)
+ Fix two typos in documentation.
+- 0.4 (2018/02/16)
+ - Revert 0.3 automatic generation of floating point variants.
+ - Move CHANGE LOG from README.md to HTML documentation.
+ - A few bug fixes and breaking changes. Please refer to
+ `polexpr.html`.
+ - Main new feature: root localization via [Sturm
+ Theorem](https://en.wikipedia.org/wiki/Sturm%27s_theorem).
+- 0.4.1 (2018/03/01)
+ Synced with xintexpr 1.3.
+- 0.4.2 (2018/03/03)
+ Documentation fix.
+- 0.5 (2018/04/08)
+ - new macros `\PolMakePrimitive` and `\PolIContent`.
+ - main (breaking) change: `\PolToSturm` creates a chain of primitive
+ integer coefficients polynomials.
+- 0.5.1 (2018/04/22)
+ The `'` character can be used in polynomial names.
+- 0.6 (2018/11/20)
+ New feature: multiplicity of roots.
+- 0.7 (2018/12/08), 0.7.1 (bugfix), 0.7.2 (bugfix) (2018/12/09)
+ New feature: finding all rational roots.
+- 0.7.3 (2019/02/04)
+ Bugfix: polynomial names ending in digits caused errors. Thanks to
+ Thomas Söll for report.
+- 0.7.4 (2019/02/12)
+ Bugfix: 20000000000 is too big for \numexpr, shouldn't I know that?
+ Thanks to Jürgen Gilg for report.
+- 0.7.5 (2020/01/31)
+ Synced with xintexpr 1.4. Requires it.
+- 0.8 (2021/03/29)
+ Complete refactoring of the package core for better integration with
+ and enhancement of xintexpr 1.4.
+
+Files of 0.8 release:
+
+- polexpr.sty, polexprcore.tex, polexprexpr.tex, polexprsturm.tex,
+- README.md,
+- polexpr.html (documentation)
+
+Acknowledgments
+---------------
+
+Thanks to Jürgen Gilg whose question about
+[xintexpr](http://www.ctan.org/pkg/xintexpr) usage for differentiating
+polynomials was the initial trigger leading to this package, and to
+Jürgen Gilg and Thomas Söll for testing it on some concrete problems.
+
+License
+-------
+
+Copyright (C) 2018-2021 Jean-François Burnol
+
+See documentation of package [xintexpr](http://www.ctan.org/pkg/xint) for
+contact information.
+
+This Work may be distributed and/or modified under the conditions of the
+LaTeX Project Public License version 1.3c. This version of this license
+is in
+
+> <http://www.latex-project.org/lppl/lppl-1-3c.txt>
+
+and version 1.3 or later is part of all distributions of LaTeX version
+2005/12/01 or later.
+
+This Work has the LPPL maintenance status author-maintained.
+
+The Author of this Work is Jean-François Burnol.
+
+This Work consists of the package files polexpr.sty, polexprcore.tex,
+polexprexpr.tex, polexprsturm.tex, this README.md and polexpr.html.
diff --git a/macros/generic/polexpr/polexpr.html b/macros/generic/polexpr/polexpr.html
new file mode 100644
index 0000000000..81cd2b4b7c
--- /dev/null
+++ b/macros/generic/polexpr/polexpr.html
@@ -0,0 +1,4086 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta charset="utf-8"/>
+<meta name="generator" content="Docutils 0.16: http://docutils.sourceforge.net/" />
+<title>Package polexpr documentation</title>
+<style type="text/css">
+
+/* Minimal style sheet for the HTML output of Docutils. */
+/* */
+/* :Author: Günter Milde, based on html4css1.css by David Goodger */
+/* :Id: $Id: minimal.css 8397 2019-09-20 11:09:34Z milde $ */
+/* :Copyright: © 2015 Günter Milde. */
+/* :License: Released under the terms of the `2-Clause BSD license`_, */
+/* in short: */
+/* */
+/* Copying and distribution of this file, with or without modification, */
+/* are permitted in any medium without royalty provided the copyright */
+/* notice and this notice are preserved. */
+/* */
+/* This file is offered as-is, without any warranty. */
+/* */
+/* .. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause */
+
+/* This CSS2.1_ stylesheet defines rules for Docutils elements without */
+/* HTML equivalent. It is required to make the document semantic visible. */
+/* */
+/* .. _CSS2.1: http://www.w3.org/TR/CSS2 */
+/* .. _validates: http://jigsaw.w3.org/css-validator/validator$link */
+
+/* alignment of text and inline objects inside block objects*/
+.align-left { text-align: left; }
+.align-right { text-align: right; }
+.align-center { clear: both; text-align: center; }
+.align-top { vertical-align: top; }
+.align-middle { vertical-align: middle; }
+.align-bottom { vertical-align: bottom; }
+
+/* titles */
+h1.title, p.subtitle {
+ text-align: center;
+}
+p.topic-title,
+p.sidebar-title,
+p.rubric,
+p.admonition-title,
+p.system-message-title {
+ font-weight: bold;
+}
+h1 + p.subtitle,
+h1 + p.section-subtitle {
+ font-size: 1.6em;
+}
+h2 + p.section-subtitle { font-size: 1.28em; }
+p.subtitle,
+p.section-subtitle,
+p.sidebar-subtitle {
+ font-weight: bold;
+ margin-top: -0.5em;
+}
+p.sidebar-title,
+p.rubric {
+ font-size: larger;
+}
+p.rubric { color: maroon; }
+a.toc-backref {
+ color: black;
+ text-decoration: none; }
+
+/* Warnings, Errors */
+div.caution p.admonition-title,
+div.attention p.admonition-title,
+div.danger p.admonition-title,
+div.error p.admonition-title,
+div.warning p.admonition-title,
+div.system-messages h1,
+div.error,
+span.problematic,
+p.system-message-title {
+ color: red;
+}
+
+/* inline literals */
+span.docutils.literal {
+ font-family: monospace;
+ white-space: pre-wrap;
+}
+/* do not wraph at hyphens and similar: */
+.literal > span.pre { white-space: nowrap; }
+
+/* Lists */
+
+/* compact and simple lists: no margin between items */
+.simple li, .compact li,
+.simple ul, .compact ul,
+.simple ol, .compact ol,
+.simple > li p, .compact > li p,
+dl.simple > dd, dl.compact > dd {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+/* Table of Contents */
+div.topic.contents { margin: 0.5em 0; }
+div.topic.contents ul {
+ list-style-type: none;
+ padding-left: 1.5em;
+}
+
+/* Enumerated Lists */
+ol.arabic { list-style: decimal }
+ol.loweralpha { list-style: lower-alpha }
+ol.upperalpha { list-style: upper-alpha }
+ol.lowerroman { list-style: lower-roman }
+ol.upperroman { list-style: upper-roman }
+
+dt span.classifier { font-style: italic }
+dt span.classifier:before {
+ font-style: normal;
+ margin: 0.5em;
+ content: ":";
+}
+
+/* Field Lists and drivatives */
+/* bold field name, content starts on the same line */
+dl.field-list > dt,
+dl.option-list > dt,
+dl.docinfo > dt,
+dl.footnote > dt,
+dl.citation > dt {
+ font-weight: bold;
+ clear: left;
+ float: left;
+ margin: 0;
+ padding: 0;
+ padding-right: 0.5em;
+}
+/* Offset for field content (corresponds to the --field-name-limit option) */
+dl.field-list > dd,
+dl.option-list > dd,
+dl.docinfo > dd {
+ margin-left: 9em; /* ca. 14 chars in the test examples */
+}
+/* start field-body on a new line after long field names */
+dl.field-list > dd > *:first-child,
+dl.option-list > dd > *:first-child
+{
+ display: inline-block;
+ width: 100%;
+ margin: 0;
+}
+/* field names followed by a colon */
+dl.field-list > dt:after,
+dl.docinfo > dt:after {
+ content: ":";
+}
+
+/* Bibliographic Fields (docinfo) */
+pre.address { font: inherit; }
+dd.authors > p { margin: 0; }
+
+/* Option Lists */
+dl.option-list { margin-left: 1.5em; }
+dl.option-list > dt { font-weight: normal; }
+span.option { white-space: nowrap; }
+
+/* Footnotes and Citations */
+dl.footnote.superscript > dd {margin-left: 1em; }
+dl.footnote.brackets > dd {margin-left: 2em; }
+dl > dt.label { font-weight: normal; }
+a.footnote-reference.brackets:before,
+dt.label > span.brackets:before { content: "["; }
+a.footnote-reference.brackets:after,
+dt.label > span.brackets:after { content: "]"; }
+a.footnote-reference.superscript,
+dl.footnote.superscript > dt.label {
+ vertical-align: super;
+ font-size: smaller;
+}
+dt.label > span.fn-backref { margin-left: 0.2em; }
+dt.label > span.fn-backref > a { font-style: italic; }
+
+/* Line Blocks */
+div.line-block { display: block; }
+div.line-block div.line-block {
+ margin-top: 0;
+ margin-bottom: 0;
+ margin-left: 40px;
+}
+
+/* Figures, Images, and Tables */
+.figure.align-left,
+figure.align-left,
+img.align-left,
+object.align-left,
+table.align-left {
+ margin-right: auto;
+}
+.figure.align-center,
+figure.align-center,
+img.align-center,
+object.align-center,
+table.align-center {
+ margin-left: auto;
+ margin-right: auto;
+}
+.figure.align-right,
+figure.align-right,
+img.align-right,
+object.align-right,
+table.align-right {
+ margin-left: auto;
+}
+.figure.align-center, .figure.align-right,
+figure.align-center, figure.align-right,
+img.align-center, img.align-right,
+object.align-center, object.align-right {
+ display: block;
+}
+/* reset inner alignment in figures and tables */
+.figure.align-left, .figure.align-right,
+figure.align-left, figure.align-right,
+table.align-left, table.align-center, table.align-right {
+ text-align: inherit;
+}
+
+/* Admonitions and System Messages */
+div.admonition,
+div.system-message,
+div.sidebar,
+aside.sidebar {
+ margin: 1em 1.5em;
+ border: medium outset;
+ padding-top: 0.5em;
+ padding-bottom: 0.5em;
+ padding-right: 1em;
+ padding-left: 1em;
+}
+
+/* Sidebar */
+div.sidebar,
+aside.sidebar {
+ width: 30%;
+ max-width: 26em;
+ float: right;
+ clear: right;
+}
+
+/* Text Blocks */
+blockquote,
+div.topic,
+pre.literal-block,
+pre.doctest-block,
+pre.math,
+pre.code {
+ margin-left: 1.5em;
+ margin-right: 1.5em;
+}
+pre.code .ln { color: gray; } /* line numbers */
+
+/* Tables */
+table { border-collapse: collapse; }
+td, th {
+ border-style: solid;
+ border-color: silver;
+ padding: 0 1ex;
+ border-width: thin;
+}
+td > p:first-child, th > p:first-child { margin-top: 0; }
+td > p, th > p { margin-bottom: 0; }
+
+table > caption {
+ text-align: left;
+ margin-bottom: 0.25em
+}
+
+table.borderless td, table.borderless th {
+ border: 0;
+ padding: 0;
+ padding-right: 0.5em /* separate table cells */
+}
+
+/* Document Header and Footer */
+/* div.header, */
+/* header { border-bottom: 1px solid black; } */
+/* div.footer, */
+/* footer { border-top: 1px solid black; } */
+
+/* new HTML5 block elements: set display for older browsers */
+header, section, footer, aside, nav, main, article, figure {
+ display: block;
+}
+
+</style>
+<style type="text/css">
+
+/* CSS31_ style sheet for the output of Docutils HTML writers. */
+/* Rules for easy reading and pre-defined style variants. */
+/* */
+/* :Author: Günter Milde, based on html4css1.css by David Goodger */
+/* :Id: $Id: plain.css 8397 2019-09-20 11:09:34Z milde $ */
+/* :Copyright: © 2015 Günter Milde. */
+/* :License: Released under the terms of the `2-Clause BSD license`_, */
+/* in short: */
+/* */
+/* Copying and distribution of this file, with or without modification, */
+/* are permitted in any medium without royalty provided the copyright */
+/* notice and this notice are preserved. */
+/* */
+/* This file is offered as-is, without any warranty. */
+/* */
+/* .. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause */
+/* .. _CSS3: http://www.w3.org/TR/CSS3 */
+
+
+/* Document Structure */
+/* ****************** */
+
+/* "page layout" */
+body {
+ margin: 0;
+ background-color: #dbdbdb;
+}
+div.document,
+main {
+ line-height:1.3;
+ counter-reset: table;
+ /* counter-reset: figure; */
+ /* avoid long lines --> better reading */
+ /* OTOH: lines should not be too short because of missing hyphenation, */
+ max-width: 50em;
+ padding: 1px 2%; /* 1px on top avoids grey bar above title (mozilla) */
+ margin: auto;
+ background-color: white;
+}
+
+/* Sections */
+
+/* Transitions */
+
+hr.docutils {
+ width: 80%;
+ margin-top: 1em;
+ margin-bottom: 1em;
+ clear: both;
+}
+
+/* Paragraphs */
+/* ========== */
+
+/* vertical space (parskip) */
+p, ol, ul, dl,
+div.line-block,
+div.topic,
+table {
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+}
+p:first-child { margin-top: 0; }
+/* (:last-child is new in CSS 3) */
+p:last-child { margin-bottom: 0; }
+
+h1, h2, h3, h4, h5, h6,
+dl > dd {
+ margin-bottom: 0.5em;
+}
+
+/* Lists */
+/* ===== */
+
+/* Definition Lists */
+
+/* lists nested in definition lists */
+/* (:only-child is new in CSS 3) */
+dd > ul:only-child, dd > ol:only-child { padding-left: 1em; }
+
+/* Description Lists */
+/* styled like in most dictionaries, encyclopedias etc. */
+dl.description > dt {
+ font-weight: bold;
+ clear: left;
+ float: left;
+ margin: 0;
+ padding: 0;
+ padding-right: 0.5em;
+}
+
+/* Field Lists */
+
+/* example for custom field-name width */
+dl.field-list.narrow > dd {
+ margin-left: 5em;
+}
+/* run-in: start field-body on same line after long field names */
+dl.field-list.run-in > dd p {
+ display: block;
+}
+
+/* Bibliographic Fields */
+
+/* generally, bibliographic fields use special definition list dl.docinfo */
+/* but dedication and abstract are placed into "topic" divs */
+div.abstract p.topic-title {
+ text-align: center;
+}
+div.dedication {
+ margin: 2em 5em;
+ text-align: center;
+ font-style: italic;
+}
+div.dedication p.topic-title {
+ font-style: normal;
+}
+
+/* Citations */
+dl.citation dt.label {
+ font-weight: bold;
+}
+span.fn-backref {
+ font-weight: normal;
+}
+
+/* Text Blocks */
+/* =========== */
+
+/* Literal Blocks */
+
+pre.literal-block,
+pre.doctest-block,
+pre.math,
+pre.code {
+ font-family: monospace;
+}
+
+/* Block Quotes */
+
+blockquote > table,
+div.topic > table {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+blockquote p.attribution,
+div.topic p.attribution {
+ text-align: right;
+ margin-left: 20%;
+}
+
+/* Tables */
+/* ====== */
+
+/* th { vertical-align: bottom; } */
+
+table tr { text-align: left; }
+
+/* "booktabs" style (no vertical lines) */
+table.booktabs {
+ border: 0;
+ border-top: 2px solid;
+ border-bottom: 2px solid;
+ border-collapse: collapse;
+}
+table.booktabs * {
+ border: 0;
+}
+table.booktabs th {
+ border-bottom: thin solid;
+}
+
+/* numbered tables (counter defined in div.document) */
+table.numbered > caption:before {
+ counter-increment: table;
+ content: "Table " counter(table) ": ";
+ font-weight: bold;
+}
+
+/* Explicit Markup Blocks */
+/* ====================== */
+
+/* Footnotes and Citations */
+/* ----------------------- */
+
+/* line on the left */
+dl.footnote {
+ padding-left: 1ex;
+ border-left: solid;
+ border-left-width: thin;
+}
+
+/* Directives */
+/* ---------- */
+
+/* Body Elements */
+/* ~~~~~~~~~~~~~ */
+
+/* Images and Figures */
+
+/* let content flow to the side of aligned images and figures */
+.figure.align-left,
+figure.align-left,
+img.align-left,
+object.align-left {
+ display: block;
+ clear: left;
+ float: left;
+ margin-right: 1em;
+}
+.figure.align-right,
+figure.align-right,
+img.align-right,
+object.align-right {
+ display: block;
+ clear: right;
+ float: right;
+ margin-left: 1em;
+}
+/* Stop floating sidebars, images and figures at section level 1,2,3 */
+h1, h2, h3 { clear: both; }
+
+/* Sidebar */
+
+/* Move right. In a layout with fixed margins, */
+/* it can be moved into the margin. */
+div.sidebar,
+aside.sidebar {
+ width: 30%;
+ max-width: 26em;
+ margin-left: 1em;
+ margin-right: -2%;
+ background-color: #ffffee;
+}
+
+/* Code */
+
+pre.code { padding: 0.7ex }
+pre.code, code { background-color: #eeeeee }
+pre.code .ln { color: gray; } /* line numbers */
+/* basic highlighting: for a complete scheme, see */
+/* http://docutils.sourceforge.net/sandbox/stylesheets/ */
+pre.code .comment, code .comment { color: #5C6576 }
+pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
+pre.code .literal.string, code .literal.string { color: #0C5404 }
+pre.code .name.builtin, code .name.builtin { color: #352B84 }
+pre.code .deleted, code .deleted { background-color: #DEB0A1}
+pre.code .inserted, code .inserted { background-color: #A3D289}
+
+/* Math */
+/* styled separately (see math.css for math-output=HTML) */
+
+/* Epigraph */
+/* Highlights */
+/* Pull-Quote */
+/* Compound Paragraph */
+/* Container */
+
+/* can be styled in a custom stylesheet */
+
+/* Document Header and Footer */
+
+footer, header,
+div.footer, div.header {
+ font-size: smaller;
+ clear: both;
+ padding: 0.5em 2%;
+ background-color: #ebebee;
+ border: none;
+}
+
+/* Inline Markup */
+/* ============= */
+
+/* Emphasis */
+/* em */
+/* Strong Emphasis */
+/* strong */
+/* Interpreted Text */
+/* span.interpreted */
+/* Title Reference */
+/* cite */
+
+/* Inline Literals */
+/* possible values: normal, nowrap, pre, pre-wrap, pre-line */
+/* span.docutils.literal { white-space: pre-wrap; } */
+
+/* Hyperlink References */
+a { text-decoration: none; }
+
+/* External Targets */
+/* span.target.external */
+/* Internal Targets */
+/* span.target.internal */
+/* Footnote References */
+/* a.footnote-reference */
+/* Citation References */
+/* a.citation-reference */
+
+</style>
+</head>
+<body>
+<div class="document" id="package-polexpr-documentation">
+<h1 class="title">Package polexpr documentation</h1>
+<p class="subtitle" id="id1">0.8 (2021/03/29)</p>
+
+<div class="contents topic" id="contents">
+<p class="topic-title">Contents</p>
+<ul class="simple">
+<li><p><a class="reference internal" href="#usage" id="id41">Usage</a></p></li>
+<li><p><a class="reference internal" href="#abstract" id="id42">Abstract</a></p></li>
+<li><p><a class="reference internal" href="#prerequisites" id="id43">Prerequisites</a></p></li>
+<li><p><a class="reference internal" href="#quick-syntax-overview" id="id44">Quick syntax overview</a></p></li>
+<li><p><a class="reference internal" href="#the-polexpr-0-8-extensions-to-the-xintexpr-syntax" id="id45">The polexpr <span class="docutils literal">0.8</span> extensions to the <span class="docutils literal">\xintexpr</span> syntax</a></p>
+<ul>
+<li><p><a class="reference internal" href="#warning-about-unstability-of-the-new-syntax" id="id46">Warning about unstability of the new syntax</a></p></li>
+<li><p><a class="reference internal" href="#infix-operators" id="id47">Infix operators <span class="docutils literal">+, <span class="pre">-,</span> *, /, **, ^</span></a></p></li>
+<li><p><a class="reference internal" href="#experimental-infix-operators" id="id48">Experimental infix operators <span class="docutils literal">//, /:</span></a></p></li>
+<li><p><a class="reference internal" href="#comparison-operators" id="id49">Comparison operators <span class="docutils literal">&lt;, &gt;, &lt;=, &gt;=, ==, !=</span></a></p></li>
+<li><p><a class="reference internal" href="#pol-nutple-expression" id="id50"><span class="docutils literal"><span class="pre">pol(&lt;nutple</span> expression&gt;)</span></a></p></li>
+<li><p><a class="reference internal" href="#xinteval-pol-expr" id="id51"><span class="docutils literal"><span class="pre">\xinteval{&lt;pol.</span> <span class="pre">expr.&gt;}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#evalp-pol-expr-pol-expr" id="id52"><span class="docutils literal"><span class="pre">evalp(&lt;pol.</span> <span class="pre">expr.&gt;,</span> &lt;pol. expr&gt;)</span></a></p></li>
+<li><p><a class="reference internal" href="#deg-pol-expr" id="id53"><span class="docutils literal"><span class="pre">deg(&lt;pol.</span> <span class="pre">expr.&gt;)</span></span></a></p></li>
+<li><p><a class="reference internal" href="#coeffs-pol-expr" id="id54"><span class="docutils literal"><span class="pre">coeffs(&lt;pol.</span> <span class="pre">expr.&gt;)</span></span></a></p></li>
+<li><p><a class="reference internal" href="#coeff-pol-expr-num-expr" id="id55"><span class="docutils literal"><span class="pre">coeff(&lt;pol.</span> <span class="pre">expr.&gt;,</span> &lt;num. <span class="pre">expr.&gt;)</span></span></a></p></li>
+<li><p><a class="reference internal" href="#lcoeff-pol-expr" id="id56"><span class="docutils literal"><span class="pre">lcoeff(&lt;pol.</span> <span class="pre">expr.&gt;)</span></span></a></p></li>
+<li><p><a class="reference internal" href="#monicpart-pol-expr" id="id57"><span class="docutils literal"><span class="pre">monicpart(&lt;pol.</span> <span class="pre">expr.&gt;)</span></span></a></p></li>
+<li><p><a class="reference internal" href="#icontent-pol-expr" id="id58"><span class="docutils literal"><span class="pre">icontent(&lt;pol.</span> <span class="pre">expr.&gt;)</span></span></a></p></li>
+<li><p><a class="reference internal" href="#primpart-pol-expr" id="id59"><span class="docutils literal"><span class="pre">primpart(&lt;pol.</span> <span class="pre">expr.&gt;)</span></span></a></p></li>
+<li><p><a class="reference internal" href="#quorem-pol-expr-pol-expr" id="id60"><span class="docutils literal"><span class="pre">quorem(&lt;pol.</span> <span class="pre">expr.&gt;,</span> &lt;pol. <span class="pre">expr.&gt;)</span></span></a></p></li>
+<li><p><a class="reference internal" href="#quo-pol-expr-pol-expr" id="id61"><span class="docutils literal"><span class="pre">quo(&lt;pol.</span> <span class="pre">expr.&gt;,</span> &lt;pol. <span class="pre">expr.&gt;)</span></span></a></p></li>
+<li><p><a class="reference internal" href="#rem-pol-expr-pol-expr" id="id62"><span class="docutils literal"><span class="pre">rem(&lt;pol.</span> <span class="pre">expr.&gt;,</span> &lt;pol. <span class="pre">expr.&gt;)</span></span></a></p></li>
+<li><p><a class="reference internal" href="#prem-pol-expr-1-pol-expr-2" id="id63"><span class="docutils literal"><span class="pre">prem(&lt;pol.</span> expr. 1&gt;, &lt;pol. expr. 2&gt;)</span></a></p></li>
+<li><p><a class="reference internal" href="#divmod-pol-expr-1-pol-expr-2" id="id64"><span class="docutils literal"><span class="pre">divmod(&lt;pol.</span> expr. 1&gt;, &lt;pol. expr. 2&gt;)</span></a></p></li>
+<li><p><a class="reference internal" href="#mod-pol-expr-1-pol-expr-2" id="id65"><span class="docutils literal"><span class="pre">mod(&lt;pol.</span> expr. 1&gt;, &lt;pol. expr. 2&gt;)</span></a></p></li>
+<li><p><a class="reference internal" href="#polgcd-pol-expr-1-pol-expr-2" id="id66"><span class="docutils literal"><span class="pre">polgcd(&lt;pol.</span> expr. 1&gt;, &lt;pol. expr. 2&gt;, <span class="pre">...)</span></span></a></p></li>
+<li><p><a class="reference internal" href="#resultant-pol-expr-1-pol-expr-2" id="id67"><span class="docutils literal"><span class="pre">resultant(&lt;pol.</span> expr. 1&gt;, &lt;pol. expr. 2&gt;)</span></a></p></li>
+<li><p><a class="reference internal" href="#disc-pol-expr" id="id68"><span class="docutils literal"><span class="pre">disc(&lt;pol.</span> <span class="pre">expr.&gt;)</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polpowmod-pol-expr-1-num-expr-pol-expr-2" id="id69"><span class="docutils literal"><span class="pre">polpowmod(&lt;pol.</span> expr. 1&gt;, &lt;num. <span class="pre">expr.&gt;,</span> &lt;pol. expr. 2&gt;)</span></a></p></li>
+<li><p><a class="reference internal" href="#rdcoeffs-pol-expr" id="id70"><span class="docutils literal"><span class="pre">rdcoeffs(&lt;pol.</span> <span class="pre">expr.&gt;)</span></span></a></p></li>
+<li><p><a class="reference internal" href="#rdzcoeffs-pol-expr" id="id71"><span class="docutils literal"><span class="pre">rdzcoeffs(&lt;pol.</span> <span class="pre">expr.&gt;)</span></span></a></p></li>
+<li><p><a class="reference internal" href="#diff1-pol-expr" id="id72"><span class="docutils literal"><span class="pre">diff1(&lt;pol.</span> <span class="pre">expr.&gt;)</span></span></a></p></li>
+<li><p><a class="reference internal" href="#diff2-pol-expr" id="id73"><span class="docutils literal"><span class="pre">diff2(&lt;pol.</span> <span class="pre">expr.&gt;)</span></span></a></p></li>
+<li><p><a class="reference internal" href="#diffn-pol-expr-p-num-expr-n" id="id74"><span class="docutils literal"><span class="pre">diffn(&lt;pol.</span> expr. P&gt;, &lt;num. expr. n&gt;)</span></a></p></li>
+<li><p><a class="reference internal" href="#antider-pol-expr-p" id="id75"><span class="docutils literal"><span class="pre">antider(&lt;pol.</span> expr. P&gt;)</span></a></p></li>
+<li><p><a class="reference internal" href="#intfrom-pol-expr-p-pol-expr-c" id="id76"><span class="docutils literal"><span class="pre">intfrom(&lt;pol.</span> expr. P&gt;, &lt;pol. expr. c&gt;)</span></a></p></li>
+<li><p><a class="reference internal" href="#integral-pol-expr-p-pol-expr-a-pol-expr-b" id="id77"><span class="docutils literal"><span class="pre">integral(&lt;pol.</span> expr. P&gt;, [&lt;pol. expr. a&gt;, &lt;pol. expr. <span class="pre">b&gt;])</span></span></a></p></li>
+</ul>
+</li>
+<li><p><a class="reference internal" href="#examples-of-localization-of-roots" id="id78">Examples of localization of roots</a></p>
+<ul>
+<li><p><a class="reference internal" href="#a-typical-example" id="id79">A typical example</a></p></li>
+<li><p><a class="reference internal" href="#a-degree-four-polynomial-with-nearby-roots" id="id80">A degree four polynomial with nearby roots</a></p></li>
+<li><p><a class="reference internal" href="#the-degree-nine-polynomial-with-0-99-0-999-0-9999-as-triple-roots" id="id81">The degree nine polynomial with 0.99, 0.999, 0.9999 as triple roots</a></p></li>
+<li><p><a class="reference internal" href="#a-degree-five-polynomial-with-three-rational-roots" id="id82">A degree five polynomial with three rational roots</a></p></li>
+<li><p><a class="reference internal" href="#a-mignotte-type-polynomial" id="id83">A Mignotte type polynomial</a></p></li>
+<li><p><a class="reference internal" href="#the-wilkinson-polynomial" id="id84">The Wilkinson polynomial</a></p></li>
+<li><p><a class="reference internal" href="#the-second-wilkinson-polynomial" id="id85">The second Wilkinson polynomial</a></p></li>
+<li><p><a class="reference internal" href="#the-degree-41-polynomial-with-2-1-9-1-8-0-0-1-1-9-2-as-roots" id="id86">The degree 41 polynomial with -2, -1.9, -1.8, ..., 0, 0.1, ..., 1.9, 2 as roots</a></p></li>
+<li><p><a class="reference internal" href="#roots-of-chebyshev-polynomials" id="id87">Roots of Chebyshev polynomials</a></p></li>
+</ul>
+</li>
+<li><p><a class="reference internal" href="#non-expandable-macros" id="id88">Non-expandable macros</a></p>
+<ul>
+<li><p><a class="reference internal" href="#poldef-polname-letter-expression-using-the-letter-as-indeterminate" id="id89"><span class="docutils literal">\poldef <span class="pre">polname(letter):=</span> expression using the letter as indeterminate;</span></a></p></li>
+<li><p><a class="reference internal" href="#poldef-letter-polname-expression-using-the-letter-as-indeterminate" id="id90"><span class="docutils literal"><span class="pre">\PolDef[letter]{polname}{expression</span> using the letter as indeterminate}</span></a></p></li>
+<li><p><a class="reference internal" href="#polgenfloatvariant-polname" id="id91"><span class="docutils literal">\PolGenFloatVariant{polname}</span></a></p></li>
+<li><p><a class="reference internal" href="#pollet-polname-2-polname-1" id="id92"><span class="docutils literal"><span class="pre">\PolLet{polname_2}={polname_1}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polgloballet-polname-2-polname-1" id="id93"><span class="docutils literal"><span class="pre">\PolGlobalLet{polname_2}={polname_1}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polassign-polname-toarray-macro" id="id94"><span class="docutils literal"><span class="pre">\PolAssign{polname}\toarray\macro</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polget-polname-fromarray-macro" id="id95"><span class="docutils literal"><span class="pre">\PolGet{polname}\fromarray\macro</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polfromcsv-polname-csv" id="id96"><span class="docutils literal"><span class="pre">\PolFromCSV{polname}{&lt;csv&gt;}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#poltypeset-pol-expr" id="id97"><span class="docutils literal"><span class="pre">\PolTypeset{&lt;pol.</span> <span class="pre">expr.&gt;}</span></span></a></p>
+<ul>
+<li><p><a class="reference internal" href="#poltypesetcmd-raw-coeff" id="id98"><span class="docutils literal">\PolTypesetCmd{raw_coeff}</span></a></p></li>
+<li><p><a class="reference internal" href="#poltypesetone-raw-coeff" id="id99"><span class="docutils literal">\PolTypesetOne{raw_coeff}</span></a></p></li>
+<li><p><a class="reference internal" href="#id9" id="id100"><span class="docutils literal">\PolTypesetMonomialCmd</span></a></p></li>
+<li><p><a class="reference internal" href="#poltypesetcmdprefix-raw-coeff" id="id101"><span class="docutils literal">\PolTypesetCmdPrefix{raw_coeff}</span></a></p></li>
+</ul>
+</li>
+<li><p><a class="reference internal" href="#id11" id="id102"><span class="docutils literal"><span class="pre">\PolTypeset*{&lt;pol.</span> <span class="pre">expr.&gt;}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#poldiff-polname-1-polname-2" id="id103"><span class="docutils literal"><span class="pre">\PolDiff{polname_1}{polname_2}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#poldiff-n-polname-1-polname-2" id="id104"><span class="docutils literal"><span class="pre">\PolDiff[N]{polname_1}{polname_2}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polantidiff-polname-1-polname-2" id="id105"><span class="docutils literal"><span class="pre">\PolAntiDiff{polname_1}{polname_2}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polantidiff-n-polname-1-polname-2" id="id106"><span class="docutils literal"><span class="pre">\PolAntiDiff[N]{polname_1}{polname_2}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#poldivide-polname-1-polname-2-polname-q-polname-r" id="id107"><span class="docutils literal"><span class="pre">\PolDivide{polname_1}{polname_2}{polname_Q}{polname_R}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polquo-polname-1-polname-2-polname-q" id="id108"><span class="docutils literal"><span class="pre">\PolQuo{polname_1}{polname_2}{polname_Q}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polrem-polname-1-polname-2-polname-r" id="id109"><span class="docutils literal"><span class="pre">\PolRem{polname_1}{polname_2}{polname_R}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polgcd-polname-1-polname-2-polname-gcd" id="id110"><span class="docutils literal"><span class="pre">\PolGCD{polname_1}{polname_2}{polname_GCD}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#non-expandable-macros-related-to-the-root-localization-routines" id="id111">Non-expandable macros related to the root localization routines</a></p>
+<ul>
+<li><p><a class="reference internal" href="#poltosturm-polname-sturmname" id="id112"><span class="docutils literal"><span class="pre">\PolToSturm{polname}{sturmname}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#id13" id="id113"><span class="docutils literal"><span class="pre">\PolToSturm*{polname}{sturmname}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polsettosturmchainsignchangesat-macro-sturmname-fraction" id="id114"><span class="docutils literal"><span class="pre">\PolSetToSturmChainSignChangesAt{\macro}{sturmname}{fraction}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polsettonbofzeroswithin-macro-sturmname-value-a-value-b" id="id115"><span class="docutils literal"><span class="pre">\PolSetToNbOfZerosWithin{\macro}{sturmname}{value_a}{value_b}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polsturmisolatezeros-sturmname" id="id116"><span class="docutils literal">\PolSturmIsolateZeros{sturmname}</span></a></p></li>
+<li><p><a class="reference internal" href="#id15" id="id117"><span class="docutils literal"><span class="pre">\PolSturmIsolateZeros*{sturmname}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#id17" id="id118"><span class="docutils literal"><span class="pre">\PolSturmIsolateZeros**{sturmname}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polsturmisolatezerosandgetmultiplicities-sturmname" id="id119"><span class="docutils literal">\PolSturmIsolateZerosAndGetMultiplicities{sturmname}</span></a></p></li>
+<li><p><a class="reference internal" href="#polsturmisolatezerosgetmultiplicitiesandrationalroots-sturmname" id="id120"><span class="docutils literal">\PolSturmIsolateZerosGetMultiplicitiesAndRationalRoots{sturmname}</span></a></p></li>
+<li><p><a class="reference internal" href="#polsturmisolatezerosandfindrationalroots-sturmname" id="id121"><span class="docutils literal">\PolSturmIsolateZerosAndFindRationalRoots{sturmname}</span></a></p></li>
+<li><p><a class="reference internal" href="#polrefineinterval-sturmname-index" id="id122"><span class="docutils literal"><span class="pre">\PolRefineInterval*{sturmname}{index}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polrefineinterval-n-sturmname-index" id="id123"><span class="docutils literal"><span class="pre">\PolRefineInterval[N]{sturmname}{index}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polensureintervallength-sturmname-index-e" id="id124"><span class="docutils literal"><span class="pre">\PolEnsureIntervalLength{sturmname}{index}{E}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polensureintervallengths-sturmname-e" id="id125"><span class="docutils literal"><span class="pre">\PolEnsureIntervalLengths{sturmname}{E}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polprintintervals-varname-sturmname" id="id126"><span class="docutils literal"><span class="pre">\PolPrintIntervals[varname]{sturmname}</span></span></a></p>
+<ul>
+<li><p><a class="reference internal" href="#polprintintervalsnorealroots" id="id127"><span class="docutils literal">\PolPrintIntervalsNoRealRoots</span></a></p></li>
+<li><p><a class="reference internal" href="#polprintintervalsbeginenv" id="id128"><span class="docutils literal">\PolPrintIntervalsBeginEnv</span></a></p></li>
+<li><p><a class="reference internal" href="#polprintintervalsendenv" id="id129"><span class="docutils literal">\PolPrintIntervalsEndEnv</span></a></p></li>
+<li><p><a class="reference internal" href="#polprintintervalsknownroot" id="id130"><span class="docutils literal">\PolPrintIntervalsKnownRoot</span></a></p></li>
+<li><p><a class="reference internal" href="#polprintintervalsunknownroot" id="id131"><span class="docutils literal">\PolPrintIntervalsUnknownRoot</span></a></p></li>
+<li><p><a class="reference internal" href="#id18" id="id132"><span class="docutils literal">\PolPrintIntervalsPrintExactZero</span></a></p></li>
+<li><p><a class="reference internal" href="#id19" id="id133"><span class="docutils literal">\PolPrintIntervalsPrintLeftEndPoint</span></a></p></li>
+<li><p><a class="reference internal" href="#id20" id="id134"><span class="docutils literal">\PolPrintIntervalsPrintRightEndPoint</span></a></p></li>
+</ul>
+</li>
+<li><p><a class="reference internal" href="#id22" id="id135"><span class="docutils literal"><span class="pre">\PolPrintIntervals*[varname]{sturmname}</span></span></a></p>
+<ul>
+<li><p><a class="reference internal" href="#polprintintervalsprintmultiplicity" id="id136"><span class="docutils literal">\PolPrintIntervalsPrintMultiplicity</span></a></p></li>
+</ul>
+</li>
+</ul>
+</li>
+<li><p><a class="reference internal" href="#polmapcoeffs-macro-polname" id="id137"><span class="docutils literal"><span class="pre">\PolMapCoeffs{\macro}{polname}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polreducecoeffs-polname" id="id138"><span class="docutils literal">\PolReduceCoeffs{polname}</span></a></p></li>
+<li><p><a class="reference internal" href="#id24" id="id139"><span class="docutils literal"><span class="pre">\PolReduceCoeffs*{polname}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polmakemonic-polname" id="id140"><span class="docutils literal">\PolMakeMonic{polname}</span></a></p></li>
+<li><p><a class="reference internal" href="#polmakeprimitive-polname" id="id141"><span class="docutils literal">\PolMakePrimitive{polname}</span></a></p></li>
+</ul>
+</li>
+<li><p><a class="reference internal" href="#expandable-macros" id="id142">Expandable macros</a></p>
+<ul>
+<li><p><a class="reference internal" href="#poleval-polname-atexpr-numerical-expression" id="id143"><span class="docutils literal"><span class="pre">\PolEval{polname}\AtExpr{numerical</span> expression}</span></a></p></li>
+<li><p><a class="reference internal" href="#poleval-polname-at-fraction" id="id144"><span class="docutils literal"><span class="pre">\PolEval{polname}\At{fraction}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polevalreduced-polname-atexpr-numerical-expression" id="id145"><span class="docutils literal"><span class="pre">\PolEvalReduced{polname}\AtExpr{numerical</span> expression}</span></a></p></li>
+<li><p><a class="reference internal" href="#polevalreduced-polname-at-fraction" id="id146"><span class="docutils literal"><span class="pre">\PolEvalReduced{polname}\At{fraction}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polfloateval-polname-atexpr-numerical-expression" id="id147"><span class="docutils literal"><span class="pre">\PolFloatEval{polname}\AtExpr{numerical</span> expression}</span></a></p></li>
+<li><p><a class="reference internal" href="#polfloateval-polname-at-fraction" id="id148"><span class="docutils literal"><span class="pre">\PolFloatEval{polname}\At{fraction}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polifcoeffisplusorminusone-a-b" id="id149"><span class="docutils literal"><span class="pre">\PolIfCoeffIsPlusOrMinusOne{A}{B}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polleadingcoeff-polname" id="id150"><span class="docutils literal">\PolLeadingCoeff{polname}</span></a></p></li>
+<li><p><a class="reference internal" href="#polnthcoeff-polname-number" id="id151"><span class="docutils literal"><span class="pre">\PolNthCoeff{polname}{number}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#poldegree-polname" id="id152"><span class="docutils literal">\PolDegree{polname}</span></a></p></li>
+<li><p><a class="reference internal" href="#policontent-polname" id="id153"><span class="docutils literal">\PolIContent{polname}</span></a></p></li>
+<li><p><a class="reference internal" href="#poltoexpr-pol-expr" id="id154"><span class="docutils literal"><span class="pre">\PolToExpr{&lt;pol.</span> <span class="pre">expr.&gt;}</span></span></a></p>
+<ul>
+<li><p><a class="reference internal" href="#id31" id="id155"><span class="docutils literal">\PolToExprVar</span></a></p></li>
+<li><p><a class="reference internal" href="#poltoexprinvar" id="id156"><span class="docutils literal">\PolToExprInVar</span></a></p></li>
+<li><p><a class="reference internal" href="#id32" id="id157"><span class="docutils literal">\PolToExprTimes</span></a></p></li>
+<li><p><a class="reference internal" href="#poltoexprcaret" id="id158"><span class="docutils literal">\PolToExprCaret</span></a></p></li>
+<li><p><a class="reference internal" href="#poltoexprcmd-raw-coeff" id="id159"><span class="docutils literal">\PolToExprCmd{raw_coeff}</span></a></p></li>
+<li><p><a class="reference internal" href="#poltoexproneterm-raw-coeff-number" id="id160"><span class="docutils literal"><span class="pre">\PolToExprOneTerm{raw_coeff}{number}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#poltoexpronetermstylea-raw-coeff-number" id="id161"><span class="docutils literal"><span class="pre">\PolToExprOneTermStyleA{raw_coeff}{number}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#poltoexpronetermstyleb-raw-coeff-number" id="id162"><span class="docutils literal"><span class="pre">\PolToExprOneTermStyleB{raw_coeff}{number}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#poltoexprtermprefix-raw-coeff" id="id163"><span class="docutils literal">\PolToExprTermPrefix{raw_coeff}</span></a></p></li>
+</ul>
+</li>
+<li><p><a class="reference internal" href="#id34" id="id164"><span class="docutils literal"><span class="pre">\PolToExpr*{&lt;pol.</span> <span class="pre">expr.&gt;}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#poltofloatexpr-pol-expr" id="id165"><span class="docutils literal"><span class="pre">\PolToFloatExpr{&lt;pol.</span> <span class="pre">expr.&gt;}</span></span></a></p>
+<ul>
+<li><p><a class="reference internal" href="#poltofloatexproneterm-raw-coeff-number" id="id166"><span class="docutils literal"><span class="pre">\PolToFloatExprOneTerm{raw_coeff}{number}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#poltofloatexprcmd-raw-coeff" id="id167"><span class="docutils literal">\PolToFloatExprCmd{raw_coeff}</span></a></p></li>
+</ul>
+</li>
+<li><p><a class="reference internal" href="#id38" id="id168"><span class="docutils literal"><span class="pre">\PolToFloatExpr*{&lt;pol.</span> <span class="pre">expr.&gt;}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#poltolist-polname" id="id169"><span class="docutils literal">\PolToList{polname}</span></a></p></li>
+<li><p><a class="reference internal" href="#poltocsv-polname" id="id170"><span class="docutils literal">\PolToCSV{polname}</span></a></p></li>
+<li><p><a class="reference internal" href="#expandable-macros-related-to-the-root-localization-routines" id="id171">Expandable macros related to the root localization routines</a></p>
+<ul>
+<li><p><a class="reference internal" href="#polsturmchainlength-sturmname" id="id172"><span class="docutils literal">\PolSturmChainLength{sturmname}</span></a></p></li>
+<li><p><a class="reference internal" href="#polsturmifzeroexactlyknown-sturmname-index-a-b" id="id173"><span class="docutils literal"><span class="pre">\PolSturmIfZeroExactlyKnown{sturmname}{index}{A}{B}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polsturmisolatedzeroleft-sturmname-index" id="id174"><span class="docutils literal"><span class="pre">\PolSturmIsolatedZeroLeft{sturmname}{index}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polsturmisolatedzeroright-sturmname-index" id="id175"><span class="docutils literal"><span class="pre">\PolSturmIsolatedZeroRight{sturmname}{index}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polsturmisolatedzeromultiplicity-sturmname-index" id="id176"><span class="docutils literal"><span class="pre">\PolSturmIsolatedZeroMultiplicity{sturmname}{index}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polsturmnbofisolatedzeros-sturmname" id="id177"><span class="docutils literal">\PolSturmNbOfIsolatedZeros{sturmname}</span></a></p></li>
+<li><p><a class="reference internal" href="#polsturmnbofrootsof-sturmname-lessthanorequalto-value" id="id178"><span class="docutils literal"><span class="pre">\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualTo{value}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polsturmnbofrootsof-sturmname-lessthanorequaltoexpr-expression" id="id179"><span class="docutils literal"><span class="pre">\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualToExpr{expression}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polsturmnbwithmultofrootsof-sturmname-lessthanorequalto-value" id="id180"><span class="docutils literal"><span class="pre">\PolSturmNbWithMultOfRootsOf{sturmname}\LessThanOrEqualTo{value}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polsturmnbwithmultofrootsof-sturmname-lessthanorequaltoexpr-expression" id="id181"><span class="docutils literal"><span class="pre">\PolSturmNbWithMultOfRootsOf{sturmname}\LessThanOrEqualToExpr{expression}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polsturmnbofrationalroots-sturmname" id="id182"><span class="docutils literal">\PolSturmNbOfRationalRoots{sturmname}</span></a></p></li>
+<li><p><a class="reference internal" href="#polsturmnbofrationalrootswithmultiplicities-sturmname" id="id183"><span class="docutils literal">\PolSturmNbOfRationalRootsWithMultiplicities{sturmname}</span></a></p></li>
+<li><p><a class="reference internal" href="#polsturmrationalroot-sturmname-k" id="id184"><span class="docutils literal"><span class="pre">\PolSturmRationalRoot{sturmname}{k}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polsturmrationalrootindex-sturmname-k" id="id185"><span class="docutils literal"><span class="pre">\PolSturmRationalRootIndex{sturmname}{k}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polsturmrationalrootmultiplicity-sturmname-k" id="id186"><span class="docutils literal"><span class="pre">\PolSturmRationalRootMultiplicity{sturmname}{k}</span></span></a></p></li>
+<li><p><a class="reference internal" href="#polintervalwidth-sturmname-index" id="id187"><span class="docutils literal"><span class="pre">\PolIntervalWidth{sturmname}{index}</span></span></a></p></li>
+</ul>
+</li>
+<li><p><a class="reference internal" href="#expandable-macros-for-use-within-execution-of-polprintintervals" id="id188">Expandable macros for use within execution of <span class="docutils literal">\PolPrintIntervals</span></a></p>
+<ul>
+<li><p><a class="reference internal" href="#polprintintervalsthevar" id="id189"><span class="docutils literal">\PolPrintIntervalsTheVar</span></a></p></li>
+<li><p><a class="reference internal" href="#polprintintervalstheindex" id="id190"><span class="docutils literal">\PolPrintIntervalsTheIndex</span></a></p></li>
+<li><p><a class="reference internal" href="#polprintintervalsthesturmname" id="id191"><span class="docutils literal">\PolPrintIntervalsTheSturmName</span></a></p></li>
+<li><p><a class="reference internal" href="#polprintintervalstheleftendpoint" id="id192"><span class="docutils literal">\PolPrintIntervalsTheLeftEndPoint</span></a></p></li>
+<li><p><a class="reference internal" href="#polprintintervalstherightendpoint" id="id193"><span class="docutils literal">\PolPrintIntervalsTheRightEndPoint</span></a></p></li>
+<li><p><a class="reference internal" href="#polprintintervalsthemultiplicity" id="id194"><span class="docutils literal">\PolPrintIntervalsTheMultiplicity</span></a></p></li>
+</ul>
+</li>
+</ul>
+</li>
+<li><p><a class="reference internal" href="#booleans-with-default-setting-as-indicated" id="id195">Booleans (with default setting as indicated)</a></p>
+<ul>
+<li><p><a class="reference internal" href="#xintverbosefalse" id="id196"><span class="docutils literal">\xintverbosefalse</span></a></p></li>
+<li><p><a class="reference internal" href="#polnewpolverbosefalse" id="id197"><span class="docutils literal">\polnewpolverbosefalse</span></a></p></li>
+<li><p><a class="reference internal" href="#poltypesetallfalse" id="id198"><span class="docutils literal">\poltypesetallfalse</span></a></p></li>
+<li><p><a class="reference internal" href="#poltoexprallfalse" id="id199"><span class="docutils literal">\poltoexprallfalse</span></a></p></li>
+</ul>
+</li>
+<li><p><a class="reference internal" href="#utilies" id="id200">Utilies</a></p>
+<ul>
+<li><p><a class="reference internal" href="#poldectostring-decimal-number" id="id201"><span class="docutils literal">\PolDecToString{decimal number}</span></a></p></li>
+<li><p><a class="reference internal" href="#polexprsetup" id="id202"><span class="docutils literal">\polexprsetup</span></a></p></li>
+</ul>
+</li>
+<li><p><a class="reference internal" href="#technicalities" id="id203">Technicalities</a></p></li>
+<li><p><a class="reference internal" href="#change-log" id="id204">CHANGE LOG</a></p></li>
+<li><p><a class="reference internal" href="#acknowledgments" id="id205">Acknowledgments</a></p></li>
+</ul>
+</div>
+<div class="section" id="usage">
+<h1><a class="toc-backref" href="#id41">Usage</a></h1>
+<p>The package can be used with TeX based formats incorporating the e-TeX
+primitives. The <span class="docutils literal">\expanded</span> primitive available generally since
+TeXLive 2019 is required.</p>
+<pre class="literal-block">\input polexpr.sty</pre>
+<p>with Plain or other non-LaTeX macro formats, or:</p>
+<pre class="literal-block">\usepackage{polexpr}</pre>
+<p>with the LaTeX macro format.</p>
+<p>The package requires <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> <span class="docutils literal">1.4d</span> or later.</p>
+<div class="admonition note">
+<p class="admonition-title">Note</p>
+<p>Until <span class="docutils literal">0.8</span> the package only had a LaTeX interface. As a result,
+parts of this documentation may still give examples using LaTeX syntax such
+as <span class="docutils literal">\newcommand</span>. Please convert to the syntax appropriate to the
+TeX macro format used if needed.</p>
+</div>
+</div>
+<div class="section" id="abstract">
+<h1><a class="toc-backref" href="#id42">Abstract</a></h1>
+<p>The package provides a parser <span class="docutils literal">\poldef</span> of algebraic polynomial
+expressions. As it is based on <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a>
+the coefficients are allowed to be arbitrary rational numbers.</p>
+<p>Once defined, a polynomial is usable by its name either as a numerical
+function in <span class="docutils literal"><span class="pre">\xintexpr/\xinteval</span></span>, or for additional polynomial
+definitions, or as argument to the package macros. The localization of
+real roots to arbitrary precision as well as the determination of all
+rational roots is implemented via such macros.</p>
+<p>Since release <span class="docutils literal">0.8</span>, polexpr extends the <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a>
+syntax to recognize
+polynomials as a new variable type (and not only as functions).
+Functionality which previously was implemented via macros such as the
+computation of a greatest common divisor is now available directly in
+<span class="docutils literal">\xintexpr</span>, <span class="docutils literal">\xinteval</span> or <span class="docutils literal">\poldef</span> via infix or functional
+syntax.</p>
+</div>
+<div class="section" id="prerequisites">
+<h1><a class="toc-backref" href="#id43">Prerequisites</a></h1>
+<ul>
+<li><p>The user must have some understanding of TeX as a macro-expansion
+based programming interface, and in particular of how <span class="docutils literal">\edef</span>
+differs from <span class="docutils literal">\def</span>: functionalities of the package as described in
+the <a class="reference internal" href="#expandable-macros">Expandable macros</a> section are suitable for usage in <span class="docutils literal">\edef</span>,
+<span class="docutils literal">\write</span> or <span class="docutils literal">\xinteval</span> context. At <span class="docutils literal">0.8</span> some of these
+macros have an even more convenient functional interface inside
+<span class="docutils literal">\xinteval</span>, as is described in a <a class="reference internal" href="#polexpr08">dedicated section</a>.</p>
+<p>Despite its name <span class="docutils literal">\poldef</span> is more to be seen as an <span class="docutils literal">\edef</span>
+although it does not define a TeX macro (at user level); and of course
+<span class="docutils literal">\edef</span> would do usually nothing on the typical input parsed by
+<span class="docutils literal">\poldef</span> which generally has no backslash in it: but if this input
+does contain macros, they will then be expanded fully and are supposed to
+produce recognizable syntax elements in this expansion only context.</p>
+<p>Note that the <span class="docutils literal">def</span> in <span class="docutils literal">\poldef</span> reminds us that the macro does
+some assignments hence is not usable in expandable only context. Its
+whole point is rather to define entities which, them, can then be used
+in the expandable only <span class="docutils literal">\xinteval</span> (or <span class="docutils literal">\poldef</span>) context.</p>
+</li>
+<li><p>The user must have some familiarity with <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> and in
+particular must know what <span class="docutils literal">\xintexpr</span>, <span class="docutils literal">\xinttheexpr</span>,
+<span class="docutils literal">\xinteval</span> and <span class="docutils literal">\xintfloatexpr</span>, <span class="docutils literal">\xintthefloatexpr</span>,
+<span class="docutils literal">\xintfloateval</span> mean and what are the good practices with them.</p></li>
+<li><p>The user will become quickly aware that exact computations with
+fractions easily lead to very big ones in very few steps; see
+<a class="reference internal" href="#polreducecoeffs-polname">\PolReduceCoeffs{polname}</a> in this context.</p></li>
+<li><p>Finally, it is mandatory to read the entire documentation before
+starting to use the package.</p></li>
+</ul>
+</div>
+<div class="section" id="quick-syntax-overview">
+<h1><a class="toc-backref" href="#id44">Quick syntax overview</a></h1>
+<p>The syntax is:</p>
+<pre class="literal-block">\poldef polname(x):= expression in variable x;</pre>
+<ul>
+<li><p>In place of <span class="docutils literal">x</span> an arbitrary <em>dummy variable</em> is authorized,
+i.e. per default one <span class="docutils literal">a, .., z, A, .., Z</span> (more letters can be declared
+under Unicode engines).</p></li>
+<li><p><span class="docutils literal">polname</span> consists of letters, digits, and the <span class="docutils literal">_</span> and <span class="docutils literal">'</span>
+characters. It <strong>must</strong> start with a letter: do not use the
+underscore <span class="docutils literal">_</span> as <em>first character</em> of a polynomial name (even
+if of catcode letter). No warning is emitted but dire consequences
+will result.</p>
+<div class="admonition hint">
+<p class="admonition-title">Hint</p>
+<p>The <span class="docutils literal">&#64;</span> is usable too, independently of whether it is of catcode
+letter or other. This has always been the case, but was not
+documented by polexpr prior to <span class="docutils literal">0.8</span>, as the author has never
+found the time to provide some official guidelines on how to name
+temporary variables and the <span class="docutils literal">&#64;</span> is used already as such internally
+to package; time has still not yet been found for <span class="docutils literal">0.8</span> to review
+the situation but it seems reasonable to recommend at any rate to
+restrict usage of <span class="docutils literal">&#64;</span> to scratch variables of defined macros and
+to avoid using it to name document variable.</p>
+</div>
+</li>
+<li><p>The colon before the equality sign is optional and its catcode does
+not matter.</p></li>
+<li><p>The semi-colon at the end of the expression is mandatory. Its catcode
+does not matter if <span class="docutils literal">\poldef</span> is not used inside the argument of
+another macro.</p></li>
+</ul>
+<p>There is an alternative syntax</p>
+<pre class="literal-block">\PolDef[optional letter]{polname}{expression in the letter}</pre>
+<p>Its optional first argument defaults to <span class="docutils literal">x</span>.</p>
+<dl>
+<dt><span class="docutils literal">\poldef <span class="pre">f(x):=</span> 1 - x + quo(x^5,1 - x + x^2);</span></dt>
+<dd><p>defines polynomial <span class="docutils literal">f</span>. The indeterminate <span class="docutils literal">x</span> must be
+only submitted to algebraic operations.</p>
+<p>The <span class="docutils literal">quo()</span> function (new at <span class="docutils literal">0.8</span>) computes the euclidean
+division quotient.</p>
+</dd>
+</dl>
+<div class="admonition important">
+<p class="admonition-title">Important</p>
+<p>For backwards compatibility one can currently also use:</p>
+<pre class="literal-block">\poldef f(x):= 1 - x + x^5/(1 - x + x^2);</pre>
+<p>Due to precedence rules the first operand is <span class="docutils literal">x^5</span>, not of course
+<span class="docutils literal"><span class="pre">1-x+x^5</span></span>.</p>
+<p>Note that <span class="docutils literal"><span class="pre">(1-x^2)/(1-x)</span></span> produces <span class="docutils literal">1+x</span>
+but <span class="docutils literal"><span class="pre">(1/(1-x))*(1-x^2)</span></span> produces zero! One also has to be aware
+of some precedence rules, for example:</p>
+<pre class="literal-block">\poldef k(x):= (x-1)(x-2)(x-3)(x-4)/(x^2-5x+4);</pre>
+<p>does compute a degree 2 polynomial because the tacit multiplication
+ties more than the division operator.</p>
+<p>In short, it is safer to use the <span class="docutils literal">quo()</span> function which avoids
+surprises.</p>
+</div>
+<div class="admonition attention" id="warningtacit">
+<p class="admonition-title">Attention!</p>
+<p>Tacit multiplication means that
+<span class="docutils literal">1/2 x^2</span> skips the space and is treated like <span class="docutils literal"><span class="pre">1/(2*x^2)</span></span>.
+But then it gives zero!</p>
+<p>Thus one must use <span class="docutils literal">(1/2)x^2</span> or <span class="docutils literal">1/2*x^2</span> or
+<span class="docutils literal"><span class="pre">(1/2)*x^2</span></span> for disambiguation: <span class="docutils literal">x - 1/2*x^2 + <span class="pre">1/3*x^3...</span></span>. It is
+simpler to move the denominator to the right: <span class="docutils literal">x - x^2/2 + x^3/3 - ...</span>.</p>
+<p>It is worth noting that <span class="docutils literal"><span class="pre">1/2(x-1)(x-2)</span></span> suffers the same issue:
+<a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a>'s tacit multiplication always &quot;ties more&quot;, hence this
+gets interpreted as <span class="docutils literal"><span class="pre">1/(2*(x-1)*(x-2))</span></span> which gives zero by
+polynomial division. Thus, use in such cases one of
+<span class="docutils literal"><span class="pre">(1/2)(x-1)(x-2)</span></span>, <span class="docutils literal"><span class="pre">1/2*(x-1)(x-2)</span></span> or <span class="docutils literal"><span class="pre">(x-1)(x-2)/2</span></span>.</p>
+</div>
+<div class="admonition warning">
+<p class="admonition-title">Warning</p>
+<p>The package does not currently know rational functions, but in order
+to leave open this as a future possibility, the usage of <span class="docutils literal">/</span> to stand
+for the
+euclidean quotient is <strong>deprecated</strong>.</p>
+<p>Please start using rather the <span class="docutils literal">quo()</span> function. It is possible
+that in a future major relase <span class="docutils literal">A/B</span> with <span class="docutils literal">B</span> a non-scalar will
+raise an error. Or, who knows, rational functions will be
+implemented sometime during the next decades, and then <span class="docutils literal">A/B</span> will
+naturally be the rational function.</p>
+</div>
+<div class="admonition important">
+<p class="admonition-title">Important</p>
+<p><span class="docutils literal">\poldef <span class="pre">P(x):=...;</span></span> defines <span class="docutils literal">P</span> both as a <em>function</em>,
+to be used as:</p>
+<pre class="literal-block">P(..numeric or even polynomial expression..)</pre>
+<p>and as a <em>variable</em> which can used inside polynomial expressions or
+as argument to some polynomial specific functions such as <span class="docutils literal">deg()</span>
+or <span class="docutils literal">polgcd()</span> <a class="footnote-reference brackets" href="#id3" id="id2">1</a>.</p>
+<dl class="footnote brackets">
+<dt class="label" id="id3"><span class="brackets"><a class="fn-backref" href="#id2">1</a></span></dt>
+<dd><p>Functional syntax accepts expressions as arguments; but the
+TeX <strong>macros</strong> described in the documentation, even the
+expandable ones, work only (there are a few exceptions to the
+general rule) with arguments being <em>names of declared
+polynomials</em>.</p>
+</dd>
+</dl>
+<p>One needs to have a clear understanding of the difference between
+<span class="docutils literal">P</span> used a function and <span class="docutils literal">P</span> used as a variable: if <span class="docutils literal">P</span> and
+<span class="docutils literal">Q</span> are both declared polynomials then:</p>
+<pre class="literal-block">(P+Q)(3)% &lt;--- attention!</pre>
+<p>is currently evaluated as <span class="docutils literal"><span class="pre">(P+Q)*3</span></span>, because <span class="docutils literal">P+Q</span> is not known
+as a <em>function</em>, but <em>only as a variable of polynomial type</em>.
+Even worse:</p>
+<pre class="literal-block">(P)(3)% &lt;--- attention!</pre>
+<p>will compute <span class="docutils literal">P*3</span>, because one can not in current <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> syntax
+enclose a function name in parentheses: consequently it is the variable
+which is used here. There is a <em>meager possibility</em> that in future
+some internal changes to <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> would let <span class="docutils literal"><span class="pre">(P)(3)</span></span> actually
+compute <span class="docutils literal">P(3)</span> and <span class="docutils literal"><span class="pre">(P+Q)(3)</span></span> compute <span class="docutils literal">P(3) + Q(3)</span>, but note
+that <span class="docutils literal"><span class="pre">(P)(P)</span></span> will then do <span class="docutils literal">P(P)</span> and not <span class="docutils literal">P*P</span>,
+the latter, current interpretation, looking more
+intuitive. Anyway, do not rely too extensively on tacit <span class="docutils literal">*</span> and use
+explicit <span class="docutils literal"><span class="pre">(P+Q)*(1+2)</span></span> if this is what is intended.</p>
+<p>As an alternative to explicit <span class="docutils literal"><span class="pre">P(3)+Q(3)</span></span> there is <span class="docutils literal">evalp(P+Q,3)</span>.</p>
+</div>
+<dl>
+<dt><span class="docutils literal"><span class="pre">\PolLet{g}={f}</span></span></dt>
+<dd><p>saves a copy of <span class="docutils literal">f</span> under name <span class="docutils literal">g</span>. Also usable without <span class="docutils literal">=</span>.</p>
+<p>Has exactly the same effect as <span class="docutils literal">\poldef <span class="pre">g(x):=f;</span></span> or <span class="docutils literal">\poldef <span class="pre">g(w):=f(w);</span></span>.</p>
+</dd>
+<dt><span class="docutils literal">\poldef <span class="pre">f(z):=</span> f^2;</span></dt>
+<dd><p>redefines <span class="docutils literal">f</span> in terms of itself. Prior to <span class="docutils literal">0.8</span> one needed
+the right hand side to be <span class="docutils literal"><span class="pre">f(z)^2</span></span>. Also, now <span class="docutils literal">sqr(f)</span> is
+possible (also <span class="docutils literal">sqr(f(x))</span> but not <span class="docutils literal"><span class="pre">sqr(f)(x)</span></span>).</p>
+</dd>
+</dl>
+<div class="admonition important">
+<p class="admonition-title">Important</p>
+<p>Note that <span class="docutils literal">f^2(z)</span> or <span class="docutils literal"><span class="pre">sqr(f)(z)</span></span> will give a logical but
+perhaps unexpected result: first <span class="docutils literal">f^2</span> is computed, then the
+opening parenthesis is seen which inserts a tacit multiplication
+<span class="docutils literal">*</span>, so in the end it is as if the input had been <span class="docutils literal">f^2 * z</span>.
+Although <span class="docutils literal">f</span> is both a variable and a function, <span class="docutils literal">f^2</span> is
+computed as a polynomial <em>variable</em> and ceases being a function.</p>
+</div>
+<dl>
+<dt><span class="docutils literal">\poldef <span class="pre">f(T):=</span> f(f);</span></dt>
+<dd><p>again modifies <span class="docutils literal">f</span>. Here it is used both as variable and as
+a function. Prior to <span class="docutils literal">0.8</span> it needed to be <span class="docutils literal">f(f(T))</span>.</p>
+</dd>
+<dt><span class="docutils literal">\poldef <span class="pre">k(z):=</span> <span class="pre">f-g(g^2)^2;</span></span></dt>
+<dd><p>if everybody followed, this should now define the zero polynomial...
+And <span class="docutils literal"><span class="pre">f-sqr(g(sqr(g)))</span></span> computes the same thing.</p>
+<p>We can check this in a typeset document like this:</p>
+<pre class="literal-block">\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</pre>
+</dd>
+<dt><span class="docutils literal">\poldef <span class="pre">f'(x):=</span> diff1(f);</span></dt>
+<dd><p>(new at <span class="docutils literal">0.8</span>)</p>
+</dd>
+<dt><span class="docutils literal"><span class="pre">\PolDiff{f}{f'}</span></span></dt>
+<dd><p>Both set <span class="docutils literal">f'</span> (or any other chosen name) to the derivative
+of <span class="docutils literal">f</span>.</p>
+</dd>
+</dl>
+<div class="admonition important">
+<p class="admonition-title">Important</p>
+<p>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
+<span class="docutils literal"><span class="pre">f'(3)^2</span></span> will not work without a prior definition of <span class="docutils literal">f'</span>.</p>
+<p>But one can now use <span class="docutils literal">diff1(f)</span> for on-the-spot construction with no
+permanent declaration, so here <span class="docutils literal"><span class="pre">evalp(diff1(f),3)^2</span></span>. And
+<span class="docutils literal"><span class="pre">diff1(f)^2</span></span> is same as <span class="docutils literal"><span class="pre">f'^2</span></span>, assuming here <span class="docutils literal">f'</span> was declared
+to be the derived polynomial.</p>
+<p>Notice that the name <span class="docutils literal">diff1()</span> is experimental and may change. Use
+<span class="docutils literal"><span class="pre">\PolDiff{f}{f'}</span></span> as the stable interface.</p>
+</div>
+<dl>
+<dt><span class="docutils literal">\PolTypeset{P}</span></dt>
+<dd><p>Typesets (switching to math mode if in text mode):</p>
+<pre class="literal-block">\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'''} $$</pre>
+<p>See <a class="reference internal" href="#poltypeset">the documentation</a> for the configurability
+via macros.</p>
+<p>Since <span class="docutils literal">0.8</span> <a class="reference internal" href="#poltypeset">\PolTypeset</a> accepts directly an
+expression, it does not have to be a pre-declared polynomial name:</p>
+<pre class="literal-block">\PolTypeset{mul(x-i,i=1..5)}</pre>
+</dd>
+<dt><span class="docutils literal">\PolToExpr{P}</span></dt>
+<dd><p>Expandably (contrarily to <a class="reference internal" href="#poltypeset">\PolTypeset</a>)
+produces <span class="docutils literal">c_n*x^n + ... + c_0</span> starting from the leading
+coefficient. The <span class="docutils literal">+</span> signs are omitted if followed by negative
+coefficients.</p>
+<p>This is useful for console or file output. This syntax is Maple and
+PSTricks <span class="docutils literal">\psplot[algebraic]</span> compatible; and also it is
+compatible with <span class="docutils literal">\poldef</span> input syntax, of course. See
+<a class="reference internal" href="#poltoexprcaret">\PolToExprCaret</a> for configuration of the <span class="docutils literal">^</span>, for example to
+use rather <span class="docutils literal">**</span> for Python syntax compliance.</p>
+<p>Changed at <span class="docutils literal">0.8</span>: the <span class="docutils literal">^</span> in output is by default of catcode 12
+so in a draft document one can use <span class="docutils literal">\PolToExpr{P}</span> inside the
+typesetting flow (without requiring math mode, where the <span class="docutils literal">*</span> would
+be funny and <span class="docutils literal">^12</span> would only put the <span class="docutils literal">1</span> as exponent anyhow;
+but arguably in text mode the <span class="docutils literal">+</span> and <span class="docutils literal">-</span> are not satisfactory
+for math, except sometimes in monospace typeface, and anyhow TeX is
+unable to break the expression across lines, barring special help).</p>
+<p>See <a class="reference internal" href="#poltoexpr-pol-expr">\PolToExpr{&lt;pol. expr.&gt;}</a> and related macros for customization.</p>
+<p>Extended at <span class="docutils literal">0.8</span> to accept as argument not only the name of a
+polynomial variable but more generally any polynomial expression.</p>
+</dd>
+</dl>
+</div>
+<div class="section" id="the-polexpr-0-8-extensions-to-the-xintexpr-syntax">
+<span id="polexpr08"></span><h1><a class="toc-backref" href="#id45">The polexpr <span class="docutils literal">0.8</span> extensions to the <span class="docutils literal">\xintexpr</span> syntax</a></h1>
+<p>All the syntax elements described in this section can be used in the
+<span class="docutils literal"><span class="pre">\xintexpr/\xinteval</span></span> context (where polynomials can be obtained from
+the <span class="docutils literal"><span class="pre">pol([])</span></span> constructor, once polexpr is loaded): their usage is
+not limited to only <span class="docutils literal">\poldef</span> context.</p>
+<div class="admonition note">
+<p class="admonition-title">Note</p>
+<p>If a variable <span class="docutils literal">myPol</span> defined via <span class="docutils literal">\xintdefvar</span> turns out
+to be a polynomial, the difference with those declared via <span class="docutils literal">\poldef</span>
+will be:</p>
+<ol class="arabic">
+<li><p><span class="docutils literal">myPol</span> is not usable as <em>function</em>, but only as a variable.
+Attention that <span class="docutils literal">f(x)</span> if <span class="docutils literal">f</span> is only a variable (even a
+polynomial one) will actually compute <span class="docutils literal">f * x</span>.</p></li>
+<li><p><span class="docutils literal">myPol</span> is not known to the polexpr package, hence for example the
+macros to achieve localization of its roots are unavailable.</p>
+<p>In a parallel universe I perhaps have implemented this expandably
+which means it could then be accessible with syntax such as
+<span class="docutils literal"><span class="pre">rightmostroot(pol([42,1,34,2,-8,1]))</span></span> but...</p>
+</li>
+</ol>
+</div>
+<div class="section" id="warning-about-unstability-of-the-new-syntax">
+<h2><a class="toc-backref" href="#id46">Warning about unstability of the new syntax</a></h2>
+<div class="admonition warning">
+<p class="admonition-title">Warning</p>
+<p>Consider the entirety of this section as <strong>UNSTABLE</strong> and
+<strong>EXPERIMENTAL</strong> (except perhaps regarding <span class="docutils literal">+</span>, <span class="docutils literal">-</span> and <span class="docutils literal">*</span>).</p>
+<p>And this applies even to items not explicitly flagged with one of
+<strong>unstable</strong>, <strong>Unstable</strong>, or <strong>UNSTABLE</strong> which only reflect that
+documentation was written over a period of time exceeding one minute,
+enough for the author mood changes to kick in.</p>
+<p>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.</p>
+</div>
+</div>
+<div class="section" id="infix-operators">
+<h2><a class="toc-backref" href="#id47">Infix operators <span class="docutils literal">+, <span class="pre">-,</span> *, /, **, ^</span></a></h2>
+<blockquote>
+<p>As has been explained in the <a class="reference internal" href="#quick-syntax-overview">Quick syntax overview</a> these infix
+operators have been made polynomial aware, not only in the
+<span class="docutils literal">\poldef</span> context, but generally in any <span class="docutils literal"><span class="pre">\xintexpr/\xinteval</span></span>
+context, inclusive of <span class="docutils literal">\xintdeffunc</span>.</p>
+<p>Conversely functions declared via <span class="docutils literal">\xintdeffunc</span> and making use of
+these operators will automatically be able to accept polynomials
+declared from <span class="docutils literal">\poldef</span> as variables.</p>
+<p>Usage of <span class="docutils literal">/</span> for euclidean division of polynomials is <strong>deprecated</strong>.
+Only in case of a scalar denominator is it to be considered stable.
+Please use rather <span class="docutils literal">quo()</span>.</p>
+</blockquote>
+<div class="admonition warning">
+<p class="admonition-title">Warning</p>
+<p>The <span class="docutils literal">pow(x,a)</span> function of <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> for <span class="docutils literal">x^a</span> with fractional
+<span class="docutils literal">a</span> will not (with current <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> <span class="docutils literal">1.4d</span>) accept a polynomial
+as first variable even if the second argument is an integer.</p>
+<p>It is possible (via <span class="docutils literal">\poormanloghack</span>) to instruct <span class="docutils literal">\xintexpr</span> to
+let <span class="docutils literal"><span class="pre">x**a</span></span> or <span class="docutils literal">x^a</span> be as <span class="docutils literal">pow(x,a)</span>. If this is done <span class="docutils literal">**</span>
+(resp. <span class="docutils literal">^</span>) will become unusable with polynomials (i.e. will create
+a low-level TeX error).</p>
+<p>And vice versa if polexpr gets loaded after the <span class="docutils literal">\poormanloghack</span>
+was used, <span class="docutils literal">**</span> and <span class="docutils literal">^</span> in <span class="docutils literal"><span class="pre">\xintexpr/\xinteval</span></span> will again only
+accept integer powers.</p>
+<p>Thus employ <span class="docutils literal">\poormanloghack</span> for at most one of <span class="docutils literal">**</span> or <span class="docutils literal">^</span>
+in order to keep one of them available for polynomials and integer
+powers.</p>
+</div>
+</div>
+<div class="section" id="experimental-infix-operators">
+<h2><a class="toc-backref" href="#id48">Experimental infix operators <span class="docutils literal">//, /:</span></a></h2>
+<blockquote>
+<p>Here is the tentative behaviour of <span class="docutils literal"><span class="pre">A//B</span></span> according to types:</p>
+<ul class="simple">
+<li><p><span class="docutils literal">A</span> non scalar and <span class="docutils literal">B</span> non scalar: euclidean quotient,</p></li>
+<li><p><span class="docutils literal">A</span> scalar and <span class="docutils literal">B</span> scalar: floored division,</p></li>
+<li><p><span class="docutils literal">A</span> scalar and <span class="docutils literal">B</span> non scalar: produces zero,</p></li>
+<li><p><span class="docutils literal">A</span> non scalar and <span class="docutils literal">B</span> scalar: coefficient per
+coefficient floored division.</p></li>
+</ul>
+<p>This is an <strong>experimental</strong> overloading of the <span class="docutils literal">//</span> and <span class="docutils literal">/:</span>
+from <span class="docutils literal">\xintexpr</span>.</p>
+<p>The behaviour in the last case, but not only, is to be considerd
+<strong>unstable</strong>. The alternative would be for <span class="docutils literal"><span class="pre">A//B</span></span> with <span class="docutils literal">B</span>
+scalar to act as <span class="docutils literal">quo(A,B)</span>. But, we have currently chosen to let
+<span class="docutils literal">//B</span> for a scalar <span class="docutils literal">B</span> 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 <span class="docutils literal">B</span> is non-scalar.</p>
+<p>The <span class="docutils literal">/:</span> operator provides the associated remainder so always
+<span class="docutils literal">A</span> is reconstructed from <span class="docutils literal"><span class="pre">(A//B)*B</span> + <span class="pre">A/:B</span></span>.</p>
+<p>If <span class="docutils literal">:</span> is active character use <span class="docutils literal">/\string:</span> (it is safer to use
+<span class="docutils literal">/\string :</span> if it is not known if <span class="docutils literal">:</span> has catcode other, letter,
+or is active, but note that <span class="docutils literal">/:</span> is fine and needs no precaution if
+<span class="docutils literal">:</span> has catcode letter, it is only an active <span class="docutils literal">:</span> which is
+problematic, like for all other characters possibly used in an
+expression).</p>
+<blockquote>
+<p><strong>UNSTABLE</strong></p>
+<p>As explained above, there are (among other things) hesitations
+about behaviour with <span class="docutils literal">pol2</span> a scalar.</p>
+</blockquote>
+</blockquote>
+</div>
+<div class="section" id="comparison-operators">
+<h2><a class="toc-backref" href="#id49">Comparison operators <span class="docutils literal">&lt;, &gt;, &lt;=, &gt;=, ==, !=</span></a></h2>
+<blockquote>
+<p><strong>NOT YET IMPLEMENTED</strong></p>
+<p>As the internal representation by <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a> and <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> 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 <span class="docutils literal">\pdfstrcmp</span> engine primitive. In fact <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> does not use
+it yet anywhere, even for normalized pure integers, although it could
+speed up signifcantly certain aspects of core arithmetic.</p>
+<p>Equality of polynomials can currently be tested by computing the
+difference, which is a bit costly. And of course the <span class="docutils literal">deg()</span>
+function allows comparing degrees. In this context note the
+following syntax:</p>
+<pre class="literal-block">(deg(Q)) ?? { zero } { non-zero scalar } { non-scalar }</pre>
+<p>for branching.</p>
+</blockquote>
+</div>
+<div class="section" id="pol-nutple-expression">
+<h2><a class="toc-backref" href="#id50"><span class="docutils literal"><span class="pre">pol(&lt;nutple</span> expression&gt;)</span></a></h2>
+<blockquote>
+<p>This converts a nutple <span class="docutils literal"><span class="pre">[c0,c1,...,cN]</span></span> into the polynomial
+variable having these coefficients. Attention that the square
+brackets are <strong>mandatory</strong>, except of course if the argument is
+actually an expression producing such a &quot;nutple&quot;.</p>
+<blockquote>
+<p>Currently, this process will not normalize the coefficients (such
+as reducing to lowest terms), it only trims out the leading zero
+coefficients.</p>
+</blockquote>
+<p>Inside <span class="docutils literal">\xintexpr</span>, this is the only (allowed) way to create ex
+nihilo a polynomial variable; inside <span class="docutils literal">\poldef</span> it is an alternative
+input syntax which is more efficient than typing <span class="docutils literal">c0 + c1 * x + c2 * x^2 + ...</span>.</p>
+</blockquote>
+<div class="admonition important">
+<p class="admonition-title">Important</p>
+<p>Whenever an expression with polynomials collapses to a constant, it
+becomes a scalar. There is currently no distinction during the
+parsing of expressions by <span class="docutils literal">\poldef</span>
+or <span class="docutils literal">\xintexpr</span> between constant polynomial variables and scalar
+variables.</p>
+<p>Naturally, <span class="docutils literal">\poldef</span> can be used to declare a constant polynomial
+<span class="docutils literal">P</span>, then <span class="docutils literal">P</span> 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 <span class="docutils literal">deg()</span> tacitly
+consider scalars to be constant polynomials).</p>
+<p>Notice that we tend to use the vocable &quot;variable&quot; to refer to
+arbitrary expressions used as function arguments, without implying
+that we are actually referring to pre-declared variables in the sense
+of <span class="docutils literal">\xintdefvar</span>.</p>
+</div>
+</div>
+<div class="section" id="xinteval-pol-expr">
+<h2><a class="toc-backref" href="#id51"><span class="docutils literal"><span class="pre">\xinteval{&lt;pol.</span> <span class="pre">expr.&gt;}</span></span></a></h2>
+<blockquote>
+<p>This is documented here for lack of a better place: it evaluates the
+polynomial expression then outputs the &quot;string&quot; <span class="docutils literal"><span class="pre">pol([c0,</span> c1, <span class="pre">...,</span> cN])</span>
+if the degree <span class="docutils literal">N</span> is at least one (and the usual scalar output else).</p>
+<p>The &quot;pol&quot; 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 <span class="docutils literal">\poldef</span> or <span class="docutils literal">\xintexpr</span> at it means basically
+executing <span class="docutils literal"><span class="pre">pol(coeffs(..expression..))</span></span> which is but a convoluted
+way to obtain the same result as <span class="docutils literal"><span class="pre">(..expression..)</span></span> (the
+parentheses delimiting the polynomial expression).</p>
+<p>For example, <span class="docutils literal"><span class="pre">\xinteval{(1+pol([0,1]))^10}</span></span> expands (in two steps)
+to:</p>
+<pre class="literal-block">pol([1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1])</pre>
+<p>You do need loading polexpr for this, else of course <span class="docutils literal"><span class="pre">pol([])</span></span>
+remains unknown to <span class="docutils literal">\xinteval{}</span> as well as the polynomial algebra !
+This example can also be done as
+<span class="docutils literal"><span class="pre">\xinteval{subs((1+x)^10,x=pol([0,1]))}</span></span>.</p>
+<p>I hesitated using as output the polynomial notation as produced by
+<a class="reference internal" href="#poltoexpr">\PolToExpr{}</a>, but finally opted for this.</p>
+</blockquote>
+</div>
+<div class="section" id="evalp-pol-expr-pol-expr">
+<h2><a class="toc-backref" href="#id52"><span class="docutils literal"><span class="pre">evalp(&lt;pol.</span> <span class="pre">expr.&gt;,</span> &lt;pol. expr&gt;)</span></a></h2>
+<blockquote>
+<p>Evaluates the first argument as a polynomial function of the
+second. Usually the second argument will be scalar, but this is not
+required:</p>
+<pre class="literal-block">\poldef K(x):= evalp(-3x^3-5x+1,-27x^4+5x-2);</pre>
+<p>If the first argument is an already declared polynomial <span class="docutils literal">P</span>, use
+rather the functional form <span class="docutils literal">P()</span> (which can accept a numerical as
+well as polynomial argument) as it is more efficient.</p>
+<p>One can also use <span class="docutils literal">subs()</span> syntax <a class="footnote-reference brackets" href="#id5" id="id4">2</a> (see <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> documentation):</p>
+<pre class="literal-block">\poldef K(x):= subs(-3y^3-5y+1, y = -27x^4+5x-2);</pre>
+<p>but the <span class="docutils literal">evalp()</span> will use a Horner evaluation scheme which is
+usually more efficient.</p>
+<dl class="footnote brackets">
+<dt class="label" id="id5"><span class="brackets"><a class="fn-backref" href="#id4">2</a></span></dt>
+<dd><p>by the way Maple uses the opposite, hence wrong, order
+<span class="docutils literal"><span class="pre">subs(x=...,</span> P)</span> but was written before computer science
+reached the <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> heights. However it makes validating
+Maple results by polexpr sometimes cumbersome, but perhaps
+they will update it at some point.</p>
+</dd>
+</dl>
+<blockquote>
+<p><strong>name unstable</strong></p>
+<p><span class="docutils literal">poleval</span>? <span class="docutils literal">evalpol</span>? <span class="docutils literal">peval</span>? <span class="docutils literal">evalp</span>? <span class="docutils literal">value</span>?
+<span class="docutils literal">eval</span>? <span class="docutils literal">evalat</span>? <span class="docutils literal">eval1at2</span>? <span class="docutils literal">evalat2nd</span>?</p>
+<p>Life is so complicated when one asks questions. Not everybody does,
+though, as is amply demonstrated these days.</p>
+<p><strong>syntax unstable</strong></p>
+<p>I am hesitating about permuting the order of the arguments.</p>
+</blockquote>
+</blockquote>
+</div>
+<div class="section" id="deg-pol-expr">
+<h2><a class="toc-backref" href="#id53"><span class="docutils literal"><span class="pre">deg(&lt;pol.</span> <span class="pre">expr.&gt;)</span></span></a></h2>
+<blockquote>
+<p>Computes the degree.</p>
+</blockquote>
+<div class="admonition important">
+<p class="admonition-title">Important</p>
+<p>As <span class="docutils literal">\xintexpr</span> does not yet support infinities, the degree of
+the zero polynomial is <span class="docutils literal"><span class="pre">-1</span></span>. Beware that this breaks additivity
+of degrees, but <span class="docutils literal"><span class="pre">deg(P)&lt;0</span></span> correctly detects the zero polynomial,
+and <span class="docutils literal"><span class="pre">deg(P)&lt;=0</span></span> detects scalars.</p>
+</div>
+</div>
+<div class="section" id="coeffs-pol-expr">
+<h2><a class="toc-backref" href="#id54"><span class="docutils literal"><span class="pre">coeffs(&lt;pol.</span> <span class="pre">expr.&gt;)</span></span></a></h2>
+<blockquote>
+<p>Produces the nutple <span class="docutils literal"><span class="pre">[c0,c1,...,cN]</span></span> of coefficients. The highest
+degree coefficient is always non zero (except for the zero
+polynomial...).</p>
+<blockquote>
+<p><strong>name unstable</strong></p>
+<p>I am considering in particular using <span class="docutils literal">polcoeffs()</span> to avoid
+having to overload <span class="docutils literal">coeffs()</span> in future when matrix type
+will be added to <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a>.</p>
+</blockquote>
+</blockquote>
+</div>
+<div class="section" id="coeff-pol-expr-num-expr">
+<h2><a class="toc-backref" href="#id55"><span class="docutils literal"><span class="pre">coeff(&lt;pol.</span> <span class="pre">expr.&gt;,</span> &lt;num. <span class="pre">expr.&gt;)</span></span></a></h2>
+<blockquote>
+<p>As expected. Produces zero if <span class="docutils literal">n</span> is negative or higher than the
+degree.</p>
+<blockquote>
+<p><strong>name and syntax unstable</strong></p>
+<p>I am hesitating with <span class="docutils literal">coeff(n,pol)</span> syntax and also perhaps
+using <span class="docutils literal">polcoeff()</span> in order to avoid having to overload
+<span class="docutils literal">coeff()</span> when matrix type will be added to <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a>.</p>
+</blockquote>
+</blockquote>
+</div>
+<div class="section" id="lcoeff-pol-expr">
+<h2><a class="toc-backref" href="#id56"><span class="docutils literal"><span class="pre">lcoeff(&lt;pol.</span> <span class="pre">expr.&gt;)</span></span></a></h2>
+<blockquote>
+<p>The leading coefficient.</p>
+</blockquote>
+</div>
+<div class="section" id="monicpart-pol-expr">
+<h2><a class="toc-backref" href="#id57"><span class="docutils literal"><span class="pre">monicpart(&lt;pol.</span> <span class="pre">expr.&gt;)</span></span></a></h2>
+<blockquote>
+<p>Divides by the leading coefficient, except that <span class="docutils literal"><span class="pre">monicpart(0)==0</span></span>.</p>
+<blockquote>
+<p><strong>unstable</strong></p>
+<p>Currently the coefficients are reduced to lowest terms (contrarily
+to legacy behaviour of <a class="reference internal" href="#polmakemonic">\PolMakeMonic</a>), and
+additionally the <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a> <span class="docutils literal">\xintREZ</span> 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.</p>
+</blockquote>
+</blockquote>
+</div>
+<div class="section" id="icontent-pol-expr">
+<h2><a class="toc-backref" href="#id58"><span class="docutils literal"><span class="pre">icontent(&lt;pol.</span> <span class="pre">expr.&gt;)</span></span></a></h2>
+<blockquote>
+<p>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.</p>
+<blockquote>
+<p><strong>name unstable</strong></p>
+<p>Some hesitation with using <span class="docutils literal">content()</span> rather.</p>
+</blockquote>
+</blockquote>
+</div>
+<div class="section" id="primpart-pol-expr">
+<h2><a class="toc-backref" href="#id59"><span class="docutils literal"><span class="pre">primpart(&lt;pol.</span> <span class="pre">expr.&gt;)</span></span></a></h2>
+<blockquote>
+<p>The quotient (except for the zero polynomial) by
+<span class="docutils literal"><span class="pre">icontent(&lt;pol.</span> <span class="pre">expr.&gt;)</span></span>. This is thus a polynomial with
+integer coefficients having <span class="docutils literal">1</span> as greatest common divisor. The
+sign of the leading coefficient is the same as in the original.</p>
+<p>And <span class="docutils literal"><span class="pre">primpart(0)==0</span></span>.</p>
+<p>The trailing zeros of the integer coefficients are extracted
+into a power of ten exponent part, in the internal representation.</p>
+</blockquote>
+</div>
+<div class="section" id="quorem-pol-expr-pol-expr">
+<h2><a class="toc-backref" href="#id60"><span class="docutils literal"><span class="pre">quorem(&lt;pol.</span> <span class="pre">expr.&gt;,</span> &lt;pol. <span class="pre">expr.&gt;)</span></span></a></h2>
+<blockquote>
+<p>Produces a nutple <span class="docutils literal">[Q,R]</span> with <span class="docutils literal">Q</span> the euclidean quotient and
+<span class="docutils literal">R</span> the remainder.</p>
+<blockquote>
+<p><strong>name unstable</strong></p>
+<p><span class="docutils literal">poldiv()</span>?</p>
+</blockquote>
+</blockquote>
+</div>
+<div class="section" id="quo-pol-expr-pol-expr">
+<h2><a class="toc-backref" href="#id61"><span class="docutils literal"><span class="pre">quo(&lt;pol.</span> <span class="pre">expr.&gt;,</span> &lt;pol. <span class="pre">expr.&gt;)</span></span></a></h2>
+<blockquote>
+<p>The euclidean quotient.</p>
+<p>The deprecated <span class="docutils literal">pol1/pol2</span> syntax computes the same polynomial.</p>
+</blockquote>
+</div>
+<div class="section" id="rem-pol-expr-pol-expr">
+<h2><a class="toc-backref" href="#id62"><span class="docutils literal"><span class="pre">rem(&lt;pol.</span> <span class="pre">expr.&gt;,</span> &lt;pol. <span class="pre">expr.&gt;)</span></span></a></h2>
+<blockquote>
+<p>The euclidean remainder. If <span class="docutils literal">pol2</span> is a (non-zero) scalar, this is
+zero.</p>
+<p>There is no infix operator associated to this, for lack of evident
+notation. Please advise.</p>
+<p><span class="docutils literal">/:</span> can be used if one is certain that <span class="docutils literal">pol2</span> is of
+degree at least one. But read the warning about it being unstable
+even in that case.</p>
+</blockquote>
+</div>
+<div class="section" id="prem-pol-expr-1-pol-expr-2">
+<span id="prem"></span><h2><a class="toc-backref" href="#id63"><span class="docutils literal"><span class="pre">prem(&lt;pol.</span> expr. 1&gt;, &lt;pol. expr. 2&gt;)</span></a></h2>
+<blockquote>
+<p>Produces a nutple <span class="docutils literal">[m, spR]</span> where <span class="docutils literal">spR</span> is the (special) pseudo
+Euclidean remainder. Its description is:</p>
+<ul>
+<li><p>the standard euclidean remainder <span class="docutils literal">R</span> is <span class="docutils literal">spR/m</span></p></li>
+<li><p><span class="docutils literal">m = b^f</span> with <span class="docutils literal">b</span> equal to the <strong>absolute value</strong> of the
+leading coefficient of <span class="docutils literal">pol2</span>,</p></li>
+<li><p><span class="docutils literal">f</span> is the number of non-zero coefficients in the euclidean
+quotient, if <span class="docutils literal"><span class="pre">deg(pol2)&gt;0</span></span> (even if the remainder vanishes).</p>
+<p>If <span class="docutils literal">pol2</span> is a scalar however, the function outputs <span class="docutils literal">[1,0]</span>.</p>
+</li>
+</ul>
+<p>With these definitions one can show that if both <span class="docutils literal">pol1</span> and
+<span class="docutils literal">pol2</span> have integer coefficients, then this is also the case of
+<span class="docutils literal">spR</span>, which makes its interest (and also <span class="docutils literal">m*Q</span> has integer
+coefficients, with <span class="docutils literal">Q</span> the euclidean quotient, if <span class="docutils literal"><span class="pre">deg(pol2)&gt;0</span></span>).
+Also, <span class="docutils literal">prem()</span> is computed faster than <span class="docutils literal">rem()</span> for such integer
+coefficients polynomials.</p>
+<div class="admonition hint">
+<p class="admonition-title">Hint</p>
+<p>If you want the euclidean quotient <span class="docutils literal">R</span> evaluated via <span class="docutils literal">spR/m</span>
+(which may be faster, even with non integer coefficients) use
+<span class="docutils literal"><span class="pre">subs(last(x)/first(x),x=prem(P,Q))</span></span> syntax as it avoids
+computing <span class="docutils literal">prem(P,Q)</span> twice. This does the trick both in
+<span class="docutils literal">\poldef</span> or in <span class="docutils literal">\xintdefvar</span>.</p>
+<p>However, as is explained in the <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> documentation, using
+such syntax in an <span class="docutils literal">\xintdeffunc</span> is (a.t.t.o.w) illusory, due to
+technicalities of how <span class="docutils literal">subs()</span> gets converted into nested
+expandable macros. One needs an auxiliary function like this:</p>
+<pre class="literal-block">\xintdeffunc lastoverfirst(x):=last(x)/first(x);
+\xintdeffunc myR(x)=lastoverfirst(prem(x));</pre>
+<p>Then, <span class="docutils literal">myR(pol1,pol2)</span> will evaluate <span class="docutils literal">prem(pol1,pol2)</span> only
+once and compute a polynomial identical to the euclidean
+remainder (internal representations of coefficients may differ).</p>
+</div>
+<p>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 <span class="docutils literal">pol1</span> and <span class="docutils literal">pol2</span> (no automatic reduction to
+lowest terms is made prior or after computation).</p>
+<p>Pay attention here that <span class="docutils literal">b</span> is the <strong>absolute value</strong> of the
+leading coefficient of <span class="docutils literal">pol2</span>. 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.</p>
+</blockquote>
+</div>
+<div class="section" id="divmod-pol-expr-1-pol-expr-2">
+<h2><a class="toc-backref" href="#id64"><span class="docutils literal"><span class="pre">divmod(&lt;pol.</span> expr. 1&gt;, &lt;pol. expr. 2&gt;)</span></a></h2>
+<blockquote>
+<p>Overloads the scalar <span class="docutils literal">divmod()</span> and associates it with the
+experimental <span class="docutils literal">//</span> and <span class="docutils literal">/:</span> as extended to the polynomial type.</p>
+<p>In particular when both <span class="docutils literal">pol1</span> and <span class="docutils literal">pol2</span> are scalars, this is
+the usual <span class="docutils literal">divmod()</span> (as in Python) and for <span class="docutils literal">pol1</span> and <span class="docutils literal">pol2</span>
+non constant polynomials, this is the same as <span class="docutils literal">quorem()</span>.</p>
+<blockquote>
+<p><strong>Highly unstable</strong> overloading of <span class="docutils literal">\xinteval</span>'s <span class="docutils literal">divmod()</span>.</p>
+</blockquote>
+</blockquote>
+</div>
+<div class="section" id="mod-pol-expr-1-pol-expr-2">
+<h2><a class="toc-backref" href="#id65"><span class="docutils literal"><span class="pre">mod(&lt;pol.</span> expr. 1&gt;, &lt;pol. expr. 2&gt;)</span></a></h2>
+<blockquote>
+<p>The <span class="docutils literal">R</span> of the <span class="docutils literal">divmod()</span> output. Same as <span class="docutils literal">R</span> of <span class="docutils literal">quorem()</span>
+when the second argument <span class="docutils literal">pol2</span> is of degree at least one.</p>
+<blockquote>
+<p><strong>Highly unstable</strong> overloading of <span class="docutils literal">\xinteval</span>'s <span class="docutils literal">mod()</span>.</p>
+</blockquote>
+</blockquote>
+</div>
+<div class="section" id="polgcd-pol-expr-1-pol-expr-2">
+<h2><a class="toc-backref" href="#id66"><span class="docutils literal"><span class="pre">polgcd(&lt;pol.</span> expr. 1&gt;, &lt;pol. expr. 2&gt;, <span class="pre">...)</span></span></a></h2>
+<blockquote>
+<p>Evaluates to the greatest common polynomial divisor of all the
+polynomial inputs. The output is a <strong>primitive</strong> (in particular,
+with integer coefficients) polynomial. It is zero if and only if all
+inputs vanish.</p>
+<p>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 &quot;nutple&quot; whose
+items are polynomials (see the documentation of the scalar <span class="docutils literal">gcd()</span>
+in <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a>).</p>
+<blockquote>
+<p>The two variable case could (and was, during development) have been
+defined at user level like this:</p>
+<pre class="literal-block">\xintdeffunc polgcd_(P,Q):=
+ (deg(Q))??{P}{1}{polgcd_(Q,primpart(last(prem(P,Q))))};
+\xintdeffunc polgcd(P,Q):=polgcd_(primpart(P),primpart(Q));%</pre>
+<p>This is basically what is done internally for two polynomials, up
+to some internal optimizations.</p>
+</blockquote>
+<p><strong>UNSTABLE</strong></p>
+<p>I hesitate between returning a <em>primitive</em> or a <em>monic</em> polynomial.
+Maple returns a primitive polynomial if all inputs <a class="footnote-reference brackets" href="#id7" id="id6">3</a> 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.</p>
+<p>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 <span class="docutils literal">monicpart()</span> to it.</p>
+<p>Attention that this is at odds with behaviour of the legacy
+<a class="reference internal" href="#polgcd">\PolGCD</a> (non expandable) macro.</p>
+<dl class="footnote brackets">
+<dt class="label" id="id7"><span class="brackets"><a class="fn-backref" href="#id6">3</a></span></dt>
+<dd><p>actually, only two polynomial arguments are allowed by Maple's
+<span class="docutils literal">gcd()</span> as far as I know.</p>
+</dd>
+</dl>
+</blockquote>
+</div>
+<div class="section" id="resultant-pol-expr-1-pol-expr-2">
+<h2><a class="toc-backref" href="#id67"><span class="docutils literal"><span class="pre">resultant(&lt;pol.</span> expr. 1&gt;, &lt;pol. expr. 2&gt;)</span></a></h2>
+<blockquote>
+<p>The resultant.</p>
+<blockquote>
+<p><strong>NOT YET IMPLEMENTED</strong></p>
+</blockquote>
+</blockquote>
+</div>
+<div class="section" id="disc-pol-expr">
+<h2><a class="toc-backref" href="#id68"><span class="docutils literal"><span class="pre">disc(&lt;pol.</span> <span class="pre">expr.&gt;)</span></span></a></h2>
+<blockquote>
+<p>The discriminant.</p>
+<blockquote>
+<p><strong>NOT YET IMPLEMENTED</strong></p>
+</blockquote>
+</blockquote>
+</div>
+<div class="section" id="polpowmod-pol-expr-1-num-expr-pol-expr-2">
+<h2><a class="toc-backref" href="#id69"><span class="docutils literal"><span class="pre">polpowmod(&lt;pol.</span> expr. 1&gt;, &lt;num. <span class="pre">expr.&gt;,</span> &lt;pol. expr. 2&gt;)</span></a></h2>
+<blockquote>
+<p>Modular exponentiation: <span class="docutils literal">mod(pol1^N, pol2)</span> in a more efficient
+manner than first computing <span class="docutils literal">pol1^N</span> then reducing modulo <span class="docutils literal">pol2</span>.</p>
+<p>Attention that this is using the <span class="docutils literal">mod()</span> operation, whose current
+experimental status is as follows:</p>
+<ul class="simple">
+<li><p>if <span class="docutils literal"><span class="pre">deg(pol2)&gt;0</span></span>, the euclidean remainder operation,</p></li>
+<li><p>if <span class="docutils literal">pol2</span> is a scalar, coefficient-wise reduction modulo <span class="docutils literal">pol2</span>.</p></li>
+</ul>
+<p><strong>UNSTABLE</strong></p>
+<blockquote>
+<p>This is currently implemented at high level via <span class="docutils literal">\xintdeffunc</span> and
+recursive definitions, which were copied over from a scalar example
+in the <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> manual:</p>
+<pre class="literal-block">\xintdeffunc polpowmod_(P, m, Q) :=
+ isone(m)?
+ % m=1: return P modulo Q
+ { mod(P,Q) }
+ % m &gt; 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};%</pre>
+<p>Negative exponents are not currently implemented.</p>
+<p>For example:</p>
+<pre class="literal-block">\xinteval{subs(polpowmod(1+x,100,x^7),x=pol([0,1]))}
+\xinteval{subs(polpowmod(1+x,20,10), x=pol([0,1]))}</pre>
+<p>produce respectively:</p>
+<pre class="literal-block">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])</pre>
+</blockquote>
+</blockquote>
+</div>
+<div class="section" id="rdcoeffs-pol-expr">
+<h2><a class="toc-backref" href="#id70"><span class="docutils literal"><span class="pre">rdcoeffs(&lt;pol.</span> <span class="pre">expr.&gt;)</span></span></a></h2>
+<blockquote>
+<p>This operates on the internal representation of the coefficients,
+reducing them to lowest terms.</p>
+<blockquote>
+<p><strong>name HIGHLY undecided</strong></p>
+</blockquote>
+</blockquote>
+</div>
+<div class="section" id="rdzcoeffs-pol-expr">
+<h2><a class="toc-backref" href="#id71"><span class="docutils literal"><span class="pre">rdzcoeffs(&lt;pol.</span> <span class="pre">expr.&gt;)</span></span></a></h2>
+<blockquote>
+<p>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.</p>
+<p>This is sometimes favourable to more efficient polynomial algebra
+computations.</p>
+<blockquote>
+<p><strong>name HIGHLY undecided</strong></p>
+</blockquote>
+</blockquote>
+</div>
+<div class="section" id="diff1-pol-expr">
+<h2><a class="toc-backref" href="#id72"><span class="docutils literal"><span class="pre">diff1(&lt;pol.</span> <span class="pre">expr.&gt;)</span></span></a></h2>
+<blockquote>
+<p>The first derivative.</p>
+<blockquote>
+<p><strong>name UNSTABLE</strong></p>
+<p>This name may be used in future to be the partial derivative with
+respect to a first variable.</p>
+</blockquote>
+</blockquote>
+</div>
+<div class="section" id="diff2-pol-expr">
+<h2><a class="toc-backref" href="#id73"><span class="docutils literal"><span class="pre">diff2(&lt;pol.</span> <span class="pre">expr.&gt;)</span></span></a></h2>
+<blockquote>
+<p>The second derivative.</p>
+<blockquote>
+<p><strong>name UNSTABLE</strong></p>
+<p>This name may be used in future to be the partial derivative with
+respect to a second variable.</p>
+</blockquote>
+</blockquote>
+</div>
+<div class="section" id="diffn-pol-expr-p-num-expr-n">
+<h2><a class="toc-backref" href="#id74"><span class="docutils literal"><span class="pre">diffn(&lt;pol.</span> expr. P&gt;, &lt;num. expr. n&gt;)</span></a></h2>
+<blockquote>
+<p>The <span class="docutils literal">n</span>th derivative of <span class="docutils literal">P</span>. For <span class="docutils literal">n&lt;0</span> computes iterated primitives
+vanishing at the origin.</p>
+<p>The coefficients are not reduced to lowest terms.</p>
+<blockquote>
+<p><strong>name and syntax UNSTABLE</strong></p>
+<p>I am also considering reversing the order of the arguments.</p>
+</blockquote>
+</blockquote>
+</div>
+<div class="section" id="antider-pol-expr-p">
+<h2><a class="toc-backref" href="#id75"><span class="docutils literal"><span class="pre">antider(&lt;pol.</span> expr. P&gt;)</span></a></h2>
+<blockquote>
+<p>The primitive of <span class="docutils literal">P</span> with no constant term. Same as <span class="docutils literal"><span class="pre">diffn(P,-1)</span></span>.</p>
+</blockquote>
+</div>
+<div class="section" id="intfrom-pol-expr-p-pol-expr-c">
+<h2><a class="toc-backref" href="#id76"><span class="docutils literal"><span class="pre">intfrom(&lt;pol.</span> expr. P&gt;, &lt;pol. expr. c&gt;)</span></a></h2>
+<blockquote>
+<p>The primitive of <span class="docutils literal">P</span> vanishing at <span class="docutils literal">c</span>, i.e. <span class="docutils literal">\int_c^x P(t)dt</span>.</p>
+<p>Also <span class="docutils literal">c</span> can be a polynomial... so if <span class="docutils literal">c</span> is monomial <span class="docutils literal">x</span>
+this will give zero!</p>
+<blockquote>
+<p><strong>UNSTABLE</strong></p>
+<p>Allowing general polynomial variable for <span class="docutils literal">c</span> adds a bit of
+overhead to the case of a pure scalar. So I am hesitating
+maintaining this feature whose interest appears dubious.</p>
+</blockquote>
+</blockquote>
+</div>
+<div class="section" id="integral-pol-expr-p-pol-expr-a-pol-expr-b">
+<h2><a class="toc-backref" href="#id77"><span class="docutils literal"><span class="pre">integral(&lt;pol.</span> expr. P&gt;, [&lt;pol. expr. a&gt;, &lt;pol. expr. <span class="pre">b&gt;])</span></span></a></h2>
+<blockquote>
+<p><span class="docutils literal">\int_a^b P(t)dt</span>.</p>
+<p>The brackets here are not denoting an optional argument
+but a <em>mandatory</em> nutple argument <span class="docutils literal">[a, b]</span> with <em>two items</em>.</p>
+<p><span class="docutils literal">a</span> and <span class="docutils literal">b</span> are not restricted to be scalars, they can be
+polynomials.</p>
+<blockquote>
+<p>To compute <span class="docutils literal"><span class="pre">\int_{x-1}^x</span> P(t)dt</span> it is more efficient to use
+<span class="docutils literal"><span class="pre">intfrom(x-1)</span></span>.</p>
+<p>Similary to compute <span class="docutils literal"><span class="pre">\int_x^{x+1}</span> P(t)dt</span>, use <span class="docutils literal"><span class="pre">-intfrom(x+1)</span></span>.</p>
+<p><strong>UNSTABLE</strong></p>
+<p>Am I right to allow general polynomials <span class="docutils literal">a</span> and <span class="docutils literal">b</span> hence add
+overhead to the pure scalar case ?</p>
+</blockquote>
+</blockquote>
+</div>
+</div>
+<div class="section" id="examples-of-localization-of-roots">
+<h1><a class="toc-backref" href="#id78">Examples of localization of roots</a></h1>
+<div class="admonition note">
+<p class="admonition-title">Note</p>
+<p>As of <span class="docutils literal">0.8</span>, <span class="docutils literal">polexpr</span> is usable with Plain TeX and not only with
+LaTeX, the examples of this section have been converted to use a
+syntax which (at least at time of writing, March 2021) works in both.</p>
+<p>This is done in order for the examples to be easy to copy-paste to
+documents using either macro format.</p>
+</div>
+<ul>
+<li><p>To make printed decimal numbers more enjoyable than via
+<span class="docutils literal">\xintSignedFrac</span> (or <span class="docutils literal">\xintSignedFwOver</span> with Plain):</p>
+<pre class="literal-block">\def\PolTypesetOne#1{\PolDecToString{\xintREZ{#1}}}%</pre>
+<p><span class="docutils literal">\PolDecToString</span> will use decimal notation to incorporate the power
+of ten part; and the <span class="docutils literal">\xintREZ</span> will have the effect to suppress
+trailing zeros if present in raw numerator (if those digits end up
+after decimal mark.) Notice that the above are expandable macros and
+that one can also do:</p>
+<pre class="literal-block">\def\PolToExprCmd#1{\PolDecToString{\xintREZ{#1}}}%</pre>
+<p>to modify output of <a class="reference internal" href="#poltoexpr-pol-expr">\PolToExpr{&lt;pol. expr.&gt;}</a>.</p>
+</li>
+<li><p>For extra info in log file use <span class="docutils literal">\xintverbosetrue</span>.</p></li>
+</ul>
+<div class="section" id="a-typical-example">
+<h2><a class="toc-backref" href="#id79">A typical example</a></h2>
+<p>In this example the polynomial is square-free.</p>
+<pre class="literal-block">\poldef f(x) := x^7 - x^6 - 2x + 1;
+
+\PolToSturm{f}{f}
+\PolSturmIsolateZeros{f}
+The \PolTypeset{f} polynomial has \PolSturmNbOfIsolatedZeros{f} distinct real
+roots which are located in the following intervals:
+\PolPrintIntervals{f}
+Here is the second root with ten more decimal digits:
+\PolRefineInterval[10]{f}{2}
+$$\PolSturmIsolatedZeroLeft{f}{2}&lt;Z_2&lt;\PolSturmIsolatedZeroRight{f}{2}$$
+And here is the first root with twenty digits after decimal mark:
+\PolEnsureIntervalLength{f}{1}{-20}
+$$\PolSturmIsolatedZeroLeft{f}{1}&lt;Z_1&lt;\PolSturmIsolatedZeroRight{f}{1}$$
+The first element of the Sturm chain has degree $\PolDegree{f_0}$. As
+this is the original degreee $\PolDegree{f}$ we know that $f$ is square free.
+Its derivative is up to a constant \PolTypeset{f_1} (in this example
+it is identical with it).
+\PolToSturm{f_1}{f_1}\PolSturmIsolateZeros{f_1}%
+The derivative has \PolSturmNbOfIsolatedZeros{f_1} distinct real
+roots:
+\PolPrintIntervals[W]{f_1}
+\PolEnsureIntervalLengths{f_1}{-10}%
+Here they are with ten digits after decimal mark:
+\PolPrintIntervals[W]{f_1}
+\PolDiff{f_1}{f''}
+\PolToSturm{f''}{f''}
+\PolSturmIsolateZeros{f''}
+The second derivative is \PolTypeset{f''}.
+It has \PolSturmNbOfIsolatedZeros{f''} distinct real
+roots:
+\PolPrintIntervals[X]{f''}
+Here is the positive one with 20 digits after decimal mark:
+\PolEnsureIntervalLength{f''}{2}{-20}%
+$$X_2 = \PolSturmIsolatedZeroLeft{f''}{2}\dots$$
+The more mathematically advanced among our dear readers will be able
+to give the exact value for $X_2$!</pre>
+</div>
+<div class="section" id="a-degree-four-polynomial-with-nearby-roots">
+<h2><a class="toc-backref" href="#id80">A degree four polynomial with nearby roots</a></h2>
+<p>Notice that this example is a bit outdated as <span class="docutils literal">0.7</span> release has
+added <span class="docutils literal"><span class="pre">\PolSturmIsolateZeros**{sturmname}</span></span> 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.</p>
+<pre class="literal-block">\PolDef{Q}{(x-1.050001)(x-1.105001)(x-1.110501)(x-1.111051)}
+\PolTypeset{Q}
+\PolToSturm{Q}{Q} % it is allowed to use same prefix for Sturm chain
+\PolSturmIsolateZeros{Q}
+\PolPrintIntervals{Q}
+% reports 1.0 &lt; Z_1 &lt; 1.1, 1.10 &lt; Z_2 &lt; 1.11, 1.110 &lt; Z_3 &lt; 1.111, and 1.111 &lt; Z_4 &lt; 1.112
+% but the above bounds do not allow minimizing separation between roots
+% so we refine:
+\PolRefineInterval*{Q}{1}
+\PolRefineInterval*{Q}{2}
+\PolRefineInterval*{Q}{3}
+\PolRefineInterval*{Q}{4}
+\PolPrintIntervals{Q}
+% reports 1.05 &lt; Z_1 &lt; 1.06, 1.105 &lt; Z_2 &lt; 1.106, 1.1105 &lt; Z_3 &lt; 1.1106,
+% and 1.11105 &lt; Z_4 &lt; 1.11106.
+\PolEnsureIntervalLengths{Q}{-6}
+\PolPrintIntervals{Q}
+% of course finds here all roots exactly</pre>
+</div>
+<div class="section" id="the-degree-nine-polynomial-with-0-99-0-999-0-9999-as-triple-roots">
+<h2><a class="toc-backref" href="#id81">The degree nine polynomial with 0.99, 0.999, 0.9999 as triple roots</a></h2>
+<pre class="literal-block">% define a user command (xinttools is loaded automatically by polexpr)
+\def\showmultiplicities#1{% #1 = &quot;sturmname&quot;
+\xintFor* ##1 in {\xintSeq{1}{\PolSturmNbOfIsolatedZeros{#1}}}\do{%
+ The multiplicity is \PolSturmIsolatedZeroMultiplicity{#1}{##1}
+ \PolSturmIfZeroExactlyKnown{#1}{##1}%
+ {at the root $x=\PolSturmIsolatedZeroLeft{#1}{##1}$}
+ {for the root such that
+ $\PolSturmIsolatedZeroLeft{#1}{##1}&lt;x&lt;\PolSturmIsolatedZeroRight{#1}{##1}$}
+ \par
+}}%
+\PolDef{f}{(x-0.99)^3(x-0.999)^3(x-0.9999)^3}
+\def\PolTypesetOne#1{\PolDecToString{\xintREZ{#1}}}
+\PolTypeset{f}\par
+\PolToSturm{f}{f}% it is allowed to use &quot;polname&quot; as &quot;sturmname&quot; too
+\PolSturmIsolateZerosAndGetMultiplicities{f}% use the &quot;sturmname&quot; here
+% or \PolSturmIsolateZeros*{f} which is exactly the same, but shorter..
+
+\showmultiplicities{f}</pre>
+<p>In this example, the output will look like this (but using math mode):</p>
+<pre class="literal-block">x^9 - 8.9667x^8 + 35.73400293x^7 - 83.070418400109x^6 + 124.143648875193123x^5
+- 123.683070924326075877x^4 + 82.149260397553075617891x^3
+- 35.07602992699900159127007x^2 + 8.7364078733314648368671733x
+- 0.967100824643585986488103299
+
+The multiplicity is 3 at the root x = 0.99
+The multiplicity is 3 at the root x = 0.999
+The multiplicity is 3 at the root x = 0.9999</pre>
+<p>On first pass, these rational roots were found (due to their relative
+magnitudes, using <span class="docutils literal">\PolSturmIsolateZeros**</span> was not needed here). But
+multiplicity computation works also with (decimal) roots not yet
+identified or with non-decimal or irrational roots.</p>
+<p>It is fun to modify only a tiny bit the polynomial and see if polexpr
+survives:</p>
+<pre class="literal-block">\PolDef{g}{f(x)+1e-27}
+\PolTypeset{g}\par
+\PolToSturm{g}{g}
+\PolSturmIsolateZeros*{g}
+
+\showmultiplicities{g}</pre>
+<p>This produces:</p>
+<pre class="literal-block">x^9 - 8.9667x^8 + 35.73400293x^7 - 83.070418400109x^6 + 124.143648875193123x^5
+- 123.683070924326075877x^4 + 82.149260397553075617891x^3
+- 35.07602992699900159127007x^2 + 8.7364078733314648368671733x
+- 0.967100824643585986488103298
+
+The multiplicity is 1 for the root such that 0.98 &lt; x &lt; 0.99
+The multiplicity is 1 for the root such that 0.9991 &lt; x &lt; 0.9992
+The multiplicity is 1 for the root such that 0.9997 &lt; x &lt; 0.9998</pre>
+<p>Which means that the multiplicity-3 roots each became a real and a pair of
+complex ones. Let's see them better:</p>
+<pre class="literal-block">\PolEnsureIntervalLengths{g}{-10}
+
+\showmultiplicities{g}</pre>
+<p>which produces:</p>
+<pre class="literal-block">The multiplicity is 1 for the root such that 0.9899888032 &lt; x &lt; 0.9899888033
+The multiplicity is 1 for the root such that 0.9991447980 &lt; x &lt; 0.9991447981
+The multiplicity is 1 for the root such that 0.9997663986 &lt; x &lt; 0.9997663987</pre>
+</div>
+<div class="section" id="a-degree-five-polynomial-with-three-rational-roots">
+<h2><a class="toc-backref" href="#id82">A degree five polynomial with three rational roots</a></h2>
+<pre class="literal-block">\poldef Q(x) := 1581755751184441 x^5
+ -14907697165025339 x^4
+ +48415668972339336 x^3
+ -63952057791306264 x^2
+ +46833913221154895 x
+ -49044360626280925;
+
+\PolToSturm{Q}{Q}
+ \def\PolTypesetCmdPrefix#1{\allowbreak\xintiiifSgn{#1}{}{+}{+}}%
+ $Q_0(x) = \PolTypeset{Q_0}$
+\PolSturmIsolateZeros**{Q}
+\PolPrintIntervals{Q}
+
+$Q_{norr}(x) = \PolTypeset{Q_norr}$</pre>
+<p>Here, all real roots are rational:</p>
+<pre class="literal-block">Z_1 = 833719/265381
+Z_2 = 165707065/52746197
+Z_3 = 355/113
+
+Q_norr(x) = x^2 + 1</pre>
+<p>And let's get their decimal expansion too:</p>
+<pre class="literal-block">% print decimal expansion of the found roots
+\def\PolPrintIntervalsPrintExactZero
+ {\xintTrunc{20}{\PolPrintIntervalsTheLeftEndPoint}\dots}
+\PolPrintIntervals{Q}
+
+Z_1 = 3.14159265358107777120...
+Z_2 = 3.14159265358979340254...
+Z_3 = 3.14159292035398230088...</pre>
+</div>
+<div class="section" id="a-mignotte-type-polynomial">
+<h2><a class="toc-backref" href="#id83">A Mignotte type polynomial</a></h2>
+<pre class="literal-block">\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
+\PolSturmIsolateZeros{P} % finds 4 real roots
+This polynomial has \PolSturmNbOfIsolatedZeros{P} distinct real roots:
+\PolPrintIntervals{P}%
+% reports -2 &lt; Z_1 &lt; -1, 0.09 &lt; Z_2 &lt; 0.10, 0.1 &lt; Z_3 &lt; 0.2, 1 &lt; Z_4 &lt; 2
+Let us refine the second and third intervals to separate the corresponding
+roots:
+\PolRefineInterval*{P}{2}% will refine to 0.0999990 &lt; Z_2 &lt; 0.0999991
+\PolRefineInterval*{P}{3}% will refine to 0.100001 &lt; Z_3 &lt; 0.100002
+\PolPrintIntervals{P}%
+Let us now get to know all roots with 10 digits after decimal mark:
+\PolEnsureIntervalLengths{P}{-10}%
+\PolPrintIntervals{P}% now all roots are known 10 decimal digits after mark
+Finally, we display 20 digits of the second root:
+\PolEnsureIntervalLength{P}{2}{-20}% makes Z_2 known with 20 digits after mark
+$$\PolSturmIsolatedZeroLeft{P}{2}&lt;Z_2&lt;\PolSturmIsolatedZeroRight{P}{2}$$</pre>
+<p>The last line produces:</p>
+<pre class="literal-block">0.09999900004999650028 &lt; Z_2 &lt; 0.09999900004999650029</pre>
+</div>
+<div class="section" id="the-wilkinson-polynomial">
+<h2><a class="toc-backref" href="#id84">The Wilkinson polynomial</a></h2>
+<p>See <a class="reference external" href="https://en.wikipedia.org/wiki/Wilkinson%27s_polynomial">Wilkinson polynomial</a>.</p>
+<pre class="literal-block">%\xintverbosetrue % for the curious...
+
+\poldef f(x) := mul((x - i), i = 1..20);
+
+\def\PolTypesetCmdPrefix#1{\allowbreak\xintiiifSgn{#1}{}{+}{+}}%
+\def\PolTypesetOne#1{\xintDecToString{#1}}%
+
+\noindent\PolTypeset{f}
+
+\PolToSturm{f}{f}
+\PolSturmIsolateZeros{f}
+\PolPrintIntervals{f}
+
+% \vfill\eject
+
+% This page is commented out because it takes about 30s on a 2GHz CPU
+% \poldef g(x) := f(x) - 2**{-23} x**19;
+
+% \PolToSturm{g}{g}
+% \noindent\PolTypeset{g_0}% integer coefficient primitive polynomial
+
+% \PolSturmIsolateZeros{g}
+% \PolEnsureIntervalLengths{g}{-10}
+
+% \let\PolPrintIntervalsPrintMultiplicity\empty
+% \PolPrintIntervals*{g}</pre>
+<p>The first polynomial:</p>
+<pre class="literal-block">f(x) = x**20
+- 210 x**19
++ 20615 x**18
+- 1256850 x**17
++ 53327946 x**16
+- 1672280820 x**15
++ 40171771630 x**14
+- 756111184500 x**13
++ 11310276995381 x**12
+- 135585182899530 x**11
++ 1307535010540395 x**10
+- 10142299865511450 x**9
++ 63030812099294896 x**8
+- 311333643161390640 x**7
++ 1206647803780373360 x**6
+- 3599979517947607200 x**5
++ 8037811822645051776 x**4
+- 12870931245150988800 x**3
++ 13803759753640704000 x**2
+- 8752948036761600000 x
++ 2432902008176640000</pre>
+<p>is handled fast enough, but the modified one <span class="docutils literal">f(x) - <span class="pre">2**-23</span> <span class="pre">x**19</span></span> takes about 20x longer.</p>
+<p>The Sturm chain polynomials
+have integer coefficients with up to 321 digits, whereas (surprisingly
+perhaps) those of the Sturm chain polynomials derived from <span class="docutils literal">f</span> never
+have more than 21 digits ...</p>
+<p>Once the Sturm chain is computed and the zeros isolated, obtaining their
+decimal digits is relatively faster. Here is for the ten real roots of
+<span class="docutils literal">f(x) - <span class="pre">2**-23</span> <span class="pre">x**19</span></span> as computed by the code above:</p>
+<pre class="literal-block">Z_1 = 0.9999999999...
+Z_2 = 2.0000000000...
+Z_3 = 2.9999999999...
+Z_4 = 4.0000000002...
+Z_5 = 4.9999999275...
+Z_6 = 6.0000069439...
+Z_7 = 6.9996972339...
+Z_8 = 8.0072676034...
+Z_9 = 8.9172502485...
+Z_10 = 20.8469081014...</pre>
+</div>
+<div class="section" id="the-second-wilkinson-polynomial">
+<h2><a class="toc-backref" href="#id85">The second Wilkinson polynomial</a></h2>
+<pre class="literal-block">\poldef f(x) := mul(x - 2^-i, i = 1..20);
+
+%\PolTypeset{f}
+
+\PolToSturm{f}{f}
+\PolSturmIsolateZeros**{f}
+\PolPrintIntervals{f}</pre>
+<p>This takes more time than the polynomial with 1, 2, .., 20 as roots but
+less than the latter modified by the <span class="docutils literal"><span class="pre">2**-23</span></span> tiny change to one of its
+coefficient.</p>
+<p>Here is the output (with release 0.7.2):</p>
+<pre class="literal-block">Z_1 = 0.00000095367431640625
+Z_2 = 0.0000019073486328125
+Z_3 = 0.000003814697265625
+Z_4 = 0.00000762939453125
+Z_5 = 0.0000152587890625
+Z_6 = 0.000030517578125
+Z_7 = 0.00006103515625
+Z_8 = 0.0001220703125
+Z_9 = 1/4096
+Z_10 = 1/2048
+Z_11 = 1/1024
+Z_12 = 1/512
+Z_13 = 1/256
+Z_14 = 1/128
+Z_15 = 0.015625
+Z_16 = 0.03125
+Z_17 = 0.0625
+Z_18 = 0.125
+Z_19 = 0.25
+Z_20 = 0.5</pre>
+<p>There is some incoherence in output format which has its source in the
+fact that some roots are found in branches which can only find decimal
+roots, whereas some are found in branches which could find general
+fractions and they use <span class="docutils literal">\xintIrr</span> before storage of the found root.
+This may evolve in future.</p>
+</div>
+<div class="section" id="the-degree-41-polynomial-with-2-1-9-1-8-0-0-1-1-9-2-as-roots">
+<h2><a class="toc-backref" href="#id86">The degree 41 polynomial with -2, -1.9, -1.8, ..., 0, 0.1, ..., 1.9, 2 as roots</a></h2>
+<pre class="literal-block">\PolDef{P}{mul((x-i*1e-1), i=-20..20)}% i/10 is same but less efficient</pre>
+<p>In the defining expression we could have used <span class="docutils literal">i/10</span> but this gives
+less efficient internal form for the coefficients (the <span class="docutils literal">10</span>'s end up
+in denominators).</p>
+<p>Using <span class="docutils literal">\PolToExpr{P}</span> after having done</p>
+<pre class="literal-block">\def\PolToExprCmd#1{\PolDecToString{\xintREZ{#1}}}</pre>
+<p>we get this expanded form:</p>
+<pre class="literal-block">x^41
+-28.7*x^39
++375.7117*x^37
+-2975.11006*x^35
++15935.28150578*x^33
+-61167.527674162*x^31
++173944.259366417394*x^29
+-373686.963560544648*x^27
++613012.0665016658846445*x^25
+-771182.31133138163125495*x^23
++743263.86672885754888959569*x^21
+-545609.076599482896371978698*x^19
++301748.325708943677229642930528*x^17
+-123655.8987669450434698869844544*x^15
++36666.1782054884005855608205864192*x^13
+-7607.85821367459445649518380016128*x^11
++1053.15135918687298508885950223794176*x^9
+-90.6380005918141132650786081964032*x^7
++4.33701563847327366842552218288128*x^5
+-0.0944770968420804735498178265088*x^3
++0.00059190121813899276854174416896*x</pre>
+<p>which shows coefficients with up to 36 significant digits...</p>
+<p>Stress test: not a hard challenge to <span class="docutils literal">xint + polexpr</span>, but be a bit
+patient!</p>
+<pre class="literal-block">\PolDef{P}{mul((x-i*1e-1), i=-20..20)}%
+\PolToSturm{P}{S} % dutifully computes S_0, ..., S_{41}
+% the [1] optional argument limits the search to interval (-10,10)
+\PolSturmIsolateZeros[1]{S} % finds *exactly* (but a bit slowly) all 41 roots!
+\PolPrintIntervals{S} % nice, isn't it?</pre>
+<div class="admonition note">
+<p class="admonition-title">Note</p>
+<p>Release <span class="docutils literal">0.5</span> has <em>experimental</em> addition of optional argument
+<span class="docutils literal">E</span> to <span class="docutils literal">\PolSturmIsolateZeros</span>. It instructs to search roots only
+in interval <span class="docutils literal"><span class="pre">(-10^E,</span> 10^E)</span>. Important: the extremities are
+<em>assumed to not be roots</em>. In this example, the <span class="docutils literal">[1]</span> in
+<span class="docutils literal"><span class="pre">\PolSturmIsolateZeros[1]{S}</span></span> gives some speed gain; without it, it
+turns out in this case that <span class="docutils literal">polexpr</span> would have started with
+<span class="docutils literal"><span class="pre">(-10^6,</span> 10^6)</span> interval.</p>
+<p>Please note that this will probably get replaced in future by the
+specification of a general interval. Do not rely on meaning of this
+optional argument keeping the same.</p>
+</div>
+</div>
+<div class="section" id="roots-of-chebyshev-polynomials">
+<h2><a class="toc-backref" href="#id87">Roots of Chebyshev polynomials</a></h2>
+<pre class="literal-block">\newcount\mycount
+\poldef T_0(x) := 1;
+\poldef T_1(x) := x;
+\mycount 2
+\xintloop
+ \poldef T_\the\mycount(x) :=
+ 2x*T_\the\numexpr\mycount-1(x)
+ - T_\the\numexpr\mycount-2(x);
+\ifnum\mycount&lt;15
+\advance\mycount 1
+\repeat
+
+$$T_{15} = \PolTypeset[X]{T_15}$$
+\PolToSturm{T_15}{T_15}
+\PolSturmIsolateZeros{T_15}
+\PolEnsureIntervalLengths{T_15}{-10}
+\PolPrintIntervals{T_15}</pre>
+</div>
+</div>
+<div class="section" id="non-expandable-macros">
+<h1><a class="toc-backref" href="#id88">Non-expandable macros</a></h1>
+<div class="admonition note">
+<p class="admonition-title">Note</p>
+<p>At <span class="docutils literal">0.8</span> <span class="docutils literal">polexpr</span> is usable with Plain TeX and not only with
+LaTeX. Some examples given in this section may be using LaTeX syntax
+such as <span class="docutils literal">\renewcommand</span>. Convert to TeX primitives as appropriate
+if testing with a non LaTeX macro format.</p>
+</div>
+<div class="section" id="poldef-polname-letter-expression-using-the-letter-as-indeterminate">
+<span id="poldef"></span><h2><a class="toc-backref" href="#id89"><span class="docutils literal">\poldef <span class="pre">polname(letter):=</span> expression using the letter as indeterminate;</span></a></h2>
+<blockquote>
+<p>This evaluates the <em>polynomial expression</em> and stores the
+coefficients in a private structure accessible later via other
+package macros, when used with argument the chosen <span class="docutils literal">polname</span>. Of
+course the <em>expression</em> can use other previously defined
+polynomials.</p>
+<p>Polynomial names must start with a letter and are constituted of
+letters, digits, underscores and the right tick <span class="docutils literal">'</span>.</p>
+<p>The whole <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> syntax is authorized:</p>
+<pre class="literal-block">\poldef mypol(z) := add((-1)^i z^(2i+1)/(2i+1)!, i = 0..10);</pre>
+<p>With fractional coefficients, beware the <a class="reference internal" href="#warningtacit">tacit multiplication issue</a>.</p>
+<p>Furthermore:</p>
+<ul class="simple">
+<li><p>a variable <span class="docutils literal">mypol</span> is defined which can be used in <span class="docutils literal">\poldef</span>
+as well as in <span class="docutils literal">\xinteval</span> for algebraic computations or as
+argument to polynomial aware functions,</p></li>
+<li><p>a function <span class="docutils literal">mypol()</span> is defined which can be used in <span class="docutils literal">\poldef</span>
+as well as in <span class="docutils literal">\xinteval</span>. It accepts there as argument scalars
+and also other polynomials (via their names, thanks to previous
+item).</p></li>
+</ul>
+<p>Notice that any function defined via <span class="docutils literal">\xintdeffunc</span> and using
+only algebraic operations (and ople indexing or slicing operations)
+should work fine in <span class="docutils literal"><span class="pre">\xintexpr/\xinteval</span></span> with such polynomial
+names as argument.</p>
+<p>In the case of a constant polynomial, the <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> 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 <span class="docutils literal">cos()</span> function).
+<strong>THIS MAY CHANGE</strong></p>
+<p>The <em>function</em> on the other hand remains a one-argument function,
+which simply has a constant value.</p>
+<div class="admonition attention">
+<p class="admonition-title">Attention!</p>
+<p>The function <span class="docutils literal">mypol()</span> is defined <strong>only</strong> for
+<span class="docutils literal"><span class="pre">\xintexpr/\xinteval</span></span>
+context. It will be unknown to <span class="docutils literal">\xintfloateval</span>.</p>
+<p>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 <span class="docutils literal">\poldef</span> or <span class="docutils literal">\PolDef</span> but
+as result of usage of the other package macros.</p>
+<p>See <a class="reference internal" href="#polgenfloatvariant-polname">\PolGenFloatVariant{polname}</a> to generate a <strong>function</strong>
+usable in <span class="docutils literal">\xintfloateval</span>. Such a function can only be
+used with scalar input, see next warning.</p>
+</div>
+<div class="admonition attention">
+<p class="admonition-title">Attention!</p>
+<p>Using the <strong>variable</strong> <span class="docutils literal">mypol</span> inside <span class="docutils literal">\xintfloateval</span> will
+generate low-level errors because the infix operators there are
+not polynomial-aware, and the polynomial specific functions such
+as <span class="docutils literal">deg()</span> are only defined for usage inside <span class="docutils literal">\xintexpr</span>.</p>
+<p>In short, currently polynomials defined via <span class="docutils literal">polexpr</span> can
+be used in floating point context only for numerical evaluations,
+via <strong>functions</strong> obtained from <a class="reference internal" href="#polgenfloatvariant-polname">\PolGenFloatVariant{polname}</a>
+usage.</p>
+<p>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.</p>
+<p><strong>THIS MAY CHANGE</strong></p>
+</div>
+<p>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.</p>
+</blockquote>
+</div>
+<div class="section" id="poldef-letter-polname-expression-using-the-letter-as-indeterminate">
+<span id="id8"></span><h2><a class="toc-backref" href="#id90"><span class="docutils literal"><span class="pre">\PolDef[letter]{polname}{expression</span> using the letter as indeterminate}</span></a></h2>
+<blockquote>
+<p>Does the same as <a class="reference internal" href="#poldef">\poldef</a> 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
+<span class="docutils literal">[letter]</span> optional argument, the variable is assumed to be <span class="docutils literal">x</span>.</p>
+</blockquote>
+</div>
+<div class="section" id="polgenfloatvariant-polname">
+<span id="polgenfloatvariant"></span><h2><a class="toc-backref" href="#id91"><span class="docutils literal">\PolGenFloatVariant{polname}</span></a></h2>
+<blockquote>
+<p>Makes the polynomial also usable in the <span class="docutils literal">\xintfloatexpr</span> parser.
+It will therein evaluates via an Horner scheme with coefficients
+already pre-rounded to the float precision.</p>
+<p>See also <a class="reference internal" href="#poltofloatexpr-pol-expr">\PolToFloatExpr{&lt;pol. expr.&gt;}</a>.</p>
+<div class="admonition attention">
+<p class="admonition-title">Attention!</p>
+<p>Any operation, for example generating the derivative polynomial,
+or dividing two polynomials or using the <span class="docutils literal">\PolLet</span>, <strong>must</strong> be
+followed by explicit usage of <span class="docutils literal">\PolGenFloatVariant{polname}</span> if
+the new polynomial is to be used in <span class="docutils literal">\xintfloateval</span> <strong>as a
+function</strong>.</p>
+</div>
+</blockquote>
+</div>
+<div class="section" id="pollet-polname-2-polname-1">
+<span id="pollet"></span><h2><a class="toc-backref" href="#id92"><span class="docutils literal"><span class="pre">\PolLet{polname_2}={polname_1}</span></span></a></h2>
+<blockquote>
+<p>Makes a copy of the already defined polynomial <span class="docutils literal">polname_1</span> to a
+new one <span class="docutils literal">polname_2</span>. Same effect as
+<span class="docutils literal"><span class="pre">\PolDef{polname_2}{polname_1(x)}</span></span> but with less overhead. The
+<span class="docutils literal">=</span> is optional.</p>
+</blockquote>
+</div>
+<div class="section" id="polgloballet-polname-2-polname-1">
+<span id="polgloballet"></span><h2><a class="toc-backref" href="#id93"><span class="docutils literal"><span class="pre">\PolGlobalLet{polname_2}={polname_1}</span></span></a></h2>
+<blockquote>
+<p>Acts globally.</p>
+</blockquote>
+</div>
+<div class="section" id="polassign-polname-toarray-macro">
+<span id="polassign"></span><h2><a class="toc-backref" href="#id94"><span class="docutils literal"><span class="pre">\PolAssign{polname}\toarray\macro</span></span></a></h2>
+<blockquote>
+<p>Defines a one-argument expandable macro <span class="docutils literal"><span class="pre">\macro{#1}</span></span> which expands
+to the (raw) #1th polynomial coefficient.</p>
+<ul class="simple">
+<li><p>Attention, coefficients here are indexed starting at 1.</p></li>
+<li><p>With #1=-1, -2, ..., <span class="docutils literal"><span class="pre">\macro{#1}</span></span> returns leading coefficients.</p></li>
+<li><p>With #1=0, returns the number of coefficients, i.e. <span class="docutils literal">1 + deg f</span>
+for non-zero polynomials.</p></li>
+<li><p>Out-of-range #1's return <span class="docutils literal">0/1[0]</span>.</p></li>
+</ul>
+<p>See also <a class="reference internal" href="#polnthcoeff-polname-number">\PolNthCoeff{polname}{number}</a>. The main difference is that
+with <span class="docutils literal">\PolAssign</span>, <span class="docutils literal">\macro</span> is made a prefix to <span class="docutils literal">1 + deg f</span>
+already defined (hidden to user) macros holding individually the
+coefficients but <a class="reference internal" href="#polnthcoeff-polname-number">\PolNthCoeff{polname}{number}</a> does each time the job
+to expandably recover the <span class="docutils literal">Nth</span> coefficient, and due to
+expandability can not store it in a macro for future usage (of course,
+it can be an argument in an <span class="docutils literal">\edef</span>.) The other difference
+is the shift by one in indexing, mentioned above (negative
+indices act the same in both.)</p>
+</blockquote>
+</div>
+<div class="section" id="polget-polname-fromarray-macro">
+<span id="polget"></span><h2><a class="toc-backref" href="#id95"><span class="docutils literal"><span class="pre">\PolGet{polname}\fromarray\macro</span></span></a></h2>
+<blockquote>
+<p>Does the converse operation to
+<span class="docutils literal"><span class="pre">\PolAssign{polname}\toarray\macro</span></span>. Each individual
+<span class="docutils literal">\macro{number}</span> gets expanded in an <span class="docutils literal">\edef</span> and then normalized
+via <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a>'s macro <span class="docutils literal">\xintRaw</span>.</p>
+<p>The leading zeros are removed from the polynomial.</p>
+<p>(contrived) Example:</p>
+<pre class="literal-block">\xintAssignArray{1}{-2}{5}{-3}\to\foo
+\PolGet{f}\fromarray\foo</pre>
+<p>This will define <span class="docutils literal">f</span> as would have <span class="docutils literal">\poldef <span class="pre">f(x):=1-2x+5x^2-3x^3;</span></span>.</p>
+<div class="admonition note">
+<p class="admonition-title">Note</p>
+<p>Prior to <span class="docutils literal">0.5</span>, coefficients were not normalized via
+<span class="docutils literal">\xintRaw</span> for internal storage.</p>
+</div>
+</blockquote>
+</div>
+<div class="section" id="polfromcsv-polname-csv">
+<span id="polfromcsv"></span><h2><a class="toc-backref" href="#id96"><span class="docutils literal"><span class="pre">\PolFromCSV{polname}{&lt;csv&gt;}</span></span></a></h2>
+<blockquote>
+<p>Defines a polynomial directly from the comma separated list of values
+(or a macro expanding to such a list) of its coefficients, the <em>first
+item</em> gives the constant term, the <em>last item</em> gives the leading
+coefficient, except if zero, then it is dropped (iteratively). List
+items are each expanded in an <span class="docutils literal">\edef</span> and then put into normalized
+form via <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a>'s macro <span class="docutils literal">\xintRaw</span>.</p>
+<p>As leading zero coefficients are removed:</p>
+<pre class="literal-block">\PolFromCSV{f}{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}</pre>
+<p>defines the zero polynomial, which holds only one coefficient.</p>
+<p>See also expandable macro <a class="reference internal" href="#poltocsv-polname">\PolToCSV</a>.</p>
+<div class="admonition note">
+<p class="admonition-title">Note</p>
+<p>Prior to <span class="docutils literal">0.5</span>, coefficients were not normalized via
+<span class="docutils literal">\xintRaw</span> for internal storage.</p>
+</div>
+</blockquote>
+</div>
+<div class="section" id="poltypeset-pol-expr">
+<span id="poltypeset"></span><h2><a class="toc-backref" href="#id97"><span class="docutils literal"><span class="pre">\PolTypeset{&lt;pol.</span> <span class="pre">expr.&gt;}</span></span></a></h2>
+<blockquote>
+<p>Typesets in descending powers, switching to math mode if in text
+mode, after evaluating the polynomial expression:</p>
+<pre class="literal-block">\PolTypeset{mul(x-i,i=1..5)}% possible since polexpr 0.8</pre>
+<p>The letter used in the input expression is by default <span class="docutils literal">x</span>,
+but can be modified by a redefinition of <a class="reference internal" href="#poltoexprinvar">\PolToExprInVar</a>.</p>
+<p>It uses also by default the letter <span class="docutils literal">x</span> on output but this one can
+be changed via an optional argument:</p>
+<pre class="literal-block">\PolTypeset[z]{polname or polynomial expression}</pre>
+<p>By default zero coefficients are skipped (use <span class="docutils literal">\poltypesetalltrue</span>
+to get all of them in output).</p>
+<p>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.</p>
+</blockquote>
+<div class="section" id="poltypesetcmd-raw-coeff">
+<span id="poltypesetcmd"></span><h3><a class="toc-backref" href="#id98"><span class="docutils literal">\PolTypesetCmd{raw_coeff}</span></a></h3>
+<blockquote>
+<p>Checks if the coefficient is <span class="docutils literal">1</span> or <span class="docutils literal"><span class="pre">-1</span></span> and then skips printing
+the <span class="docutils literal">1</span>, except for the constant term. Also it sets conditional
+<a class="reference internal" href="#polifcoeffisplusorminusone-a-b">\PolIfCoeffIsPlusOrMinusOne{A}{B}</a>.</p>
+<p>The actual printing of the coefficients, when not equal to plus or
+minus one is handled by <a class="reference internal" href="#poltypesetone-raw-coeff">\PolTypesetOne{raw_coeff}</a>.</p>
+</blockquote>
+</div>
+<div class="section" id="poltypesetone-raw-coeff">
+<span id="poltypesetone"></span><h3><a class="toc-backref" href="#id99"><span class="docutils literal">\PolTypesetOne{raw_coeff}</span></a></h3>
+<blockquote>
+<p>Defaults to <span class="docutils literal">\xintSignedFrac</span> (LaTeX) or <span class="docutils literal">\xintSignedFwOver</span>
+(else). But these <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a> very old legacy macros are a bit
+annoyin as they insist in exhibiting a power of ten rather than
+using simpler decimal notation.</p>
+<p>As alternative one can do things such as:</p>
+<pre class="literal-block">\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}}}</pre>
+</blockquote>
+</div>
+<div class="section" id="id9">
+<span id="poltypesetmonomialcmd"></span><h3><a class="toc-backref" href="#id100"><span class="docutils literal">\PolTypesetMonomialCmd</span></a></h3>
+<blockquote>
+<p>This decides how a monomial (in variable <span class="docutils literal">\PolVar</span> and with
+exponent <span class="docutils literal">\PolIndex</span>) is to be printed. The default does nothing
+for the constant term, <span class="docutils literal">\PolVar</span> for the first degree and
+<span class="docutils literal"><span class="pre">\PolVar^{\PolIndex}</span></span> for higher degrees monomials. Beware that
+<span class="docutils literal">\PolIndex</span> expands to digit tokens and needs termination in
+<span class="docutils literal">\ifnum</span> tests.</p>
+</blockquote>
+</div>
+<div class="section" id="poltypesetcmdprefix-raw-coeff">
+<span id="poltypesetcmdprefix"></span><h3><a class="toc-backref" href="#id101"><span class="docutils literal">\PolTypesetCmdPrefix{raw_coeff}</span></a></h3>
+<blockquote>
+<p>Expands to a <span class="docutils literal">+</span> if the <span class="docutils literal">raw_coeff</span> is zero or positive, and to
+nothing if <span class="docutils literal">raw_coeff</span> is negative, as in latter case the
+<span class="docutils literal">\xintSignedFrac</span> (or <span class="docutils literal">\xintSignedFwOver</span>) used by
+<a class="reference internal" href="#poltypesetcmd-raw-coeff">\PolTypesetCmd{raw_coeff}</a> will put the <span class="docutils literal">-</span> 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.</p>
+</blockquote>
+</div>
+</div>
+<div class="section" id="id11">
+<span id="id10"></span><h2><a class="toc-backref" href="#id102"><span class="docutils literal"><span class="pre">\PolTypeset*{&lt;pol.</span> <span class="pre">expr.&gt;}</span></span></a></h2>
+<blockquote>
+<p>Typesets in ascending powers. Use e.g. <span class="docutils literal">[h]</span> optional argument
+(after the <span class="docutils literal">*</span>) to use letter <span class="docutils literal">h</span> rather than <span class="docutils literal">x</span>.</p>
+<p>Extended at <span class="docutils literal">0.8</span> to accept general expressions and not only
+polynomial names. Redefine <a class="reference internal" href="#poltoexprinvar">\PolToExprInVar</a> to use in the
+expression another letter than default <span class="docutils literal">x</span>.</p>
+</blockquote>
+</div>
+<div class="section" id="poldiff-polname-1-polname-2">
+<span id="poldiff"></span><h2><a class="toc-backref" href="#id103"><span class="docutils literal"><span class="pre">\PolDiff{polname_1}{polname_2}</span></span></a></h2>
+<blockquote>
+<p>This sets <span class="docutils literal">polname_2</span> to the first derivative of <span class="docutils literal">polname_1</span>. It
+is allowed to issue <span class="docutils literal"><span class="pre">\PolDiff{f}{f}</span></span>, effectively replacing <span class="docutils literal">f</span>
+by <span class="docutils literal">f'</span>.</p>
+<p>Coefficients of the result <span class="docutils literal">polname_2</span> are irreducible fractions
+(see <a class="reference internal" href="#technicalities">Technicalities</a> for the whole story.)</p>
+</blockquote>
+</div>
+<div class="section" id="poldiff-n-polname-1-polname-2">
+<span id="poldiff-n"></span><h2><a class="toc-backref" href="#id104"><span class="docutils literal"><span class="pre">\PolDiff[N]{polname_1}{polname_2}</span></span></a></h2>
+<blockquote>
+<p>This sets <span class="docutils literal">polname_2</span> to the <span class="docutils literal">N</span>-th derivative of <span class="docutils literal">polname_1</span>.
+Identical arguments is allowed. With <span class="docutils literal">N=0</span>, same effect as
+<span class="docutils literal"><span class="pre">\PolLet{polname_2}={polname_1}</span></span>. With negative <span class="docutils literal">N</span>, switches to
+using <span class="docutils literal">\PolAntiDiff</span>.</p>
+</blockquote>
+</div>
+<div class="section" id="polantidiff-polname-1-polname-2">
+<span id="polantidiff"></span><h2><a class="toc-backref" href="#id105"><span class="docutils literal"><span class="pre">\PolAntiDiff{polname_1}{polname_2}</span></span></a></h2>
+<blockquote>
+<p>This sets <span class="docutils literal">polname_2</span> to the primitive of <span class="docutils literal">polname_1</span> vanishing
+at zero.</p>
+<p>Coefficients of the result <span class="docutils literal">polname_2</span> are irreducible fractions
+(see <a class="reference internal" href="#technicalities">Technicalities</a> for the whole story.)</p>
+</blockquote>
+</div>
+<div class="section" id="polantidiff-n-polname-1-polname-2">
+<span id="polantidiff-n"></span><h2><a class="toc-backref" href="#id106"><span class="docutils literal"><span class="pre">\PolAntiDiff[N]{polname_1}{polname_2}</span></span></a></h2>
+<blockquote>
+<p>This sets <span class="docutils literal">polname_2</span> to the result of <span class="docutils literal">N</span> successive integrations on
+<span class="docutils literal">polname_1</span>. With negative <span class="docutils literal">N</span>, it switches to using <span class="docutils literal">\PolDiff</span>.</p>
+</blockquote>
+</div>
+<div class="section" id="poldivide-polname-1-polname-2-polname-q-polname-r">
+<span id="poldivide"></span><h2><a class="toc-backref" href="#id107"><span class="docutils literal"><span class="pre">\PolDivide{polname_1}{polname_2}{polname_Q}{polname_R}</span></span></a></h2>
+<blockquote>
+<p>This sets <span class="docutils literal">polname_Q</span> and <span class="docutils literal">polname_R</span> to be the quotient and
+remainder in the Euclidean division of <span class="docutils literal">polname_1</span> by
+<span class="docutils literal">polname_2</span>.</p>
+</blockquote>
+</div>
+<div class="section" id="polquo-polname-1-polname-2-polname-q">
+<span id="polquo"></span><h2><a class="toc-backref" href="#id108"><span class="docutils literal"><span class="pre">\PolQuo{polname_1}{polname_2}{polname_Q}</span></span></a></h2>
+<blockquote>
+<p>This sets <span class="docutils literal">polname_Q</span> to be the quotient in the Euclidean division
+of <span class="docutils literal">polname_1</span> by <span class="docutils literal">polname_2</span>.</p>
+</blockquote>
+</div>
+<div class="section" id="polrem-polname-1-polname-2-polname-r">
+<span id="polrem"></span><h2><a class="toc-backref" href="#id109"><span class="docutils literal"><span class="pre">\PolRem{polname_1}{polname_2}{polname_R}</span></span></a></h2>
+<blockquote>
+<p>This sets <span class="docutils literal">polname_R</span> to be the remainder in the Euclidean division
+of <span class="docutils literal">polname_1</span> by <span class="docutils literal">polname_2</span>.</p>
+</blockquote>
+</div>
+<div class="section" id="polgcd-polname-1-polname-2-polname-gcd">
+<span id="polgcd"></span><h2><a class="toc-backref" href="#id110"><span class="docutils literal"><span class="pre">\PolGCD{polname_1}{polname_2}{polname_GCD}</span></span></a></h2>
+<blockquote>
+<p>This sets <span class="docutils literal">polname_GCD</span> to be the (monic) GCD of the two first
+polynomials. It is a unitary polynomial except if both <span class="docutils literal">polname_1</span>
+and <span class="docutils literal">polname_2</span> vanish, then <span class="docutils literal">polname_GCD</span> is the zero
+polynomial.</p>
+</blockquote>
+</div>
+<div class="section" id="non-expandable-macros-related-to-the-root-localization-routines">
+<h2><a class="toc-backref" href="#id111">Non-expandable macros related to the root localization routines</a></h2>
+<div class="section" id="poltosturm-polname-sturmname">
+<span id="poltosturm"></span><h3><a class="toc-backref" href="#id112"><span class="docutils literal"><span class="pre">\PolToSturm{polname}{sturmname}</span></span></a></h3>
+<blockquote>
+<p>With <span class="docutils literal">polname</span> being for example <span class="docutils literal">P</span>, the macro starts by
+computing polynomials <span class="docutils literal">P</span> and <span class="docutils literal">P'</span>, then computes the (opposite
+of the) remainder in euclidean division, iteratively.</p>
+<p>The last non-zero remainder <span class="docutils literal">P_N_</span> (where <span class="docutils literal">N</span> is obtainable as
+<a class="reference internal" href="#polsturmchainlength-sturmname">\PolSturmChainLength{sturmname}</a>) is up to a factor
+the GCD of <span class="docutils literal">P</span> and <span class="docutils literal">P'</span> hence it is a constant if and only if
+<span class="docutils literal">P</span> is square-free.</p>
+<div class="admonition note">
+<p class="admonition-title">Note</p>
+<ul class="simple">
+<li><p>Since <span class="docutils literal">0.5</span> all these polynomials are divided by their rational
+content, so they have integer coefficients with no common factor,
+and the last one if a constant is either <span class="docutils literal">1</span> or <span class="docutils literal"><span class="pre">-1</span></span>.</p></li>
+<li><p>After this normalization to primitive polynomials, they are
+stored internally as <span class="docutils literal">sturmname_k_</span>, <span class="docutils literal">k=0,1, ...</span>.</p></li>
+<li><p>These polynomials are used internally only. To keep them as
+genuine declared polynomials also after the macro call, use the
+starred variant <a class="reference internal" href="#id12">PolToSturm*</a>.</p></li>
+</ul>
+</div>
+<div class="admonition note">
+<p class="admonition-title">Note</p>
+<p>It is perfectly allowed to use the polynomial name as Sturm chain name:
+<span class="docutils literal"><span class="pre">\PolToSturm{f}(f}</span></span>.</p>
+</div>
+<p>The macro then declares <span class="docutils literal">sturmname_0</span>, <span class="docutils literal">sturmname_1</span>, ..., which are
+the (non-declared) <span class="docutils literal">sturmname_k_</span> divided by the last one. Division is
+not done if this last one is the constant <span class="docutils literal">1</span> or <span class="docutils literal"><span class="pre">-1</span></span>, i.e. if the
+original polynomial was square-free. These polynomials are primitive
+polynomials too, i.e. with integer coefficients having no common factor.</p>
+<p>Thus <span class="docutils literal">sturmname_0</span> has exactly the same real and complex roots as
+polynomial <span class="docutils literal">polname</span>, but with each root now of multiplicity one:
+i.e. it is the &quot;square-free part&quot; of original polynomial <span class="docutils literal">polname</span>.</p>
+<p>Notice that <span class="docutils literal">sturmname_1</span> isn't necessarily the derivative of
+<span class="docutils literal">sturmname_0</span> due to the various normalizations.</p>
+<p>The polynomials <span class="docutils literal">sturmname_k</span> main utility is for the execution of
+<a class="reference internal" href="#polsturmisolatezeros-sturmname">\PolSturmIsolateZeros{sturmname}</a>. Be careful not to use these
+names <span class="docutils literal">sturmname_0</span>, <span class="docutils literal">sturmname_1</span>, etc... for defining other
+polynomials after having done <span class="docutils literal"><span class="pre">\PolToSturm{polname}{sturmname}</span></span> and
+before executing <span class="docutils literal">\PolSturmIsolateZeros{sturmname}</span> else the
+latter will behave erroneously.</p>
+<p><a class="reference internal" href="#polsturmchainlength-sturmname">\PolSturmChainLength{sturmname}</a> gives the index of the last
+element of the Sturm chain.</p>
+</blockquote>
+</div>
+<div class="section" id="id13">
+<span id="id12"></span><h3><a class="toc-backref" href="#id113"><span class="docutils literal"><span class="pre">\PolToSturm*{polname}{sturmname}</span></span></a></h3>
+<blockquote>
+<p>Does the same as <a class="reference internal" href="#poltosturm">un-starred version</a> and additionally it
+keeps for user usage the memory of the <em>un-normalized</em> Sturm chain
+polynomials <span class="docutils literal">sturmname_k_</span>, <span class="docutils literal">k=0,1, <span class="pre">...,</span> N</span>, with
+<span class="docutils literal">N</span> being <a class="reference internal" href="#polsturmchainlength-sturmname">\PolSturmChainLength{sturmname}</a>.</p>
+<div class="admonition note">
+<p class="admonition-title">Note</p>
+<p>This behaviour was modified at <span class="docutils literal">0.6</span>, anyhow the macro was
+broken at <span class="docutils literal">0.5</span>.</p>
+</div>
+<div class="admonition hint">
+<p class="admonition-title">Hint</p>
+<p>The square-free part of <span class="docutils literal">polname</span> is <span class="docutils literal">sturmname_0</span>, and their
+quotient is the polynomial with name
+<span class="docutils literal">sturname_\PolSturmChainLength{sturmname}_</span>. 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 <span class="docutils literal">f</span> as
+a product <span class="docutils literal">c f_1 f_2 f_3 ...</span> of a constant and square-free (primitive)
+polynomials, where each <span class="docutils literal">f_i</span> divides its predecessor.</p>
+</div>
+</blockquote>
+</div>
+<div class="section" id="polsettosturmchainsignchangesat-macro-sturmname-fraction">
+<span id="polsettosturmchainsignchangesat"></span><h3><a class="toc-backref" href="#id114"><span class="docutils literal"><span class="pre">\PolSetToSturmChainSignChangesAt{\macro}{sturmname}{fraction}</span></span></a></h3>
+<blockquote>
+<p>Sets macro <span class="docutils literal">\macro</span> to the number of sign changes in the Sturm
+chain with name prefix <span class="docutils literal">sturmname</span>, at location <span class="docutils literal">fraction</span>
+(which must be in format as acceptable by the <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a> macros.)</p>
+<div class="admonition note">
+<p class="admonition-title">Note</p>
+<p>The author was lazy and did not provide rather an expandable
+variant, where one would do <span class="docutils literal"><span class="pre">\edef\macro{\PolNbOf...}</span></span>.</p>
+<p>This will presumably get added in a future release.</p>
+<p>After some hesitation it was decided the macro would by default
+act globally. To make the scope of its macro definition local,
+use <span class="docutils literal">[\empty]</span> as extra optional argument.</p>
+</div>
+</blockquote>
+</div>
+<div class="section" id="polsettonbofzeroswithin-macro-sturmname-value-a-value-b">
+<span id="polsettonbofzeroswithin"></span><h3><a class="toc-backref" href="#id115"><span class="docutils literal"><span class="pre">\PolSetToNbOfZerosWithin{\macro}{sturmname}{value_a}{value_b}</span></span></a></h3>
+<blockquote>
+<p>Applies the <a class="reference external" href="https://en.wikipedia.org/wiki/Sturm%27s_theorem">Sturm Theorem</a> to set <span class="docutils literal">\macro</span> to the exact number
+of <strong>distinct</strong> roots of <span class="docutils literal">sturmname_0</span> in the interval <span class="docutils literal">(value_a, value_b]</span> (the macro first re-orders the value for <span class="docutils literal">value_a &lt;= value_b</span> to hold).</p>
+<div class="admonition note">
+<p class="admonition-title">Note</p>
+<p>The author was lazy and did not provide rather an expandable
+variant, where one would do <span class="docutils literal"><span class="pre">\edef\macro{\PolNbOf...}</span></span>.</p>
+<p>This will presumably get added in future.</p>
+<p>After some hesitation it was decided the macro would by default
+act globally. To make the scope of its macro definition local,
+use <span class="docutils literal">[\empty]</span> as extra optional argument.</p>
+</div>
+<p>See also the expandable
+<a class="reference internal" href="#polsturmnbofrootsof-sturmname-lessthanorequalto-value">\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualTo{value}</a>, from
+which it is immediate (with <span class="docutils literal">\numexpr</span>) to create an expandable
+variant of this macro. However the difference is that this macro
+requires only <a class="reference internal" href="#poltosturm">\PolToSturm</a> to have been executed,
+whereas the expandable variant requires prior execution of
+<a class="reference internal" href="#polsturmisolatezeros">\PolSturmIsolateZeros</a>.</p>
+<p>See also the expandable
+<a class="reference internal" href="#polsturmnbwithmultofrootsof-sturmname-lessthanorequalto-value">\PolSturmNbWithMultOfRootsOf{sturmname}\LessThanOrEqualTo{value}</a>
+which requires prior execution of
+<a class="reference internal" href="#id14">\PolSturmIsolateZeros*</a>.</p>
+</blockquote>
+</div>
+<div class="section" id="polsturmisolatezeros-sturmname">
+<span id="polsturmisolatezeros"></span><h3><a class="toc-backref" href="#id116"><span class="docutils literal">\PolSturmIsolateZeros{sturmname}</span></a></h3>
+<blockquote>
+<p>The macros locates, using <a class="reference external" href="https://en.wikipedia.org/wiki/Sturm%27s_theorem">Sturm theorem</a>, as many disjoint
+intervals as there are (real) roots.</p>
+<div class="admonition important">
+<p class="admonition-title">Important</p>
+<p>The Sturm chain must have been produced by an earlier
+<a class="reference internal" href="#poltosturm-polname-sturmname">\PolToSturm{polname}{sturmname}</a>.</p>
+<p>Why does this macro ask for argument the name of Sturm chain,
+rather than the name of a polynomial? well this is mainly for
+legacy reason, and because it is accompanied by other macros for
+which it is simpler to assume the argument will be the name of an
+already computed Sturm chain.</p>
+<p>Notice that <span class="docutils literal"><span class="pre">\PolToSturm{f}{f}</span></span> is perfectly legal (the
+<span class="docutils literal">sturmname</span> can be same as the <span class="docutils literal">polname</span>): it defines
+polynomials <span class="docutils literal">f_0</span>, <span class="docutils literal">f_1</span>, ... having <span class="docutils literal">f</span> has name prefix.</p>
+<p>Such a prior call
+to <span class="docutils literal">\PolToSturm</span> must have been made at any rate for
+<span class="docutils literal">\PolSturmIsolateZeros</span> to be usable.</p>
+</div>
+<p>After its execution they are two types of such intervals (stored in
+memory and accessible via macros or <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> variables, see below):</p>
+<ul class="simple">
+<li><p>singleton <span class="docutils literal">{a}</span>: then <span class="docutils literal">a</span> is a root, (necessarily a decimal
+number, but not all such decimal numbers are exactly identified yet).</p></li>
+<li><p>open intervals <span class="docutils literal">(a,b)</span>: then there is exactly one root <span class="docutils literal">z</span>
+such that <span class="docutils literal">a &lt; z &lt; b</span>, and the end points are guaranteed to not
+be roots.</p></li>
+</ul>
+<p>The interval boundaries are decimal numbers, originating
+in iterated decimal subdivision from initial intervals
+<span class="docutils literal"><span class="pre">(-10^E,</span> 0)</span> and <span class="docutils literal">(0, 10^E)</span> with <span class="docutils literal">E</span> 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 <span class="docutils literal">(a/10^f, <span class="pre">(a+1)/10^f)</span></span> with <span class="docutils literal">a</span> an integer, which is
+neither <span class="docutils literal">0</span> nor <span class="docutils literal"><span class="pre">-1</span></span>. Hence either <span class="docutils literal">a</span> and <span class="docutils literal">a+1</span> are both positive
+or they are both negative.</p>
+<p>One does not <em>a priori</em> 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.</p>
+<div class="admonition important">
+<p class="admonition-title">Important</p>
+<p>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.</p>
+<p>See <a class="reference internal" href="#polrefineinterval-sturmname-index">\PolRefineInterval*{sturmname}{index}</a> which addresses
+this issue.</p>
+</div>
+<p>The interval boundaries (and exactly found roots) are made available
+for future computations in <span class="docutils literal">\xintexpr</span>-essions or polynomial
+definitions as variables <span class="docutils literal">&lt;sturmname&gt;L_1</span>,
+<span class="docutils literal">&lt;sturmname&gt;L_2</span>, etc..., for the left end-points and
+<span class="docutils literal">&lt;sturmname&gt;R_1</span>, <span class="docutils literal">&lt;sturmname&gt;R_2</span>, ..., for the right
+end-points.</p>
+<p>Thus for example, if <span class="docutils literal">sturmname</span> is <span class="docutils literal">f</span>, one can use the
+<a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> variables <span class="docutils literal">fL_1</span>, <span class="docutils literal">fL_2</span>, ... to refer in expressions
+to the left end-points (or to the exact root, if left and right end
+points coincide). Additionally, <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> variable <span class="docutils literal">fZ_1_isknown</span>
+will have value <span class="docutils literal">1</span> if the root in the first interval is known,
+and <span class="docutils literal">0</span> otherwise. And similarly for the other intervals.</p>
+<p>Also, macros <a class="reference internal" href="#polsturmisolatedzeroleft-sturmname-index">\PolSturmIsolatedZeroLeft{sturmname}{index}</a> and
+<a class="reference internal" href="#polsturmisolatedzeroright-sturmname-index">\PolSturmIsolatedZeroRight{sturmname}{index}</a> are provided which
+expand to these same values, written in decimal notation (i.e.
+pre-processed by <a class="reference internal" href="#poldectostring">\PolDecToString</a>.) And there
+is also <a class="reference internal" href="#polsturmifzeroexactlyknown-sturmname-index-a-b">\PolSturmIfZeroExactlyKnown{sturmname}{index}{A}{B}</a>.</p>
+<div class="admonition important">
+<p class="admonition-title">Important</p>
+<p>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.</p>
+</div>
+<p>These variables and macros are automatically updated when one next
+uses macros such as <a class="reference internal" href="#polrefineinterval-sturmname-index">\PolRefineInterval*{sturmname}{index}</a>.</p>
+<p>The start of decimal expansion of a positive <span class="docutils literal">k</span>-th root is given
+by <a class="reference internal" href="#polsturmisolatedzeroleft">\PolSturmIsolatedZeroLeft{sturmname}{k}</a>, and for a negative root it is given
+by <a class="reference internal" href="#polsturmisolatedzeroright">PolSturmIsolatedZeroRight{sturmname}{k}</a>. These two decimal
+numbers are either both zero or both of the same sign.</p>
+<p>The number of distinct roots is obtainable expandably as
+<a class="reference internal" href="#polsturmnbofisolatedzeros-sturmname">\PolSturmNbOfIsolatedZeros{sturmname}</a>.</p>
+<p>Furthermore
+<a class="reference internal" href="#polsturmnbofrootsof-sturmname-lessthanorequalto-value">\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualTo{value}</a> and
+<a class="reference internal" href="#polsturmnbofrootsof-sturmname-lessthanorequaltoexpr-expression">\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualToExpr{expression}</a>.
+will expandably compute respectively the number of real roots at
+most equal to <span class="docutils literal">value</span> or <span class="docutils literal">expression</span>, and the same but with
+multiplicities.</p>
+<div class="admonition note">
+<p class="admonition-title">Note</p>
+<p>The current polexpr implementation defines the <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> variables
+and <a class="reference external" href="http://www.ctan.org/pkg/xint">xinttools</a> arrays described above with <strong>global scpe</strong>. On the
+other hand the Sturm sequence polynomials do obey the current scope.</p>
+</div>
+<div class="admonition note">
+<p class="admonition-title">Note</p>
+<p>As all computations are done <em>exactly</em> there can be no errors...
+apart those due to bad coding by author. The results are exact
+bounds for the mathematically exact real roots.</p>
+<p>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.</p>
+</div>
+</blockquote>
+</div>
+<div class="section" id="id15">
+<span id="id14"></span><h3><a class="toc-backref" href="#id117"><span class="docutils literal"><span class="pre">\PolSturmIsolateZeros*{sturmname}</span></span></a></h3>
+<blockquote>
+<p>The macro does the same as <a class="reference internal" href="#polsturmisolatezeros-sturmname">\PolSturmIsolateZeros{sturmname}</a> and
+then in addition it does the extra work to determine all
+multiplicities (of the real roots):
+after executing this macro,
+<a class="reference internal" href="#polsturmisolatedzeromultiplicity-sturmname-index">\PolSturmIsolatedZeroMultiplicity{sturmname}{index}</a> will expand
+to the multiplicity of the root located in the <span class="docutils literal">index</span>-th
+interval (intervals are enumerated from left to right, with index
+starting at <span class="docutils literal">1</span>).</p>
+<p>Furthermore, if for example the <span class="docutils literal">sturmname</span> is <span class="docutils literal">f</span>, <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a>
+variables <span class="docutils literal">fM_1</span>, <span class="docutils literal">fM_2</span>... hold the multiplicities thus
+computed.</p>
+<div class="admonition note">
+<p class="admonition-title">Note</p>
+<p>It is <strong>not</strong> necessary to have executed the <a class="reference internal" href="#id12">PolToSturm*</a> 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 <em>user-level</em>
+genuine polynomials.</p>
+</div>
+<p>See <a class="reference internal" href="#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</a> for an example.</p>
+</blockquote>
+</div>
+<div class="section" id="id17">
+<span id="id16"></span><h3><a class="toc-backref" href="#id118"><span class="docutils literal"><span class="pre">\PolSturmIsolateZeros**{sturmname}</span></span></a></h3>
+<blockquote>
+<p>The macro does the same as <a class="reference internal" href="#id15">\PolSturmIsolateZeros*{sturmname}</a> and
+in addition it does the extra work to determine all the <em>rational</em>
+roots.</p>
+<div class="admonition note">
+<p class="admonition-title">Note</p>
+<p>After execution of this macro, a root is &quot;known&quot; if and only if
+it is rational.</p>
+</div>
+<p>Furthermore, primitive polynomial <span class="docutils literal">sturmname_sqf_norr</span> is created
+to match the (square-free) <span class="docutils literal">sturmname_0</span> from which all rational
+roots have been removed (see <a class="reference internal" href="#polexprsetup">\polexprsetup</a> for customizing this
+name). The number of distinct rational roots is thus the difference
+between the degrees of these two polynomials (see also
+<a class="reference internal" href="#polsturmnbofrationalroots-sturmname">\PolSturmNbOfRationalRoots{sturmname}</a>).</p>
+<p>And <span class="docutils literal">sturmname_norr</span> is <span class="docutils literal">sturmname_0_</span> from which all rational
+roots have been removed (see <a class="reference internal" href="#polexprsetup">\polexprsetup</a>), i.e. it contains
+the irrational roots of the original polynomial, with the same
+multiplicities.</p>
+<p>See <a class="reference internal" href="#a-degree-five-polynomial-with-three-rational-roots">A degree five polynomial with three rational
+roots</a> for an example.</p>
+</blockquote>
+</div>
+<div class="section" id="polsturmisolatezerosandgetmultiplicities-sturmname">
+<span id="polsturmisolatezerosandgetmultiplicities"></span><h3><a class="toc-backref" href="#id119"><span class="docutils literal">\PolSturmIsolateZerosAndGetMultiplicities{sturmname}</span></a></h3>
+<blockquote>
+<p>This is another name for <a class="reference internal" href="#id15">\PolSturmIsolateZeros*{sturmname}</a>.</p>
+</blockquote>
+</div>
+<div class="section" id="polsturmisolatezerosgetmultiplicitiesandrationalroots-sturmname">
+<span id="polsturmisolatezerosgetmultiplicitiesandrationalroots"></span><h3><a class="toc-backref" href="#id120"><span class="docutils literal">\PolSturmIsolateZerosGetMultiplicitiesAndRationalRoots{sturmname}</span></a></h3>
+<blockquote>
+<p>This is another name for <a class="reference internal" href="#id17">\PolSturmIsolateZeros**{sturmname}</a>.</p>
+</blockquote>
+</div>
+<div class="section" id="polsturmisolatezerosandfindrationalroots-sturmname">
+<h3><a class="toc-backref" href="#id121"><span class="docutils literal">\PolSturmIsolateZerosAndFindRationalRoots{sturmname}</span></a></h3>
+<blockquote>
+<p>This works exactly like <a class="reference internal" href="#id17">\PolSturmIsolateZeros**{sturmname}</a>
+(inclusive of declaring the polynomials <span class="docutils literal">sturmname_sqf_norr</span> and
+<span class="docutils literal">sturmname_norr</span> with no rational roots) except that it does <em>not</em>
+compute the multiplicities of the <em>non-rational</em> roots.</p>
+<div class="admonition note">
+<p class="admonition-title">Note</p>
+<p>There is no macro to find the rational roots but not compute
+their multiplicities at the same time.</p>
+</div>
+<div class="admonition attention">
+<p class="admonition-title">Attention!</p>
+<p>This macro does <em>not</em> define <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> variables
+<span class="docutils literal">sturmnameM_1</span>, <span class="docutils literal">sturmnameM_2</span>, ... holding the
+multiplicities and it leaves the multiplicity array (whose accessor
+is <a class="reference internal" href="#polsturmisolatedzeromultiplicity-sturmname-index">\PolSturmIsolatedZeroMultiplicity{sturmname}{index}</a>) into
+a broken state, as all non-rational roots will supposedly have
+multiplicity one. This means that the output of
+<a class="reference internal" href="#id21">\PolPrintIntervals*</a> for example will be
+erroneous for the intervals with irrational roots.</p>
+<p>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 <em>any</em>
+rational root anyhow).</p>
+</div>
+</blockquote>
+</div>
+<div class="section" id="polrefineinterval-sturmname-index">
+<span id="polrefineinterval"></span><h3><a class="toc-backref" href="#id122"><span class="docutils literal"><span class="pre">\PolRefineInterval*{sturmname}{index}</span></span></a></h3>
+<blockquote>
+<p>The <span class="docutils literal">index</span>-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 <span class="docutils literal">k</span>th root is then
+strictly separated from the other roots.</p>
+</blockquote>
+</div>
+<div class="section" id="polrefineinterval-n-sturmname-index">
+<span id="polrefineinterval-n"></span><h3><a class="toc-backref" href="#id123"><span class="docutils literal"><span class="pre">\PolRefineInterval[N]{sturmname}{index}</span></span></a></h3>
+<blockquote>
+<p>The <span class="docutils literal">index</span>-th interval (starting count at one) is further
+subdivided once, reducing its length by a factor of 10. This is done
+<span class="docutils literal">N</span> times if the optional argument <span class="docutils literal">[N]</span> is present.</p>
+</blockquote>
+</div>
+<div class="section" id="polensureintervallength-sturmname-index-e">
+<span id="polensureintervallength"></span><h3><a class="toc-backref" href="#id124"><span class="docutils literal"><span class="pre">\PolEnsureIntervalLength{sturmname}{index}{E}</span></span></a></h3>
+<blockquote>
+<p>The <span class="docutils literal">index</span>-th interval is subdivided until its length becomes at
+most <span class="docutils literal">10^E</span>. This means (for <span class="docutils literal">E&lt;0</span>) that the first <span class="docutils literal"><span class="pre">-E</span></span> digits
+after decimal mark of the <span class="docutils literal">k</span>th root will then be known exactly.</p>
+</blockquote>
+</div>
+<div class="section" id="polensureintervallengths-sturmname-e">
+<span id="polensureintervallengths"></span><h3><a class="toc-backref" href="#id125"><span class="docutils literal"><span class="pre">\PolEnsureIntervalLengths{sturmname}{E}</span></span></a></h3>
+<blockquote>
+<p>The intervals as obtained from <span class="docutils literal">\PolSturmIsolateZeros</span> are (if
+necessary) subdivided further by (base 10) dichotomy in order for
+each of them to have length at most <span class="docutils literal">10^E</span> (length will be shorter
+than <span class="docutils literal">10^E</span> in output only if it did not change or became zero.)</p>
+<p>This means that decimal expansions of all roots will be known with
+<span class="docutils literal"><span class="pre">-E</span></span> digits (for <span class="docutils literal">E&lt;0</span>) after decimal mark.</p>
+</blockquote>
+</div>
+<div class="section" id="polprintintervals-varname-sturmname">
+<span id="polprintintervals"></span><h3><a class="toc-backref" href="#id126"><span class="docutils literal"><span class="pre">\PolPrintIntervals[varname]{sturmname}</span></span></a></h3>
+<blockquote>
+<p>This is a convenience macro which prints the bounds for the roots
+<span class="docutils literal">Z_1</span>, <span class="docutils literal">Z_2</span>, ... (the optional argument <span class="docutils literal">varname</span> allows to
+specify a replacement for the default <span class="docutils literal">Z</span>). This will be done (by
+default) in a
+math mode <span class="docutils literal">array</span>, one interval per row, and pattern <span class="docutils literal">rcccl</span>,
+where the second and fourth column hold the <span class="docutils literal">&lt;</span> sign, except when
+the interval reduces to a singleton, which means the root is known
+exactly.</p>
+<div class="admonition note">
+<p class="admonition-title">Note</p>
+<p>The explanations here and in this section are for LaTeX. With
+other TeX macro formats, the LaTeX syntax such as for example
+<span class="docutils literal"><span class="pre">\begin{array}{rcccl}</span></span> which appears in the documentation here
+is actually replaced with quasi-equivalent direct use of TeX
+primitives.</p>
+</div>
+<p>See next macros which govern its output.</p>
+</blockquote>
+<div class="section" id="polprintintervalsnorealroots">
+<h4><a class="toc-backref" href="#id127"><span class="docutils literal">\PolPrintIntervalsNoRealRoots</span></a></h4>
+<blockquote>
+<p>Executed in place of an <span class="docutils literal">array</span> environment, when there are no
+real roots. Default definition:</p>
+<pre class="literal-block">\newcommand\PolPrintIntervalsNoRealRoots{}</pre>
+</blockquote>
+</div>
+<div class="section" id="polprintintervalsbeginenv">
+<h4><a class="toc-backref" href="#id128"><span class="docutils literal">\PolPrintIntervalsBeginEnv</span></a></h4>
+<blockquote>
+<p>Default definition:</p>
+<pre class="literal-block">\newcommand\PolPrintIntervalsBeginEnv{\[\begin{array}{rcccl}}</pre>
+</blockquote>
+</div>
+<div class="section" id="polprintintervalsendenv">
+<h4><a class="toc-backref" href="#id129"><span class="docutils literal">\PolPrintIntervalsEndEnv</span></a></h4>
+<blockquote>
+<p>Default definition:</p>
+<pre class="literal-block">\newcommand\PolPrintIntervalsEndEnv{\end{array}\]}</pre>
+</blockquote>
+</div>
+<div class="section" id="polprintintervalsknownroot">
+<h4><a class="toc-backref" href="#id130"><span class="docutils literal">\PolPrintIntervalsKnownRoot</span></a></h4>
+<blockquote>
+<p>Default definition:</p>
+<pre class="literal-block">\newcommand\PolPrintIntervalsKnownRoot{%
+ &amp;&amp;\PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}%
+ &amp;=&amp;\PolPrintIntervalsPrintExactZero
+}</pre>
+</blockquote>
+</div>
+<div class="section" id="polprintintervalsunknownroot">
+<h4><a class="toc-backref" href="#id131"><span class="docutils literal">\PolPrintIntervalsUnknownRoot</span></a></h4>
+<blockquote>
+<p>Default definition:</p>
+<pre class="literal-block">\newcommand\PolPrintIntervalsUnknownRoot{%
+ \PolPrintIntervalsPrintLeftEndPoint&amp;&lt;&amp;%
+ \PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}&amp;&lt;&amp;%
+ \PolPrintIntervalsPrintRightEndPoint
+}</pre>
+</blockquote>
+</div>
+<div class="section" id="id18">
+<span id="polprintintervalsprintexactzero"></span><h4><a class="toc-backref" href="#id132"><span class="docutils literal">\PolPrintIntervalsPrintExactZero</span></a></h4>
+<blockquote>
+<p>Default definition:</p>
+<pre class="literal-block">\newcommand\PolPrintIntervalsPrintExactZero{\PolPrintIntervalsTheLeftEndPoint}</pre>
+</blockquote>
+</div>
+<div class="section" id="id19">
+<span id="polprintintervalsprintleftendpoint"></span><h4><a class="toc-backref" href="#id133"><span class="docutils literal">\PolPrintIntervalsPrintLeftEndPoint</span></a></h4>
+<blockquote>
+<p>Default definition:</p>
+<pre class="literal-block">\newcommand\PolPrintIntervalsPrintLeftEndPoint{\PolPrintIntervalsTheLeftEndPoint}</pre>
+</blockquote>
+</div>
+<div class="section" id="id20">
+<span id="polprintintervalsprintrightendpoint"></span><h4><a class="toc-backref" href="#id134"><span class="docutils literal">\PolPrintIntervalsPrintRightEndPoint</span></a></h4>
+<blockquote>
+<p>Default definition is:</p>
+<pre class="literal-block">\newcommand\PolPrintIntervalsPrintRightEndPoint{\PolPrintIntervalsTheRightEndPoint}</pre>
+</blockquote>
+</div>
+</div>
+<div class="section" id="id22">
+<span id="id21"></span><h3><a class="toc-backref" href="#id135"><span class="docutils literal"><span class="pre">\PolPrintIntervals*[varname]{sturmname}</span></span></a></h3>
+<blockquote>
+<p>This starred variant produces an alternative output (which
+displays the root multiplicity), and is provided as an
+example of customization.</p>
+<p>As replacement for <a class="reference internal" href="#polprintintervalsknownroot">\PolPrintIntervalsKnownRoot</a>,
+<a class="reference internal" href="#polprintintervalsprintexactzero">\PolPrintIntervalsPrintExactZero</a>,
+<a class="reference internal" href="#polprintintervalsunknownroot">\PolPrintIntervalsUnknownRoot</a> it uses its own
+<span class="docutils literal"><span class="pre">\POL&#64;&#64;PrintIntervals...</span></span> macros. We only reproduce here one
+definition:</p>
+<pre class="literal-block">\newcommand\POL&#64;&#64;PrintIntervalsPrintExactZero{%
+ \displaystyle
+ \xintSignedFrac{\PolPrintIntervalsTheLeftEndPoint}%
+}%</pre>
+<p>Multiplicities are printed using this auxiliary macro:</p>
+</blockquote>
+<div class="section" id="polprintintervalsprintmultiplicity">
+<h4><a class="toc-backref" href="#id136"><span class="docutils literal">\PolPrintIntervalsPrintMultiplicity</span></a></h4>
+<blockquote>
+<p>whose default definition is:</p>
+<pre class="literal-block">\newcommand\PolPrintIntervalsPrintMultiplicity{(\mbox{mult. }\PolPrintIntervalsTheMultiplicity)}</pre>
+</blockquote>
+</div>
+</div>
+</div>
+<div class="section" id="polmapcoeffs-macro-polname">
+<span id="polmapcoeffs"></span><h2><a class="toc-backref" href="#id137"><span class="docutils literal"><span class="pre">\PolMapCoeffs{\macro}{polname}</span></span></a></h2>
+<blockquote>
+<p>It modifies ('in-place': original coefficients get lost) each
+coefficient of the defined polynomial via the <em>expandable</em> macro
+<span class="docutils literal">\macro</span>. The degree is adjusted as necessary if some leading
+coefficients vanish after the operation. In replacement text of
+<span class="docutils literal">\macro</span>, <span class="docutils literal">\index</span> expands to the coefficient index (which is
+defined to be zero for the constant term).</p>
+<p>Notice that <span class="docutils literal">\macro</span> will have to handle inputs of the shape
+<span class="docutils literal">A/B[N]</span> (<a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a> internal notation). This means that it probably
+will have to be expressed in terms of macros from <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a> package.</p>
+<p>Example:</p>
+<pre class="literal-block">\def\foo#1{\xintMul{#1}{\the\numexpr\index*\index\relax}}</pre>
+<p>(or with <span class="docutils literal"><span class="pre">\xintSqr{\index}</span></span>) to replace <span class="docutils literal">n</span>-th coefficient
+<span class="docutils literal">f_n</span> by <span class="docutils literal">f_n*n^2</span>.</p>
+</blockquote>
+</div>
+<div class="section" id="polreducecoeffs-polname">
+<span id="polreducecoeffs"></span><h2><a class="toc-backref" href="#id138"><span class="docutils literal">\PolReduceCoeffs{polname}</span></a></h2>
+<blockquote>
+<p>About the same as <span class="docutils literal"><span class="pre">\PolMapCoeffs{\xintIrr}{polname}</span></span> (but
+maintaining a <span class="docutils literal">[0]</span> postfix for speedier <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a> parsing when
+polynomial function is used for computations.) This is a
+one-argument macro, working 'in-place'.</p>
+</blockquote>
+</div>
+<div class="section" id="id24">
+<span id="id23"></span><h2><a class="toc-backref" href="#id139"><span class="docutils literal"><span class="pre">\PolReduceCoeffs*{polname}</span></span></a></h2>
+<blockquote>
+<p>This starred variant leaves un-touched the decimal exponent in the
+internal representation of the fractional coefficients, i.e. if a
+coefficient is internally <span class="docutils literal">A/B[N]</span>, then <span class="docutils literal">A/B</span> is reduced to
+smallest terms, but the <span class="docutils literal">10^N</span> part is kept as is. Note: if the
+polynomial is freshly defined directly via <a class="reference internal" href="#polfromcsv">\PolFromCSV</a> its coefficients might still be internally in some
+format like <span class="docutils literal">1.5e7</span>; the macro will anyhow always first do the
+needed conversion to strict format <span class="docutils literal">A/B[N]</span>.</p>
+<p>Evaluations with polynomials treated by this can be much faster than
+with those handled by the non-starred variant
+<a class="reference internal" href="#polreducecoeffs-polname">\PolReduceCoeffs{polname}</a>: 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 <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a> macros used internally by
+<a class="reference internal" href="#polevalat">\PolEval</a>.</p>
+</blockquote>
+</div>
+<div class="section" id="polmakemonic-polname">
+<span id="polmakemonic"></span><h2><a class="toc-backref" href="#id140"><span class="docutils literal">\PolMakeMonic{polname}</span></a></h2>
+<blockquote>
+<p>Divides by the leading coefficient. It is recommended to execute
+<a class="reference internal" href="#id24">\PolReduceCoeffs*{polname}</a> 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.</p>
+</blockquote>
+</div>
+<div class="section" id="polmakeprimitive-polname">
+<span id="polmakeprimitive"></span><h2><a class="toc-backref" href="#id141"><span class="docutils literal">\PolMakePrimitive{polname}</span></a></h2>
+<blockquote>
+<p>Divides by the integer content see (<a class="reference internal" href="#policontent">\PolIContent</a>). This thus produces a polynomial with integer
+coefficients having no common factor. The sign of the leading
+coefficient is not modified.</p>
+</blockquote>
+</div>
+</div>
+<div class="section" id="expandable-macros">
+<h1><a class="toc-backref" href="#id142">Expandable macros</a></h1>
+<div class="admonition note">
+<p class="admonition-title">Note</p>
+<p>At <span class="docutils literal">0.8</span> <span class="docutils literal">polexpr</span> is usable with Plain TeX and not only with
+LaTeX. Some examples given in this section may be using LaTeX syntax
+such as <span class="docutils literal">\renewcommand</span>. Convert to TeX primitives as appropriate
+if testing with a non LaTeX macro format.</p>
+</div>
+<p>All these macros expand completely in two steps except <span class="docutils literal">\PolToExpr</span>
+and <span class="docutils literal">\PolToFloatExpr</span> (and their auxiliaries) which need a
+<span class="docutils literal">\write</span>, <span class="docutils literal">\edef</span> or a <span class="docutils literal"><span class="pre">\csname...\endcsname</span></span> context.</p>
+<div class="section" id="poleval-polname-atexpr-numerical-expression">
+<span id="polevalatexpr"></span><h2><a class="toc-backref" href="#id143"><span class="docutils literal"><span class="pre">\PolEval{polname}\AtExpr{numerical</span> expression}</span></a></h2>
+<blockquote>
+<p>It boils down to
+<span class="docutils literal">\xinttheexpr polname(numerical <span class="pre">expression)\relax</span></span>.</p>
+</blockquote>
+</div>
+<div class="section" id="poleval-polname-at-fraction">
+<span id="polevalat"></span><h2><a class="toc-backref" href="#id144"><span class="docutils literal"><span class="pre">\PolEval{polname}\At{fraction}</span></span></a></h2>
+<blockquote>
+<p>Evaluates the polynomial at value <span class="docutils literal">fraction</span> which must be in (or
+expand to) a format acceptable to the <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a> macros.</p>
+</blockquote>
+</div>
+<div class="section" id="polevalreduced-polname-atexpr-numerical-expression">
+<span id="polevalreducedatexpr"></span><h2><a class="toc-backref" href="#id145"><span class="docutils literal"><span class="pre">\PolEvalReduced{polname}\AtExpr{numerical</span> expression}</span></a></h2>
+<blockquote>
+<p>Boils down to <span class="docutils literal">\xinttheexpr reduce(polname(numerical <span class="pre">expression))\relax</span></span>.</p>
+</blockquote>
+</div>
+<div class="section" id="polevalreduced-polname-at-fraction">
+<span id="polevalreducedat"></span><h2><a class="toc-backref" href="#id146"><span class="docutils literal"><span class="pre">\PolEvalReduced{polname}\At{fraction}</span></span></a></h2>
+<blockquote>
+<p>Evaluates the polynomial at value <span class="docutils literal">fraction</span> which must be in (or
+expand to) a format acceptable to the <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a> macros, and produce
+an irreducible fraction.</p>
+</blockquote>
+</div>
+<div class="section" id="polfloateval-polname-atexpr-numerical-expression">
+<span id="polfloatevalatexpr"></span><h2><a class="toc-backref" href="#id147"><span class="docutils literal"><span class="pre">\PolFloatEval{polname}\AtExpr{numerical</span> expression}</span></a></h2>
+<blockquote>
+<p>Boils down to <span class="docutils literal">\xintthefloatexpr polname(numerical <span class="pre">expression)\relax</span></span>.</p>
+<p>This is done via a Horner Scheme (see <a class="reference internal" href="#poldef">\poldef</a> and
+<a class="reference internal" href="#polgenfloatvariant-polname">\PolGenFloatVariant{polname}</a>), with already rounded
+coefficients. <a class="footnote-reference brackets" href="#id27" id="id25">4</a> To use the <em>exact coefficients</em> with <em>exactly
+executed</em> additions and multiplications, just insert it in the float
+expression as in this example: <a class="footnote-reference brackets" href="#id28" id="id26">5</a></p>
+<pre class="literal-block">\xintthefloatexpr 3.27*\xintexpr f(2.53)\relax^2\relax</pre>
+<p>The <span class="docutils literal">f(2.53)</span> is exactly computed then rounded at the time of
+getting raised to the power <span class="docutils literal">2</span>. Moving the <span class="docutils literal">^2</span> inside, that
+operation would also be treated exactly.</p>
+<dl class="footnote brackets">
+<dt class="label" id="id27"><span class="brackets"><a class="fn-backref" href="#id25">4</a></span></dt>
+<dd><p>Anyway each floating point operation starts by rounding its
+operands to the floating point precision.</p>
+</dd>
+<dt class="label" id="id28"><span class="brackets"><a class="fn-backref" href="#id26">5</a></span></dt>
+<dd><p>The <span class="docutils literal">\xintexpr</span> here could be <span class="docutils literal">\xinttheexpr</span> but that
+would be less efficient. Cf. <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> documentation about
+nested expressions.</p>
+</dd>
+</dl>
+</blockquote>
+</div>
+<div class="section" id="polfloateval-polname-at-fraction">
+<span id="polfloatevalat"></span><h2><a class="toc-backref" href="#id148"><span class="docutils literal"><span class="pre">\PolFloatEval{polname}\At{fraction}</span></span></a></h2>
+<blockquote>
+<p>Evaluates the polynomial at value <span class="docutils literal">fraction</span> which must be in (or
+expand to) a format acceptable to the <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a> macros, and produces
+a floating point number.</p>
+</blockquote>
+</div>
+<div class="section" id="polifcoeffisplusorminusone-a-b">
+<span id="polifcoeffisplusorminusone"></span><h2><a class="toc-backref" href="#id149"><span class="docutils literal"><span class="pre">\PolIfCoeffIsPlusOrMinusOne{A}{B}</span></span></a></h2>
+<blockquote>
+<p>This macro is a priori undefined.</p>
+<p>It is defined via the default <a class="reference internal" href="#poltypesetcmd-raw-coeff">\PolTypesetCmd{raw_coeff}</a> to be
+used if needed in the execution of <a class="reference internal" href="#poltypesetmonomialcmd">\PolTypesetMonomialCmd</a>,
+e.g. to insert a <span class="docutils literal">\cdot</span> in front of <span class="docutils literal"><span class="pre">\PolVar^{\PolIndex}</span></span> if
+the coefficient is not plus or minus one.</p>
+<p>The macro will execute <span class="docutils literal">A</span> if the coefficient has been found to be
+plus or minus one, and <span class="docutils literal">B</span> if not.</p>
+</blockquote>
+</div>
+<div class="section" id="polleadingcoeff-polname">
+<span id="polleadingcoeff"></span><h2><a class="toc-backref" href="#id150"><span class="docutils literal">\PolLeadingCoeff{polname}</span></a></h2>
+<blockquote>
+<p>Expands to the leading coefficient.</p>
+</blockquote>
+</div>
+<div class="section" id="polnthcoeff-polname-number">
+<span id="polnthcoeff"></span><h2><a class="toc-backref" href="#id151"><span class="docutils literal"><span class="pre">\PolNthCoeff{polname}{number}</span></span></a></h2>
+<blockquote>
+<p>It expands to the raw <span class="docutils literal">N</span>-th coefficient (<span class="docutils literal">0/1[0]</span> if the index
+number is out of range). With <span class="docutils literal"><span class="pre">N=-1</span></span>, <span class="docutils literal"><span class="pre">-2</span></span>, ... expands to the
+leading coefficients.</p>
+</blockquote>
+</div>
+<div class="section" id="poldegree-polname">
+<span id="poldegree"></span><h2><a class="toc-backref" href="#id152"><span class="docutils literal">\PolDegree{polname}</span></a></h2>
+<blockquote>
+<p>It expands to the degree. This is <span class="docutils literal"><span class="pre">-1</span></span> if zero polynomial but this
+may change in future. Should it then expand to <span class="docutils literal"><span class="pre">-\infty</span></span> ?</p>
+</blockquote>
+</div>
+<div class="section" id="policontent-polname">
+<span id="policontent"></span><h2><a class="toc-backref" href="#id153"><span class="docutils literal">\PolIContent{polname}</span></a></h2>
+<blockquote>
+<p>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.</p>
+<p>See <a class="reference internal" href="#polmakeprimitive">\PolMakePrimitive</a>.</p>
+</blockquote>
+</div>
+<div class="section" id="poltoexpr-pol-expr">
+<span id="poltoexpr"></span><h2><a class="toc-backref" href="#id154"><span class="docutils literal"><span class="pre">\PolToExpr{&lt;pol.</span> <span class="pre">expr.&gt;}</span></span></a></h2>
+<blockquote>
+<p>Produces expandably <a class="footnote-reference brackets" href="#id30" id="id29">6</a> the string <span class="docutils literal"><span class="pre">coeff_N*x^N+...</span></span>, i.e. the
+polynomial is using descending powers.</p>
+<dl class="footnote brackets">
+<dt class="label" id="id30"><span class="brackets"><a class="fn-backref" href="#id29">6</a></span></dt>
+<dd><p>requires exhaustive expansion, for example as triggered by
+<span class="docutils literal">\write</span> or <span class="docutils literal">\edef</span>.</p>
+</dd>
+</dl>
+<p>Since <span class="docutils literal">0.8</span> the input is not restricted to be a polynomial name but
+is allowed to be an arbitrary expression (where by default the
+letter <span class="docutils literal">x</span> is recognized as the indeterminate; see
+<a class="reference internal" href="#poltoexprinvar">\PolToExprInVar</a>).</p>
+<p>The default output (which also by default uses the letter <span class="docutils literal">x</span> and is
+completely configurable, see in particular <a class="reference internal" href="#poltoexprvar">\PolToExprVar</a>) is
+compatible with both</p>
+<ul class="simple">
+<li><p>the Maple's input format,</p></li>
+<li><p>and the PSTricks <span class="docutils literal">\psplot[algebraic]</span> input format.</p></li>
+</ul>
+<p>Attention that it is not compatible with Python, but see
+<a class="reference internal" href="#poltoexprcaret">\PolToExprCaret</a> in this regard.</p>
+<p>It has the following characteristics:</p>
+<ul class="simple">
+<li><p>vanishing coefficients are skipped (issue <span class="docutils literal">\poltoexpralltrue</span> to
+override this and produce output such as <span class="docutils literal">x^3+0*x^2+0*x^1+0</span>),</p></li>
+<li><p>negative coefficients are not prefixed by a <span class="docutils literal">+</span> sign (else,
+Maple would not be happy),</p></li>
+<li><p>coefficients numerically equal to <span class="docutils literal">1</span> (or <span class="docutils literal"><span class="pre">-1</span></span>) are present
+only via their sign,</p></li>
+<li><p>the letter <span class="docutils literal">x</span> is used and the degree one monomial is output as
+<span class="docutils literal">x</span>, not as <span class="docutils literal">x^1</span>.</p></li>
+<li><p>(<span class="docutils literal">0.8</span>) the caret <span class="docutils literal">^</span> is of catcode 12. This means that one
+can for convenience typeset in regular text mode, for example
+using <span class="docutils literal">\texttt</span> (in LaTeX). But TeX will not know how to break
+the expression across end-of-lines anyhow. Formerly <span class="docutils literal">^</span> 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.</p></li>
+</ul>
+<p>Complete customization is possible, see the next macros. Any user
+redefinition must maintain the expandability property.</p>
+</blockquote>
+<div class="section" id="id31">
+<span id="poltoexprvar"></span><h3><a class="toc-backref" href="#id155"><span class="docutils literal">\PolToExprVar</span></a></h3>
+<blockquote>
+<p>Defaults to <span class="docutils literal">x</span>. The letter used in input.</p>
+</blockquote>
+</div>
+<div class="section" id="poltoexprinvar">
+<h3><a class="toc-backref" href="#id156"><span class="docutils literal">\PolToExprInVar</span></a></h3>
+<blockquote>
+<p>Defaults to <span class="docutils literal">x</span>: the letter used as the polynomial indeterminate.</p>
+<p>Recall that declared polynomials are more efficiently used in
+algebraic expressions without the <span class="docutils literal">(x)</span>, i.e. <span class="docutils literal">P*Q</span> is better
+than <span class="docutils literal"><span class="pre">P(x)*Q(x)</span></span>. Thus the input, even if an expression, does not
+have to contain any <span class="docutils literal">x</span>.</p>
+<p>(new with <span class="docutils literal">0.8</span>)</p>
+</blockquote>
+</div>
+<div class="section" id="id32">
+<span id="poltoexprtimes"></span><h3><a class="toc-backref" href="#id157"><span class="docutils literal">\PolToExprTimes</span></a></h3>
+<blockquote>
+<p>Defaults to <span class="docutils literal">*</span>.</p>
+</blockquote>
+</div>
+<div class="section" id="poltoexprcaret">
+<h3><a class="toc-backref" href="#id158"><span class="docutils literal">\PolToExprCaret</span></a></h3>
+<blockquote>
+<p>Defaults to <span class="docutils literal">^</span> of catcode 12. Set it to
+expand to <span class="docutils literal">**</span> for Python compatible output.</p>
+<p>(new with <span class="docutils literal">0.8</span>)</p>
+</blockquote>
+</div>
+<div class="section" id="poltoexprcmd-raw-coeff">
+<span id="poltoexprcmd"></span><h3><a class="toc-backref" href="#id159"><span class="docutils literal">\PolToExprCmd{raw_coeff}</span></a></h3>
+<blockquote>
+<p>Defaults to <span class="docutils literal"><span class="pre">\xintPRaw{\xintRawWithZeros{#1}}</span></span>.</p>
+<p>This means that the coefficient value is printed-out as a fraction
+<span class="docutils literal">a/b</span>, skipping the <span class="docutils literal">/b</span> part if <span class="docutils literal">b</span> turns out to be one.</p>
+<p>Configure it to be <span class="docutils literal"><span class="pre">\xintPRaw{\xintIrr{#1}}</span></span> if the fractions
+must be in irreducible terms.</p>
+<p>An alternative is <span class="docutils literal"><span class="pre">\xintDecToString{\xintREZ{#1}}</span></span> which uses
+integer or decimal fixed point format such as <span class="docutils literal">23.0071</span> if the
+internal representation of the number only has a power of ten as
+denominator (the effect of <span class="docutils literal">\xintREZ</span> here is to remove trailing
+decimal zeros). The behaviour of <span class="docutils literal">\xintDecToString</span> 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 <span class="docutils literal">23.007/2</span> or <span class="docutils literal">23.007/25</span> can appear in output
+and not their finite decimal expansion with no denominator.</p>
+</blockquote>
+</div>
+<div class="section" id="poltoexproneterm-raw-coeff-number">
+<span id="poltoexproneterm"></span><h3><a class="toc-backref" href="#id160"><span class="docutils literal"><span class="pre">\PolToExprOneTerm{raw_coeff}{number}</span></span></a></h3>
+<blockquote>
+<p>This is the macro which from the coefficient and the exponent
+produces the corresponding term in output, such as <span class="docutils literal">2/3*x^7</span>.</p>
+<p>For its default definition, see the source code. It uses
+<a class="reference internal" href="#poltoexprcmd">\PolToExprCmd</a>, <a class="reference internal" href="#poltoexprtimes">\PolToExprTimes</a>, <a class="reference internal" href="#poltoexprvar">\PolToExprVar</a> and
+<a class="reference internal" href="#poltoexprcaret">\PolToExprCaret</a>.</p>
+</blockquote>
+</div>
+<div class="section" id="poltoexpronetermstylea-raw-coeff-number">
+<span id="poltoexpronetermstylea"></span><h3><a class="toc-backref" href="#id161"><span class="docutils literal"><span class="pre">\PolToExprOneTermStyleA{raw_coeff}{number}</span></span></a></h3>
+<blockquote>
+<p>This holds the default package meaning of <span class="docutils literal">\PolToExprOneTerm</span>.</p>
+</blockquote>
+</div>
+<div class="section" id="poltoexpronetermstyleb-raw-coeff-number">
+<span id="poltoexpronetermstyleb"></span><h3><a class="toc-backref" href="#id162"><span class="docutils literal"><span class="pre">\PolToExprOneTermStyleB{raw_coeff}{number}</span></span></a></h3>
+<blockquote>
+<p>This holds an alternative meaning, which puts the fractional part of
+a coefficient after the monomial, i.e. like this:</p>
+<pre class="literal-block">2*x^11/3+3*x^8/7-x^5-x^4/4-x^3-x^2/2-2*x+1</pre>
+<p><a class="reference internal" href="#poltoexprcmd">\PolToExprCmd</a> isn't used at all in this style. But
+<a class="reference internal" href="#poltoexprtimes">\PolToExprTimes</a>, <a class="reference internal" href="#poltoexprvar">\PolToExprVar</a> and <a class="reference internal" href="#poltoexprcaret">\PolToExprCaret</a> are obeyed.</p>
+<p>To activate it use <span class="docutils literal">\let\PolToExprOneTerm\PolToExprOneTermStyleB</span>.
+To revert to the package default behaviour, issue
+<span class="docutils literal">\let\PolToExprOneTerm\PolToExprOneTermStyleA</span>.</p>
+</blockquote>
+</div>
+<div class="section" id="poltoexprtermprefix-raw-coeff">
+<span id="poltoexprtermprefix"></span><h3><a class="toc-backref" href="#id163"><span class="docutils literal">\PolToExprTermPrefix{raw_coeff}</span></a></h3>
+<blockquote>
+<p>It receives as argument the coefficient. Its default behaviour is
+to produce a <span class="docutils literal">+</span> if the coefficient is positive, which will thus
+serve to separate the monomials in the output. This is to match
+the default for <a class="reference internal" href="#poltoexprcmd-raw-coeff">\PolToExprCmd{raw_coeff}</a> which in case of a
+positive coefficient does not output an explicit <span class="docutils literal">+</span> prefix.</p>
+</blockquote>
+</div>
+</div>
+<div class="section" id="id34">
+<span id="id33"></span><h2><a class="toc-backref" href="#id164"><span class="docutils literal"><span class="pre">\PolToExpr*{&lt;pol.</span> <span class="pre">expr.&gt;}</span></span></a></h2>
+<blockquote>
+<p>Ascending powers: <span class="docutils literal"><span class="pre">coeff_0+coeff_1*x+coeff_2*x^2+...</span></span>.</p>
+<p>Extended at <span class="docutils literal">0.8</span> to accept general expressions as input.</p>
+<p>Customizable with the same macros as for
+<a class="reference internal" href="#poltoexpr-pol-expr">\PolToExpr{&lt;pol. expr.&gt;}</a>.</p>
+</blockquote>
+</div>
+<div class="section" id="poltofloatexpr-pol-expr">
+<span id="poltofloatexpr"></span><h2><a class="toc-backref" href="#id165"><span class="docutils literal"><span class="pre">\PolToFloatExpr{&lt;pol.</span> <span class="pre">expr.&gt;}</span></span></a></h2>
+<blockquote>
+<p>Similar to <a class="reference internal" href="#poltoexpr-pol-expr">\PolToExpr{&lt;pol. expr.&gt;}</a> but using <a class="reference external" href="\PolToFloatExprCmd{raw_coeff}">\PolToFloatExprCmd</a> which by default rounds and
+converts the coefficients to floating point format.</p>
+<div class="admonition note">
+<p class="admonition-title">Note</p>
+<p>This is unrelated to <a class="reference internal" href="#polgenfloatvariant-polname">\PolGenFloatVariant{polname}</a>:
+<a class="reference internal" href="#poltofloatexprcmd-raw-coeff">\PolToFloatExprCmd{raw_coeff}</a> operates on the <em>exact</em>
+coefficients anew (and may thus produce something else than
+the coefficients of the polynomial function acting
+in <span class="docutils literal">\xintfloateval</span> if the floating point precision was changed
+in between).</p>
+</div>
+<p>Extended at <span class="docutils literal">0.8</span> to accept general expressions as input.</p>
+</blockquote>
+<div class="section" id="poltofloatexproneterm-raw-coeff-number">
+<span id="poltofloatexproneterm"></span><h3><a class="toc-backref" href="#id166"><span class="docutils literal"><span class="pre">\PolToFloatExprOneTerm{raw_coeff}{number}</span></span></a></h3>
+<blockquote>
+<p>Similar to <a class="reference external" href="\PolToExprOneTerm{raw_coeff}{number}">\PolToExprOneTerm</a>. But does not treat
+especially coefficients equal to plus or minus one.</p>
+</blockquote>
+</div>
+<div class="section" id="poltofloatexprcmd-raw-coeff">
+<span id="id36"></span><h3><a class="toc-backref" href="#id167"><span class="docutils literal">\PolToFloatExprCmd{raw_coeff}</span></a></h3>
+<blockquote>
+<p>The one-argument macro used by <span class="docutils literal">\PolToFloatExprOneTerm</span>.
+It defaults to <span class="docutils literal"><span class="pre">\xintFloat{#1}</span></span>.</p>
+<div class="admonition caution">
+<p class="admonition-title">Caution!</p>
+<p>Currently <span class="docutils literal">\xintFloat{0}</span> outputs <span class="docutils literal">0.e0</span>
+which is perfectly acceptable input for Python, but not for
+Maple. Thus, one should better leave the <span class="docutils literal">\\ifpoltoexprall</span> TeX
+Boolean to its default <a class="reference internal" href="#poltoexprallfalse">\poltoexprallfalse</a>, if one intends to use
+the output in a Maple worksheet.</p>
+<p>But even then the zero polynomial will cause a problem. Workaround:</p>
+<pre class="literal-block">\renewcommand\PolToFloatExprCmd[1]{\xintiiifZero{#1}{0.0}{\xintFloat{#1}}}</pre>
+<p>Usage of <span class="docutils literal">\xintiiifZero</span> and not <span class="docutils literal">\xintifZero</span> is only for
+optimization (I can't help it) because <span class="docutils literal">#1</span> is known to be
+in <span class="docutils literal">xintfrac</span> raw format.</p>
+</div>
+</blockquote>
+</div>
+</div>
+<div class="section" id="id38">
+<span id="id37"></span><h2><a class="toc-backref" href="#id168"><span class="docutils literal"><span class="pre">\PolToFloatExpr*{&lt;pol.</span> <span class="pre">expr.&gt;}</span></span></a></h2>
+<blockquote>
+<p>Ascending powers.</p>
+<p>Extended at <span class="docutils literal">0.8</span> to accept general expressions as input.</p>
+</blockquote>
+</div>
+<div class="section" id="poltolist-polname">
+<span id="poltolist"></span><h2><a class="toc-backref" href="#id169"><span class="docutils literal">\PolToList{polname}</span></a></h2>
+<blockquote>
+<p>Expands to <span class="docutils literal"><span class="pre">{coeff_0}{coeff_1}...{coeff_N}</span></span> with <span class="docutils literal">N</span> = degree, and
+<span class="docutils literal">coeff_N</span> the leading coefficient
+(the zero polynomial does give <span class="docutils literal">{0/1[0]}</span> and not an
+empty output.)</p>
+</blockquote>
+</div>
+<div class="section" id="poltocsv-polname">
+<span id="poltocsv"></span><h2><a class="toc-backref" href="#id170"><span class="docutils literal">\PolToCSV{polname}</span></a></h2>
+<blockquote>
+<p>Expands to <span class="docutils literal">coeff_0, coeff_1, coeff_2, <span class="pre">.....,</span> coeff_N</span>, starting
+with constant term and ending with leading coefficient. Converse
+to <a class="reference internal" href="#polfromcsv-polname-csv">\PolFromCSV</a>.</p>
+</blockquote>
+</div>
+<div class="section" id="expandable-macros-related-to-the-root-localization-routines">
+<h2><a class="toc-backref" href="#id171">Expandable macros related to the root localization routines</a></h2>
+<div class="section" id="polsturmchainlength-sturmname">
+<span id="polsturmchainlength"></span><h3><a class="toc-backref" href="#id172"><span class="docutils literal">\PolSturmChainLength{sturmname}</span></a></h3>
+<blockquote>
+<p>Returns the integer <span class="docutils literal">N</span> such that <span class="docutils literal">sturmname_N</span> is the last one
+in the Sturm chain <span class="docutils literal">sturmname_0</span>, <span class="docutils literal">sturmname_1</span>, ...</p>
+<p>See <a class="reference internal" href="#poltosturm-polname-sturmname">\PolToSturm{polname}{sturmname}</a>.</p>
+</blockquote>
+</div>
+<div class="section" id="polsturmifzeroexactlyknown-sturmname-index-a-b">
+<span id="polsturmifzeroexactlyknown"></span><h3><a class="toc-backref" href="#id173"><span class="docutils literal"><span class="pre">\PolSturmIfZeroExactlyKnown{sturmname}{index}{A}{B}</span></span></a></h3>
+<blockquote>
+<p>Executes <span class="docutils literal">A</span> if the <span class="docutils literal">index</span>-th interval reduces to a singleton,
+i.e. the root is known exactly, else <span class="docutils literal">B</span>.</p>
+<div class="admonition note">
+<p class="admonition-title">Note</p>
+<p><span class="docutils literal">index</span> is allowed to be something like <span class="docutils literal">1+2*3</span> as it is fed
+to <span class="docutils literal"><span class="pre">\the\numexpr...\relax</span></span>.</p>
+</div>
+</blockquote>
+</div>
+<div class="section" id="polsturmisolatedzeroleft-sturmname-index">
+<span id="polsturmisolatedzeroleft"></span><h3><a class="toc-backref" href="#id174"><span class="docutils literal"><span class="pre">\PolSturmIsolatedZeroLeft{sturmname}{index}</span></span></a></h3>
+<blockquote>
+<p>Expands to the left end-point for the <span class="docutils literal">index</span>-th interval, as
+computed by some earlier <a class="reference internal" href="#polsturmisolatezeros-sturmname">\PolSturmIsolateZeros{sturmname}</a>.</p>
+<div class="admonition note">
+<p class="admonition-title">Note</p>
+<p>Of course, this is kept updated by macros such as
+<a class="reference internal" href="#polrefineinterval-n">\PolRefineInterval{sturmname}{index}</a>.</p>
+</div>
+<p>The value is pre-formatted using <a class="reference internal" href="#poldectostring">\PolDecTostring</a>.</p>
+</blockquote>
+</div>
+<div class="section" id="polsturmisolatedzeroright-sturmname-index">
+<span id="polsturmisolatedzeroright"></span><h3><a class="toc-backref" href="#id175"><span class="docutils literal"><span class="pre">\PolSturmIsolatedZeroRight{sturmname}{index}</span></span></a></h3>
+<blockquote>
+<p>Expands to the right end-point for the <span class="docutils literal">index</span>-th interval as
+computed by some earlier <a class="reference internal" href="#polsturmisolatezeros-sturmname">\PolSturmIsolateZeros{sturmname}</a> and
+possibly refined afterwards.</p>
+<p>The value is pre-formatted using <a class="reference internal" href="#poldectostring">\PolDecTostring</a>.</p>
+</blockquote>
+</div>
+<div class="section" id="polsturmisolatedzeromultiplicity-sturmname-index">
+<span id="polsturmisolatedzeromultiplicity"></span><h3><a class="toc-backref" href="#id176"><span class="docutils literal"><span class="pre">\PolSturmIsolatedZeroMultiplicity{sturmname}{index}</span></span></a></h3>
+<blockquote>
+<p>Expands to the multiplicity of the unique root contained in the
+<span class="docutils literal">index</span>-th interval.</p>
+<div class="admonition attention">
+<p class="admonition-title">Attention!</p>
+<p>A prior execution of <a class="reference internal" href="#id15">\PolSturmIsolateZeros*{sturmname}</a> is mandatory.</p>
+</div>
+<p>See <a class="reference internal" href="#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</a> for an example of use.</p>
+</blockquote>
+</div>
+<div class="section" id="polsturmnbofisolatedzeros-sturmname">
+<span id="polsturmnbofisolatedzeros"></span><h3><a class="toc-backref" href="#id177"><span class="docutils literal">\PolSturmNbOfIsolatedZeros{sturmname}</span></a></h3>
+<blockquote>
+<p>Expands to the number of real roots of the polynomial
+<span class="docutils literal">&lt;sturmname&gt;_0</span>, i.e. the number of distinct real roots of the
+polynomial originally used to create the Sturm chain via
+<a class="reference internal" href="#poltosturm-polname-sturmname">\PolToSturm{polname}{sturmname}</a>.</p>
+</blockquote>
+<div class="admonition warning">
+<p class="admonition-title">Warning</p>
+<p>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.</p>
+</div>
+</div>
+<div class="section" id="polsturmnbofrootsof-sturmname-lessthanorequalto-value">
+<h3><a class="toc-backref" href="#id178"><span class="docutils literal"><span class="pre">\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualTo{value}</span></span></a></h3>
+<blockquote>
+<p>Expands to the number of distinct roots (of the polynomial used to
+create the Sturm chain) less than or equal to the <span class="docutils literal">value</span> (i.e. a
+number of fraction recognizable by the <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a> macros).</p>
+<div class="admonition attention">
+<p class="admonition-title">Attention!</p>
+<p><a class="reference internal" href="#polsturmisolatezeros-sturmname">\PolSturmIsolateZeros{sturmname}</a> must have been executed
+beforehand.</p>
+<p>And the argument is a <span class="docutils literal">sturmname</span>, not a <span class="docutils literal">polname</span> (this is
+why the macro contains Sturm in its name), simply to be reminded
+of the above constraint.</p>
+</div>
+</blockquote>
+</div>
+<div class="section" id="polsturmnbofrootsof-sturmname-lessthanorequaltoexpr-expression">
+<h3><a class="toc-backref" href="#id179"><span class="docutils literal"><span class="pre">\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualToExpr{expression}</span></span></a></h3>
+<blockquote>
+<p>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 <span class="docutils literal">expression</span>.</p>
+<div class="admonition attention">
+<p class="admonition-title">Attention!</p>
+<p><a class="reference internal" href="#polsturmisolatezeros-sturmname">\PolSturmIsolateZeros{sturmname}</a> must have been executed
+beforehand.</p>
+</div>
+</blockquote>
+</div>
+<div class="section" id="polsturmnbwithmultofrootsof-sturmname-lessthanorequalto-value">
+<h3><a class="toc-backref" href="#id180"><span class="docutils literal"><span class="pre">\PolSturmNbWithMultOfRootsOf{sturmname}\LessThanOrEqualTo{value}</span></span></a></h3>
+<blockquote>
+<p>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 <span class="docutils literal">value</span>.</p>
+<div class="admonition attention">
+<p class="admonition-title">Attention!</p>
+<p><a class="reference internal" href="#id15">\PolSturmIsolateZeros*{sturmname}</a> (or the double starred
+variant) must have been executed beforehand.</p>
+</div>
+</blockquote>
+</div>
+<div class="section" id="polsturmnbwithmultofrootsof-sturmname-lessthanorequaltoexpr-expression">
+<h3><a class="toc-backref" href="#id181"><span class="docutils literal"><span class="pre">\PolSturmNbWithMultOfRootsOf{sturmname}\LessThanOrEqualToExpr{expression}</span></span></a></h3>
+<blockquote>
+<p>Expands to the total number of roots (counted with multiplicities)
+which are less than or equal to the given <span class="docutils literal">expression</span>.</p>
+<div class="admonition attention">
+<p class="admonition-title">Attention!</p>
+<p><a class="reference internal" href="#id15">\PolSturmIsolateZeros*{sturmname}</a> (or the double starred
+variant) must have been executed beforehand.</p>
+</div>
+</blockquote>
+</div>
+<div class="section" id="polsturmnbofrationalroots-sturmname">
+<h3><a class="toc-backref" href="#id182"><span class="docutils literal">\PolSturmNbOfRationalRoots{sturmname}</span></a></h3>
+<blockquote>
+<p>Expands to the number of rational roots (without multiplicities).</p>
+<div class="admonition attention">
+<p class="admonition-title">Attention!</p>
+<p><a class="reference internal" href="#id17">\PolSturmIsolateZeros**{sturmname}</a> must have been executed
+beforehand.</p>
+</div>
+</blockquote>
+</div>
+<div class="section" id="polsturmnbofrationalrootswithmultiplicities-sturmname">
+<h3><a class="toc-backref" href="#id183"><span class="docutils literal">\PolSturmNbOfRationalRootsWithMultiplicities{sturmname}</span></a></h3>
+<blockquote>
+<p>Expands to the number of rational roots (counted with multiplicities).</p>
+<div class="admonition attention">
+<p class="admonition-title">Attention!</p>
+<p><a class="reference internal" href="#id17">\PolSturmIsolateZeros**{sturmname}</a> must have been executed
+beforehand.</p>
+</div>
+</blockquote>
+</div>
+<div class="section" id="polsturmrationalroot-sturmname-k">
+<h3><a class="toc-backref" href="#id184"><span class="docutils literal"><span class="pre">\PolSturmRationalRoot{sturmname}{k}</span></span></a></h3>
+<blockquote>
+<p>Expands to the <span class="docutils literal">k</span>th rational root (they are ordered and indexed
+starting at 1 for the most negative).</p>
+<div class="admonition attention">
+<p class="admonition-title">Attention!</p>
+<p><a class="reference internal" href="#id17">\PolSturmIsolateZeros**{sturmname}</a> must have been executed
+beforehand.</p>
+</div>
+</blockquote>
+</div>
+<div class="section" id="polsturmrationalrootindex-sturmname-k">
+<h3><a class="toc-backref" href="#id185"><span class="docutils literal"><span class="pre">\PolSturmRationalRootIndex{sturmname}{k}</span></span></a></h3>
+<blockquote>
+<p>Expands to <span class="docutils literal">index</span> of the <span class="docutils literal">k</span>th rational root as part of the
+ordered real roots (without multiplicities). I.e., above macro
+<a class="reference internal" href="#polsturmrationalroot-sturmname-k">\PolSturmRationalRoot{sturmname}{k}</a> is equivalent to this
+nested call:</p>
+<pre class="literal-block">\PolSturmIsolatedZeroLeft{sturmname}{\PolSturmRationalRootIndex{sturmname}{k}}</pre>
+<div class="admonition attention">
+<p class="admonition-title">Attention!</p>
+<p><a class="reference internal" href="#id17">\PolSturmIsolateZeros**{sturmname}</a> must have been executed
+beforehand.</p>
+</div>
+</blockquote>
+</div>
+<div class="section" id="polsturmrationalrootmultiplicity-sturmname-k">
+<h3><a class="toc-backref" href="#id186"><span class="docutils literal"><span class="pre">\PolSturmRationalRootMultiplicity{sturmname}{k}</span></span></a></h3>
+<blockquote>
+<p>Expands to the multiplicity of the <span class="docutils literal">k</span>th rational root.</p>
+<div class="admonition attention">
+<p class="admonition-title">Attention!</p>
+<p><a class="reference internal" href="#id17">\PolSturmIsolateZeros**{sturmname}</a> must have been executed
+beforehand.</p>
+</div>
+</blockquote>
+</div>
+<div class="section" id="polintervalwidth-sturmname-index">
+<span id="polintervalwidth"></span><h3><a class="toc-backref" href="#id187"><span class="docutils literal"><span class="pre">\PolIntervalWidth{sturmname}{index}</span></span></a></h3>
+<blockquote>
+<p>The <span class="docutils literal">10^E</span> width of the current <span class="docutils literal">index</span>-th root localization
+interval. Output is in <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a> raw <span class="docutils literal">1/1[E]</span> format (if not zero).</p>
+</blockquote>
+</div>
+</div>
+<div class="section" id="expandable-macros-for-use-within-execution-of-polprintintervals">
+<h2><a class="toc-backref" href="#id188">Expandable macros for use within execution of <span class="docutils literal">\PolPrintIntervals</span></a></h2>
+<p>These macros are for usage within custom user redefinitions of
+<a class="reference internal" href="#polprintintervalsknownroot">\PolPrintIntervalsKnownRoot</a>, <a class="reference internal" href="#polprintintervalsunknownroot">\PolPrintIntervalsUnknownRoot</a>, or
+in redefinitions of <a class="reference internal" href="#polprintintervalsprintexactzero">PolPrintIntervalsPrintExactZero</a> (used in the
+default for the former) and of <a class="reference internal" href="#polprintintervalsprintleftendpoint">\PolPrintIntervalsPrintLeftEndPoint</a>,
+<a class="reference internal" href="#polprintintervalsprintrightendpoint">\PolPrintIntervalsPrintRightEndPoint</a> (used in the default for the
+latter).</p>
+<div class="admonition attention">
+<p class="admonition-title">Attention!</p>
+<p>Some macros formerly mentioned here got removed at 0.7:
+<span class="docutils literal">\PolPrintIntervalsTheEndPoint</span>,
+<span class="docutils literal"><span class="pre">\PolIfEndPointIsPositive{A}{B}</span></span>,
+<span class="docutils literal"><span class="pre">\PolIfEndPointIsNegative{A}{B}</span></span>,
+<span class="docutils literal"><span class="pre">\PolIfEndPointIsZero{A}{B}</span></span>.</p>
+</div>
+<div class="section" id="polprintintervalsthevar">
+<h3><a class="toc-backref" href="#id189"><span class="docutils literal">\PolPrintIntervalsTheVar</span></a></h3>
+<blockquote>
+<p>Expands to the name (default <span class="docutils literal">Z</span>) used for representing the roots,
+which was passed as optional argument <span class="docutils literal">varname</span> to
+<a class="reference internal" href="#polprintintervals-varname-sturmname">\PolPrintIntervals[varname]{sturmname}</a>.</p>
+</blockquote>
+</div>
+<div class="section" id="polprintintervalstheindex">
+<h3><a class="toc-backref" href="#id190"><span class="docutils literal">\PolPrintIntervalsTheIndex</span></a></h3>
+<blockquote>
+<p>Expands to the index of the considered interval (indexing starting
+at 1 for the leftmost interval).</p>
+</blockquote>
+</div>
+<div class="section" id="polprintintervalsthesturmname">
+<h3><a class="toc-backref" href="#id191"><span class="docutils literal">\PolPrintIntervalsTheSturmName</span></a></h3>
+<blockquote>
+<p>Expands to the argument which was passed as <span class="docutils literal">sturmname</span> to
+<a class="reference internal" href="#polprintintervals-varname-sturmname">\PolPrintIntervals[varname]{sturmname}</a>.</p>
+</blockquote>
+</div>
+<div class="section" id="polprintintervalstheleftendpoint">
+<h3><a class="toc-backref" href="#id192"><span class="docutils literal">\PolPrintIntervalsTheLeftEndPoint</span></a></h3>
+<blockquote>
+<p>The left end point of the interval, as would be produced by
+<a class="reference internal" href="#polsturmisolatedzeroleft">\PolSturmIsolatedZeroLeft</a> if it was
+used with arguments the Sturm chain name and interval index returned
+by <a class="reference internal" href="#polprintintervalsthesturmname">\PolPrintIntervalsTheSturmName</a> and
+<a class="reference internal" href="#polprintintervalstheindex">\PolPrintIntervalsTheIndex</a>.</p>
+</blockquote>
+</div>
+<div class="section" id="polprintintervalstherightendpoint">
+<h3><a class="toc-backref" href="#id193"><span class="docutils literal">\PolPrintIntervalsTheRightEndPoint</span></a></h3>
+<blockquote>
+<p>The right end point of the interval, as would be produced by
+<a class="reference internal" href="#polsturmisolatedzeroright">\PolSturmIsolatedZeroRight</a> for
+this Sturm chain name and index.</p>
+</blockquote>
+</div>
+<div class="section" id="polprintintervalsthemultiplicity">
+<h3><a class="toc-backref" href="#id194"><span class="docutils literal">\PolPrintIntervalsTheMultiplicity</span></a></h3>
+<blockquote>
+<p>The multiplicity of the unique root within the interval of index
+<a class="reference internal" href="#polprintintervalstheindex">\PolPrintIntervalsTheIndex</a>. Makes sense only if the starred (or
+double-starred) variant of <a class="reference internal" href="#polsturmisolatezeros">\PolSturmIsolateZeros</a> was used earlier.</p>
+</blockquote>
+</div>
+</div>
+</div>
+<div class="section" id="booleans-with-default-setting-as-indicated">
+<h1><a class="toc-backref" href="#id195">Booleans (with default setting as indicated)</a></h1>
+<div class="section" id="xintverbosefalse">
+<h2><a class="toc-backref" href="#id196"><span class="docutils literal">\xintverbosefalse</span></a></h2>
+<blockquote>
+<p>This is actually an <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> configuration. Setting it to
+<span class="docutils literal">true</span> triggers the writing of information to the log when new
+polynomial or scalar variables are defined.</p>
+<div class="admonition caution">
+<p class="admonition-title">Caution!</p>
+<p>The macro and variable meanings as written to the log are to be
+considered unstable and undocumented internal structures.</p>
+</div>
+</blockquote>
+</div>
+<div class="section" id="polnewpolverbosefalse">
+<h2><a class="toc-backref" href="#id197"><span class="docutils literal">\polnewpolverbosefalse</span></a></h2>
+<blockquote>
+<p>When <span class="docutils literal">\poldef</span> is used, both a variable and a function are
+defined. The default <span class="docutils literal">\polnewpolverbosefalse</span> 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.</p>
+<p>However <a class="reference internal" href="#polgenfloatvariant-polname">\PolGenFloatVariant{polname}</a> does still print out the
+information relative to the polynomial function it defines for use in
+<span class="docutils literal">\xintfloateval{}</span> as there is no float polynomial variable, only the
+function, and it is the only way to see its rounded coefficients
+(<span class="docutils literal">\xintverbosefalse</span> suppresses also that info).</p>
+<p>If set to <span class="docutils literal">true</span>, it overrides in both cases
+<span class="docutils literal">\xintverbosefalse</span>. The setting only affects polynomial
+declarations. Scalar variables such as those holding information on
+roots obey only the <span class="docutils literal"><span class="pre">\xintverbose...</span></span> setting.</p>
+<p>(new with <span class="docutils literal">0.8</span>)</p>
+</blockquote>
+</div>
+<div class="section" id="poltypesetallfalse">
+<h2><a class="toc-backref" href="#id198"><span class="docutils literal">\poltypesetallfalse</span></a></h2>
+<blockquote>
+<p>If <span class="docutils literal">true</span>, <a class="reference internal" href="#poltypeset">\PolTypeset</a> will also typeset the vanishing
+coefficients.</p>
+</blockquote>
+</div>
+<div class="section" id="poltoexprallfalse">
+<h2><a class="toc-backref" href="#id199"><span class="docutils literal">\poltoexprallfalse</span></a></h2>
+<blockquote>
+<p>If <span class="docutils literal">true</span>, <a class="reference internal" href="#poltoexpr-pol-expr">\PolToExpr{&lt;pol. expr.&gt;}</a> and <a class="reference internal" href="#poltofloatexpr-pol-expr">\PolToFloatExpr{&lt;pol. expr.&gt;}</a> will
+also include the vanishing coefficients in their outputs.</p>
+</blockquote>
+</div>
+</div>
+<div class="section" id="utilies">
+<h1><a class="toc-backref" href="#id200">Utilies</a></h1>
+<div class="section" id="poldectostring-decimal-number">
+<span id="poldectostring"></span><h2><a class="toc-backref" href="#id201"><span class="docutils literal">\PolDecToString{decimal number}</span></a></h2>
+<blockquote>
+<p>This is a utility macro to print decimal numbers. It has been
+backported to <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a> (release <span class="docutils literal">1.3</span> of <span class="docutils literal">2018/03/01</span>) under
+the name <span class="docutils literal">\xintDecToString</span>, and the <span class="docutils literal">polexpr</span> macro is simply
+now an alias to it.</p>
+<p>For example
+<span class="docutils literal"><span class="pre">\PolDecToString{123.456e-8}</span></span> will expand to <span class="docutils literal">0.00000123456</span>
+and <span class="docutils literal"><span class="pre">\PolDecToString{123.450e-8}</span></span> to <span class="docutils literal">0.00000123450</span> which
+illustrates that trailing zeros are not trimmed. To trim trailing
+zeroes, one can use <span class="docutils literal"><span class="pre">\PolDecToString{\xintREZ{#1}}</span></span>.</p>
+<p>The precise behaviour of this macro may evolve in future releases of
+<a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a>.</p>
+</blockquote>
+</div>
+<div class="section" id="polexprsetup">
+<h2><a class="toc-backref" href="#id202"><span class="docutils literal">\polexprsetup</span></a></h2>
+<blockquote>
+<p>Serves to customize the package. Currently only two keys are
+recognized:</p>
+<ul class="simple">
+<li><p><span class="docutils literal">norr</span>: the postfix that <a class="reference internal" href="#id17">\PolSturmIsolateZeros**{sturmname}</a>
+should append to <span class="docutils literal">sturmname</span> to declare the primitive polynomial
+obtained from original one after removal of all rational roots.
+The default value is <span class="docutils literal">_norr</span> (standing for “no rational roots”).</p></li>
+<li><p><span class="docutils literal">sqfnorr</span>: the postfix that <a class="reference internal" href="#id17">\PolSturmIsolateZeros**{sturmname}</a>
+should append to <span class="docutils literal">sturmname</span> to declare the primitive polynomial
+obtained from original one after removal of all rational roots and
+suppression of all multiplicities.
+The default value is <span class="docutils literal">_sqf_norr</span> (standing for “square-free with
+no rational roots”).</p></li>
+</ul>
+<p>The package executes <span class="docutils literal">\polexprsetup{norr=_norr, sqfnorr=_sqf_norr}</span> as default.</p>
+</blockquote>
+</div>
+</div>
+<div class="section" id="technicalities">
+<h1><a class="toc-backref" href="#id203">Technicalities</a></h1>
+<ul>
+<li><p>The catcode of the semi-colon is reset temporarily by <a class="reference internal" href="#poldef">\poldef</a> macro in case some other package (for example the French
+babel module) may have made it active. This will fail though if the
+whole thing was already part of a macro argument, in such cases one
+can use <a class="reference internal" href="#id8">\PolDef{f}{P(x)}</a>
+rather. The colon in <span class="docutils literal">:=</span> may be active with no consequences.</p></li>
+<li><p>As a consequence of <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a> addition and subtraction always using
+least common multiples for the denominators <a class="footnote-reference brackets" href="#id40" id="id39">7</a>, user-chosen common
+denominators survive additions and multiplications. For example, this:</p>
+<pre class="literal-block">\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;</pre>
+<p>gives internally the polynomial:</p>
+<pre class="literal-block">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</pre>
+<p>where all coefficients have the same denominator 6. Notice though that
+<span class="docutils literal">\PolToExpr{PQ}</span> outputs the <span class="docutils literal">6/6*x^3</span> as <span class="docutils literal">x^3</span> because (by
+default) it recognizes and filters out coefficients equal to one or
+minus one (since release <span class="docutils literal">0.3</span>). One can use for example
+<span class="docutils literal">\PolToCSV{PQ}</span> to see the internally stored coefficients.</p>
+<dl class="footnote brackets">
+<dt class="label" id="id40"><span class="brackets"><a class="fn-backref" href="#id39">7</a></span></dt>
+<dd><p>prior to <span class="docutils literal">0.4.1</span>, <span class="docutils literal">polexpr</span> used to temporarily patch
+during the parsing of polynomials the <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a> macros. This
+patch was backported to <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> at release <span class="docutils literal">1.3</span>.</p>
+</dd>
+</dl>
+</li>
+<li><p><a class="reference internal" href="#poldiff-polname-1-polname-2">\PolDiff{polname_1}{polname_2}</a> always applies <span class="docutils literal">\xintIrr</span> to the
+resulting coefficients, except that the <em>power of ten</em> part <span class="docutils literal">[N]</span>
+(for example an input in scientific notation such as <span class="docutils literal">1.23e5</span> gives
+<span class="docutils literal">123/1[3]</span> internally in xintfrac) is not taken into account in the
+reduction of the fraction. This is tentative and may change.</p>
+<p>Same remark for <a class="reference internal" href="#polantidiff-polname-1-polname-2">\PolAntiDiff{polname_1}{polname_2}</a>.</p>
+</li>
+<li><p>Currently, the package stores all coefficients from index <span class="docutils literal">0</span> 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 <span class="docutils literal">\poldef <span class="pre">f(x):=x^1000</span> + x^500;</span> the subsequent definition <span class="docutils literal">\poldef <span class="pre">g(x):=</span> <span class="pre">f(x)^2;</span></span> 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.</p></li>
+<li><p>As is to be expected internal structures of the package are barely
+documented and unstable. Don't use them.</p></li>
+</ul>
+</div>
+<div class="section" id="change-log">
+<h1><a class="toc-backref" href="#id204">CHANGE LOG</a></h1>
+<ul>
+<li><p>v0.1 (2018/01/11): initial release. Features:</p>
+<ul class="simple">
+<li><p>The <a class="reference internal" href="#poldef">\poldef</a> parser itself,</p></li>
+<li><p>Differentiation and anti-differentiation,</p></li>
+<li><p>Euclidean division and GCDs,</p></li>
+<li><p>Various utilities such as <a class="reference internal" href="#polfromcsv">\PolFromCSV</a>,
+<a class="reference internal" href="#polmapcoeffs">\PolMapCoeffs</a>,
+<a class="reference internal" href="#poltocsv">\PolToCSV</a>, <a class="reference internal" href="#poltoexpr">\PolToExpr</a>, ...</p></li>
+</ul>
+<p>Only one-variable polynomials so far.</p>
+</li>
+<li><p>v0.2 (2018/01/14)</p>
+<ul class="simple">
+<li><p>Fix: <span class="docutils literal">&quot;README thinks \numexpr recognizes ^ operator&quot;</span>.</p></li>
+<li><p>Convert README to reStructuredText markup.</p></li>
+<li><p>Move main documentation from README to separate <span class="docutils literal">polexpr.txt</span> file.</p></li>
+<li><p>Provide <span class="docutils literal">polexpr.html</span> as obtained via <a class="reference external" href="http://docutils.sourceforge.net/docs/index.html">DocUtils</a> <span class="docutils literal">rst2html.py</span>.</p></li>
+<li><p>Convert README to (CTAN compatible) Markdown markup.</p></li>
+</ul>
+<p>Due to lack of available time the test suite might not be extensive
+enough. Bug reports are very welcome!</p>
+</li>
+<li><p>v0.3 (2018/01/17)</p>
+<ul>
+<li><p>bug fixes:</p>
+<ul>
+<li><p>the <span class="docutils literal">0.1</span> <a class="reference internal" href="#polevalat">\PolEval</a> accepted expressions for its second
+argument, but this was removed by mistake at <span class="docutils literal">0.2</span>. Restored.</p>
+<p><strong>Attention</strong>: at <span class="docutils literal">0.4</span> this has been reverted again, and
+<a class="reference internal" href="#polevalatexpr">\PolEval{P}\AtExpr{foo}</a> syntax is needed for
+using expressions in the second argument.</p>
+</li>
+</ul>
+</li>
+<li><p>incompatible or breaking changes:</p>
+<ul class="simple">
+<li><p><a class="reference internal" href="#poltoexpr">\PolToExpr</a> now by default uses <em>descending</em>
+powers (it also treats differently coefficients equal to 1 or -1.)
+Use <a class="reference internal" href="#id33">\PolToExpr*</a> for <em>ascending</em> powers.</p></li>
+<li><p><a class="reference internal" href="#polevalat">\PolEval</a> reduced the output to smallest terms,
+but as this is costly with big fractions and not needed if e.g.
+wrapped in an <span class="docutils literal">\xintRound</span> or <span class="docutils literal">\xintFloat</span>, this step has been
+removed; the former meaning is available as <a class="reference internal" href="#polevalreducedat">\PolEvalReduced</a>.</p></li>
+</ul>
+</li>
+<li><p>new (or newly documented) macros:</p>
+<ul class="simple">
+<li><p><a class="reference internal" href="#poltypesetcmd">\PolTypesetCmd</a></p></li>
+<li><p><a class="reference internal" href="#poltypesetcmdprefix">\PolTypesetCmdPrefix</a></p></li>
+<li><p><a class="reference internal" href="#poltypesetmonomialcmd">\PolTypesetMonomialCmd</a></p></li>
+<li><p><a class="reference internal" href="#polevalreducedat">\PolEvalReducedAt</a></p></li>
+<li><p><a class="reference internal" href="#poltofloatexpr">\PolToFloatExpr</a></p></li>
+<li><p><a class="reference internal" href="#poltoexproneterm">\PolToExprOneTerm</a></p></li>
+<li><p><a class="reference internal" href="#poltofloatexproneterm">\PolToFloatExprOneTerm</a></p></li>
+<li><p><a class="reference internal" href="#poltoexprcmd">\PolToExprCmd</a></p></li>
+<li><p><a class="reference internal" href="#id36">\PolToFloatExprCmd</a></p></li>
+<li><p><a class="reference internal" href="#poltoexprtermprefix">\PolToExprTermPrefix</a></p></li>
+<li><p><a class="reference internal" href="#poltoexprvar">\PolToExprVar</a></p></li>
+<li><p><a class="reference internal" href="#poltoexprtimes">\PolToExprTimes</a></p></li>
+</ul>
+</li>
+<li><p>improvements:</p>
+<ul>
+<li><p>documentation has a table of contents, internal hyperlinks,
+standardized signature notations and added explanations.</p></li>
+<li><p>one can do <span class="docutils literal"><span class="pre">\PolLet{g}={f}</span></span> or <span class="docutils literal"><span class="pre">\PolLet{g}{f}</span></span>.</p></li>
+<li><p><span class="docutils literal">\PolToExpr{f}</span> is highly customizable.</p></li>
+<li><p><a class="reference internal" href="#poldef">\poldef</a> and other defining macros prepare the polynomial
+functions for usage within <span class="docutils literal">\xintthefloatexpr</span> (or
+<span class="docutils literal">\xintdeffloatvar</span>). Coefficients are pre-rounded to the
+floating point precision. Indispensible for numerical algorithms,
+as exact fractions, even reduced, quickly become very big. See the
+documentation about how to use the exact polynomials also in
+floating point context.</p>
+<p><strong>Attention</strong>: this has been reverted at <span class="docutils literal">0.4</span>. The macro
+<a class="reference internal" href="#polgenfloatvariant">\PolGenFloatVariant</a> must be used for
+generation floating point polynomial functions.</p>
+</li>
+</ul>
+</li>
+</ul>
+</li>
+<li><p>v0.3.1 (2018/01/18)</p>
+<p>Fixes two typos in example code included in the documentation.</p>
+</li>
+<li><p>v0.4 (2018/02/16)</p>
+<ul>
+<li><p>bug fixes:</p>
+<ul class="simple">
+<li><p>when Euclidean division gave a zero remainder, the internal
+representation of this zero polynomial could be faulty; this
+could cause mysterious bugs in conjunction with other package
+macros such as <a class="reference internal" href="#polmapcoeffs">\PolMapCoeffs</a>.</p></li>
+<li><p><a class="reference internal" href="#polgcd">\PolGCD</a> was buggy in case of first polynomial being
+of lesser degree than the second one.</p></li>
+</ul>
+</li>
+<li><p>breaking changes:</p>
+<ul>
+<li><p>formerly <a class="reference internal" href="#polevalat">\PolEval{P}\At{foo}</a> allowed <span class="docutils literal">foo</span> to
+be an expression, which was transparently handled via
+<span class="docutils literal">\xinttheexpr</span>. Now, <span class="docutils literal">foo</span> must be a fraction (or a macro
+expanding to such) in the format acceptable by <span class="docutils literal">xintfrac.sty</span>
+macros. Use <a class="reference internal" href="#polevalatexpr">\PolEval{P}\AtExpr{foo}</a> for more
+general arguments using expression syntax. E.g., if <span class="docutils literal">foo</span> is the
+name of a variable known to <span class="docutils literal">\xintexpr</span>.</p>
+<p>The same holds for <a class="reference internal" href="#polevalreducedat">\PolEvalReduced</a>
+and <a class="reference internal" href="#polfloatevalat">\PolFloatEval</a>.</p>
+</li>
+<li><p>the <span class="docutils literal">3.0</span> automatic generation of floating point variants has
+been reverted. Not only do <em>not</em> the package macros automatically
+generate floating point variants of newly created polynomials,
+they actually make pre-existing such variant undefined.</p>
+<p>See <a class="reference internal" href="#polgenfloatvariant">\PolGenFloatVariant</a>.</p>
+</li>
+</ul>
+</li>
+<li><p>new non-expandable macros:</p>
+<ul class="simple">
+<li><p><a class="reference internal" href="#polgenfloatvariant">\PolGenFloatVariant</a></p></li>
+<li><p><a class="reference internal" href="#polgloballet">\PolGlobalLet</a></p></li>
+<li><p><a class="reference internal" href="#poltypesetone">\PolTypesetOne</a></p></li>
+<li><p><a class="reference internal" href="#polquo">\PolQuo</a></p></li>
+<li><p><a class="reference internal" href="#polrem">\PolRem</a></p></li>
+<li><p><a class="reference internal" href="#poltosturm">\PolToSturm</a></p></li>
+<li><p><a class="reference internal" href="#id12">\PolToSturm*</a></p></li>
+<li><p><a class="reference internal" href="#polsettosturmchainsignchangesat">\PolSetToSturmChainSignChangesAt</a></p></li>
+<li><p><a class="reference internal" href="#polsettonbofzeroswithin">\PolSetToNbOfZerosWithin</a></p></li>
+<li><p><a class="reference internal" href="#polsturmisolatezeros">\PolSturmIsolateZeros</a></p></li>
+<li><p><a class="reference internal" href="#polrefineinterval">\PolRefineInterval*</a></p></li>
+<li><p><a class="reference internal" href="#polrefineinterval-n">\PolRefineInterval[N]</a></p></li>
+<li><p><a class="reference internal" href="#polensureintervallength">\PolEnsureIntervalLength</a></p></li>
+<li><p><a class="reference internal" href="#polensureintervallengths">\PolEnsureIntervalLengths</a></p></li>
+<li><p><a class="reference internal" href="#polprintintervals">\PolPrintIntervals</a></p></li>
+<li><p><a class="reference internal" href="#polprintintervalsprintexactzero">\PolPrintIntervalsPrintExactZero</a></p></li>
+<li><p><a class="reference internal" href="#polprintintervalsprintleftendpoint">\PolPrintIntervalsPrintLeftEndPoint</a></p></li>
+<li><p><a class="reference internal" href="#polprintintervalsprintrightendpoint">\PolPrintIntervalsPrintRightEndPoint</a></p></li>
+<li><p><a class="reference internal" href="#id23">\PolReduceCoeffs*</a></p></li>
+<li><p><a class="reference internal" href="#polmakemonic">\PolMakeMonic</a></p></li>
+</ul>
+</li>
+<li><p>new expandable macros:</p>
+<ul class="simple">
+<li><p><a class="reference internal" href="#poltoexpronetermstylea">\PolToExprOneTermStyleA</a></p></li>
+<li><p><a class="reference internal" href="#polifcoeffisplusorminusone">\PolIfCoeffIsPlusOrMinusOne</a></p></li>
+<li><p><a class="reference internal" href="#polleadingcoeff">\PolLeadingCoeff</a></p></li>
+<li><p><a class="reference internal" href="#polsturmchainlength">\PolSturmChainLength</a></p></li>
+<li><p><a class="reference internal" href="#polsturmnbofisolatedzeros">\PolSturmNbOfIsolatedZeros</a></p></li>
+<li><p><a class="reference internal" href="#polsturmifzeroexactlyknown">\PolSturmIfZeroExactlyKnown</a></p></li>
+<li><p><a class="reference internal" href="#polsturmisolatedzeroleft">\PolSturmIsolatedZeroLeft</a></p></li>
+<li><p><a class="reference internal" href="#polsturmisolatedzeroright">\PolSturmIsolatedZeroRight</a></p></li>
+<li><p><span class="docutils literal">\PolPrintIntervalsTheEndPoint</span> (removed at 0.7)</p></li>
+<li><p><a class="reference internal" href="#polprintintervalstheindex">\PolPrintIntervalsTheIndex</a></p></li>
+<li><p><span class="docutils literal">\PolIfEndPointIsPositive</span> (removed at 0.7)</p></li>
+<li><p><span class="docutils literal">\PolIfEndPointIsNegative</span> (removed at 0.7)</p></li>
+<li><p><span class="docutils literal">\PolIfEndPointIsZero</span> (removed at 0.7)</p></li>
+<li><p><a class="reference internal" href="#polintervalwidth">\PolIntervalWidth</a></p></li>
+<li><p><a class="reference internal" href="#poldectostring">\PolDecToString</a></p></li>
+</ul>
+</li>
+<li><p>improvements:</p>
+<p>The main new feature is implementation of the <a class="reference external" href="https://en.wikipedia.org/wiki/Sturm%27s_theorem">Sturm algorithm</a>
+for localization of the real roots of polynomials.</p>
+</li>
+</ul>
+</li>
+<li><p>v0.4.1 (2018/03/01)</p>
+<p>Synced with xint 1.3.</p>
+</li>
+<li><p>v0.4.2 (2018/03/03)</p>
+<p>Documentation fix.</p>
+</li>
+<li><p>v0.5 (2018/04/08)</p>
+<ul class="simple">
+<li><p>bug fixes:</p>
+<ul>
+<li><p><a class="reference internal" href="#polget-polname-fromarray-macro">\PolGet{polname}\fromarray\macro</a> crashed when <span class="docutils literal">\macro</span> was
+an <a class="reference external" href="http://www.ctan.org/pkg/xint">xinttools</a> array macro with no items. It now produces the zero
+polynomial.</p></li>
+</ul>
+</li>
+<li><p>breaking changes:</p>
+<ul>
+<li><p><a class="reference internal" href="#poltosturm">\PolToSturm</a> creates primitive integer coefficients polynomials.
+This speeds up localization of roots via
+<a class="reference internal" href="#polsturmisolatezeros">\PolSturmIsolateZeros</a>. In case of user protests the author
+will make available again the code producing the bona fide Sturm
+polynomials as used formerly.</p></li>
+<li><p>polynomials created from <a class="reference internal" href="#polfromcsv">\PolFromCSV</a> or <a class="reference internal" href="#polget">\PolGet</a>
+get their coefficients normalized via <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a>'s <span class="docutils literal">\xintRaw</span>.</p></li>
+</ul>
+</li>
+<li><p>experimental change:</p>
+<ul>
+<li><p>optional argument to <a class="reference internal" href="#polsturmisolatezeros">\PolSturmIsolateZeros</a> (see <a class="reference internal" href="#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</a> for usage). It will presumably be replaced in future by
+an interval specification.</p></li>
+</ul>
+</li>
+<li><p>new non-expandable macro:</p>
+<ul>
+<li><p><a class="reference internal" href="#polmakeprimitive">\PolMakePrimitive</a></p></li>
+</ul>
+</li>
+<li><p>new expandable macro:</p>
+<ul>
+<li><p><a class="reference internal" href="#policontent">\PolIContent</a></p></li>
+</ul>
+</li>
+</ul>
+</li>
+<li><p>v0.5.1 (2018/04/22)</p>
+<ul class="simple">
+<li><p>new feature:</p>
+<ul>
+<li><p>the character <span class="docutils literal">'</span> can be used in polynomial names.</p></li>
+</ul>
+</li>
+</ul>
+</li>
+<li><p>v0.6 (2018/11/20)</p>
+<ul class="simple">
+<li><p>bugfix:</p>
+<ul>
+<li><p>the starred variant <a class="reference internal" href="#id13">\PolToSturm*{polname}{sturmname}</a> was
+broken. On the occasion of the fix, its meaning has been modified,
+see its documentation.</p></li>
+<li><p>using <a class="reference internal" href="#poltosturm">\PolToSturm</a> with a constant polynomial
+caused a division by zero error.</p></li>
+</ul>
+</li>
+<li><p>new macro:</p>
+<ul>
+<li><p><a class="reference internal" href="#id14">\PolSturmIsolateZeros*</a>
+acts like the <a class="reference internal" href="#polsturmisolatezeros">non-starred variant</a> then computes all the multiplicities.</p></li>
+</ul>
+</li>
+<li><p>new expandable macros:</p>
+<ul>
+<li><p><a class="reference internal" href="#polsturmisolatedzeromultiplicity-sturmname-index">\PolSturmIsolatedZeroMultiplicity{sturmname}{index}</a></p></li>
+<li><p><a class="reference internal" href="#polsturmnbofrootsof-sturmname-lessthanorequalto-value">\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualTo{value}</a></p></li>
+<li><p><a class="reference internal" href="#polsturmnbofrootsof-sturmname-lessthanorequaltoexpr-expression">\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualToExpr{expression}</a></p></li>
+<li><p><a class="reference internal" href="#polsturmnbwithmultofrootsof-sturmname-lessthanorequalto-value">\PolSturmNbWithMultOfRootsOf{sturmname}\LessThanOrEqualTo{value}</a></p></li>
+<li><p><a class="reference internal" href="#polsturmnbwithmultofrootsof-sturmname-lessthanorequaltoexpr-expression">\PolSturmNbWithMultOfRootsOf{sturmname}\LessThanOrEqualToExpr{expression}</a></p></li>
+</ul>
+</li>
+</ul>
+</li>
+<li><p>v0.7 (2018/12/08), v0.7.1 (bugfix), v0.7.2 (2nd bugfix) (2018/12/09)</p>
+<ul class="simple">
+<li><p>breaking changes:</p>
+<ul>
+<li><p>although <a class="reference internal" href="#polprintintervals-varname-sturmname">\PolPrintIntervals[varname]{sturmname}</a> default output
+remains the same, some auxiliary macros for user-customization
+have been removed: <span class="docutils literal">\PolPrintIntervalsTheEndPoint</span>,
+<span class="docutils literal"><span class="pre">\PolIfEndPointIsPositive{A}{B}</span></span>,
+<span class="docutils literal"><span class="pre">\PolIfEndPointIsNegative{A}{B}</span></span>, and
+<span class="docutils literal"><span class="pre">\PolIfEndPointIsZero{A}{B}</span></span>.</p></li>
+</ul>
+</li>
+<li><p>bugfix:</p>
+<ul>
+<li><p>it could happen that, contrarily to documentation, an interval
+computed by <a class="reference internal" href="#polsturmisolatezeros-sturmname">\PolSturmIsolateZeros{sturmname}</a> had zero as an
+endpoint,</p></li>
+<li><p><a class="reference internal" href="#polensureintervallength-sturmname-index-e">\PolEnsureIntervalLength{sturmname}{index}{E}</a> could under
+certain circumstances erroneously replace a non-zero root by
+zero,</p></li>
+<li><p><a class="reference internal" href="#polensureintervallengths-sturmname-e">\PolEnsureIntervalLengths{sturmname}{E}</a> crashed when used with
+a polynomial with no real roots, hence for which no isolation intervals
+existed (thanks to Thomas Söll for report).</p></li>
+</ul>
+</li>
+<li><p>new macros:</p>
+<ul>
+<li><p><a class="reference internal" href="#id17">\PolSturmIsolateZeros**{sturmname}</a></p></li>
+<li><p><a class="reference internal" href="#polsturmisolatezerosgetmultiplicitiesandrationalroots-sturmname">\PolSturmIsolateZerosGetMultiplicitiesAndRationalRoots{sturmname}</a></p></li>
+<li><p><a class="reference internal" href="#polsturmisolatezerosandfindrationalroots-sturmname">\PolSturmIsolateZerosAndFindRationalRoots{sturmname}</a></p></li>
+<li><p><a class="reference internal" href="#polexprsetup">\polexprsetup</a></p></li>
+<li><p><a class="reference internal" href="#id21">\PolPrintIntervals*</a></p></li>
+<li><p><a class="reference internal" href="#polprintintervalsnorealroots">\PolPrintIntervalsNoRealRoots</a></p></li>
+<li><p><a class="reference internal" href="#polprintintervalsbeginenv">\PolPrintIntervalsBeginEnv</a></p></li>
+<li><p><a class="reference internal" href="#polprintintervalsendenv">\PolPrintIntervalsEndEnv</a></p></li>
+<li><p><a class="reference internal" href="#polprintintervalsknownroot">\PolPrintIntervalsKnownRoot</a></p></li>
+<li><p><a class="reference internal" href="#polprintintervalsunknownroot">\PolPrintIntervalsUnknownRoot</a></p></li>
+<li><p><a class="reference internal" href="#polprintintervalsprintmultiplicity">\PolPrintIntervalsPrintMultiplicity</a></p></li>
+</ul>
+</li>
+<li><p>new expandable macros:</p>
+<ul>
+<li><p><a class="reference internal" href="#polsturmnbofrationalroots-sturmname">\PolSturmNbOfRationalRoots{sturmname}</a></p></li>
+<li><p><a class="reference internal" href="#polsturmnbofrationalrootswithmultiplicities-sturmname">\PolSturmNbOfRationalRootsWithMultiplicities{sturmname}</a></p></li>
+<li><p><a class="reference internal" href="#polsturmrationalroot-sturmname-k">\PolSturmRationalRoot{sturmname}{k}</a></p></li>
+<li><p><a class="reference internal" href="#polsturmrationalrootindex-sturmname-k">\PolSturmRationalRootIndex{sturmname}{k}</a></p></li>
+<li><p><a class="reference internal" href="#polsturmrationalrootmultiplicity-sturmname-k">\PolSturmRationalRootMultiplicity{sturmname}{k}</a></p></li>
+<li><p><a class="reference internal" href="#polprintintervalsthevar">\PolPrintIntervalsTheVar</a></p></li>
+<li><p><a class="reference internal" href="#polprintintervalsthesturmname">\PolPrintIntervalsTheSturmName</a></p></li>
+<li><p><a class="reference internal" href="#polprintintervalsthemultiplicity">\PolPrintIntervalsTheMultiplicity</a></p></li>
+</ul>
+</li>
+</ul>
+</li>
+<li><p>v0.7.3 (2019/02/04)</p>
+<ul class="simple">
+<li><p>bugfix:</p>
+<ul>
+<li><p>Debugging information not destined to user showed in log if root
+finding was done under <span class="docutils literal">\xintverbosetrue</span> regime.</p></li>
+<li><p><a class="reference internal" href="#polprintintervalsthevar">\PolPrintIntervalsTheVar</a> remained defined after
+<a class="reference internal" href="#polprintintervals">\PolPrintIntervals</a> but was left undefined after
+<a class="reference internal" href="#id21">\PolPrintIntervals*</a> (reported by Jürgen Gilg). Now remains
+defined in both cases, and <a class="reference internal" href="#polprintintervalsthesturmname">\PolPrintIntervalsTheSturmName</a>
+also.</p></li>
+<li><p>Polynomial names ending in digits caused errors (reported by Thomas
+Söll).</p></li>
+</ul>
+</li>
+</ul>
+</li>
+<li><p>v0.7.4 (2019/02/12)</p>
+<ul class="simple">
+<li><p>bugfix:</p>
+<ul>
+<li><p>20000000000 is too big for <span class="docutils literal">\numexpr</span>, shouldn't I know that?
+Thanks to Jürgen Gilg for report.</p></li>
+</ul>
+</li>
+</ul>
+</li>
+<li><p>v0.7.5 (2020/01/31)</p>
+<p>Synced with xintexpr 1.4. Requires it.</p>
+</li>
+<li><p>v0.8 (2021/03/29)</p>
+<p>Synced with xintexpr 1.4d. Requires it.</p>
+<ul class="simple">
+<li><p>breaking changes:</p>
+<ul>
+<li><p>As the usability of character <span class="docutils literal">'</span> in names has been extended
+from <span class="docutils literal">\poldef</span> to also generally <span class="docutils literal">\xintexpr</span>, <span class="docutils literal">\xintdefvar</span>,
+and <span class="docutils literal">\xintdeffunc</span>, it breaks there the infix operators
+<span class="docutils literal">'and'</span>, <span class="docutils literal">'or'</span>, <span class="docutils literal">'xor'</span> and <span class="docutils literal">'mod'</span>. See the <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a>
+documentation for the <span class="docutils literal">&amp;&amp;</span>, <span class="docutils literal">||</span>, <span class="docutils literal">xor()</span> and <span class="docutils literal">/:</span>
+alternatives.</p></li>
+<li><p><a class="reference internal" href="#poltoexpr">\PolToExpr</a> by default uses a catcode 12
+<span class="docutils literal">^</span>. See its documentation and the new configuration
+<a class="reference internal" href="#poltoexprcaret">\PolToExprCaret</a>.</p></li>
+</ul>
+</li>
+<li><p>deprecated:</p>
+<ul>
+<li><p>Usage of <span class="docutils literal">P/Q</span> for the euclidean quotient of two polynomials is
+deprecated. Start using <span class="docutils literal">quo(P,Q)</span> in its place.</p></li>
+</ul>
+</li>
+<li><p>bugfix:</p>
+<ul>
+<li><p>The <span class="docutils literal">\xintglobaldefstrue</span> setting was obeyed only partially
+by the polexpr macros defining polynomials.</p></li>
+<li><p>The <span class="docutils literal">\xintexpr</span> variables storing the values of the extremities
+of the intervals as found by <a class="reference internal" href="#polsturmisolatezeros">\PolSturmIsolateZeros</a> were not updated at 0.7.5 to the
+xintexpr 1.4 format and thus caused low-level TeX errors if used.</p></li>
+<li><p>Attempting to use in <span class="docutils literal">\poldef</span> a function previously declared
+via <span class="docutils literal">\xintdeffunc</span> which made usage of the indexing or slicing
+&quot;ople&quot; syntax typically caused <span class="docutils literal">TeX capacity exceeded</span> error.
+Indeed 0.7.5 only partially made polexpr able to cope with the
+extended possibilities for xintexpr 1.4 user-declared functions.
+Hopefully <span class="docutils literal">0.8</span> achieves full functionality in this context.</p></li>
+</ul>
+</li>
+<li><p>new macros:</p>
+<ul>
+<li><p><a class="reference internal" href="#polnewpolverbosefalse">\polnewpolverbosefalse</a></p></li>
+<li><p><a class="reference internal" href="#poltoexprcaret">\PolToExprCaret</a></p></li>
+<li><p><a class="reference internal" href="#poltoexprinvar">\PolToExprInVar</a></p></li>
+<li><p>alongside the major new functionalities described in the next item
+<a class="reference internal" href="#poltypeset">\PolTypeset</a> and <a class="reference internal" href="#poltoexpr">\PolToExpr</a> have
+been enhanced to accept as argument a general expression and not
+only a pre-declared polynomial name.</p></li>
+</ul>
+</li>
+<li><p>new features:</p>
+<ul>
+<li><p>The package is usable under Plain and probably most any TeX format,
+and not only under LaTeX.</p></li>
+<li><p>The core of the package has been rewritten entirely in order to
+start letting <span class="docutils literal">\xintexpr</span> recognize a polynomial type as a genuine
+variable. This has allowed:</p>
+<ul>
+<li><p>to solve the reduced inter-operability problems between polexpr
+and <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> which arose as consequences to the deep <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> <span class="docutils literal">1.4</span>
+evolution,</p></li>
+<li><p>to make available most of the functionality associated to
+expandable macros directly in the <span class="docutils literal">\xinteval</span> syntax as
+operators or functions,</p></li>
+<li><p>to provide (expandable) functional interface in <span class="docutils literal">\xinteval</span> to
+features previously available only via (for some, non-expandable)
+macro interface such as gcd computations.</p></li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+<p>See the updated <a class="reference internal" href="#quick-syntax-overview">Quick syntax overview</a> and then <a class="reference internal" href="#polexpr08">the extended syntax
+description</a>.</p>
+</li>
+</ul>
+</div>
+<div class="section" id="acknowledgments">
+<h1><a class="toc-backref" href="#id205">Acknowledgments</a></h1>
+<p>Thanks to Jürgen Gilg whose question about <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> usage for
+differentiating polynomials was the initial trigger leading to this
+package, and to Jürgen Gilg and Thomas Söll for testing it on some
+concrete problems.</p>
+<p>Renewed thanks to them on occasion of the <span class="docutils literal">0.6</span>, <span class="docutils literal">0.7</span>, and <span class="docutils literal">0.8</span>
+releases for their continued interest.</p>
+<p>See README.md for the License.</p>
+</div>
+</div>
+</body>
+</html>
diff --git a/macros/generic/polexpr/polexpr.sty b/macros/generic/polexpr/polexpr.sty
new file mode 100644
index 0000000000..c94a4e8d61
--- /dev/null
+++ b/macros/generic/polexpr/polexpr.sty
@@ -0,0 +1,1057 @@
+% author: Jean-François Burnol
+% License: LPPL 1.3c (author-maintained)
+% Usage: \input polexpr.sty (Plain or other macro formats)
+% or \usepackage{polexpr} (LaTeX macro format)
+% polexpr.sty (this file) inputs:
+% polexprcore.tex
+% polexprexpr.tex
+% polexprsturm.tex
+\begingroup\catcode61\catcode48\catcode32=10\relax%
+ \catcode13=5 % ^^M
+ \endlinechar=13 %
+ \catcode123=1 % {
+ \catcode125=2 % }
+ \catcode64=11 % @
+ \catcode35=6 % #
+ \catcode44=12 % ,
+ \catcode45=12 % -
+ \catcode46=12 % .
+ \catcode58=12 % :
+ \def\z {\endgroup}%
+ \expandafter\let\expandafter\x\csname ver@polexpr.sty\endcsname
+ \expandafter\let\expandafter\w\csname ver@xintexpr.sty\endcsname
+ \expandafter
+ \ifx\csname PackageInfo\endcsname\relax
+ \def\y#1#2{\immediate\write-1{Package #1 Info: #2.}}%
+ \else
+ \def\y#1#2{\PackageInfo{#1}{#2}}%
+ \fi
+ \expandafter
+ % I don't think engine exists providing \expanded but not \numexpr
+ \ifx\csname expanded\endcsname\relax
+ \y{polexpr}{\expanded not available, aborting input}%
+ \aftergroup\endinput
+ \else
+ \ifx\x\relax % plain-TeX, first loading of polexpr.sty
+ \ifx\w\relax % but xintexpr.sty not yet loaded.
+ \expandafter\def\expandafter\z\expandafter
+ {\z\input xintexpr.sty\relax}%
+ \fi
+ \else
+ \def\empty {}%
+ \ifx\x\empty % LaTeX, first loading,
+ % variable is initialized, but \ProvidesPackage not yet seen
+ \ifx\w\relax % xintexpr.sty not yet loaded.
+ \expandafter\def\expandafter\z\expandafter
+ {\z\RequirePackage{xintexpr}[2021/02/20]}%
+ \fi
+ \else
+ \aftergroup\endinput % polexpr already loaded.
+ \fi
+ \fi
+ \fi
+\z%
+\XINTsetupcatcodes%
+\XINT_providespackage
+\ProvidesPackage{polexpr}%
+ [2021/03/29 v0.8 Polynomial expressions with rational coefficients (JFB)]%
+\begingroup
+ \def\x#1/#2/#3 #4\xint:{#1#2#3}%
+ \ifnum\expandafter\x\expanded{\csname ver@xintexpr.sty\endcsname}\xint:
+ <20210220 % actually 20200131 (xint 1.4) is presumably ok
+ \immediate\write128{! Package polexpr error: xintexpr too old, aborting input}%
+ \else\expandafter\xint_gobble_i
+ \fi
+\endinput\endgroup
+\let\PolDecToString\xintDecToString
+\long\def\POL@ifstar#1#2%
+{%
+ \begingroup\def\@tempa{#1}\def\@tempb{#2}%
+ \futurelet\@let@token\POL@@ifstar
+}%
+\def\POL@@ifstar
+{%
+ \xint_firstofone{\ifx} \@let@token\def\next{\POL@@again\POL@@ifstar}\else
+ \ifx*\@let@token\def\next##1{\expandafter\endgroup\@tempa}\else
+ \def\next{\expandafter\endgroup\@tempb}\fi\fi\next
+}%
+\xint_firstofone{\def\POL@@again#1} {\futurelet\@let@token#1}%
+\long\def\POL@chkopt#1[#2]%
+{%
+ \begingroup\def\@tempa{#1}\def\@tempb{#1[#2]}%
+ \futurelet\@let@token\POL@@ifopt
+}%
+\def\POL@@ifopt
+{%
+ \xint_firstofone{\ifx} \@let@token\def\next{\POL@@again\POL@@ifopt}\else
+ \ifx[\@let@token\def\next{\expandafter\endgroup\@tempa}\else %]
+ \def\next{\expandafter\endgroup\@tempb}\fi\fi\next
+}%
+% \polexprsetup added at 0.7
+\catcode`! 3
+\def\polexprsetup#1{\POL@setup_parsekeys #1,=!,\xint_bye}%
+\def\POL@setup_parsekeys #1=#2#3,{%
+ \ifx!#2\expandafter\xint_bye\fi
+ \csname POL@setup_setkey_\xint_zapspaces #1 \xint_gobble_i\endcsname
+ \xint_firstoftwo
+ {\PackageWarning{polexpr}{The \detokenize{#1} key is unknown! ignoring}}%
+ {\xintZapLastSpaces{#2#3}}%
+ \POL@setup_parsekeys
+}%
+\def\POL@setup_setkey_norr #1#2{\edef\POL@norr}%
+\def\POL@setup_setkey_sqfnorr #1#2{\edef\POL@sqfnorr}%
+\polexprsetup{norr=_norr, sqfnorr=_sqf_norr}
+\catcode`! 11 % special catcode for ! as used in xintexpr.sty
+%
+\newif\ifxintveryverbose
+\newif\ifpolnewpolverbose
+\newif\ifpoltypesetall
+\newif\ifpoltoexprall
+%%
+%% Main data format for non-expandable manipulations
+%%
+%% The main exchange structure is:
+%% N.\empty{coeff0}{coeff1}....{coeffN}
+%% It is stored in macros \POLuserpol@<name of polynomial>
+%% The \empty is basically there to avoid brace-stripping
+%% in some grabbing contexts (maybe I should revisit this)
+%%
+%% The zero polynomial is stored as -1.\empty{0/1[0]}
+%% Degree zero polynomials are 0.\empty{numeric value}
+%%
+%% Depending on input path the numeric values coeff0, coeff1, ...., coeffN
+%% may have been or not already converted into A/B[n] format.
+%% As a rule, computations are not followed with reducing the fractions
+%% to smallest terms; the innocent may be unaware that computing
+%% with fractions quickly give gigantic numbers. There is \PolReduceCoeffs
+%% to do that.
+%%
+%% This base structure is maintained at 0.8 for legacy reasons but perhaps I
+%% need to revisit this. A characteristic of the package so far is that it
+%% thus stores and manipulate polynomials basically as the complete sequence
+%% of coefficients, (using the xintfrac "zero" for missing coefficients) which
+%% means that it will handle poorly polynomials of high degrees such as X^500.
+%%
+%% Test if zero
+\def\POL@ifZero#1{\expandafter\POL@ifZero@aux#1;}%
+\def\POL@ifZero@aux #1#2;{\if-#1\expandafter\xint_firstoftwo
+ \else\expandafter\xint_secondoftwo
+ \fi}%
+%% Split into degree and coefficients
+% The \expandafter chain removes the \empty token
+\def\POL@split#1.#2;#3#4%
+ {\def#3{#1}\expandafter\def\expandafter#4\expandafter{#2}}%
+%% Define from values stored in a "macros-array"
+\def\POL@resultfromarray #1{%
+ \edef\POL@result{\ifnum\count@>\z@
+ \the\numexpr\count@-\@ne.\noexpand\empty
+ \xintiloop [1+1]%
+ \expandafter\POL@braceit\csname POL@array#1\xintiloopindex\endcsname
+ \ifnum\xintiloopindex<\count@
+ \repeat
+ \else-1.\noexpand\empty{0/1[0]}\fi}%
+}%
+\def\POL@braceit#1{{#1}}% needed as \xintiloopindex can not "see" through braces
+%%
+%% Conversion between legacy data storage and the one used for the
+%% the novel polexpr 0.8 notion of \xintexpr polynomial variables
+%%
+%% The 0.8 expandable implementation of core algebra is also manipulating
+%% the complete list of coefficients. The internal data structure is
+%% (this is the numeric leaf in xintexpr ople terminology) currently:
+%% PN.{coeff0}{coeff1}....{coeffN}
+%% where the P letter identifies the polynomial type.
+%% Here the degree N is *always* at least 1: if some evaluation ends
+%% up in a constant polynomial it will always be output as a genuine
+%% scalar numeric variable, as a rule in in A/B[n] format
+%%
+%% This is not definitive and I need to think about it more (in particular
+%% in the distant perspective of supporting multi-variable polynomials).
+%% However modifying this will be costly labor at this stage.
+%%
+\input polexprcore.tex\relax % load expandable algebra
+\def\POL@vartolegacy #1% \romannumeral\POL@vartolegacy ... \xint:
+{%
+ \if 0#1\xint_dothis\POL@vartolegacy@zero\fi
+ \if P#1\xint_dothis\POL@vartolegacy@pol\fi
+ \xint_orthat\POL@vartolegacy@scalar #1%
+}%
+\def\POL@vartolegacy@zero #1\xint:{\xint_c_ -1.\empty{0/1[0]}}%
+\def\POL@vartolegacy@scalar #1\xint:{\xint_c_ 0.\empty{#1}}%
+\def\POL@vartolegacy@pol P#1.#2\xint:{\xint_c_ #1.\empty#2}%
+%
+\def\POL@tovar#1{\romannumeral\expandafter\expandafter\expandafter
+ \POL@legacytovar\csname POLuserpol@#1\endcsname}%
+\def\POL@legacytovar #1.% \romannumeral\POL@legacytovar N.\empty{c0}...
+{%
+ \ifnum #1<\xint_c_i\xint_dothis\POL@legacytovar@scalar\fi
+ \xint_orthat\POL@legacytovar@pol #1.%
+}%
+\def\POL@legacytovar@scalar #1.\empty#2{\xint_c_ #2}%
+\def\POL@legacytovar@pol #1.\empty{\xint_c_ P#1.}%
+%%
+%% Extend \xintexpr (\xintdefvar, \xintdeffunc) to recognize the new
+%% polynomial type
+%%
+%% **** It does NOT apply to \xintfloatexpr context
+%%
+\input polexprexpr.tex\relax
+%%
+%% \poldef
+%%
+\def\PolDef{\POL@chkopt\POL@oPolDef[x]}%
+\def\POL@oPolDef[#1]#2#3{\poldef #2(#1):=#3;}%
+\def\poldef{\edef\POL@restoresemicolon{\catcode59=\the\catcode59\relax}%
+ \catcode59 12 \POL@defpol}%
+\def\POL@defpol #1(#2)#3=#4;{%
+ \POL@restoresemicolon
+ \edef\POL@polname{\xint_zapspaces #1 \xint_gobble_i}%
+\begingroup
+ \unless\ifxintveryverbose\xintverbosefalse\fi
+ %% RADICAL CHANGE AT 0.8:
+ %% we define a **variable** not a **function**
+ %% ever since polexpr initial version, a function was defined and
+ %% the associated macros was then deconstructed in further analysis
+ %% via non-expandable approach. At 0.8 the polynomial algebra has
+ %% been implemented expandably allowing direct plug-in into \xintexpr
+ \xintdefvar __pol = subs(#4,#2=qraw({{P1.{0/1[0]}{1/1[0]}}}));%
+ \expandafter
+\endgroup
+ \expandafter\def\expandafter\POL@result\expandafter
+ {\romannumeral0\expandafter\xint_stop_atfirstofone
+ \romannumeral0\csname XINT_expr_varvalue___pol\endcsname}%
+ \XINT_global\expandafter\def\csname POLuserpol@\POL@polname\expandafter\endcsname
+ \expandafter{\romannumeral\expandafter\POL@vartolegacy\POL@result\xint:}%
+ \expandafter\POL@newpol\expandafter{\POL@polname}%
+}%
+\def\POL@newpol#1{%
+ % 0.7.5 had some complicated special handling of constant
+ % polynomials, but these are complications of the past
+ % First a variable usable in \poldef but not in \xintexpr for arithmetic
+ % only for special dedicated functions such as coeff(), deg()
+ % (when they will be implemented). In \poldef, composition of polynomials
+ % in P(Q) syntax will be more efficient than P(Q(x)).
+ % This will use \XINT_global and obey \xintverbose... setting
+ \XINT_expr_defvar_one{#1}{{\POL@tovar{#1}}}%
+ % Second a function usable not only in \poldef but also in \xintexpr
+ % Will use \XINT_global
+ \POL@newpolhorner{#1}%
+ \POL@defpolfunc{#1}{expr}%
+ \XINT_global\expandafter\let\csname XINT_flexpr_func_#1\endcsname\@undefined
+ \ifpolnewpolverbose\POL@info{#1}\fi
+}%
+\def\POL@newfloatpol#1{%
+ \POL@newfloatpolhorner{#1}%
+ \POL@defpolfunc{#1}{flexpr}%
+ \ifpolnewpolverbose\POL@floatinfo{#1}%
+ \else
+ \ifxintverbose\POL@floatinfo{#1}\fi
+ \fi
+}%
+\def\POL@info #1{%
+ \xintMessage {polexpr}{Info}%
+ {Function #1 for the \string\xintexpr\space parser is
+ \ifxintglobaldefs(globally) \fi
+ associated to \string\XINT_expr_polfunc_#1\space
+ with meaning:
+ \expandafter\meaning
+ \csname XINT_expr_polfunc_#1\endcsname}%
+}%
+\def\POL@floatinfo #1{%
+ \xintMessage {polexpr}{Info}%
+ {Function #1 for the \string\xintfloatexpr\space parser is
+ \ifxintglobaldefs(globally) \fi
+ associated to \string\XINT_flexpr_polfunc_#1\space
+ with meaning:
+ \expandafter\meaning
+ \csname XINT_flexpr_polfunc_#1\endcsname}%
+}%
+%
+\def\POL@newpolhorner#1{%
+ \expandafter\expandafter\expandafter\POL@split
+ \csname POLuserpol@#1\endcsname;\POL@var@deg\POL@var@coeffs
+ \edef\POL@var@coeffs{\xintRevWithBraces{\POL@var@coeffs}}%
+ \begingroup
+ \expandafter\POL@newpol@horner\POL@var@coeffs\relax
+ \expandafter
+ \endgroup
+ \expandafter\XINT_global
+ \expandafter\def\csname XINT_expr_polfunc_#1\expandafter\endcsname
+ \expandafter##\expandafter1\expandafter{\POL@tmp{##1}}%
+}%
+\def\POL@newfloatpolhorner#1{%
+ %% redefine function to expand by Horner scheme. Is this useful?
+ %% perhaps bad idea for numerical evaluation of thing such as (1+x)^10?
+% note: I added {0/1[0]} item to zero polynomial also to facilitate this
+ \expandafter\expandafter\expandafter\POL@split
+ \csname POLuserpol@#1\endcsname;\POL@var@deg\POL@var@coeffs
+ \edef\POL@var@coeffs{\xintRevWithBraces{\POL@var@coeffs}}%
+ \begingroup
+ \expandafter\POL@newpol@floathorner\POL@var@coeffs\relax
+ \expandafter
+ \endgroup
+ \expandafter\def\csname XINT_flexpr_polfunc_#1\expandafter\endcsname
+ \expandafter##\expandafter1\expandafter{\POL@tmp{##1}}%
+}%
+\def\POL@newpol@horner#1{\let\xintPolAdd\relax\let\xintPolMul\relax
+ \def\POL@tmp##1{#1}\POL@newpol@horner@loop.}%
+\def\POL@newpol@horner@loop.#1{%
+ \if\relax#1\expandafter\xint_gob_til_dot\fi
+ \edef\POL@tmp##1{\xintiiifZero{#1}
+ {\xint_firstofone}{\xintPolAdd{#1}}%
+ {\xintPolMul{##1}{\POL@tmp{##1}}}}%
+ \POL@newpol@horner@loop.%
+}%
+\def\POL@newpol@floathorner#1{\let\XINTinFloatAdd\relax\let\XINTinFloatMul\relax
+ \edef\POL@tmp##1{\XINTinFloatdigits{#1}}%
+ \POL@newpol@floathorner@loop.}%
+\def\POL@newpol@floathorner@loop.#1{%
+ \if\relax#1\expandafter\xint_gob_til_dot\fi
+ \edef\POL@tmp##1{\xintiiifZero{#1}
+ {\xint_firstofone}{\XINTinFloatAdd{\XINTinFloatdigits{#1}}}%
+ {\XINTinFloatMul{##1}{\POL@tmp{##1}}}}%
+ \POL@newpol@floathorner@loop.%
+}%
+%%
+%% Non-expandable polynomial manipulations
+%%
+\def\PolGenFloatVariant#1{\POL@newfloatpol{#1}}%
+%
+\def\PolLet#1#2{\if=\noexpand#2\expandafter\xint_firstoftwo
+ \else\expandafter\xint_secondoftwo\fi
+ \POL@@let\POL@let{#1}{#2}}%
+\def\POL@@let#1#2#3{\POL@let{#1}{#3}}%
+\def\POL@let#1#2{%
+ \XINT_global
+ \expandafter\let\csname POLuserpol@#1\expandafter\endcsname
+ \csname POLuserpol@#2\endcsname
+ \XINT_expr_defvar_one{#1}{{\POL@tovar{#1}}}%
+ \XINT_global
+ \expandafter\let\csname XINT_expr_polfunc_#1\expandafter\endcsname
+ \csname XINT_expr_polfunc_#2\endcsname
+ \POL@defpolfunc{#1}{expr}%
+ \ifpolnewpolverbose\POL@info{#1}\fi
+}%
+\def\PolGlobalLet#1#2{\begingroup\xintglobaldefstrue\PolLet{#1}{#2}\endgroup}
+%
+\def\PolAssign#1{\def\POL@polname{#1}\POL@assign}% zap spaces in #1?
+\def\POL@assign#1\toarray#2{%
+ \expandafter\expandafter\expandafter\POL@split
+ \csname POLuserpol@\POL@polname\endcsname;\POL@var@deg\POL@var@coeffs
+ \xintAssignArray\POL@var@coeffs\to#2%
+ % modify \#200 macro to return 0/1[0] for out of range indices
+ \@namedef{\xint_arrayname00}##1##2##3{%
+ \@namedef{\xint_arrayname00}####1{%
+ \ifnum####1>##1 \xint_dothis{ 0/1[0]}\fi
+ \ifnum####1>\m@ne \xint_dothis
+ {\expandafter\expandafter\expandafter##3%
+ \csname##2####1\endcsname}\fi
+ \unless\ifnum-####1>##1 \xint_dothis
+ {\expandafter\expandafter\expandafter##3%
+ \csname##2\the\numexpr##1+####1+\@ne\endcsname}\fi
+ \xint_orthat{ 0/1[0]}}% space stops a \romannumeral0
+ }%
+ \csname\xint_arrayname00\expandafter\expandafter\expandafter\endcsname
+ \expandafter\expandafter\expandafter
+ {\csname\xint_arrayname0\expandafter\endcsname\expandafter}\expandafter
+ {\xint_arrayname}{ }%
+}%
+\def\PolGet{}%
+\def\PolGet#1#2\fromarray#3{%
+ \begingroup % closed in \POL@getfromarray
+ \POL@getfromarray{#1}{#3}%
+ \POL@newpol{#1}%
+}%
+\def\POL@getfromarray#1#2{%
+ \count@=#2{0} %<- intentional space
+ \ifnum\count@=\z@
+ \def\POL@result{-1.\empty{0/1[0]}}% 0.5 fix for empty array
+ \else
+ \xintloop
+ \edef\POL@tmp{#2{\count@}}%
+ \edef\POL@tmp{\xintRaw{\POL@tmp}}%
+% sadly xinttools (current 1.3a) arrays have no setters for individual items...
+ \expandafter\let\csname POL@tmparray\the\count@\endcsname\POL@tmp
+ \if0\xintiiSgn{\POL@tmp}%
+ \advance\count@\m@ne
+ \repeat
+ \count\tw@\count@
+ \xintloop
+ \ifnum\count@>\@ne
+ \advance\count@\m@ne
+ \edef\POL@tmp{#2{\count@}}%
+ \edef\POL@tmp{\xintRaw{\POL@tmp}}%
+ \expandafter\let\csname POL@tmparray\the\count@\endcsname\POL@tmp
+ \repeat
+ \count@\count\tw@
+ \def\POL@tmp##1.{{\csname POL@tmparray##1\endcsname}}%
+ \edef\POL@result{\the\numexpr\count@-\@ne.\noexpand\empty
+ \xintiloop[1+1]%
+ \expandafter\POL@tmp\xintiloopindex.%
+ \ifnum\xintiloopindex<\count@
+ \repeat}%
+ \fi
+ \expandafter
+ \endgroup
+ \expandafter
+ \XINT_global
+ \expandafter
+ \def\csname POLuserpol@#1\expandafter\endcsname
+ \expandafter{\POL@result}%
+}%
+%
+\def\PolFromCSV#1#2{%
+ \begingroup % closed in \POL@getfromarray
+ \xintAssignArray\xintCSVtoList{#2}\to\POL@arrayA
+ \POL@getfromarray{#1}\POL@arrayA
+ \POL@newpol{#1}%
+}%
+%
+\def\PolMapCoeffs#1#2{% #1 = macro, #2 = name
+ \POL@mapcoeffs{#1}{#2}%
+ \POL@newpol{#2}%
+}%
+\def\POL@mapcoeffs#1#2{%
+ \begingroup
+ \def\POL@mapcoeffs@macro{#1}%
+ \expandafter\expandafter\expandafter\POL@split
+ \csname POLuserpol@#2\endcsname;\POL@mapcoeffs@deg\POL@mapcoeffs@coeffs
+% ATTENTION à ne pas faire un \expandafter ici, car brace removal si 1 item
+ \xintAssignArray\POL@mapcoeffs@coeffs\to\POL@arrayA
+ \def\index{0}%
+ \count@\z@
+ \expandafter\POL@map@loop\expandafter.\POL@mapcoeffs@coeffs\relax
+ \xintloop
+% this abuses that \POL@arrayA0 is never 0.
+ \xintiiifZero{\csname POL@arrayA\the\count@\endcsname}%
+ {\iftrue}%
+ {\iffalse}%
+ \advance\count@\m@ne
+ \repeat
+% donc en sortie \count@ est 0 ssi pol nul.
+ \POL@resultfromarray A%
+ \expandafter
+ \endgroup
+ \expandafter
+ \XINT_global
+ \expandafter
+ \def\csname POLuserpol@#2\expandafter\endcsname\expandafter{\POL@result}%
+}%
+\def\POL@map@loop.#1{\if\relax#1\expandafter\xint_gob_til_dot\fi
+ \advance\count@\@ne
+ \edef\POL@map@coeff{\POL@mapcoeffs@macro{#1}}%
+ \expandafter
+ \let\csname POL@arrayA\the\count@\endcsname\POL@map@coeff
+ \edef\index{\the\numexpr\index+\@ne}%
+ \POL@map@loop.}%
+%
+\def\POL@xintIrr#1{\xintIrr{#1}[0]}%
+\def\PolReduceCoeffs{\POL@ifstar\POL@sreducecoeffs\POL@reducecoeffs}%
+\def\POL@reducecoeffs#1{\PolMapCoeffs{\POL@xintIrr}{#1}}%
+\def\POL@sreducecoeffs#1{\PolMapCoeffs{\xintPIrr}{#1}}%
+%
+\def\PolMakeMonic#1{%
+ \edef\POL@leadingcoeff{\PolLeadingCoeff{#1}}%
+ \edef\POL@leadingcoeff@inverse{\xintDiv{1/1[0]}{\POL@leadingcoeff}}%
+ \PolMapCoeffs{\xintMul{\POL@leadingcoeff@inverse}}{#1}%
+}%
+%
+%% \PolMakePrimitive (0.5)
+% This uses expandable \PolIContent
+% Note: the integer coefficients stored in A/1[n] form with
+% A not having trailing zeroes, due to usage of \xintREZ here.
+\def\POL@makeprim@macro#1%
+ {\xintREZ{\xintNum{\xintDiv{#1}{\POL@makeprim@icontent}}}}%
+\def\PolMakePrimitive#1{%
+ % This does not need a full user declared polynomial on input, only
+ % a \POLuserpol@name macro, but on output it is fully declared
+ \edef\POL@makeprim@icontent{\PolIContent{#1}}%
+ \PolMapCoeffs\POL@makeprim@macro{#1}%
+}%
+\def\POL@makeprimitive#1{%
+ % Avoids declaring the polynomial, internal usage in \PolToSturm
+ \edef\POL@makeprim@icontent{\PolIContent{#1}}%
+ \POL@mapcoeffs\POL@makeprim@macro{#1}%
+}%
+%
+%% Euclidean division
+% now based on the expandable routine from polexprcore.tex
+%
+\def\PolDivide#1#2#3#4{% #3=quotient, #4=remainder of #1 by #2
+ \POL@divide{#1}{#2}%
+ \XINT_global\expandafter\let\csname POLuserpol@#3\endcsname\POL@Q
+ \POL@newpol{#3}%
+ \XINT_global\expandafter\let\csname POLuserpol@#4\endcsname\POL@R
+ \POL@newpol{#4}%
+}%
+\def\PolQuo#1#2#3{% #3=quotient of #1 by #2
+ \POL@divide{#1}{#2}%
+ \XINT_global\expandafter\let\csname POLuserpol@#3\endcsname\POL@Q
+ \POL@newpol{#3}%
+}%
+\def\PolRem#1#2#3{% #3=remainder of #1 by #2
+ \POL@divide{#1}{#2}%
+ \XINT_global\expandafter\let\csname POLuserpol@#3\endcsname\POL@R
+ \POL@newpol{#3}%
+}%
+\def\POL@divide#1#2{%
+ % much simpler at 0.8 thanks to our expandable macros
+ \xintAssign\xintPolQuoRem{\POL@tovar{#1}}{\POL@tovar{#2}}\to\POL@Q\POL@R
+ \odef\POL@Q{\romannumeral\expandafter\POL@vartolegacy\POL@Q\xint:}%
+ \odef\POL@R{\romannumeral\expandafter\POL@vartolegacy\POL@R\xint:}%
+}%
+%% Euclidean special pseudo-remainder
+\def\POL@getprem#1#2{%
+ \let\POL@Q\undefined % trap errors in Sturm code update to use \POL@prem
+ % this was simpler before I converted \xintPolPRem into returning a tuple...
+ \odef\POL@R{\romannumeral\expandafter\POL@vartolegacy
+ \romannumeral0\expandafter\xint_stop_atsecondoftwo
+ \romannumeral`&&@\xintPolPRem{\POL@tovar{#1}}{\POL@tovar{#2}}%
+ \xint:}%
+}%
+%
+%%%%%%%%%%%%
+%%
+%% Things are currenly implemented twice : here the legacy macros
+%% such as GCD or Diff, and in polexprcore.tex the expandable
+%% support macros for the \xinteval interface.
+%%
+%% Soon, I will probably remove all legacy code (like I did already
+%% for division) and make the user macros simple wrappers to the
+%% expandable code.
+%%
+%% But for 0.8 release, I preferred not to yet, as I did not have
+%% really the time to compare speed. Usage of the "special
+%% pseudo euclidean remainder" (expandable) code in Sturm chain
+%% construction proved very beneficial as it divided by 3 the
+%% \PolToSturm execution time on the Wilkinson perturbed type 1
+%% example in the documentation.
+%%
+%%%%%%%%%%%%
+%
+%% GCD
+%
+% It seems I didn't even use here the (now deleted) macros implementing
+% division, and I redid here what was needed: this code, which I leave
+% standing as I have other priorities, does not use the \POL@divide !
+%
+\def\PolGCD#1#2#3{% sets #3 to the (unitary) G.C.D. of #1 and #2
+ \POL@GCD{#1}{#2}{#3}%
+ \POL@newpol{#3}%
+}%
+\def\POL@GCD #1#2#3{%
+ \begingroup
+ \expandafter\let\expandafter\POL@A\csname POLuserpol@#1\endcsname
+ \expandafter\let\expandafter\POL@B\csname POLuserpol@#2\endcsname
+ \expandafter\POL@split\POL@A;\POL@degA\POL@polA
+ \expandafter\POL@split\POL@B;\POL@degB\POL@polB
+ \ifnum\POL@degA<\z@
+ \expandafter\xint_firstoftwo\else\expandafter\xint_secondoftwo
+ \fi
+ {\ifnum\POL@degB<\z@
+ \expandafter\xint_firstoftwo\else\expandafter\xint_secondoftwo
+ \fi
+ {\def\POL@result{-1.\empty{0/1[0]}}}%
+ {\xintAssignArray\POL@polB\to\POL@arrayB
+ \POL@normalize{B}%
+ \POL@gcd@exit BA}}%
+ {\ifnum\POL@degB<\z@
+ \expandafter\xint_firstoftwo\else\expandafter\xint_secondoftwo
+ \fi
+ {\xintAssignArray\POL@polA\to\POL@arrayA
+ \POL@normalize{A}%
+ \POL@gcd@exit AB}%
+ {\ifnum\POL@degA<\POL@degB\space
+ \let\POL@tmp\POL@B\let\POL@B\POL@A\let\POL@A\POL@tmp
+ \let\POL@tmp\POL@degB\let\POL@degB\POL@degA\let\POL@degA\POL@tmp
+ \let\POL@tmp\POL@polB\let\POL@polB\POL@polA\let\POL@polA\POL@tmp
+ \fi
+ \xintAssignArray\POL@polA\to\POL@arrayA
+ \xintAssignArray\POL@polB\to\POL@arrayB
+ \POL@gcd AB%
+ }}%
+ \expandafter
+ \endgroup
+ \expandafter
+ \XINT_global
+ \expandafter\def\csname POLuserpol@#3\expandafter\endcsname
+ \expandafter{\POL@result}%
+}%
+\def\POL@normalize#1{%
+ \expandafter\def\expandafter\POL@tmp\expandafter
+ {\csname POL@array#1\csname POL@array#10\endcsname\endcsname}%
+ \edef\POL@normalize@leading{\POL@tmp}%
+ \expandafter\def\POL@tmp{1/1[0]}%
+ \count@\csname POL@deg#1\endcsname\space
+ \xintloop
+ \ifnum\count@>\z@
+ \expandafter\edef\csname POL@array#1\the\count@\endcsname
+ {\xintIrr{\xintDiv
+ {\csname POL@array#1\the\count@\endcsname}%
+ {\POL@normalize@leading}}[0]}%
+ \advance\count@\m@ne
+ \repeat
+}%
+\def\POL@gcd#1#2{%
+ \POL@normalize{#2}%
+ \edef\POL@degQ{\the\numexpr\csname POL@deg#1\endcsname
+ -\csname POL@deg#2\endcsname}%
+ \count@\numexpr\csname POL@deg#1\endcsname+\@ne\relax
+ \count\tw@\numexpr\POL@degQ+\@ne\relax
+ \xintloop
+ \POL@gcd@getremainder@loopbody#1#2%
+ \ifnum\count\tw@>\z@
+ \repeat
+ \expandafter\def\csname POL@array#10\endcsname{1}%
+ \xintloop
+ \xintiiifZero{\csname POL@array#1\the\count@\endcsname}%
+ {\iftrue}%
+ {\iffalse}%
+ \advance\count@\m@ne
+ \repeat
+ \expandafter\edef\csname POL@deg#1\endcsname{\the\numexpr\count@-\@ne}%
+ \ifnum\count@<\@ne
+ \expandafter\POL@gcd@exit
+ \else
+ \expandafter\edef\csname POL@array#10\endcsname{\the\count@}%
+ \expandafter\POL@gcd
+ \fi{#2}{#1}%
+}%
+\def\POL@gcd@getremainder@loopbody#1#2{%
+ \edef\POL@gcd@ratio{\csname POL@array#1\the\count@\endcsname}%
+ \advance\count@\m@ne
+ \advance\count\tw@\m@ne
+ \count4 \count@
+ \count6 \csname POL@deg#2\endcsname\space
+ \xintloop
+ \ifnum\count6>\z@
+ \expandafter\edef\csname POL@array#1\the\count4\endcsname
+ {\xintSub
+ {\csname POL@array#1\the\count4\endcsname}%
+ {\xintMul
+ {\POL@gcd@ratio}%
+ {\csname POL@array#2\the\count6\endcsname}}}%
+ \advance\count4 \m@ne
+ \advance\count6 \m@ne
+ \repeat
+}%
+\def\POL@gcd@exit#1#2{%
+ \count@\numexpr\csname POL@deg#1\endcsname+\@ne\relax
+ \POL@resultfromarray #1%
+}%
+%
+%% DIFFERENTIATION
+%
+\def\POL@diff@loop@one #1/#2[#3]#4%
+ {\xintIrr{\xintiiMul{#4}{#1}/#2[0]}[#3]}%
+\def\POL@diff#1{\POL@diff@loop1.}%
+\def\POL@diff@loop#1.#2{%
+ \if\relax#2\expandafter\xint_gob_til_dot\fi
+ {\expandafter\POL@diff@loop@one\romannumeral0\xintraw{#2}{#1}}%
+ \expandafter\POL@diff@loop\the\numexpr#1+\@ne.%
+}%
+\def\PolDiff{\POL@chkopt\POL@oPolDiff[1]}%
+\def\POL@oPolDiff[#1]{%
+ % optional parameter is how many times to derivate
+ % first mandatory arg is name of polynomial function to derivate,
+ % same name as in \NewPolExpr
+ % second mandatory arg name of derivative
+ \edef\POL@iterindex{\the\numexpr#1\relax}%
+ \ifnum\POL@iterindex<\z@
+ \expandafter\xint_firstoftwo
+ \else
+ \expandafter\xint_secondoftwo
+ \fi
+ {\PolAntiDiff[-\POL@iterindex]}{\POL@Diff}%
+}%
+\def\POL@Diff{%
+ \ifcase\POL@iterindex\space
+ \expandafter\POL@Diff@no
+ \or\expandafter\POL@Diff@one
+ \else\xint_afterfi{\POL@Iterate\POL@Diff@one}%
+ \fi
+}%
+\def\POL@Diff@no #1#2{\POL@let{#2}{#1}}%
+\def\POL@Diff@one #1#2{\POL@Diff@@one {#1}{#2}\POL@newpol{#2}}%
+\def\POL@Diff@@one#1#2{%
+ \expandafter\expandafter\expandafter\POL@split
+ \csname POLuserpol@#1\endcsname;\POL@var@deg\POL@var@coeffs
+ \ifnum\POL@var@deg<\@ne
+ \XINT_global\@namedef{POLuserpol@#2}{-1.\empty{0/1[0]}}%
+ \else
+ \edef\POL@var@coeffs{\expandafter\POL@diff\POL@var@coeffs\relax}%
+ \XINT_global\expandafter\edef\csname POLuserpol@#2\endcsname
+ {\the\numexpr\POL@var@deg-\@ne.\noexpand\empty\POL@var@coeffs}%
+ \fi
+}%
+% lazy way but allows to share with AntiDiff
+\def\POL@Iterate#1#2#3{%
+ \begingroup
+ \xintverbosefalse
+ #1{#2}{#3}%
+ \xintloop
+ \ifnum\POL@iterindex>\tw@
+ #1{#3}{#3}%
+ \edef\POL@iterindex{\the\numexpr\POL@iterindex-\@ne}%
+ \repeat
+ \expandafter
+ \endgroup\expandafter
+ \XINT_global
+ \expandafter
+ \def\csname POLuserpol@#3\expandafter\endcsname
+ \expandafter{\romannumeral`&&@\csname POLuserpol@#3\endcsname}%
+ #1{#3}{#3}%
+}%
+%
+%% ANTI-DIFFERENTIATION
+%
+\def\POL@antidiff@loop@one #1/#2[#3]#4%
+ {\xintIrr{#1/\xintiiMul{#4}{#2}[0]}[#3]}%
+\def\POL@antidiff{\POL@antidiff@loop1.}%
+\def\POL@antidiff@loop#1.#2{%
+ \if\relax#2\expandafter\xint_gob_til_dot\fi
+ {\expandafter\POL@antidiff@loop@one\romannumeral0\xintraw{#2}{#1}}%
+ \expandafter\POL@antidiff@loop\the\numexpr#1+\@ne.%
+}%
+\def\PolAntiDiff{\POL@chkopt\POL@oPolAntiDiff[1]}%
+\def\POL@oPolAntiDiff[#1]{%
+ % optional parameter is how many times to derivate
+ % first mandatory arg is name of polynomial function to derivate,
+ % same name as in \NewPolExpr
+ % second mandatory arg name of derivative
+ \edef\POL@iterindex{\the\numexpr#1\relax}%
+ \ifnum\POL@iterindex<\z@
+ \expandafter\xint_firstoftwo
+ \else
+ \expandafter\xint_secondoftwo
+ \fi
+ {\PolDiff[-\POL@iterindex]}{\POL@AntiDiff}%
+}%
+\def\POL@AntiDiff{%
+ \ifcase\POL@iterindex\space
+ \expandafter\POL@AntiDiff@no
+ \or\expandafter\POL@AntiDiff@one
+ \else\xint_afterfi{\POL@Iterate\POL@AntiDiff@one}%
+ \fi
+}%
+\let\POL@AntiDiff@no\POL@Diff@no
+\def\POL@AntiDiff@one #1#2{\POL@AntiDiff@@one{#1}{#2}\POL@newpol{#2}}%
+\def\POL@AntiDiff@@one#1#2{%
+ \expandafter\expandafter\expandafter\POL@split
+ \csname POLuserpol@#1\endcsname;\POL@var@deg\POL@var@coeffs
+ \ifnum\POL@var@deg<\z@
+ \XINT_global\@namedef{POLuserpol@#2}{-1.\empty{0/1[0]}}%
+ \else
+ \edef\POL@var@coeffs{\expandafter\POL@antidiff\POL@var@coeffs\relax}%
+ \XINT_global\expandafter\edef\csname POLuserpol@#2\endcsname
+ {\the\numexpr\POL@var@deg+\@ne.\noexpand\empty{0/1[0]}\POL@var@coeffs}%
+ \fi
+}%
+%
+%%
+%% Localization of roots
+%%
+% this is big. It provides also output macros, of both expandable and
+% non-expandable type
+\input polexprsturm.tex\relax
+%
+%
+%% Non-expandable output macros
+%
+\def\PolTypesetCmdPrefix#1{\xintiiifSgn{#1}{}{+}{+}}%
+\def\PolTypesetCmd#1{\xintifOne{\xintiiAbs{#1}}%
+ {\ifnum\PolIndex=\z@\xintiiSgn{#1}\else
+ \xintiiifSgn{#1}{-}{}{}\fi
+ \let\PolIfCoeffIsPlusOrMinusOne\xint_firstoftwo}%
+ {\PolTypesetOne{#1}%
+ \let\PolIfCoeffIsPlusOrMinusOne\xint_secondoftwo}%
+ }%
+\ifdefined\frac
+\def\PolTypesetOne{\xintSignedFrac}%
+\else
+\def\PolTypesetOne{\xintSignedFwOver}%
+\fi
+\catcode`^ 7
+\def\PolTypesetMonomialCmd{%
+ \ifcase\PolIndex\space
+ %
+ \or\PolVar
+ \else\PolVar^{\PolIndex}%
+ \fi
+}%
+\catcode`^ 11 % normal xint catcode
+\def\PolTypeset{\POL@ifstar
+ {\def\POL@ts@ascending{1}\POL@Typeset}%
+ {\def\POL@ts@ascending{0}\POL@Typeset}%
+}%
+%%
+%% \PolTypeset
+%%
+%% extended at 0.8 to handle arbitrary expressions on input
+%%
+\def\POL@Typeset{\POL@chkopt\POL@oPOL@Typeset[x]}%
+\def\POL@oPOL@Typeset[#1]#2{%
+ \ifmmode\let\POL@endtypeset\empty\else$\def\POL@endtypeset{$}\fi
+ \ifcsname POLuserpol@#2\endcsname
+ \expandafter\expandafter\expandafter\POL@split
+ \csname POLuserpol@#2\endcsname;\POL@var@deg\POL@var@coeffs
+ \else
+ \xintAssign\expandafter\xint_firstofone\romannumeral0\xintbareeval
+ subs((deg(x),coeffs(x)),x=subs(#2,\PolToExprInVar=pol([0,1])))\relax
+ \to\POL@var@deg\POL@var@coeffs
+ \fi
+ \if\POL@ts@ascending1%
+ \def\PolIndex{0}%
+ \let\POL@ts@reverse\xint_firstofone
+ \let\POL@@ne@or@m@ne\@ne
+ \else
+ \let\PolIndex\POL@var@deg
+ \ifnum\PolIndex<\z@\def\PolIndex{0}\fi
+ \let\POL@ts@reverse\xintRevWithBraces
+ \let\POL@@ne@or@m@ne\m@ne
+ \fi
+ \def\PolVar{#1}%
+ \ifnum\POL@var@deg<\z@
+ \PolTypesetCmd{0/1[0]}\PolTypesetMonomialCmd
+ \else
+ \ifnum\POL@var@deg=\z@
+ \expandafter\PolTypesetCmd\POL@var@coeffs\PolTypesetMonomialCmd
+ \else
+ \def\POL@ts@prefix##1{\let\POL@ts@prefix\PolTypesetCmdPrefix}%
+ \expandafter\POL@ts@loop
+ \romannumeral-`0\POL@ts@reverse{\POL@var@coeffs}\relax
+ \fi
+ \fi
+ \POL@endtypeset
+}%
+\def\POL@ts@loop{\ifpoltypesetall\expandafter\xint_firstoftwo
+ \else\expandafter\xint_secondoftwo\fi
+ {\POL@ts@nocheck}{\POL@ts@check}.%
+}%
+\def\POL@ts@check.#1{%
+ \if\relax#1\expandafter\xint_gob_til_dot\fi
+ \xintiiifZero{#1}%
+ {}%
+ {\POL@ts@prefix{#1}\PolTypesetCmd{#1}\PolTypesetMonomialCmd}%
+ \edef\PolIndex{\the\numexpr\PolIndex+\POL@@ne@or@m@ne}\POL@ts@check.%
+}%
+\def\POL@ts@nocheck.#1{%
+ \if\relax#1\expandafter\xint_gob_til_dot\fi
+ \POL@ts@prefix{#1}\PolTypesetCmd{#1}\PolTypesetMonomialCmd
+ \edef\PolIndex{\the\numexpr\PolIndex+\POL@@ne@or@m@ne}\POL@ts@nocheck.%
+}%
+%
+%%
+%% Expandable output macros (legacy)
+%%
+\def\POL@eval@fork#1\At#2#3\krof{#2}%
+\def\PolEval#1#2#3{\romannumeral`&&@\POL@eval@fork
+ #2\PolEvalAt
+ \At\PolEvalAtExpr\krof {#1}{#3}%
+}%
+\def\PolEvalAt#1#2{%
+ \xintpraw{\csname XINT_expr_polfunc_#1\endcsname{#2}}%
+}%
+\def\POL@eval#1#2{%
+ \csname XINT_expr_polfunc_#1\endcsname{#2}%
+}%
+\def\PolEvalAtExpr#1#2{\xinttheexpr #1(#2)\relax}%
+%
+\def\PolEvalReduced#1#2#3{\romannumeral`&&@\POL@eval@fork
+ #2\PolEvalReducedAt
+ \At\PolEvalReducedAtExpr\krof {#1}{#3}%
+}%
+\def\PolEvalReducedAt#1#2{%
+ \xintpraw % in order not to print denominator if the latter equals 1
+ {\xintIrr{\csname XINT_expr_polfunc_#1\endcsname{#2}}[0]}%
+}%
+\def\PolEvalReducedAtExpr#1#2{%
+ \xintpraw
+ {\expandafter\xintIrr\romannumeral`&&@\xintthebareeval#1(#2)\relax[0]}%
+}%
+%
+\def\PolFloatEval#1#2#3{\romannumeral`&&@\POL@eval@fork
+ #2\PolFloatEvalAt
+ \At\PolFloatEvalAtExpr\krof {#1}{#3}%
+}%
+\def\PolFloatEvalAt#1#2{%
+ \xintpfloat{\csname XINT_flexpr_polfunc_#1\endcsname{#2}}%
+}%
+\def\PolFloatEvalAtExpr#1#2{\xintthefloatexpr #1(#2)\relax}%
+\def\PolLeadingCoeff#1{%
+ \romannumeral`&&@\expandafter\expandafter\expandafter\xintlastitem
+ \expandafter\expandafter\expandafter
+ {\csname POLuserpol@#1\endcsname}%
+}%
+%
+\def\PolNthCoeff#1#2{\romannumeral`&&@%
+ \expandafter\POL@nthcoeff
+ \romannumeral0\xintnthelt{\ifnum\numexpr#2<\z@#2\else(#2)+1\fi}%
+ {\expandafter\expandafter\expandafter
+ \xint_gob_til_dot\csname POLuserpol@#1\endcsname}@%
+}%
+\def\POL@nthcoeff#1@{\if @#1@\expandafter\xint_firstoftwo
+ \else\expandafter\xint_secondoftwo\fi
+ {0/1[0]}{#1}}%
+%
+% returns -1 for zero polynomial for context of numerical expression
+% should it return -\infty?
+\def\PolDegree#1{\romannumeral`&&@\expandafter\expandafter\expandafter
+ \POL@degree\csname POLuserpol@#1\endcsname;}%
+\def\POL@degree #1.#2;{#1}%
+%
+\def\PolToList#1{\romannumeral`&&@\expandafter\expandafter\expandafter
+ \xint_gob_til_dot\csname POLuserpol@#1\endcsname}%
+%
+\def\PolToCSV#1{\romannumeral0\xintlistwithsep{, }{\PolToList{#1}}}%
+%
+% \PolIContent (0.5)
+% Why did I call this IContent and not Content? Ah, I see Maple terminology
+% But I realize now I misread the Maple doc, its icontent() is the gcd of
+% all coeffs of a multivariate polynomial. Whereas content(,) second argument
+% specifies which variable to consider expression as being univariate in it
+%
+\def\POL@icontent#1{\romannumeral0\expandafter\XINT_fgcd_out
+ \romannumeral0\expandafter\XINT_fgcdof\romannumeral`&&@#1^}%
+% Since xintexpr 1.4d, \xintGCDof always outputs an irreducible fraction A/B.
+% (with B=1 if A/B integer).
+\def\PolIContent#1{\xintGCDof{\PolToList{#1}}}%
+%
+\def\PolToExprCmd#1{\xintPRaw{\xintRawWithZeros{#1}}}%
+\def\PolToFloatExprCmd#1{\xintFloat{#1}}%
+% \def\PolTypesetCmdPrefix#1{\xintiiifSgn{#1}{}{+}{+}}%
+\let\PolToExprTermPrefix\PolTypesetCmdPrefix
+\def\PolToExprOneTermStyleA#1#2{%
+ \ifnum#2=\z@
+ \PolToExprCmd{#1}%
+ \else
+ \xintifOne{\xintiiAbs{#1}}
+ {\xintiiifSgn{#1}{-}{}{}}% + from \PolToExprTermPrefix
+ {\PolToExprCmd{#1}\PolToExprTimes}%
+ \fi
+ \ifcase\xintiiAbs{#2} %<-- space here mandatory
+ \or\PolToExprVar
+ \else\PolToExprVar\PolToExprCaret\xintiiAbs{#2}%
+ \fi
+}%
+\let\PolToExprOneTerm\PolToExprOneTermStyleA
+\def\PolToExprOneTermStyleB#1#2{%
+ \ifnum#2=\z@
+ \xintNumerator{#1}%
+ \else
+ \xintifOne{\xintiiAbs{\xintNumerator{#1}}}
+ {\xintiiifSgn{#1}{-}{}{}}% + from \PolToExprTermPrefix
+ {\xintNumerator{#1}\PolToExprTimes}%
+ \fi
+ \ifcase\xintiiAbs{#2} %<-- space here mandatory
+ \or\PolToExprVar
+ \else\PolToExprVar\PolToExprCaret\xintiiAbs{#2}%
+ \fi
+ \xintiiifOne{\xintDenominator{#1}}{}{/\xintDenominator{#1}}%
+}%
+\def\PolToFloatExprOneTerm#1#2{%
+ \ifnum#2=\z@
+ \PolToFloatExprCmd{#1}%
+ \else
+ \PolToFloatExprCmd{#1}\PolToExprTimes
+ \fi
+ \ifcase\xintiiAbs{#2} %<-- space here mandatory
+ \or\PolToExprVar
+ \else\PolToExprVar\PolToExprCaret\xintiiAbs{#2}%
+ \fi
+}%
+\def\PolToExprTimes{*}%
+\def\PolToExprVar{x}%
+\def\PolToExprInVar{x}%
+\edef\PolToExprCaret{\string ^}%
+%%
+%% \PolToExpr
+%%
+%% extended at 0.8 to handle arbitrary expressions on input
+%%
+\def\PolToExpr#1{%
+ \if*\noexpand#1\expandafter\xint_firstoftwo\else
+ \expandafter\xint_secondoftwo\fi
+ \PolToExprAscending\PolToExprDescending{#1}}%
+\def\PolToFloatExpr#1{%
+ \if*\noexpand#1\expandafter\xint_firstoftwo\else
+ \expandafter\xint_secondoftwo\fi
+ \PolToFloatExprAscending\PolToFloatExprDescending{#1}}%
+\def\PolToExpr@getit#1%
+{%
+ \ifcsname XINT_expr_varvalue_#1\endcsname
+ \csname XINT_expr_varvalue_#1\expandafter\endcsname
+ \else
+ \expandafter\xint_firstofone\romannumeral0%
+ \xintbareeval subs(#1,\PolToExprInVar=pol([0,1]))\expandafter\relax
+ \fi
+}%
+\def\PolToExprAscending#1#2{%
+ \expandafter\POL@toexpr\romannumeral0\PolToExpr@getit{#2}%
+ \PolToExprOneTerm\POL@toexprA
+}%
+\def\PolToFloatExprAscending#1#2{%
+ \expandafter\POL@toexpr\romannumeral0\PolToExpr@getit{#2}%
+ \PolToFloatExprOneTerm\POL@toexprA
+}%
+\def\PolToExprDescending#1{%
+ \expandafter\POL@toexpr\romannumeral0\PolToExpr@getit{#1}%
+ \PolToExprOneTerm\POL@toexprD
+}%
+\def\PolToFloatExprDescending#1{%
+ \expandafter\POL@toexpr\romannumeral0\PolToExpr@getit{#1}%
+ \PolToFloatExprOneTerm\POL@toexprD
+}%
+\def\POL@toexpr#1#2#3{\POL@toexpr@fork#3#2#1\relax}%
+\def\POL@toexpr@fork #1#2#3{%
+ \POL_Pfork
+ #3\POL@toexpr@pol
+ P\POL@toexpr@cst
+ \krof #1#2#3%
+}%
+\def\POL@toexpr@cst#1#2#3\relax{#2{#3}{0}}%
+\def\POL@toexpr@pol#1#2P#3.{#1{#3}#2\empty}%
+% now back to legacy pre 0.8 code
+\def\POL@toexprA #1#2\empty#3{%
+ \ifpoltoexprall\expandafter\POL@toexprall@b
+ \else\expandafter\POL@toexpr@b
+ \fi {#3}#2{0}1.%
+}%
+\def\POL@toexprD #1#2#3\relax{% #3 has \empty to prevent brace removal
+ \expandafter\POL@toexprD@a\expandafter#2%
+ \the\numexpr #1\expandafter.\romannumeral0\xintrevwithbraces{#3}\relax
+}%
+\def\POL@toexprD@a #1#2.#3{%
+ \ifpoltoexprall\expandafter\POL@toexprall@b
+ \else\expandafter\POL@toexpr@b
+ \fi{#3}#1{-#2}\the\numexpr\@ne+-#2.%
+}%
+\def\POL@toexpr@b #1#2#3{%
+ \xintiiifZero{#1}%
+ {\expandafter\POL@toexpr@loop\expandafter\POL@toexpr@b}%
+ {#2{#1}{#3}%
+ \expandafter\POL@toexpr@loop\expandafter\POL@toexpr@c}%
+ \expandafter#2%
+}%
+\def\POL@toexpr@c #1#2#3{%
+ \xintiiifZero{#1}%
+ {}%
+ {\PolToExprTermPrefix{#1}#2{#1}{#3}}%
+ \expandafter\POL@toexpr@loop\expandafter\POL@toexpr@c
+ \expandafter#2%
+}%
+\def\POL@toexprall@b #1#2#3{%
+ #2{#1}{#3}%
+ \expandafter\POL@toexpr@loop\expandafter\POL@toexprall@c
+ \expandafter#2%
+}%
+\def\POL@toexprall@c #1#2#3{%
+ \PolToExprTermPrefix{#1}#2{#1}{#3}%
+ \expandafter\POL@toexpr@loop\expandafter\POL@toexprall@c
+ \expandafter#2%
+}%
+\def\POL@toexpr@loop#1#2#3.#4{%
+ \if\relax#4\expandafter\xint_gob_til_dot\fi
+ #1{#4}#2{#3}\the\numexpr\@ne+#3.%
+}%
+\XINT_restorecatcodes_endinput%
diff --git a/macros/generic/polexpr/polexprcore.tex b/macros/generic/polexpr/polexprcore.tex
new file mode 100644
index 0000000000..e071729e42
--- /dev/null
+++ b/macros/generic/polexpr/polexprcore.tex
@@ -0,0 +1,1366 @@
+%% This file polexprcore.tex is part of the polexpr package (0.8, 2021/03/29)
+%% Core routines to match infix operators +, -, *, //, /:, ^, ** and some
+%% functions
+%% The atoms representing polynomials inside \xintexpr are
+%% - for constants: a numeric value (indistinguishable. from scalars)
+%% - for degree at least 1: P<degree>.{c0}{c1}....{cN} with N = degree
+%% Auxiliaries
+\long\def\POL_Pfork #1P#2#3\krof{#2}%
+\long\def\POL_PPfork #1PP#2#3\krof{#2}%
+\long\def\POL_zeroPfork #10P#2#3\krof{#2}%
+\long\def\POL_secondofthree#1#2#3{#2}%
+% \long\def\POL_Apply:x #1#2%
+% {%
+% \POL_apply:x_loop {#1}#2%
+% \xint_Bye\xint_Bye\xint_Bye\xint_Bye
+% \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+% }%
+\long\def\POL_bBye#1\xint_Bye{}%
+\long\def\POL_apply:x_loop #1#2#3#4#5#6#7#8#9%
+{%
+ \POL_bBye #2\xint_Bye{#1{#2}}%
+ \POL_bBye #3\xint_Bye{#1{#3}}%
+ \POL_bBye #4\xint_Bye{#1{#4}}%
+ \POL_bBye #5\xint_Bye{#1{#5}}%
+ \POL_bBye #6\xint_Bye{#1{#6}}%
+ \POL_bBye #7\xint_Bye{#1{#7}}%
+ \POL_bBye #8\xint_Bye{#1{#8}}%
+ \POL_bBye #9\xint_Bye{#1{#9}}%
+ \POL_apply:x_loop {#1}%
+}%
+\long\def\POL_apply:x_iloop #1#2#3#4#5#6#7#8#9%
+{%
+ \POL_bBye #2\xint_Bye{#10{#2}}%
+ \POL_bBye #3\xint_Bye{#11{#3}}%
+ \POL_bBye #4\xint_Bye{#12{#4}}%
+ \POL_bBye #5\xint_Bye{#13{#5}}%
+ \POL_bBye #6\xint_Bye{#14{#6}}%
+ \POL_bBye #7\xint_Bye{#15{#7}}%
+ \POL_bBye #8\xint_Bye{#16{#8}}%
+ \POL_bBye #9\xint_Bye{#17{#9}}%
+ \POL_apply:x_iloop_a#1%
+}%
+\def\POL_apply:x_iloop_a#1#2.%
+{%
+ \expandafter\POL_apply:x_iloop
+ \expandafter{\expandafter#1\the\numexpr\xint_c_viii+#1.}%
+}%
+\long\def\POL_apply:x_iloop #1#2#3#4#5#6#7#8#9%
+{%
+ \POL_bBye #2\xint_Bye{#10{#2}}%
+ \POL_bBye #3\xint_Bye{#11{#3}}%
+ \POL_bBye #4\xint_Bye{#12{#4}}%
+ \POL_bBye #5\xint_Bye{#13{#5}}%
+ \POL_bBye #6\xint_Bye{#14{#6}}%
+ \POL_bBye #7\xint_Bye{#15{#7}}%
+ \POL_bBye #8\xint_Bye{#16{#8}}%
+ \POL_bBye #9\xint_Bye{#17{#9}}%
+ \POL_apply:x_iloop_a#1%
+}%
+\def\POL_apply:x_iloop_a#1#2.%
+{%
+ \expandafter\POL_apply:x_iloop
+ \expandafter{\expandafter#1\the\numexpr\xint_c_viii+#1.}%
+}%
+%%
+%% ADDITION
+%%
+\def\xintPolAdd #1%
+{%
+ \expanded\expandafter\POL_add_in\romannumeral`&&@#1\xint:
+}%
+\def\POL_add_in #1\xint:#2%
+{%
+ {%
+ \expandafter\POL_add_fork
+% Fragile but this macro is not public anyhow and won't get arbitrary input
+% At odds with systematic \xint: style further down
+ \romannumeral`&&@#2\xint_bye\xint_bye\xint_bye\xint_bye\empty
+ #1\xint_bye\xint_bye\xint_bye\xint_bye\empty
+ \empty
+ }%
+}%
+% Careful that first means "first here" i.e. the original second argument,
+% and vice versa
+\def\POL_add_fork #1#2\empty#3%
+{%
+ \POL_PPfork
+ #1#3{\POL_add_a}%
+ #1P{\POL_add_second_is_scalar}%
+ #3P{\POL_add_first_is_scalar}%
+ PP{\POL_add_both_are_scalar}%
+ \krof #1#2\empty#3%
+}%
+\def\POL_add_first_is_scalar #1\xint_bye#2\empty#3.#4%
+{%
+ #3.{\xintAdd{#1}{#4}}%
+}%
+\def\POL_add_second_is_scalar #1.#2#3\empty#4\xint_bye#5\empty\empty
+{%
+ #1.{\xintAdd{#2}{#4}}#3%
+}%
+\def\POL_add_both_are_scalar #1\xint_bye#2\empty#3\xint_bye#4\empty\empty
+{%
+ \xintAdd{#1}{#3}%
+}%
+\def\POL_add_a P#1.#2#3#4#5\empty P#6.#7#8#9%
+{%
+ \expandafter\POL_add_b
+ \expanded\bgroup\unexpanded{#1.#6.}%
+ \xint_bye #2\POL_add_Eb\xint_bye
+ \xint_bye #7\POL_add_Fb\xint_bye {\xintAdd{#2}{#7}}%
+ \xint_bye #3\POL_add_Ec\xint_bye
+ \xint_bye #8\POL_add_Fc\xint_bye {\xintAdd{#3}{#8}}%
+ \xint_bye #4\POL_add_Ed\xint_bye
+ \xint_bye #9\POL_add_Fd\xint_bye {\xintAdd{#4}{#9}}%
+ \POL_add_A #5\empty
+}%
+\def\POL_add_b #1.#2.%
+{%
+ \ifnum#1=#2 \expandafter\POL_add_c
+ \else
+ \ifnum#1>#2 P#1.\else P#2.\fi
+ \fi
+}%
+% No brace stripping possible, because constant polynomials are really
+% represented by scalars in all those internal contexts, so real
+% polynomials have at least two coefficients
+\def\POL_add_c #1\empty
+{%
+ \expandafter\POL_add_d
+ \romannumeral0\XINT_revwbr_loop {}%
+ #1\xint:\xint:\xint:\xint:%
+ \xint:\xint:\xint:\xint:\xint_bye
+ \xint_bye
+}%
+% Attention, reused in various other locations. It is all f-expandable.
+\def\POL_add_d #1%
+{%
+% abuse of \XINT_Sgn internals compatible to #1 being \xint_bye
+ \if0\XINT_Sgn#1\xint:
+ \xint_dothis\POL_add_d
+ \fi
+ \xint_orthat{\POL_add_e {#1}}%
+}%
+\def\POL_add_e #1%
+{%
+ \xint_bye#1\POL_add_e_zero\xint_bye \POL_add_f\empty{#1}%
+}%
+\def\POL_add_e_zero\xint_bye\POL_add_f\empty #1{0/1[0]}%
+% #1 starts with \empty to avoid brace stripping.
+\def\POL_add_f #1\xint_bye
+{%
+ \expandafter\POL_add_g
+ \the\numexpr
+ \xintLength{#1}-\xint_c_ii\expandafter.%
+ \romannumeral0\expandafter
+ \XINT_revwbr_loop\expandafter {\expandafter}%
+ #1\xint:\xint:\xint:\xint:%
+ \xint:\xint:\xint:\xint:\xint_bye
+}%
+\def\POL_add_g #1.%
+{%
+ \ifnum#1=\xint_c_\expandafter\POL_add_h\fi
+ P#1.%
+}%
+\def\POL_add_h P0.#1{#1}%
+% Attention reused in \POL_mul_d and \POL_quorem_c
+\def\POL_add_A #1#2#3#4#5\empty#6#7#8#9%
+{%
+ \xint_bye #1\POL_add_Ea\xint_bye
+ \xint_bye #6\POL_add_Fa\xint_bye {\xintAdd{#1}{#6}}%
+ \xint_bye #2\POL_add_Eb\xint_bye
+ \xint_bye #7\POL_add_Fb\xint_bye {\xintAdd{#2}{#7}}%
+ \xint_bye #3\POL_add_Ec\xint_bye
+ \xint_bye #8\POL_add_Fc\xint_bye {\xintAdd{#3}{#8}}%
+ \xint_bye #4\POL_add_Ed\xint_bye
+ \xint_bye #9\POL_add_Fd\xint_bye {\xintAdd{#4}{#9}}%
+ \POL_add_A #5\empty
+}%
+\def\POL_add_Ea\xint_bye
+ \xint_bye #1\POL_add_Fa\xint_bye #2\xint_bye\xint_bye
+ \POL_add_Eb\xint_bye\xint_bye#3\POL_add_Fb\xint_bye #4\xint_bye\xint_bye
+ \POL_add_Ec\xint_bye\xint_bye#5\POL_add_Fc\xint_bye #6\xint_bye\xint_bye
+ \POL_add_Ed\xint_bye\xint_bye#7\POL_add_Fd\xint_bye #8%
+ \POL_add_A#9\empty
+{%
+ \xint_bye #1\POL_add_G\xint_bye{#1}%
+ \xint_bye #3\POL_add_G\xint_bye{#3}%
+ \xint_bye #5\POL_add_G\xint_bye{#5}%
+ \xint_bye #7\POL_add_G\xint_bye{#7}%
+ \iffalse{\fi}%
+}%
+\def\POL_add_G#1\empty{\iffalse{\fi}}%
+\def\POL_add_Fa\xint_bye #1%
+ \xint_bye #2\POL_add_Eb \xint_bye
+ \xint_bye\xint_bye\POL_add_Fb\xint_bye #3%
+ \xint_bye #4\POL_add_Ec \xint_bye
+ \xint_bye\xint_bye\POL_add_Fc\xint_bye #5%
+ \xint_bye #6\POL_add_Ed #7\POL_add_A
+ #8\empty#9\empty
+{%
+ \expandafter\xint_bye\POL_secondofthree #1%
+ \POL_add_G\xint_bye{\POL_secondofthree#1}%
+ \xint_bye #2\POL_add_G\xint_bye{#2}%
+ \xint_bye #4\POL_add_G\xint_bye{#4}%
+ \xint_bye #6\POL_add_G\xint_bye{#6}%
+ \iffalse{\fi}#8\empty%
+}%
+\def\POL_add_Eb\xint_bye
+ \xint_bye #1\POL_add_Fb\xint_bye #2\xint_bye\xint_bye
+ \POL_add_Ec\xint_bye\xint_bye#3\POL_add_Fc\xint_bye #4\xint_bye\xint_bye
+ \POL_add_Ed\xint_bye\xint_bye#5\POL_add_Fd\xint_bye #6%
+ \POL_add_A#7\empty
+{%
+ \xint_bye #1\POL_add_G\xint_bye{#1}%
+ \xint_bye #3\POL_add_G\xint_bye{#3}%
+ \xint_bye #5\POL_add_G\xint_bye{#5}%
+ \iffalse{\fi}%
+}%
+\def\POL_add_Fb\xint_bye #1%
+ \xint_bye #2\POL_add_Ec \xint_bye
+ \xint_bye\xint_bye\POL_add_Fc\xint_bye #3%
+ \xint_bye #4\POL_add_Ed #5\POL_add_A
+ #6\empty#7\empty
+{%
+ \expandafter\xint_bye\POL_secondofthree #1%
+ \POL_add_G\xint_bye{\POL_secondofthree#1}%
+ \xint_bye #2\POL_add_G\xint_bye{#2}%
+ \xint_bye #4\POL_add_G\xint_bye{#4}%
+ \iffalse{\fi}#6\empty
+}%
+\def\POL_add_Ec\xint_bye
+ \xint_bye #1\POL_add_Fc\xint_bye #2\xint_bye\xint_bye
+ \POL_add_Ed\xint_bye\xint_bye#3\POL_add_Fd\xint_bye #4%
+ \POL_add_A#5\empty
+{%
+ \xint_bye #1\POL_add_G\xint_bye{#1}%
+ \xint_bye #3\POL_add_G\xint_bye{#3}%
+ \iffalse{\fi}%
+}%
+\def\POL_add_Fc\xint_bye #1\xint_bye #2\POL_add_Ed #3\POL_add_A
+ #4\empty#5\empty
+{%
+ \expandafter\xint_bye\POL_secondofthree #1%
+ \POL_add_G\xint_bye{\POL_secondofthree#1}%
+ \xint_bye #2\POL_add_G\xint_bye{#2}%
+ \iffalse{\fi}#4\empty
+}%
+\def\POL_add_Ed\xint_bye\xint_bye#1\POL_add_Fd\xint_bye#2\POL_add_A#3\empty
+{%
+ \xint_bye #1\POL_add_G\xint_bye{#1}%
+ \iffalse{\fi}%
+}%
+\def\POL_add_Fd\xint_bye#1\POL_add_A #2\empty#3\empty
+{%
+ \expandafter\xint_bye \POL_secondofthree #1%
+ \POL_add_G\xint_bye{\POL_secondofthree#1}%
+ \iffalse{\fi}#2\empty
+}%
+%%
+%% OPPOSITE
+%%
+\def\xintPolOpp #1%
+{%
+ \expanded{%
+ \expandafter\POL_opp_fork\romannumeral`&&@#1%
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ }%
+}%
+\def\POL_opp_fork #1%
+{%
+ \if P#1\xint_dothis\POL_opp_a\fi
+ \xint_orthat\POL_opp_scalar #1%
+}%
+\def\POL_opp_scalar #1\xint_Bye#2\xint_bye
+{%
+ \XINT_Opp #1%
+}%
+\def\POL_opp_a #1.%
+{%
+ #1.\POL_apply:x_loop{\XINT_Opp}%
+}%
+%%
+%% SUBTRACTION
+%%
+\def\xintPolSub #1%
+{%
+ \expanded\expandafter\POL@sub\romannumeral`&&@#1\xint:
+}%
+\def\POL@sub #1\xint:#2%
+{%
+ {%
+ \expandafter
+ \POL_add_fork\expanded{%
+ \expandafter\POL_opp_fork \romannumeral`&&@#2%
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ }%
+ \xint_bye\xint_bye\xint_bye\xint_bye\empty
+ #1\xint_bye\xint_bye\xint_bye\xint_bye\empty
+ \empty
+ }%
+}%
+%%
+%% MULTIPLICATION
+%%
+\def\xintPolSqr #1%
+{%
+ \expanded\expandafter\POL_sqr_in\romannumeral`&&@#1\xint:
+}%
+\def\POL_sqr_in #1\xint:
+{%
+ {%
+ \expandafter\POL_mul_fork
+ #1\xint_bye
+ #1\xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ }%
+}%
+%
+\def\xintPolMul #1%
+{%
+ \expanded\expandafter\POL_mul_in\romannumeral`&&@#1\xint:
+}%
+\def\POL_mul_in #1\xint:#2%
+{%
+ {%
+ \expandafter\POL_mul_fork
+ \romannumeral`&&@#2\xint_bye
+ #1\xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ }%
+}%
+\def\POL_mul_fork #1#2\xint_bye#3%
+{%
+ \POL_PPfork
+ #1#3{\POL_mul_a}%
+ #1P{\POL_mul_second_is_scalar}%
+ #3P{\POL_mul_first_is_scalar}%
+ PP{\POL_mul_both_are_scalar}%
+ \krof #1#2\xint_bye#3%
+}%
+\def\POL_mul_both_are_scalar #1\xint_bye#2\xint_Bye#3\xint_bye
+{%
+ \xintMul{#1}{#2}%
+}%
+\def\POL_mul_second_is_scalar #1\xint_bye#2\xint_Bye
+{%
+ \POL_mul_first_is_scalar #2\xint_bye#1\xint_Bye
+}%
+\def\POL_mul_first_is_scalar #1%
+{%
+ \xint_gob_til_zero#1\POL_mul_zero0\POL_mul_scalar #1%
+}%
+\def\POL_mul_zero0\POL_mul_scalar #1\xint_bye#2\xint_bye{0/1[0]}%
+\def\POL_mul_scalar #1\xint_bye P#2.%
+{%
+ P#2.\POL_apply:x_loop{\xintMul{#1}}%
+}%
+\def\POL_mul_a P#1.#2#3P#4.#5\xint_bye
+{%
+ P\the\numexpr#1+#4.%
+ \expandafter\POL_mul_b
+ \expanded{\POL_apply:x_loop{\xintMul{#2}}#5\xint_bye}%
+ \xint:
+ #3\empty#5\xint_bye
+}%
+\def\POL_mul_b #1{{#1}\POL_mul_c\empty}%
+\def\POL_mul_c #1\xint:#2%
+{%
+ \xint_bye#2\POL_mul_E\xint_bye
+ \expandafter\POL_mul_d\expandafter{#1}{#2}%
+}%
+\def\POL_mul_d #1#2#3\empty#4\xint_bye
+{%
+ \expandafter\POL_mul_b
+ \expanded\bgroup
+ \expandafter\POL_add_A
+ \expanded{\POL_apply:x_loop{\xintMul{#2}}#4\xint_bye}%
+ \xint_bye\xint_bye\xint_bye\xint_bye\empty
+ #1\xint_bye\xint_bye\xint_bye\xint_bye\empty
+ \xint:
+ #3\empty#4\xint_bye
+}%
+\def\POL_mul_E\xint_bye
+ \expandafter\POL_mul_d\expandafter#1#2\xint_bye
+% This #1 starts with \empty
+{%
+ #1%
+}%
+%%
+%% POWERS
+%%
+\def\xintPolPow #1%
+{%
+ \expanded\expandafter\POL_pow_in\romannumeral`&&@#1\xint:
+}%
+\def\POL_pow_in #1\xint:#2%
+{%
+ {%
+ \expandafter\POL_pow_fork\the\numexpr \xintNum{#2}.#1\empty
+ }%
+}%
+\def\POL_pow_fork #1#2.%
+{%
+ \xint_UDzerominusfork
+ #1-\POL_pow_zero
+ 0#1\POL_pow_neg
+ 0-\POL_pow_pos
+ \krof
+ #1#2.%
+}%
+\def\POL_pow_zero #1\empty{1/1[0]}%
+\def\POL_pow_neg #1.#2%
+{%
+ \POL_Pfork #2{\POL_pow_neg_pol}P{\POL_pow_scalar}\krof #1.#2%
+}%
+\def\POL_pow_pos #1.#2%
+{%
+ \POL_Pfork #2{\POL_pow_a}P{\POL_pow_scalar}\krof #1.#2%
+}%
+\def\POL_pow_scalar #1.#2\empty
+{%
+ \xintPow{#2}{#1}%
+}%
+\def\POL_pow_neg_pol #1.#2\empty
+{%
+ \romannumeral0\XINT_signalcondition{InvalidOperation}%
+ {Not supported: polynomial to negative power #1}{}{1/1[0]}%
+}%
+\def\POL_pow_a #1.%
+{%
+% trailing \empty will disappear in expanded context (old comment)
+ \ifnum#1=\xint_c_i\xint_afterfi\xint_gob_til_dot\fi
+ \expandafter\POL_pow_b \the\numexpr#1-\xint_c_i.%
+}%
+\def\POL_pow_b #1.%
+{%
+ \ifodd #1 \xint_dothis{\expandafter\POL_pow_even}\fi
+ \xint_orthat{\expandafter\POL_pow_odd}\the\numexpr#1/\xint_c_ii.%
+}%
+\def\POL_pow_even #1.#2\empty
+{%
+ \expandafter\POL_pow_a
+ \expanded{\unexpanded{#1.}%
+ \POL_mul_a#2\xint_bye
+ #2\xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ }\empty
+}%
+\def\POL_pow_odd #1.#2\empty
+{%
+ \expanded
+ {\unexpanded{\POL_mul_a #2\xint_bye}%
+ \expandafter\POL_pow_a
+ \expanded{\unexpanded{#1.}%
+ \POL_mul_a#2\xint_bye
+ #2\xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ }%
+ \empty
+ }%
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+}%
+%%
+%% DIVISION
+%%
+%
+% / is deprecated for polynomial Euclidean division
+%
+\def\xintPolQuo #1%
+{%
+ \romannumeral0\expandafter\xint_stop_atfirstoftwo
+ \expanded\expandafter\POL_quorem_in\romannumeral`&&@#1\xint:
+}%
+% there is no operator, for lack of obvious best notation
+\def\xintPolRem #1%
+{%
+ \romannumeral0\expandafter\xint_stop_atsecondoftwo
+ \expanded\expandafter\POL_quorem_in\romannumeral`&&@#1\xint:
+}%
+% //
+\def\xintPolDivModQ #1%
+{%
+ \romannumeral0\expandafter\xint_stop_atfirstoftwo
+ \expanded\expandafter\POL_divmod_in\romannumeral`&&@#1\xint:
+}%
+% /:
+\def\xintPolDivModR #1%
+{%
+ \romannumeral0\expandafter\xint_stop_atsecondoftwo
+ \expanded\expandafter\POL_divmod_in\romannumeral`&&@#1\xint:
+}%
+% "divmod" will apply coefficient per coefficient when divisor is scalar
+% I have found it convenient to treat constant polynomials
+% as really being scalars. But I need perhaps to think more about it.
+\def\xintPolDivMod #1%
+{%
+ \expanded\expandafter\POL_divmod_in\romannumeral`&&@#1\xint:
+}%
+% the euclidean division
+\def\xintPolQuoRem #1%
+{%
+ \expanded\expandafter\POL_quorem_in\romannumeral`&&@#1\xint:
+}%
+\def\POL_quorem_in #1\xint:#2%
+{%
+ {%
+ \expandafter\POL_quorem_fork
+ \romannumeral`&&@#2\xint_bye#1\xint_bye
+ }%
+}%
+% the overloading of divmod which does euclidean division if divisor is not a scalar
+\def\POL_divmod_in #1\xint:#2%
+{%
+ {%
+ \expandafter\POL_divmod_fork
+ \romannumeral`&&@#2\xint_bye#1\xint_bye
+ }%
+}%
+% "first" and "second" refer to the actual positions, permuted compared
+% to original arguments
+\def\POL_quorem_fork #1#2\xint_bye#3%
+{%
+ \POL_PPfork
+ #1#3{\POL_quorem_a}% both polynomials -> {eucl. quotient}{remainder}
+ #1P{\POL_quorem_second_is_scalar}% -> {zero quotient}{scalar}
+ #3P{\POL_quorem_first_is_scalar}% -> {polynomial/scalar}{zero}
+ PP{\POL_quorem_both_are_scalar}% -> {scalar/scalar}{zero}
+ \krof #1#2\xint_bye#3%
+}%
+\def\POL_quorem_first_is_scalar #1\xint_bye#2\xint_bye
+{%
+ {\expandafter\POL_quorem_first_is_scalar_i\expandafter
+ {\romannumeral0\xintinv{#1}}%
+ #2\xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye}{0/1[0]}%
+}%
+\def\POL_quorem_first_is_scalar_i #1#2.%
+{%
+ #2.\POL_apply:x_loop{\xintMul{#1}}%
+}%
+% #2 was initial first argument and is scalar
+\def\POL_quorem_second_is_scalar #1\xint_bye#2\xint_bye
+{%
+ {0/1[0]}{#2}%
+}%
+\def\POL_quorem_both_are_scalar #1\xint_bye#2\xint_bye
+{%
+ {\xintDiv{#2}{#1}}{0/1[0]}%
+}%
+% attention that "first", "second" refer to the actual arguments positions
+\def\POL_divmod_fork #1#2\xint_bye#3%
+{%
+ \POL_PPfork
+ #1#3{\POL_quorem_a}% both polynomials -> {eucl. quotient}{remainder}
+ #1P{\POL_quorem_second_is_scalar}% -> {zero quotient}{scalar}
+ #3P{\POL_divmod_first_is_scalar}% -> {per coeff//scalar}{per coeff/:scalar}
+ PP{\POL_divmod_both_are_scalar}% -> {s1//s2}{s1/:s2}
+ \krof #1#2\xint_bye#3%
+}%
+\def\POL_divmod_both_are_scalar #1\xint_bye#2\xint_bye
+{%
+ \xintDivMod{#2}{#1}%
+}%
+\def\POL_divmod_first_is_scalar #1\xint_bye #2.#3\xint_bye
+{%
+ \expandafter\POL_divmod_first_is_scalar_a
+ \expanded{\unexpanded{{#1}}\expandafter}%
+ \romannumeral0\XINT_revwbr_loop {}%
+ #3\xint:\xint:\xint:\xint:%
+ \xint:\xint:\xint:\xint:\xint_bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ \iffalse{\fi}%
+ \xint:
+}%
+\long\def\POL_exchange_args#1#2#3{#1{#3}{#2}}%
+\def\POL_divmod_first_is_scalar_a #1%
+{%
+ \expandafter\POL_divmod_first_is_scalar_b
+ \expanded\bgroup
+ \POL_apply:x_loop{\POL_exchange_args\xintDivMod{#1}}%
+}%
+% attention re-use of \POL_add_d
+\def\POL_divmod_first_is_scalar_b #1\xint:
+{%
+ {\expandafter\POL_add_d\expanded{%
+ \POL_apply:x_loop{\expandafter\xint_firstoftwo\xint_firstofone}%
+ #1\xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye}\xint_bye}%
+ {\expandafter\POL_add_d\expanded{%
+ \POL_apply:x_loop{\expandafter\xint_secondoftwo\xint_firstofone}%
+ #1\xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye}\xint_bye}%
+}%
+\def\POL_quorem_a P#1.#2\xint_bye P#3.#4\xint_bye
+{%
+ \ifnum#1>#3 \xint_dothis{\POL_quorem_easy #3.}\fi
+ \xint_orthat
+ {\expandafter\POL_quorem_EQuo
+ \expanded\bgroup
+ \expandafter\POL_quorem_b\the\numexpr#3-#1\expandafter.%
+ \expanded\bgroup
+ \xintRevWithBraces
+ }%
+ {#2}%
+ \noexpand\xint_Bye
+ \xint:
+ \expandafter\POL_placemark_loop
+ \the\numexpr#1-\xint_c_vii\expandafter.%
+ \romannumeral0\xintrevwithbraces{#4}%
+% This added {1} is related to termination clean-up (a bit annoying) process
+ {1}%
+ \the\numexpr#3-#1.%
+ \iffalse{\fi}%
+}%
+\def\POL_quorem_easy #1.#2\xintrevwithbraces#3#4.#5#6%
+{%
+ {0/1[0]}{P#1.#3}%
+}%
+\def\POL_placemark_loop #1#2.%
+{%
+ \xint_gob_til_minus#1\POL_placemark_loop_end-%
+ \expandafter\POL_placemark_step\the\numexpr#1#2-\xint_c_viii.%
+}%
+\def\POL_placemark_step #1.#2#3#4#5#6#7#8#9%
+{%
+ {#2}{#3}{#4}{#5}{#6}{#7}{#8}{#9}\POL_placemark_loop#1.%
+}%
+\def\POL_placemark_loop_end-%
+ \expandafter\POL_placemark_step\the\numexpr-#1-\xint_c_viii.%
+{%
+ \csname POL_placemark_end#1\endcsname
+}%
+\expandafter\def\csname POL_placemark_end1\endcsname
+ #1#2#3#4#5#6#7{{#1}{#2}{#3}{#4}{#5}{#6}{#7}\noexpand\xint_bye\xint:}%
+\expandafter\def\csname POL_placemark_end2\endcsname
+ #1#2#3#4#5#6{{#1}{#2}{#3}{#4}{#5}{#6}\noexpand\xint_bye\xint:}%
+\expandafter\def\csname POL_placemark_end3\endcsname
+ #1#2#3#4#5{{#1}{#2}{#3}{#4}{#5}\noexpand\xint_bye\xint:}%
+\expandafter\def\csname POL_placemark_end4\endcsname
+ #1#2#3#4{{#1}{#2}{#3}{#4}\noexpand\xint_bye\xint:}%
+\expandafter\def\csname POL_placemark_end5\endcsname
+ #1#2#3{{#1}{#2}{#3}\noexpand\xint_bye\xint:}%
+\expandafter\def\csname POL_placemark_end6\endcsname
+ #1#2{{#1}{#2}\noexpand\xint_bye\xint:}%
+\expandafter\def\csname POL_placemark_end7\endcsname
+ #1{{#1}\noexpand\xint_bye\xint:}%
+\expandafter\def\csname POL_placemark_end8\endcsname
+ {\noexpand\xint_bye\xint:}%
+\def\POL_quorem_b #1.#2#3\xint:#4#5\xint:#6%
+{%
+% \xintDiv FG computes F/G
+ \expandafter\POL_quorem_c\romannumeral0\xintdiv{\XINT_Opp#4}{#2}.%
+ #1.{#2}#3\xint:
+% there is already \xint_Bye at ends of #3
+ #3\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+% this terminates the \expanded from \POL_apply:x_loop
+ \iffalse{\fi}%
+ \xint_bye\xint_bye\xint_bye\xint_bye\empty
+ #5\xint_bye\xint_bye\xint_bye\empty
+% a \iffalse{\fi} will get inserted by \POL_add_A here
+ {#6}\xint_bye\xint:
+}%
+\def\POL_quorem_c #1.#2.#3\xint:%
+{%
+ {\XINT_Opp#1}%
+ \expandafter\POL_quorem_d\the\numexpr#2-\xint_c_i\expandafter.%
+ \expanded\bgroup
+ \unexpanded{#3}\xint:
+ \expandafter\POL_add_A
+ \expanded\bgroup
+ \POL_apply:x_loop{\xintMul{#1}}%
+}%
+\def\POL_quorem_d #1#2.%
+{%
+ \xint_gob_til_minus#1\POL_quorem_E-%
+ \POL_quorem_b #1#2.%
+}%
+\def\POL_quorem_E-\POL_quorem_b-1.#1\xint:#2\xint_bye\xint:#3.%
+{%
+% this terminates the \POL_quorem_a \expanded
+ \iffalse{\fi}\xint:#3.%
+% recycling some termination code from addition
+ {\expandafter\POL_quorem_ERem_fix\expanded{\POL_add_d#2\xint_bye}}%
+}%
+\def\POL_quorem_ERem_fix #1%
+{%
+ \if P#1\expandafter\POL_quorem_ERem_fix_a\fi 0/1[0]%
+}%
+\def\POL_quorem_ERem_fix_a 0/1[0]#1.#2%
+{%
+ \ifcase #1
+ \or
+ \expandafter\xint_firstofone
+ \else
+ P\the\numexpr#1-\xint_c_i.%
+ \fi
+}%
+\def\POL_quorem_EQuo#1\xint:#2.%
+{%
+ {\ifnum#2=\xint_c_
+ #1%
+ \else
+ P#2.\romannumeral0\XINT_revwbr_loop {}%
+ #1\xint:\xint:\xint:\xint:%
+ \xint:\xint:\xint:\xint:\xint_bye
+ \fi}%
+}%
+\def\xintPolPRem #1%
+{%
+ \expanded\expandafter\POL_prem_in\romannumeral`&&@#1\xint:
+}%
+\def\POL_prem_in #1\xint:#2%
+{%
+ \bgroup
+ \expandafter\POL_prem_fork
+ \romannumeral`&&@#2\xint:#1\xint:
+ \POL_prem_end
+}%
+\def\POL_prem_fork #1#2\xint:#3%
+{%
+ \POL_PPfork
+ #1#3{\POL_prem_a}% both polynomials
+ #1P{\POL_prem_second_is_scalar}% -> scalar
+ #3P{\POL_prem_first_is_scalar}% -> zero
+ PP{\POL_prem_both_are_scalar}% -> zero
+ \krof #1#2\xint:#3%
+}%
+\def\POL_prem_first_is_scalar #1\xint:#2\xint:\POL_prem_end
+{%
+ \iffalse{\fi}{1/1[0]}{0/1[0]}%
+}%
+\def\POL_prem_second_is_scalar #1\xint:#2\xint:\POL_prem_end
+{%
+ \iffalse{\fi}{1/1[0]}{#2}%
+}%
+\def\POL_prem_both_are_scalar #1\xint:#2\xint:\POL_prem_end
+{%
+ \iffalse{\fi}{1/1[0]}{0/1[0]}%
+}%
+\def\POL_prem_a P#1.#2\xint: P#3.#4\xint:
+{%
+ \ifnum#1>#3 \xint_dothis{\POL_prem_easy #3.}\fi
+ \xint_orthat
+ {\expandafter\POL_prem_b\the\numexpr#3-#1\expandafter.%
+ \expanded\bgroup
+ \xintRevWithBraces
+ }%
+ {#2}%
+ \noexpand\xint_Bye
+ \xint:
+ \expandafter\POL_placeBye_loop
+ \the\numexpr#1-\xint_c_vii\expandafter.%
+ \romannumeral0\xintrevwithbraces{#4}%
+ {1/1[0]}%
+ \iffalse{\fi}%
+}%
+\def\POL_prem_easy #1.#2\xintrevwithbraces#3#4\POL_prem_end
+{%
+ \iffalse{\fi}{1/1[0]}{P#1.#3}%
+}%
+\def\POL_placeBye_loop #1#2.%
+{%
+ \xint_gob_til_minus#1\POL_placeBye_loop_end-%
+ \expandafter\POL_placeBye_step\the\numexpr#1#2-\xint_c_viii.%
+}%
+\def\POL_placeBye_step #1.#2#3#4#5#6#7#8#9%
+{%
+ {#2}{#3}{#4}{#5}{#6}{#7}{#8}{#9}\POL_placeBye_loop#1.%
+}%
+\def\POL_placeBye_loop_end-%
+ \expandafter\POL_placeBye_step\the\numexpr-#1-\xint_c_viii.%
+{%
+ \csname POL_placeBye_end#1\endcsname
+}%
+\expandafter\def\csname POL_placeBye_end1\endcsname
+ #1#2#3#4#5#6#7{{#1}{#2}{#3}{#4}{#5}{#6}{#7}\noexpand\xint_Bye\xint:{1}}%
+\expandafter\def\csname POL_placeBye_end2\endcsname
+ #1#2#3#4#5#6{{#1}{#2}{#3}{#4}{#5}{#6}\noexpand\xint_Bye\xint:{1}}%
+\expandafter\def\csname POL_placeBye_end3\endcsname
+ #1#2#3#4#5{{#1}{#2}{#3}{#4}{#5}\noexpand\xint_Bye\xint:{1}}%
+\expandafter\def\csname POL_placeBye_end4\endcsname
+ #1#2#3#4{{#1}{#2}{#3}{#4}\noexpand\xint_Bye\xint:{1}}%
+\expandafter\def\csname POL_placeBye_end5\endcsname
+ #1#2#3{{#1}{#2}{#3}\noexpand\xint_Bye\xint:{1}}%
+\expandafter\def\csname POL_placeBye_end6\endcsname
+ #1#2{{#1}{#2}\noexpand\xint_Bye\xint:{1}}%
+\expandafter\def\csname POL_placeBye_end7\endcsname
+ #1{{#1}\noexpand\xint_Bye\xint:{1}}%
+\expandafter\def\csname POL_placeBye_end8\endcsname
+ {\noexpand\xint_Bye\xint:{1}}%
+\def\POL_prem_b_skip#1#2\unexpanded#3#4#5\xint_Bye#6\xint:#7#8#9%
+{%
+ \iffalse{\fi\expandafter}\xint_gobble_i#5#1%
+}%
+\def\POL_prem_b #1.#2#3\xint:#4#5\xint:#6#7%
+{%
+ \expandafter\POL_prem_c\the\numexpr#1-\xint_c_i\expandafter.%
+ \expanded\bgroup
+ \unexpanded{{#2}#3}\xint:
+ \if0\XINT_Sgn#4\xint:\xint_afterfi
+ {\expandafter\POL_prem_b_skip\expandafter
+ {\expandafter{\romannumeral0\xintmul{#6}{#7}}\xint_Bye\xint:{#6}}%
+ }%
+ \fi
+ \expandafter\POL_add_A
+ \expanded\bgroup
+ \expanded{\noexpand\POL_apply:x_loop{\noexpand\xintMul
+ {\if1\XINT_Sgn#2\xint:\expandafter\XINT_Opp\fi#4}}}%
+% there is already \xint_Bye at ends of #3
+ #3\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+% separator for \POL_add_A
+ \unexpanded{\xint_bye\xint_bye\xint_bye\xint_bye\empty}%
+% there is already \xint_Bye at ends of #5
+ \expanded{\noexpand\POL_apply:x_loop{\noexpand\xintMul{\XINT_Abs#2}}}%
+ #5\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ \unexpanded{\xint_bye\xint_bye\xint_bye\xint_bye\empty}%
+% a \iffalse{\fi} will get inserted by \POL_add_A exit routine and if will
+% terminate the \expanded triggered here after \POL_prem_c
+% what is next will have already have been expanded
+ {\xintMul{\xintMul{\XINT_Abs#2}{#6}}{#7}}\noexpand\xint_Bye\xint:
+ {\xintMul{\XINT_Abs#2}{#6}}%
+% This terminates the \expanded following \POL_add_A
+ \iffalse{\fi}%
+}%
+\def\POL_prem_c #1%
+{%
+ \xint_gob_til_minus#1\POL_prem_E_-\POL_prem_b#1%
+}%
+% attention that #2 here has a two dummies at end
+% advantage is that \POL_add_a will always think it is non scalar
+\def\POL_prem_E_-\POL_prem_b-1.#1\xint:#2\xint_Bye\xint:#3%
+{%
+ \expandafter\POL_prem_E\expanded{\POL_add_d#2\xint_bye}%
+}%
+\def\POL_prem_E #1%
+{%
+ \if P#1\expandafter\POL_prem_E_i
+ \else\expandafter\POL_prem_E_zero
+ \fi #1%
+}%
+\def\POL_prem_E_zero #1\POL_prem_end{\iffalse{\fi}{#1}{0/1[0]}}%
+\def\POL_prem_E_i P#1.%
+{%
+ \ifnum #1>\xint_c_i\POL_prem_E_ii#1.\fi
+ \POL_prem_E_iii%
+}%
+\def\POL_prem_E_iii#1\POL_prem_end{\iffalse{\fi}#1}%
+\def\POL_prem_E_ii#1.#2\POL_prem_E_iii#3%
+ {#2{#3}{P\the\numexpr#1-\xint_c_i\iffalse}\fi.}%
+\def\POL_prem_end{\iffalse{{\fi}}}%
+%%
+%% SUPPORT FOR FUNCTIONAL INTERFACE
+%%
+% should I do a qpol([]) ?, i.e. without testing for leading zeros, hence
+% would be faster ? but advantage would arise only for very high degree
+% pol([]) this one checks for zeros in the right most coeffs
+\def\xintPolPol#1{\romannumeral`&&@\expandafter\POL_add_d
+ \romannumeral0\expandafter\XINT_revwbr_loop\expandafter
+ {\expandafter}%
+ \romannumeral`&&@#1\xint:\xint:\xint:\xint:
+ \xint:\xint:\xint:\xint:\xint_bye
+ \xint_bye
+}%
+% attention to not overwrite macro names (there is a legacy \PolEvalAt)
+\def\xintPolEvalAt#1#2%
+{%
+% generally, #2 will be scalar, but we allow also a polynomial here
+% should I test for #2 being the monomial, hence handle it very quickly?
+ \romannumeral`&&@\expandafter\POL_evalat_in\romannumeral`&&@#2\xint:
+ #1\xint:\xint:\xint:\xint:
+ \xint:\xint:\xint:\xint:\xint_bye\xint:
+}%
+\def\POL_evalat_in #1\xint:
+{%
+ \expandafter\POL_evalat_fork\expanded{\unexpanded{#1\xint:}\expandafter}%
+ \romannumeral`&&@%
+}%
+\def\POL_evalat_fork #1\xint:#2%
+{%
+ \POL_Pfork
+ #2{\POL_evalat_pol}%
+ P{\POL_evalat_cst}%
+ \krof #1\xint:#2%
+}%
+\def\POL_evalat_cst #1\xint: #2\xint:#3\xint_bye\xint:{#2}%
+\def\POL_evalat_pol #1\xint: P#2.%
+{%
+ \expanded{\unexpanded{\POL_evalat_a#1\xint:}\expandafter}%
+ \romannumeral0\XINT_revwbr_loop{}%
+}%
+\def\POL_evalat_a#1\xint:#2%
+{%
+ \POL_evalat_loop#2\xint:#1\xint:
+}%
+\def\POL_evalat_loop#1\xint:#2\xint:#3%
+{%
+ \xint_gob_til_xint:#3\POL_evalat_E\xint:
+% I have dropped here my old strict \xintFoo = \romannumeral0\xintfoo style
+% ATTENTION! We must allow evaluating at a polynomial expression
+ \expandafter\POL_evalat_loop
+ \romannumeral`&&@\xintPolAdd{#3}{\xintPolMul{#2}{#1}}\xint:#2\xint:
+}%
+\def\POL_evalat_E\xint:\expandafter\POL_evalat_loop
+ \romannumeral`&&@\xintPolAdd #1#2\xint:#3\xint:
+{%
+ \xint_thirdofthree#2%
+}%
+%
+\def\xintPolDeg#1%
+{%
+ \romannumeral`&&@\expandafter\POL_deg_fork\romannumeral`&&@#1\xint:
+}%
+\def\POL_deg_fork #1%
+{%
+ \POL_zeroPfork
+ #1P{\POL_deg_zero}%
+ 0#1{\POL_deg_pol}%
+ 0P{\POL_deg_cst}%
+ \krof #1%
+}%
+% usual hesitations about using or not raw frac format
+\def\POL_deg_zero#1\xint:{-1}%
+\def\POL_deg_cst #1\xint:{0}%
+\def\POL_deg_pol P#1.#2\xint:{#1}%
+%
+\def\xintPolCoeffs#1%
+{%
+ \romannumeral`&&@\expandafter\POL_coeffs_fork\romannumeral`&&@#1\xint:
+}%
+\def\POL_coeffs_fork #1%
+{%
+ \POL_Pfork
+ #1\POL_coeffs_pol
+ P\POL_coeffs_cst
+ \krof #1%
+}%
+% usual hesitations about using or not raw frac format
+\def\POL_coeffs_cst #1\xint:{{#1}}%
+% no brace stripping possible, at least two coefficients
+% annoying that we had to put this delimiter \xint:
+\def\POL_coeffs_pol P#1.#2\xint:{#2}%
+%
+\def\xintPolCoeff#1#2%
+{%
+ \romannumeral`&&@\expandafter\POL_coeff_fork
+ \the\numexpr\xintNum{#2}\expandafter.%
+ \romannumeral`&&@#1\xint:
+}%
+\def\POL_coeff_fork #1.#2%
+{%
+ \POL_Pfork
+ #2\POL_coeff_pol
+ P\POL_coeff_cst
+ \krof #1.#2%
+}%
+\def\POL_coeff_cst#1%
+{%
+ \xint_UDzerofork
+ #1\POL_coeff_itself
+ 0\POL_coeff_zero
+ \krof #1%
+}%
+\def\POL_coeff_itself#1.#2\xint:{#2}%
+\def\POL_coeff_zero#1\xint:{0/1[0]}%
+\def\POL_coeff_pol #1.P#2.%
+{%
+ \ifnum#1<\xint_c_\xint_dothis\POL_coeff_zero\fi
+ \ifnum#1>#2 \xint_dothis\POL_coeff_zero\fi
+ \xint_orthat\POL_coeff_a{#1}%
+}%
+\def\POL_coeff_a#1{\expandafter\POL_coeff_b\romannumeral\xintgobble{#1}}%
+\def\POL_coeff_b#1#2\xint:{#1}%
+%
+\def\xintPolLCoeff#1%
+{%
+ \romannumeral`&&@\expandafter\POL_lcoeff_fork
+ \romannumeral`&&@#1\xint:
+}%
+\def\POL_lcoeff_fork #1%
+{%
+ \POL_Pfork
+ #1\POL_lcoeff_pol
+ P\POL_lcoeff_cst
+ \krof #1%
+}%
+\def\POL_lcoeff_cst#1\xint:{#1}%
+\def\POL_lcoeff_pol P#1.%
+{%
+ \expandafter\POL_lcoeff_a\romannumeral\xintgobble{#1}%
+}%
+\def\POL_lcoeff_a#1\xint:{#1}%
+%
+\def\xintPolMonicPart#1%
+{%
+ \romannumeral`&&@\expandafter\POL_monicpart_fork
+ \romannumeral`&&@#1\xint:
+}%
+\def\POL_monicpart_fork #1%
+{%
+ \POL_Pfork
+ #1\POL_monicpart_pol
+ P\POL_monicpart_cst
+ \krof #1%
+}%
+% monicpart(0) must be 0 to avoid breaking algorithms
+\def\POL_monicpart_cst#1#2\xint:{\if#10\xint_dothis0\fi\xint_orthat1/1[0]}%
+\def\POL_monicpart_pol P#1.#2\xint:%
+{%
+ \expanded{%
+ P#1.%
+ \expandafter\POL_monicpart_a\romannumeral\xintgobble{#1}%
+ #2#2\xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ }%
+}%
+\def\POL@DivByFirstAndIrrAndREZ#1#2{\xintREZ{\xintIrr{\xintDiv{#2}{#1}}}}%
+\def\POL_monicpart_a#1%
+{%
+ \POL_apply:x_loop{\POL@DivByFirstAndIrrAndREZ{#1}}%
+}%
+%
+\def\xintPolIContent#1%
+{%
+ \romannumeral`&&@\expandafter\POL_icontent_fork
+ \romannumeral`&&@#1^%
+}%
+\def\POL_icontent_fork #1%
+{%
+ \POL_Pfork
+ #1\POL_icontent_pol
+ P\POL_icontent_cst
+ \krof #1%
+}%
+\def\POL_icontent_cst #1^{\xintIrr{\xintAbs{#1}}[0]}%
+\def\POL_icontent_pol P#1.%
+{%
+% 1.4d xintfrac \XINT_fgcdof much saner than 1.4 version !
+% \XINT_fgcd_out does \xintIrr
+ \expandafter\XINT_fgcd_out\romannumeral0\XINT_fgcdof
+}%
+%
+\def\xintPolPrimPart#1%
+{%
+ \romannumeral`&&@\expandafter\POL_primpart_fork
+ \romannumeral`&&@#1\xint:
+}%
+\def\POL_primpart_fork #1%
+{%
+ \POL_Pfork
+ #1\POL_primpart_pol
+ P\POL_primpart_cst
+ \krof #1%
+}%
+\def\POL_primpart_cst#1#2\xint:{\if#10\xint_dothis0\fi\xint_orthat1/1[0]}%
+\def\POL_primpart_pol P#1.#2\xint:%
+{%
+ \expanded{%
+ P#1.\expandafter\POL_primpart_a
+ \romannumeral0\expandafter\XINT_fgcd_out
+ \romannumeral0\XINT_fgcdof#2^\xint:
+ #2\xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ }%
+}%
+% cf legacy \POL@makeprim@macro
+\def\POL@DivByFirstAndNumAndREZ#1#2{\xintREZ{\xintNum{\xintDiv{#2}{#1}}}}%
+\def\POL_primpart_a#1\xint:{\POL_apply:x_loop{\POL@DivByFirstAndNumAndREZ{#1}}}%
+%
+\def\xintPolRedCoeffs#1%
+{%
+ \romannumeral`&&@\expandafter\POL_redcoeffs_fork
+ \romannumeral`&&@#1\xint:
+}%
+\def\POL_redcoeffs_fork #1%
+{%
+ \POL_Pfork
+ #1\POL_redcoeffs_pol
+ P\POL_redcoeffs_cst
+ \krof #1%
+}%
+\def\POL_redcoeffs_cst#1\xint:{\xintIrr{#1}[0]}%
+\def\POL_redcoeffs_pol P#1.#2\xint:%
+{%
+ \expanded{%
+ P#1.\POL_apply:x_loop\POL@xintIrr
+ #2\xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ }%
+}%
+%
+\def\xintPolSRedCoeffs#1%
+{%
+ \romannumeral`&&@\expandafter\POL_sredcoeffs_fork
+ \romannumeral`&&@#1\xint:
+}%
+\def\POL_sredcoeffs_fork #1%
+{%
+ \POL_Pfork
+ #1\POL_sredcoeffs_pol
+ P\POL_sredcoeffs_cst
+ \krof #1%
+}%
+\def\POL_sredcoeffs_cst#1\xint:{\xintREZ{\xintIrr{#1}[0]}}%
+\def\POL_sredcoeffs_pol P#1.#2\xint:%
+{%
+ \expanded{%
+ P#1.\POL_apply:x_loop\POL@xintIrrAndREZ
+ #2\xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ }%
+}%
+\def\POL@xintIrrAndREZ#1{\xintREZ{\xintIrr{#1}[0]}}%
+%
+\def\xintPolDiffOne#1%
+{%
+ \romannumeral`&&@\expandafter\POL_diffone_fork
+ \romannumeral`&&@#1\xint:
+}%
+\def\POL_diffone_fork #1%
+{%
+ \POL_Pfork
+ #1\POL_diffone_pol
+ P\POL_diffone_cst
+ \krof #1%
+}%
+\def\POL_diffone_cst#1\xint:{0/1[0]}%
+\def\POL_diffone_pol P#1.#2#3\xint:%
+{%
+ \expanded{%
+ \ifnum#1=\xint_c_i #3%
+ \else
+ P\the\numexpr#1-\xint_c_i.%
+ \POL_apply:x_iloop{\POL_diffone_diff1.}%
+ #3\xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ \fi
+ }%
+}%
+\def\POL_diffone_diff#1.#2#3{\xintMul{#1+#2}{#3}}%
+%
+\def\xintPolAntiOne#1%
+{%
+ \romannumeral`&&@\expandafter\POL_antione_fork
+ \romannumeral`&&@#1\xint:
+}%
+\def\POL_antione_fork #1%
+{%
+ \POL_Pfork
+ #1\POL_antione_pol
+ P\POL_antione_cst
+ \krof #1%
+}%
+\def\POL_antione_cst#1%
+{%
+ \xint_gob_til_zero#1\POL_antione_zero0\POL_antione_cst_i#1%
+}%
+\def\POL_antione_cst_i#1\xint:{P1.{0/1[O]}{#1}}%
+\def\POL_antione_zero#1\xint:{0/1[0]}%
+\def\POL_antione_pol P#1.#2\xint:%
+{%
+ \expanded{%
+ P\the\numexpr#1+\xint_c_i.{0/1[0]}%
+ \POL_apply:x_iloop{\POL_antione_anti1.}%
+ #2\xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ }%
+}%
+\def\POL_antione_anti#1.#2#3{\xintDiv{#3}{#1+#2}}%
+%
+% #2 can be a polynomial
+\def\xintPolIntFrom#1%#2%
+{%
+ \romannumeral`&&@\expandafter\POL_intfrom_a\expandafter
+ {\romannumeral`&&@\xintPolAntiOne{#1}}%
+}%
+\def\POL_intfrom_a #1#2%
+{%
+ \xintPolSub{#1}{\xintPolEvalAt{#1}{#2}}%
+}%
+%
+\def\xintPolIntegral#1#2%
+{%
+ \romannumeral`&&@\expandafter\POL_integral_a\expanded
+ {\xintPolAntiOne{#1}\xint:#2\xint:}%
+}%
+\def\POL_integral_a #1\xint:#2#3\xint:
+{%
+ \xintPolSub{\xintPolEvalAt{#1}{#3}}{\xintPolEvalAt{#1}{#2}}%
+}%
+%
+\def\xintPolDiffTwo#1%
+{%
+ \romannumeral`&&@\expandafter\POL_difftwo_fork
+ \romannumeral`&&@#1\xint:
+}%
+\def\POL_difftwo_fork #1%
+{%
+ \POL_Pfork
+ #1\POL_difftwo_pol
+ P\POL_difftwo_cst
+ \krof #1%
+}%
+\def\POL_difftwo_cst#1\xint:{0/1[0]}%
+\def\POL_difftwo_pol P#1.%
+{%
+ \ifcase #1
+ \or \expandafter\POL_difftwo_zeroout
+ \or \expandafter\POL_difftwo_cstout
+ \else\expandafter\POL_difftwo_polout
+ \fi #1.%
+}%
+\def\POL_difftwo_zeroout#1\xint:{0/1[0]}%
+\def\POL_difftwo_cstout 2.#1#2#3\xint:{\xintMul{2}{#3}}%
+\def\POL_difftwo_polout #1.#2#3#4\xint:%
+{%
+ \expanded{%
+ P\the\numexpr#1-\xint_c_ii.%
+ \POL_apply:x_iloop{\POL_difftwo_diff2.}%
+ #4\xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ }%
+}%
+\def\POL_difftwo_diff#1.#2#3{\xintMul{\the\numexpr(#1+#2)*(#1+#2-\xint_c_i)\relax}{#3}}%
+%
+\def\POL_diffone_iter_fork #1%
+{%
+ \POL_Pfork
+ #1\POL_diffone_iter_pol
+ P\POL_diffone_iter_cst
+ \krof #1%
+}%
+\def\POL_diffone_iter_cst#1\xint:{0/1[0]\xint:}%
+\def\POL_diffone_iter_pol P#1.#2#3\xint:%
+{%
+ \expanded{%
+ \ifnum#1=\xint_c_i #3%
+ \else
+ P\the\numexpr#1-\xint_c_i.%
+ \POL_apply:x_iloop{\POL_diffone_diff1.}%
+ #3\xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ \fi
+ }\xint:
+}%
+%
+\def\POL_antione_iter_fork #1%
+{%
+ \POL_Pfork
+ #1\POL_antione_iter_pol
+ P\POL_antione_iter_cst
+ \krof #1%
+}%
+\def\POL_antione_iter_cst#1%
+{%
+ \xint_gob_til_zero#1\POL_antione_iter_zero0\POL_antione_iter_cst_i#1%
+}%
+\def\POL_antione_iter_cst_i#1\xint:{P1.{0/1[O]}{#1}\xint:}%
+\def\POL_antione_iter_zero#1\xint:{0/1[0]\xint:}%
+\def\POL_antione_iter_pol P#1.#2\xint:%
+{%
+ \expanded{%
+ P\the\numexpr#1+\xint_c_i.{0/1[0]}%
+ \POL_apply:x_iloop{\POL_antione_anti1.}%
+ #2\xint_Bye\xint_Bye\xint_Bye\xint_Bye
+ \xint_Bye\xint_Bye\xint_Bye\xint_Bye\xint_bye
+ }\xint:
+}%
+%
+\def\xintPolDiffN#1#2%
+{%
+ \romannumeral`&&@\expandafter\POL_diffn_fork
+ \the\numexpr\xintNum{#2}\expandafter.%
+ \romannumeral`&&@#1\xint:
+}%
+\def\POL_diffn_fork #1%
+{%
+ \xint_UDzerominusfork
+ #1-\POL_diffn_none
+ 0#1\POL_diffn_anti
+ 0-\POL_diffn_diff
+ \krof #1%
+}%
+\def\POL_diffn_none0.#1\xint:{#1}%
+\def\POL_diffn_diff#1.%#2\xint:%
+{%
+ \ifnum#1>\xint_c_i
+ \expandafter\POL_diffn_diff\the\numexpr#1-\xint_c_i\expandafter.%
+ \romannumeral`&&@\expandafter\POL_diffone_iter_fork
+ \else
+ \expandafter\POL_diffone_fork
+ \fi
+}%
+\def\POL_diffn_anti#1.%#2\xint:%
+{%
+ \ifnum#1<-\xint_c_i
+ \expandafter\POL_diffn_anti\the\numexpr#1+\xint_c_i\expandafter.%
+ \romannumeral`&&@\expandafter\POL_antione_iter_fork
+ \else
+ \expandafter\POL_antione_fork
+ \fi
+}%
+%
+% Support for (multi-variable) polgcd
+%
+\def\xintPolGCDof #1%
+{%
+ \romannumeral`&&@\expandafter\POL_polgcdof\romannumeral`&&@#1^%
+}%
+\def\XINT_PolGCDof{\romannumeral`&&@\POL_polgcdof}%
+\def\POL_polgcdof #1%
+{%
+ \romannumeral`&&@\expandafter
+ \POL_polgcdof_chkempty\romannumeral`&&@#1\xint:
+}%
+\def\POL_polgcdof_chkempty #1%
+{%
+ \xint_gob_til_^#1\POL_polgcdof_empty ^\POL_polgcdof_in #1%
+}%
+\def\POL_polgcdof_empty #1\xint:{1/1[0]}% hesitation
+\def\POL_polgcdof_in #1\xint:
+{%
+ \expandafter\POL_polgcdof_loop
+ \romannumeral`&&@\xintPolPrimPart{#1}\xint:
+}%
+\def\POL_polgcdof_loop #1\xint:#2%
+{%
+ \expandafter\POL_polgcdof_chkend\romannumeral`&&@#2\xint:#1\xint:\xint:
+}%
+\def\POL_polgcdof_chkend #1%
+{%
+ \xint_gob_til_^#1\POL_polgcdof_end ^\POL_polgcdof_loop_pair #1%
+}%
+% hesitation with returning a monic polynomial
+%\def\POL_polgcdof_end #1\xint:#2\xint:\xint:{\xintPolMonicPart{#2}}%
+\def\POL_polgcdof_end #1\xint:#2\xint:\xint:{#2}%
+\def\POL_polgcdof_loop_pair #1\xint:
+{%
+ \expandafter\POL_polgcdof_loop
+ \romannumeral`&&@\expandafter\POL_polgcd_pair
+ \romannumeral`&&@\xintPolPrimPart{#1}\xint:
+}%
+% MEMO comme le #2 sera au début le pgcd accumulé il sera souvent de plus
+% petit degré donc il y aura souvent un premier mod "easy" un peu inutile
+% J'hésite à faire une permutation avant de lancer le polgcd_pair
+\def\POL_polgcd_pair#1\xint:#2\xint:
+{%
+ \xintiiifSgn {\xintPolDeg {#1}}%
+ {#2}%
+ {1}%
+ {\expandafter\POL_polgcd_pair
+ \romannumeral`&&@\xintPolPrimPart
+ {\expandafter\xint_secondoftwo
+ \romannumeral`&&@\xintPolPRem {#2}{#1}}\xint:
+ #1\xint:
+ }%
+}%
+%
+\endinput
diff --git a/macros/generic/polexpr/polexprexpr.tex b/macros/generic/polexpr/polexprexpr.tex
new file mode 100644
index 0000000000..9b60e7bab0
--- /dev/null
+++ b/macros/generic/polexpr/polexprexpr.tex
@@ -0,0 +1,179 @@
+%% This file polexprexpr.tex is part of the polexpr package (0.8, 2021/03/29)
+%% Extending \xintexpr syntax:
+%%
+%% 1. Authorize ' in variable and function names
+%% This currently breaks infix operators 'and', 'or', 'xor', 'mod'
+%% hence forces usage everywhere of &&, ||, /: and xor() syntax
+%% (if : is active then use /\string : input syntax!)
+%%
+%% 2. Map infix operators to the polexprcore macros
+%%
+%% Overloading of infix operators must be done even outside of \poldef's
+%% scope else functions declared via \xintdeffunc would not be usable in
+%% \poldef as they would be using the xintfrac macros unaware of polynomials
+%%
+%% The overloading of // and /: is experimental.
+%%
+%% 3. Support for the polynomial functions to work in \xintdeffunc
+%%
+%% 4. Support macros for the new functions acting on polynomial variables
+%
+% 1.
+\def\XINT_expr_scanfunc_b #1%
+{%
+ \ifcat \relax#1\xint_dothis{\iffalse{\fi}(_#1}\fi
+ \if (#1\xint_dothis{\iffalse{\fi}(`}\fi
+ \if 1\ifcat a#10\fi
+ \ifnum\xint_c_ix<1\string#1 0\fi
+ \if @#10\fi
+ \if _#10\fi
+ \if '#10\fi
+ 1%
+ \xint_dothis{\iffalse{\fi}(_#1}\fi
+ \xint_orthat {#1\XINT_expr_scanfunc_a}%
+}%
+% 2.
+% the minus sign as prefix
+\def\POL_tmp #1#2%
+{%
+ \expandafter\def\csname XINT_expr_exec_#1\endcsname##1##2##3% \XINT_expr_exec_<op><level>
+ {%
+ \expandafter ##1\expandafter ##2\expandafter
+ {\romannumeral`&&@\XINT:NEhook:f:one:from:one{\romannumeral`&&@#2##3}}%
+ }%
+}%
+\POL_tmp{-xii} \xintPolOpp
+\POL_tmp{-xiv} \xintPolOpp
+\POL_tmp{-xvi} \xintPolOpp
+\POL_tmp{-xviii}\xintPolOpp
+% infix operators
+\def\POL_tmp #1#2%
+{%
+ \expandafter\def\csname XINT_expr_exec_#1\endcsname##1##2##3##4% \XINT_expr_exec_<op>
+ {%
+ \expandafter##2\expandafter##3\expandafter
+ {\romannumeral`&&@\XINT:NEhook:f:one:from:two{\romannumeral`&&@#2##1##4}}%
+ }%
+}%
+\POL_tmp + \xintPolAdd
+\POL_tmp - \xintPolSub
+\POL_tmp * \xintPolMul
+\POL_tmp / \xintPolQuo
+% there is no infix operator mapped to \xintPolRem
+% for lack of notation: perhaps /; ? advices welcome
+\POL_tmp{//}\xintPolDivModQ
+\POL_tmp{/:}\xintPolDivModR
+\POL_tmp ^ \xintPolPow
+\expandafter\let\csname XINT_expr_op_**\expandafter\endcsname
+ \csname XINT_expr_op_^\endcsname
+% 3.
+% Matches with "mysterious stuff" section of xintexpr source code
+\let\POL:NEhook:polfunc\expandafter
+\toks0\expandafter{\XINT_expr_redefinemacros}%
+\toks2 {\let\POL:NEhook:polfunc\POL:NE:polfunc}%
+\edef\XINT_expr_redefinemacros{\the\toks0 \the\toks2}%
+\catcode`~ 12
+\def\POL@defpolfunc #1#2%
+{%
+ \expandafter\POL@defpolfunc_a
+ \csname XINT_#2_func_#1\expandafter\endcsname
+ \csname XINT_#2_polfunc_#1\endcsname
+}%
+\def\POL@defpolfunc_a #1#2%
+{%
+ \XINT_global
+ \def#1##1##2##3%
+ {%
+ \expandafter##1\expandafter##2\expandafter{%
+ \romannumeral`&&@\POL:NEhook:polfunc{\romannumeral`&&@#2##3}}%
+ }%
+}%
+\def\POL:NE:polfunc #1{%
+\def\POL:NE:polfunc ##1%
+{%
+ \if0\XINT:NE:hastilde ##1~!\relax % this ! of catcode 11
+ \XINT:NE:hashash ##1#1!\relax 0\else
+ \xint_dothis\POL:NE:polfunc_a\fi
+ \xint_orthat\POL:NE:polfunc_b
+ ##1&&A%
+}}\expandafter\POL:NE:polfunc\string#%
+\def\POL:NE:polfunc_a\romannumeral`&&@#1#2&&A%
+{%
+% If we are here #2 was not braced; \string is done with \escapechar126
+ \expandafter{\expanded{~romannumeral~POL:NE:usepolfunc%
+ {\expandafter\xint_gobble_i\string#1}}#2}%
+}%
+\def\POL:NE:polfunc_b#1{%
+\def\POL:NE:polfunc_b\romannumeral`&&@##1##2&&A%
+{%
+ \expandafter{%
+ \romannumeral`&&@%
+ \if0\XINT:NE:hastilde ##2~!\relax
+ \XINT:NE:hashash ##2#1!\relax 0\else
+ \POL:NE:polfunc_c\fi
+ ##1{##2}}%
+}}\expandafter\POL:NE:polfunc_b\string#%
+% In this case the \expandafter inserted by \POL:NE:usepolfunc
+% expansion will be superfluous
+\def\POL:NE:polfunc_c#1#2% #1=\fi
+{%
+ \expanded{#1~romannumeral~POL:NE:usepolfunc%
+ {\expandafter\xint_gobble_i\string#2}}%
+}%
+% This \expandafter is in case there is an \expanded after that due
+% to some slicing constructs
+% Call: \romannumeral\POL:NE:usepolfunc
+\def\POL:NE:usepolfunc#1{`&&@\csname#1\expandafter\endcsname}%
+\catcode`~ 3 % its normal catcode in xint bundle
+% 4.
+\def\POL_tmp #1#2#3%
+{%
+ \expandafter\def\csname XINT_expr_func_#1\endcsname##1##2##3%
+ {%
+ \expandafter ##1\expandafter ##2\expandafter
+ {%
+ \romannumeral`&&@#2{\romannumeral`&&@#3##3}%
+ }%
+ }%
+}%
+\POL_tmp {sqr} \XINT:NEhook:f:one:from:one \xintPolSqr
+\POL_tmp {pol} \XINT:NEhook:f:one:from:one \xintPolPol
+\POL_tmp {deg} \XINT:NEhook:f:one:from:one \xintPolDeg
+\POL_tmp {coeffs} \XINT:NEhook:f:one:from:one \xintPolCoeffs
+\POL_tmp {coeff} \XINT:NEhook:f:one:from:two \xintPolCoeff
+\POL_tmp {lcoeff} \XINT:NEhook:f:one:from:one \xintPolLCoeff
+\POL_tmp {monicpart} \XINT:NEhook:f:one:from:one \xintPolMonicPart
+\POL_tmp {icontent} \XINT:NEhook:f:one:from:one \xintPolIContent
+\POL_tmp {primpart} \XINT:NEhook:f:one:from:one \xintPolPrimPart
+\POL_tmp {rdcoeffs} \XINT:NEhook:f:one:from:one \xintPolRedCoeffs
+\POL_tmp {rdzcoeffs} \XINT:NEhook:f:one:from:one \xintPolSRedCoeffs
+\POL_tmp {diff1} \XINT:NEhook:f:one:from:one \xintPolDiffOne
+\POL_tmp {diff2} \XINT:NEhook:f:one:from:one \xintPolDiffTwo
+\POL_tmp {diffn} \XINT:NEhook:f:one:from:two \xintPolDiffN
+\POL_tmp {antider} \XINT:NEhook:f:one:from:one \xintPolAntiOne
+\POL_tmp {integral} \XINT:NEhook:f:one:from:two \xintPolIntegral
+\POL_tmp {quorem} \XINT:NEhook:f:one:from:two \xintPolQuoRem
+\POL_tmp {quo} \XINT:NEhook:f:one:from:two \xintPolQuo
+\POL_tmp {rem} \XINT:NEhook:f:one:from:two \xintPolRem
+\POL_tmp {prem} \XINT:NEhook:f:one:from:two \xintPolPRem
+\POL_tmp {divmod} \XINT:NEhook:f:one:from:two \xintPolDivMod
+\POL_tmp {mod} \XINT:NEhook:f:one:from:two \xintPolDivModR
+\POL_tmp {evalp} \XINT:NEhook:f:one:from:two \xintPolEvalAt
+\def\XINT_expr_func_polgcd #1#2#3%
+{%
+ \expandafter #1\expandafter #2\expandafter{\expandafter
+ {\romannumeral`&&@\XINT:NEhook:f:from:delim:u\XINT_PolGCDof#3^}}%
+}%
+% this is provisory
+\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};%
+%
+\endinput
diff --git a/macros/generic/polexpr/polexprsturm.tex b/macros/generic/polexpr/polexprsturm.tex
new file mode 100644
index 0000000000..3fa1861558
--- /dev/null
+++ b/macros/generic/polexpr/polexprsturm.tex
@@ -0,0 +1,1775 @@
+%% This file polexprsturm.tex is part of the polexpr package (0.8, 2021/03/29)
+%% Sturm Algorithm (polexpr 0.4)
+%% 0.5 uses primitive polynomials for faster evaluations afterwards
+%% 0.6 corrects misuse of \@ifstar! (mumble). \PolToSturm* was broken.
+%% 0.6's \PolToSturm* defines both normalized and unnormalized, the
+%% unnormalized using two underscores, so both are available
+%% Sole difference is that \PolToSturm* also declares them as
+%% user polynomials, whereas the non-starred only keeps the macros
+%% holding the coefficients in memory
+%% 0.6 fixes the case of a constant polynomial P which caused division
+%% by zero error from P'.
+%% 0.8 - fixes 0.7.5 failure to have updated to xint 1.4 format the defined
+%% \xintexpr variables holding the localization intervals extremities
+%% - also, it uses the prem() in computing the Sturm chain, for a 3X
+%% speed gain in the case of the "perturbed" first Wilkinson example
+%%
+\newcount\POL@count
+\newif\ifPOL@tosturm@makefirstprimitive\POL@tosturm@makefirstprimitivetrue
+\newif\ifPOL@isolz@nextwillneedrefine
+%%
+\def\PolToSturm{\POL@ifstar{\PolToSturm@@}{\PolToSturm@}}%
+\def\POL@aux@toint#1{\xintREZ{\xintNum{#1}}}% for polynomials with int. coeffs!
+%% Attention that some macros rely upon this one setting \POL@sturmname
+%% and \POL@sturm@N as it does
+\def\PolToSturm@#1#2{%
+ \edef\POL@sturmname{#2}%
+ % 0.6 uses 2 underscores (one before index, one after) to keep in memory
+ % the unnormalized chain
+ % This supposes #1 to be a genuine polynomial, not only a name with
+ % a \POLuserpol@#1 macro
+ \POL@let{\POL@sturmname _0_}{#1}%
+ \ifnum\PolDegree{#1}=\z@
+ \def\POL@sturm@N{0}%
+ \POL@count\z@
+ % if I applied the same as for positive degree, I should make it -1
+ % if constant is negative. I also don't worry if polynomial is zero.
+ \XINT_global\@namedef{POLuserpol@\POL@sturmname _0}{0.\empty{1/1[0]}}%
+ \else
+ \ifPOL@tosturm@makefirstprimitive\POL@makeprimitive{\POL@sturmname _0_}\fi
+ \POL@tosturm@dosturm
+ \fi
+ \expandafter
+ \let\csname PolSturmChainLength_\POL@sturmname\endcsname\POL@sturm@N
+ % declare the normalized ones as full-fledged polynomials
+ % \POL@count\z@
+ \xintloop
+ \POL@newpol{\POL@sturmname _\the\POL@count}%
+ \unless\ifnum\POL@sturm@N=\POL@count
+ \advance\POL@count\@ne
+ \repeat
+}%
+\def\PolToSturm@@#1#2{\PolToSturm@{#1}{#2}\POL@tosturm@declareunnormalized}%
+\def\POL@tosturm@declareunnormalized{%
+ % optionally declare also the unnormalized ones
+ \POL@count\z@
+ \xintloop
+ \POL@newpol{\POL@sturmname _\the\POL@count _}%
+ \unless\ifnum\POL@sturm@N=\POL@count
+ \advance\POL@count\@ne
+ \repeat
+}%
+\def\POL@tosturm@dosturm{%
+ \POL@Diff@@one{\POL@sturmname _0_}{\POL@sturmname _1_}%
+ % re-utiliser \POL@varcoeffs directement?
+ \POL@makeprimitive{\POL@sturmname _1_}% does not do \POL@newpol
+ \POL@count\@ne
+ \xintloop
+ % prior to 0.8, code was using here \POL@divide
+ \POL@getprem{\POL@sturmname _\the\numexpr\POL@count-\@ne\relax _}%
+ {\POL@sturmname _\the\POL@count _}%
+ \expandafter\POL@split\POL@R;\POL@degR\POL@polR
+ \unless\ifnum\POL@degR=\m@ne
+ \advance\POL@count\@ne
+ \XINT_global\expandafter\let
+ \csname POLuserpol@\POL@sturmname _\the\POL@count _\endcsname\POL@R
+ \edef\POL@makeprim@icontent{-\POL@icontent\POL@polR}%
+ % this avoids the \POL@newpol from \PolMapCoeffs
+ \POL@mapcoeffs\POL@makeprim@macro{\POL@sturmname _\the\POL@count _}%
+ \repeat
+ \edef\POL@sturm@N{\the\POL@count}%
+ % normalize (now always done even by starred variant)
+ \ifnum\PolDegree{\POL@sturmname _\POL@sturm@N _}>\z@
+ % \POL@count\POL@sturm@N\relax
+ \xintloop
+ \advance\POL@count\m@ne
+ \POL@divide{\POL@sturmname _\the\POL@count _}%
+ {\POL@sturmname _\POL@sturm@N _}%
+ \XINT_global\expandafter
+ \let\csname POLuserpol@\POL@sturmname _\the\POL@count\endcsname\POL@Q
+ % quotient actually belongs to Z[X] and is primitive
+ \POL@mapcoeffs\POL@aux@toint{\POL@sturmname _\the\POL@count}%
+ \ifnum\POL@count>\z@
+ \repeat
+ \XINT_global\@namedef{POLuserpol@\POL@sturmname _\POL@sturm@N}{0.\empty{1/1[0]}}%
+ \else % they are already normalized
+ \advance\POL@count\@ne % attention to include last one also
+ \xintloop
+ \advance\POL@count\m@ne
+ \XINT_global\expandafter\let
+ \csname POLuserpol@\POL@sturmname _\the\POL@count\expandafter\endcsname
+ \csname POLuserpol@\POL@sturmname _\the\POL@count _\endcsname
+ \ifnum\POL@count>\z@
+ \repeat
+ \fi
+ % Back to \PolToSturm@, \POL@count holds 0
+}%
+\def\PolSturmChainLength#1{%
+ \romannumeral`&&@\csname PolSturmChainLength_#1\endcsname
+}%
+\def\PolSetToSturmChainSignChangesAt{%
+ \POL@chkopt\POL@oPolSetToSturmChainSignChangesAt[\global]%
+}%
+\def\POL@oPolSetToSturmChainSignChangesAt[#1]#2#3#4{%
+ \edef\POL@sturmchain@X{\xintREZ{#4}}%
+ \edef\POL@sturmname{#3}%
+ \edef\POL@sturmlength{\PolSturmChainLength{\POL@sturmname}}%
+ \POL@sturmchain@getSV@at\POL@sturmchain@X
+ #1\let#2\POL@sturmchain@SV
+}%
+\def\POL@sturmchain@getSV@at#1{% ATTENTION USES \POL@count
+ \def\POL@sturmchain@SV{0}%
+ \edef\POL@sturmchain@sign{\xintiiSgn{\POL@eval{\POL@sturmname _0}{#1}}}%
+ \let\POL@isolz@lastsign\POL@sturmchain@sign
+ \POL@count \z@
+ \ifnum\POL@isolz@lastsign=\z@
+ \edef\POL@isolz@lastsign
+ {\xintiiSgn{\POL@eval{\POL@sturmname _1}{#1}}}%
+ \POL@count \@ne
+ \fi
+ \xintloop
+ \unless\ifnum\POL@sturmlength=\POL@count
+ \advance\POL@count \@ne
+ \edef\POL@isolz@newsign
+ {\xintiiSgn{\POL@eval{\POL@sturmname _\the\POL@count}{#1}}}%
+ \ifnum\POL@isolz@newsign=\numexpr-\POL@isolz@lastsign\relax
+ \edef\POL@sturmchain@SV{\the\numexpr\POL@sturmchain@SV+\@ne}%
+ \let\POL@isolz@lastsign=\POL@isolz@newsign
+ \fi
+ \repeat
+}%
+\def\PolSetToNbOfZerosWithin{%
+ \POL@chkopt\POL@oPolSetToNbOfZerosWithin[\global]%
+}%
+\def\POL@oPolSetToNbOfZerosWithin[#1]#2#3#4#5{%
+ \edef\POL@tmpA{\xintREZ{#4}}%
+ \edef\POL@tmpB{\xintREZ{#5}}%
+ \edef\POL@sturmname{#3}%
+ \edef\POL@sturmlength{\PolSturmChainLength{\POL@sturmname}}%
+ \POL@sturmchain@getSV@at\POL@tmpA
+ \let\POL@SVA\POL@sturmchain@SV
+ \POL@sturmchain@getSV@at\POL@tmpB
+ \let\POL@SVB\POL@sturmchain@SV
+ \ifnum\POL@SVA<\POL@SVB\space
+ #1\edef#2{\the\numexpr\POL@SVB-\POL@SVA}%
+ \else
+ #1\edef#2{\the\numexpr\POL@SVA-\POL@SVB}%
+ \fi
+}%
+% 0.6 added starred variant to count multiplicities
+% 0.7 added double starred variant to locate all rational roots
+\def\PolSturmIsolateZeros{\POL@ifstar
+ {\PolSturmIsolateZerosAndGetMultiplicities}%
+ {\PolSturmIsolateZeros@}%
+}%
+\def\PolSturmIsolateZerosAndGetMultiplicities{\POL@ifstar
+ {\PolSturmIsolateZerosGetMultiplicitiesAndRationalRoots}%
+ {\PolSturmIsolateZerosAndGetMultiplicities@}%
+}%
+% on aurait besoin de ça dans xint, mais il aurait un \xintRaw{#1} alors
+\def\POL@xintfrac@getNDE #1%
+ {\expandafter\POL@xintfrac@getNDE@i\romannumeral`&&@#1}%
+\def\POL@xintfrac@getNDE@i #1/#2[#3]#4#5#6{\def#4{#1}\def#5{#2}\def#6{#3}}%
+%
+\def\PolSturmIsolateZerosGetMultiplicitiesAndRationalRoots{%
+ \POL@chkopt\POL@oPolSturmIsolateZerosGetMultiplicitiesAndRationalRoots[\empty]%
+}%
+\def\POL@oPolSturmIsolateZerosGetMultiplicitiesAndRationalRoots[#1]#2{%
+ \PolSturmIsolateZerosAndFindRationalRoots[#1]{#2}%
+ \ifnum\POL@isolz@NbOfRoots>\z@
+ % get multiplicities of irrational (real) roots, if any
+ \ifnum\POL@findrat@nbofirrroots>\z@
+ \POL@findrat@getirrmult
+ \fi
+ \POL@isolzmult@defvar@M
+ \fi
+}%
+% added at 0.7
+\def\PolSturmIsolateZerosAndFindRationalRoots{%
+ \POL@chkopt\POL@oPolSturmIsolateZerosAndFindRationalRoots[\empty]%
+}%
+\def\POL@oPolSturmIsolateZerosAndFindRationalRoots[#1]#2{%
+ % #1 optional E such that roots are searched in -10^E < x < 10^E
+ % both -10^E and +10^E must not be roots!
+ % #2 name of Sturm chain (already pre-computed)
+ \edef\POL@sturmname{#2}%
+ \edef\POL@sturm@N{\@nameuse{PolSturmChainLength_\POL@sturmname}}%
+ % isolate the roots (detects case of constant polynomial)
+ \PolSturmIsolateZeros@{\POL@sturmname}%
+ \ifnum\POL@isolz@NbOfRoots=\z@
+ % no real roots, define empty arrays nevertheless
+ \begingroup\globaldefs\@ne
+ \expandafter\xintAssignArray\expandafter\to\csname POL_ZM\POL@sturmname*\endcsname
+ \expandafter\xintAssignArray\expandafter\to\csname POL_RI\POL@sturmname*\endcsname
+ \endgroup
+ \else
+ % all we currently know is that multiplicities are at least one
+ \begingroup\globaldefs\@ne
+ \expandafter\POL@initarray\csname POL_ZM\POL@sturmname*\endcsname{1}%
+ \endgroup
+ % on ne va pas utiliser de Horner, mais des divisions par X - x, et ces
+ % choses vont évoluer, ainsi que le coefficient dominant entier
+ % (pour \POL@divide entre autres if faut des noms de user pol)
+ \XINT_global
+ \expandafter\let
+ \csname POLuserpol@\POL@sturmname\POL@sqfnorr\expandafter\endcsname
+ \csname POLuserpol@\POL@sturmname _0\endcsname
+ \XINT_global
+ \expandafter\let
+ \csname POLuserpol@\POL@sturmname\POL@norr\expandafter\endcsname
+ \csname POLuserpol@\POL@sturmname _0_\endcsname
+ % attention formé avec\xintREZ d'où le \xintAbs pas \xintiiAbs
+ % D and its exponent E will get updated along the way
+ \edef\POL@findrat@D{\xintAbs{\PolLeadingCoeff{\POL@sturmname _0}}}%
+ \POL@xintfrac@getNDE\POL@findrat@D\POL@findrat@Dint\POL@_\POL@findrat@Dexp
+ \xintiiifOne{\POL@findrat@Dint}
+ {\let\POL@findrat@E\POL@findrat@Dexp} % aussi ok pour 1[0]
+ {\edef\POL@findrat@E{\the\numexpr\xintLen{\POL@findrat@Dint}%
+ +\POL@findrat@Dexp}}%
+% ATTENTION QUE LA CONVENTION DE SIGNE POUR \POL@findrat@E EST OPPOSÉE À CELLE
+% POUR LE CODE PLUS ANCIEN FAISANT "REFINE"
+ \POL@initarray\POL@IfMultIsKnown\xint_secondoftwo
+ \let\POL@findrat@nbofirrroots\POL@isolz@NbOfRoots
+ % find all rational roots, and their multiplicities,
+ % factor them out in passing from original (Sturm root) polynomial
+ \ifnum\POL@findrat@E<7
+ \def\POL@findrat@index{1}%
+ \POL@findrat@loop@secondpass@direct
+ \else
+ % we do a first pass scanning for "small" roots p/q (i.e. q < 1000)
+ \def\POL@findrat@index{1}%
+ \POL@findrat@loop@firstpass
+ % and now we do the final pass finding them all
+ \def\POL@findrat@index{1}%
+ \POL@findrat@loop@secondpass
+ \fi
+ % declare the new polynomials
+ \POL@newpol{\POL@sturmname\POL@sqfnorr}% without multiplicities
+ \POL@newpol{\POL@sturmname\POL@norr}% with multiplicities
+ % declare the array holding the interval indices for the rational roots
+ \expandafter\POL@findrat@doRRarray\csname POL_RI\POL@sturmname*\endcsname
+ \fi
+}%
+\def\POL@findrat@doRRarray#1{%
+ % il faudrait un \xintAssignArray* qui fasse même expansion que \xintFor*
+ \edef\POL@temp{%
+ \xintiloop[1+1]
+ \romannumeral0\csname POL_ZK\POL@sturmname*\xintiloopindex\endcsname
+ \xintbracediloopindex % I should have named it \xintiloopbracedindex...
+ {}%
+ \ifnum\xintiloopindex<\POL@isolz@NbOfRoots\space
+ \repeat }%
+ \begingroup\globaldefs\@ne
+ % attention de ne surtout pas faire un \expandafter ici, car en cas d'un
+ % seul item, \xintAssignArray l'unbraces...
+ \xintAssignArray\POL@temp\to#1%
+ \endgroup
+}%
+\def\POL@findrat@loop@firstpass{%
+ \PolSturmIfZeroExactlyKnown{\POL@sturmname}{\POL@findrat@index}%
+ \POL@findrat@loop@decimal% get its multiplicity
+ \POL@findrat@loop@aa % refine interval and check
+ \edef\POL@findrat@index{\the\numexpr\POL@findrat@index+\@ne}%
+ \ifnum\POL@findrat@index>\POL@isolz@NbOfRoots
+ \else
+ \expandafter\POL@findrat@loop@firstpass
+ \fi
+}%
+\def\POL@findrat@loop@aa{%
+ % we do a first pass to identify roots with denominators < 1000
+ \PolEnsureIntervalLength{\POL@sturmname}{\POL@findrat@index}{-6}%
+ % attention that perhaps now the root is known!
+ \PolSturmIfZeroExactlyKnown{\POL@sturmname}{\POL@findrat@index}%
+ \POL@findrat@loop@decimal
+ \POL@findrat@loop@a
+}%
+\def\POL@findrat@loop@decimal{% we have an already found decimal root
+ % we do not go via @storeit, as it is already stored
+ % j'ai beaucoup hésité néanmoins, car je pourrais faire \xintIrr ici,
+ % mais attention aussi à l'interaction avec le \PolDecToString. Les racines
+ % trouvées directement (qui peuvent être des nombres décimaux) sont elles
+ % stockées comme fraction irréductibles (modulo action additionnelle de
+ % \PolDecToString).
+ \POL@xintfrac@getNDE
+ {\xintIrr{\POL@xintexprGetVar{\POL@sturmname L_\POL@findrat@index}}[0]}%
+ \POL@findrat@xN\POL@findrat@xD\POl@_
+ % we can't move this to updatequotients because other branch will
+ % need to do the division first anyhow
+ \edef\POLuserpol@_findrat@oneterm{1.\noexpand\empty
+ {\xintiiOpp\POL@findrat@xN/1[0]}{\POL@findrat@xD/1[0]}}%
+ \POL@divide{\POL@sturmname\POL@sqfnorr}{_findrat@oneterm}% the one without mult.
+ %\expandafter\POL@split\POL@R;\POL@degR\POL@polR
+ \POL@findrat@loop@updatequotients
+ \POL@findrat@loop@getmultiplicity
+}%
+% lacking from xint 1.3c, but \xintSgn has overhead, so we define ii version
+\def\xintiiifNeg{\romannumeral0\xintiiifneg }%
+\def\xintiiifneg #1%
+{%
+ \ifcase \xintiiSgn{#1}
+ \expandafter\xint_stop_atsecondoftwo
+ \or\expandafter\xint_stop_atsecondoftwo
+ \else\expandafter\xint_stop_atfirstoftwo
+ \fi
+}%
+\def\POL@findrat@getE #1/1[#2]{#2}% /1 as it should be there.
+% so an error will arise if not but cf \POL@refine@getE where I did not put it
+\def\POL@findrat@loop@a{%
+ % attention that the width may have been already smaller than 10^{-6}
+ \POL@get@IsoLeft@rawin
+ \POL@get@IsoRight@rawin
+ \edef\POL@findrat@localW
+ {\the\numexpr-\expandafter\POL@findrat@getE
+ % do I really need the \xintREZ?
+ \romannumeral0\xintrez
+ {\xintSub{\POL@IsoRight@rawin}{\POL@IsoLeft@rawin}}%
+ }% at least 6, maybe larger
+ \expandafter\POL@get@Int@aux
+ \POL@IsoLeft@rawin\POL@IsoLeft@Int{-\POL@findrat@localW}%
+ \expandafter\POL@get@Int@aux
+ \POL@IsoRight@rawin\POL@IsoRight@Int{-\POL@findrat@localW}%
+ % in case of odd, some waste here
+ \edef\POL@findrat@halflocalW{\the\numexpr(\POL@findrat@localW+1)/2-1}%
+ % Legendre Theorem will be used now but we separate a branch where
+ % everything can be done with \numexpr
+ \ifnum\POL@findrat@localW>9
+ % not implemented yet by lazyness!
+ % this root will be handled in second pass only
+ \else
+ \POL@findrat@gcdloop
+ \fi
+}%
+\def\POL@findrat@gcdloop{%
+ % we must be careful with sign
+ % but we are certain no extremity is a root
+ \let\POL@findrat@ifnegative\xint_secondoftwo
+ \xintiiifSgn\POL@IsoLeft@Int
+ \POL@findrat@gcdloop@n
+ \POL@error@thisisimpossible
+ \POL@findrat@gcdloop@p
+}%
+\def\POL@findrat@gcdloop@n{%
+ \let\POL@findrat@ifnegative\xint_firstoftwo
+ \let\POL@temp\POL@IsoRight@Int
+ \edef\POL@IsoRight@Int{\xintiiOpp{\POL@IsoLeft@Int}}%
+ \edef\POL@IsoLeft@Int{\xintiiOpp{\POL@temp}}%
+ \POL@findrat@gcdloop@p
+}%
+\def\POL@findrat@gcdloop@p{%
+ \edef\POL@findrat@gcdloop@Ap{\xintDec{\xintDouble\POL@IsoRight@Int}}%
+ \edef\POL@findrat@gcdloop@A
+ % at most 2e9: this is acceptable to \numexpr
+ {2\romannumeral\xintreplicate\POL@findrat@localW{0}}%
+ \xintAssign
+ \xintiiDivision\POL@findrat@gcdloop@Ap\POL@findrat@gcdloop@A
+ \to\POL@findrat@gcdloop@B\POL@findrat@gcdloop@An
+ % on fait de la tambouille pour n'utiliser que \numexpr par la suite
+ % le reste @An est < 2.10^9 au pire donc ok pour \numexpr
+ % we will drop integral part in our updating P
+ \let\POL@findrat@gcdloop@Binitial\POL@findrat@gcdloop@B
+ \def\POL@findrat@gcdloop@B{0}% do as if B1 = 0
+ \def\POL@findrat@gcdloop@Pp{1}% P0
+ \def\POL@findrat@gcdloop@P{0}% P1
+ \def\POL@findrat@gcdloop@Qp{0}% Q0
+ \def\POL@findrat@gcdloop@Q{1}% Q1
+ % A2=An can not be zero, as Ap (=A0) is odd and A (=A1=200...000) is even
+ % first Binitial + P1/Q1 ( = Binitial) can not be root
+ \let\POL@findrat@gcdloop@Ap\POL@findrat@gcdloop@A % A1
+ \let\POL@findrat@gcdloop@A\POL@findrat@gcdloop@An % A2
+ \def\next{\POL@findrat@gcdloop@update}%
+ \def\POL@findrat@gcdloop@done{0}%
+ \POL@findrat@gcdloop@body
+}%
+\def\POL@findrat@gcdloop@body{%
+ % annoying that \numexpr has no divmod... use counts? but groups annoying
+ \edef\POL@findrat@gcdloop@B
+ {\the\numexpr(\POL@findrat@gcdloop@Ap+\POL@findrat@gcdloop@A/2)/%
+ \POL@findrat@gcdloop@A - \@ne}%
+ \edef\POL@findrat@gcdloop@An
+ {\the\numexpr\POL@findrat@gcdloop@Ap-%
+ \POL@findrat@gcdloop@B*\POL@findrat@gcdloop@A}%
+ \edef\POL@findrat@gcdloop@Pn
+ {\the\numexpr\POL@findrat@gcdloop@Pp+%
+ \POL@findrat@gcdloop@B*\POL@findrat@gcdloop@P}%
+ \edef\POL@findrat@gcdloop@Qn
+ {\the\numexpr\POL@findrat@gcdloop@Qp+%
+ \POL@findrat@gcdloop@B*\POL@findrat@gcdloop@Q}%
+ \ifnum\expandafter\xintLength\expandafter{\POL@findrat@gcdloop@Qn}%
+ >\POL@findrat@halflocalW\space
+ \let\next\empty % no solution was found
+ \else
+ % with these conditions on denom, only candidates are by Legendre
+ % theorem among the convergents as computed here
+ \ifnum\POL@findrat@gcdloop@Qn>\POL@findrat@gcdloop@An\space
+ % means that P/Q is in interval and is thus a candidate
+ % it is automatically irreducible
+ \edef\POL@findrat@x{\xintiiAdd
+ {\xintiiMul{\POL@findrat@gcdloop@Qn}{\POL@findrat@gcdloop@Binitial}}%
+ {\POL@findrat@gcdloop@Pn}/\POL@findrat@gcdloop@Qn[0]}%
+ \POL@findrat@gcdloop@testit
+ \if1\POL@findrat@gcdloop@done
+ \let\next\empty % a solution was found
+ \fi
+ \fi
+ \fi
+ \next
+}%
+\def\POL@findrat@gcdloop@update{%
+ \ifnum\POL@findrat@gcdloop@An>\z@
+ \let\POL@findrat@gcdloop@Ap\POL@findrat@gcdloop@A
+ \let\POL@findrat@gcdloop@A\POL@findrat@gcdloop@An
+ \let\POL@findrat@gcdloop@Pp\POL@findrat@gcdloop@P
+ \let\POL@findrat@gcdloop@P\POL@findrat@gcdloop@Pn
+ \let\POL@findrat@gcdloop@Qp\POL@findrat@gcdloop@Q
+ \let\POL@findrat@gcdloop@Q\POL@findrat@gcdloop@Qn
+ \expandafter\POL@findrat@gcdloop@body
+ \fi
+}%
+\def\POL@findrat@gcdloop@testit{%
+ % zero should never occur here
+ \POL@findrat@ifnegative{\edef\POL@findrat@x{-\POL@findrat@x}}{}%
+ \POL@xintfrac@getNDE\POL@findrat@x\POL@findrat@xN\POL@findrat@xD\POL@_
+ \edef\POLuserpol@_findrat@oneterm{1.\noexpand\empty
+ {\xintiiOpp{\POL@findrat@xN}/1[0]}{\POL@findrat@xD/1[0]}}%
+ \POL@divide{\POL@sturmname\POL@sqfnorr}{_findrat@oneterm}% the one without mult.
+ \expandafter\POL@split\POL@R;\POL@degR\POL@polR
+ \ifnum\POL@degR=\m@ne % found a root
+ \POL@findrat@loop@storeit
+ \POL@findrat@loop@updatequotients
+ \POL@findrat@loop@getmultiplicity % will continue updating the mult. one
+ \def\POL@findrat@gcdloop@done{1}%
+ \fi
+}%
+% This is second phase
+\def\POL@findrat@loop@secondpass{%
+ \PolSturmIfZeroExactlyKnown{\POL@sturmname}{\POL@findrat@index}%
+ {}% nothing more to be done, already stored
+ \POL@findrat@loop@bb % refine interval and check
+ \edef\POL@findrat@index{\the\numexpr\POL@findrat@index+\@ne}%
+ \ifnum\POL@findrat@index>\POL@isolz@NbOfRoots
+ \else
+ \expandafter\POL@findrat@loop@secondpass
+ \fi
+}%
+\def\POL@findrat@loop@secondpass@direct{%
+ \PolSturmIfZeroExactlyKnown{\POL@sturmname}{\POL@findrat@index}%
+ \POL@findrat@loop@decimal
+ \POL@findrat@loop@bb
+ \edef\POL@findrat@index{\the\numexpr\POL@findrat@index+\@ne}%
+ \ifnum\POL@findrat@index>\POL@isolz@NbOfRoots
+ \else
+ \expandafter\POL@findrat@loop@secondpass@direct
+ \fi
+}%
+\def\POL@findrat@loop@bb{%
+ \PolEnsureIntervalLength{\POL@sturmname}{\POL@findrat@index}{-\POL@findrat@E}%
+ % ATTENTION THAT PERHAPS NOW THE ROOT IS KNOWN!
+ \PolSturmIfZeroExactlyKnown{\POL@sturmname}{\POL@findrat@index}%
+ \POL@findrat@loop@decimal
+ \POL@findrat@loop@b
+}%
+\def\POL@findrat@loop@b{%
+ \edef\POL@findrat@Lscaled{\xintMul{\POL@findrat@D}%
+ {\POL@xintexprGetVar{\POL@sturmname L_\POL@findrat@index}}}%
+ \edef\POL@findrat@Rscaled{\xintMul{\POL@findrat@D}%
+ {\POL@xintexprGetVar{\POL@sturmname R_\POL@findrat@index}}}%
+ \xintiiifNeg{\POL@findrat@Lscaled}% using ii version is an abuse
+ {% negative interval (right bound possibly zero!)
+ % truncate towards zero (i.e. to the right) the left bound
+ \edef\POL@findrat@Num{\xintNum{\POL@findrat@Lscaled}/1[0]}%
+ % interval boundaries are not root hence in case that was exact
+ % this will not be found as a root; check if in interval
+ \xintifLt\POL@findrat@Num\POL@findrat@Rscaled
+ \POL@findrat@loop@c
+ {}% iterate
+ }%
+ {% positive interval (left bound possibly zero!)
+ % truncate towards zero (i.e. to the left) the right bound
+ \edef\POL@findrat@Num{\xintNum{\POL@findrat@Rscaled}/1[0]}%
+ % check if in interval
+ \xintifGt\POL@findrat@Num\POL@findrat@Lscaled
+ \POL@findrat@loop@c
+ {}% iterate
+ }%
+}%
+\def\POL@findrat@loop@c{%
+ % safer to do the edef as \POL@findrat@x used later in storeit
+ \edef\POL@findrat@x{\xintIrr{\xintDiv\POL@findrat@Num\POL@findrat@D}[0]}%
+ \POL@xintfrac@getNDE\POL@findrat@x\POL@findrat@xN\POL@findrat@xD\POL@_
+ \edef\POLuserpol@_findrat@oneterm{1.\noexpand\empty
+ {\xintiiOpp{\POL@findrat@xN}/1[0]}{\POL@findrat@xD/1[0]}}%
+ \POL@divide{\POL@sturmname\POL@sqfnorr}{_findrat@oneterm}% the one without mult.
+ \expandafter\POL@split\POL@R;\POL@degR\POL@polR
+ \ifnum\POL@degR=\m@ne % found a root
+ \POL@findrat@loop@storeit
+ \POL@findrat@loop@updatequotients
+ \POL@findrat@loop@getmultiplicity % will continue updating the mult. one
+ \fi
+ % iterate
+}%
+\def\POL@findrat@loop@storeit{%
+ % update storage, I can not use storeleftandright here (due to rawout etc...)
+ \expandafter
+ \xdef\csname POL_ZL\POL@sturmname*\POL@findrat@index\endcsname
+ {\PolDecToString{\POL@findrat@x}}%
+ \global\expandafter
+ \let\csname POL_ZR\POL@sturmname*\POL@findrat@index\expandafter\endcsname
+ \csname POL_ZL\POL@sturmname*\POL@findrat@index\endcsname
+ \global\expandafter
+ \let\csname POL_ZK\POL@sturmname*\POL@findrat@index\endcsname
+ \xint_stop_atfirstoftwo
+ \begingroup\xintglobaldefstrue
+ % skip some overhead of \xintdefvar...
+ % BUT attention to changes in xint 1.4 internal format !
+ \XINT_expr_defvar_one{\POL@sturmname L_\POL@findrat@index}%
+ {{\POL@findrat@x}}%
+ \XINT_expr_defvar_one{\POL@sturmname R_\POL@findrat@index}%
+ {{\POL@findrat@x}}%
+ \XINT_expr_defvar_one{\POL@sturmname Z_\POL@findrat@index _isknown}%
+ {{1}}%
+ \endgroup
+}%
+\def\POL@findrat@loop@updatequotients{%
+ % attention last division must have been one testing vanishing of\POL@sqfnorr
+ \XINT_global\expandafter\let\csname POLuserpol@\POL@sturmname\POL@sqfnorr\endcsname\POL@Q
+ % quotient belongs to Z[X] and is primitive
+ \POL@mapcoeffs\POL@aux@toint{\POL@sturmname\POL@sqfnorr}%
+ % update the one with multiplicities
+ \POL@divide{\POL@sturmname\POL@norr}{_findrat@oneterm}%
+ \XINT_global\expandafter\let\csname POLuserpol@\POL@sturmname\POL@norr\endcsname\POL@Q
+ \POL@mapcoeffs\POL@aux@toint{\POL@sturmname\POL@norr}
+ % updating of \POL@findrat@D at end of execution of getmultiplicity
+}%
+\def\POL@findrat@loop@getmultiplicity{%
+ % the one without multiplicity must not be divided again!
+ % check if we have remaining multiplicity
+ \POL@divide{\POL@sturmname\POL@norr}{_findrat@oneterm}%
+ \expandafter\POL@split\POL@R;\POL@degR\POL@polR
+ \ifnum\POL@degR=\m@ne % yes
+ \XINT_global\expandafter\let\csname POLuserpol@\POL@sturmname\POL@norr\endcsname\POL@Q
+ \POL@mapcoeffs\POL@aux@toint{\POL@sturmname\POL@norr}%
+ \expandafter
+ \xdef
+ \csname POL_ZM\POL@sturmname*\POL@findrat@index\endcsname
+ {\the\numexpr
+ \csname POL_ZM\POL@sturmname*\POL@findrat@index\endcsname+\@ne}%
+ \expandafter\POL@findrat@loop@getmultiplicity
+ \else
+ % done with multiplicity for this rational root, update stuff
+ \edef\POL@findrat@nbofirrroots
+ {\the\numexpr\POL@findrat@nbofirrroots-\@ne}%
+ \@namedef{POL@IfMultIsKnown\POL@findrat@index}{\xint_firstoftwo}%
+ \edef\POL@findrat@D{\xintAbs{\PolLeadingCoeff{\POL@sturmname\POL@sqfnorr}}}%
+ \POL@xintfrac@getNDE\POL@findrat@D\POL@findrat@Dint\POL@_\POL@findrat@Dexp
+ \xintiiifOne{\POL@findrat@Dint}
+ {\let\POL@findrat@E\POL@findrat@Dexp} % aussi ok pour 1[0]
+ {\edef\POL@findrat@E{\the\numexpr\xintLen{\POL@findrat@Dint}%
+ +\POL@findrat@Dexp}}%
+ \fi
+}%
+\def\POL@findrat@getirrmult{%
+ % first get the GCD of remaining pol with its derivative
+ \POL@divide{\POL@sturmname\POL@norr}{\POL@sturmname\POL@sqfnorr}%
+ \expandafter\let
+ % attention au _ (cf. grosse astuce pour \POL@isolzmult@loop)
+ \csname POLuserpol@@_1\POL@sturmname _\endcsname\POL@Q
+ \ifnum\PolDegree{@_1\POL@sturmname _}>\z@
+ % il reste des multiplicités (mais peut-être pour des racines complexes)
+ % (ou pour des racines en-dehors de l'intervalle optionnel)
+ % attention recyclage ici de \POL@isolzmult@loop qui dépend de
+ % la grosse astuce avec \@gobble
+ \POL@makeprimitive{@_1\POL@sturmname _}%
+ \let\POL@originalsturmname\POL@sturmname
+ % trick to get isolzmult@loop to define @@lastGCD to @_1sturmname_
+ % because it will do \POL@sturmname _\POL@sturm@N _
+ \edef\POL@sturmname{@_1\POL@sturmname}%
+ \let\POL@sturm@N\@gobble% !
+ \let\POL@isolz@NbOfRoots@with_unknown_mult\POL@findrat@nbofirrroots
+ \POL@tosturm@makefirstprimitivefalse
+\expanded{\unexpanded{%
+ \unless\ifxintveryverbose\xintverbosefalse\polnewpolverbosefalse\fi
+ \POL@isolzmult@loop
+}\ifxintverbose\noexpand\xintverbosetrue\fi
+ \ifpolnewpolverbose\noexpand\polnewpolverbosetrue\fi}%
+ \POL@tosturm@makefirstprimitivetrue
+ \let\POL@sturmname\POL@originalsturmname
+ \fi
+}%
+\def\PolSturmIsolateZerosAndGetMultiplicities@{%
+ \POL@chkopt\POL@oPolSturmIsolateZerosAndGetMultiplicities@[\empty]%
+}%
+\def\POL@oPolSturmIsolateZerosAndGetMultiplicities@[#1]#2{%
+ % #1 optional E such that roots are searched in -10^E < x < 10^E
+ % both -10^E and +10^E must not be roots!
+ % #2 name of Sturm chain (already pre-computed)
+ \edef\POL@sturmname{#2}%
+ \edef\POL@sturm@N{\@nameuse{PolSturmChainLength_\POL@sturmname}}%
+ % isolate the roots (detects case of constant polynomial)
+ \PolSturmIsolateZeros@{\POL@sturmname}%
+ \ifnum\POL@isolz@NbOfRoots=\z@
+ % no roots, define empty array nevertheless
+ \begingroup\globaldefs\@ne
+ \expandafter\xintAssignArray\expandafter\to\csname POL_ZM\POL@sturmname*\endcsname
+ \endgroup
+ \else
+ % all we currently know is that multiplicities are at least one
+ \begingroup\globaldefs\@ne
+ \expandafter\POL@initarray\csname POL_ZM\POL@sturmname*\endcsname{1}%
+ \endgroup
+ % check if GCD had positive degree (hence some roots, maybe complex, have
+ % multiplicity)
+ \ifnum\PolDegree{\POL@sturmname _\POL@sturm@N _}>\z@
+ % scratch array of flags to signal known multiplicities
+ \POL@initarray\POL@IfMultIsKnown\xint_secondoftwo
+ % this count has utility for the case there are other roots
+ % either complex or outside interval (in case of optional argument)
+ \let\POL@isolz@NbOfRoots@with_unknown_mult\POL@isolz@NbOfRoots
+ % store Sturm chain name, it is needed and altered in isolzmult@loop
+ \let\POL@originalsturmname\POL@sturmname
+ \POL@tosturm@makefirstprimitivefalse
+\expanded{\unexpanded{%
+ \unless\ifxintveryverbose\xintverbosefalse\polnewpolverbosefalse\fi
+ \POL@isolzmult@loop
+}\ifxintverbose\noexpand\xintverbosetrue\fi
+ \ifpolnewpolverbose\noexpand\polnewpolverbosetrue\fi}%
+ \POL@tosturm@makefirstprimitivetrue
+ \let\POL@sturmname\POL@originalsturmname
+ \fi
+ \POL@isolzmult@defvar@M
+ \fi
+}%
+\def\POL@isolzmult@defvar@M{%
+ % Attention that is used not only in ...GetMultiplicities@ but also
+ % in FindRationalRoots
+ \begingroup\xintglobaldefstrue
+ % added at 0.7
+ \let\x\POL@isolz@NbOfRoots
+ \xintloop
+ % skip some overhead of \xintdefvar...
+ % ATTENTION to xint 1.4 internal changes !
+ \XINT_expr_defvar_one{\POL@sturmname M_\x}%
+ {{\csname POL_ZM\POL@sturmname*\x\endcsname}}%
+ \edef\x{\the\numexpr\x-\@ne}%
+ \ifnum\x>\z@
+ \repeat
+ \endgroup
+}%
+\def\POL@isolzmult@loop{%
+ % we are here only if last iteration gave a new GCD still of degree > 0
+ % \POL@sturm@N is the one from last iteration
+ % Attention to not use \POL@sturmname directly in first arg. of \PolToSturm
+ % Attention that we need for the case of known roots also to have the last
+ % GCD (with its multiplicities) known as a genuine polynomial
+ % - because of usage of \POL@eval in @isknown branch
+ % - because \PolToSturm@ does a \POL@let which would be anomalous
+ % if the extended structure is not existing
+ \edef\POL@isolzmult@lastGCD{\POL@sturmname _\POL@sturm@N _}%
+ \edef\POL@isolzmult@newsturmname{@_1\POL@sturmname}%
+ \POL@newpol{\POL@isolzmult@lastGCD}%
+ \PolToSturm@{\POL@isolzmult@lastGCD}{\POL@isolzmult@newsturmname}%
+ % now both \POL@sturmname and \POL@sturm@N have changed
+ \edef\POL@isolzmult@newGCDdegree{\PolDegree{\POL@sturmname _\POL@sturm@N _}}%
+ \let\POL@isolzmult@index\POL@isolz@NbOfRoots
+ \xintloop
+ % ATTENTION that this executes macros which also modifies \POL@sturmname!
+ % (but not \POL@sturm@N)
+ \POL@isolzmult@doone
+ \edef\POL@isolzmult@index{\the\numexpr\POL@isolzmult@index-\@ne}%
+ \if1\ifnum\POL@isolz@NbOfRoots@with_unknown_mult=\z@ 0\fi
+ \ifnum\POL@isolzmult@index=\z@ 0\fi 1%
+ \repeat
+ \let\POL@sturmname\POL@isolzmult@newsturmname
+ \if1\ifnum\POL@isolz@NbOfRoots@with_unknown_mult=\z@ 0\fi
+ % (if new GCD is constant, time to abort)
+ \ifnum\POL@isolzmult@newGCDdegree=\z@ 0\fi 1%
+ \expandafter\POL@isolzmult@loop
+ \fi
+}%
+\def\POL@isolzmult@doone{%
+ \csname POL@IfMultIsKnown\POL@isolzmult@index\endcsname
+ {}% nothing to do
+ {\POL@SturmIfZeroExactlyKnown{\POL@originalsturmname}%
+ {\POL@isolzmult@index}%
+ \POL@isolzmult@loop@isknown
+ \POL@isolzmult@loop@isnotknown
+ \POL@isolzmult@loop@sharedbody
+ }%
+}%
+\def\POL@isolzmult@loop@isknown{%
+ \xintifZero
+ % attention that \POL@eval requires a declared polynomial
+ {\POL@eval{\POL@isolzmult@lastGCD}%
+ {\POL@xintexprGetVar{\POL@originalsturmname L_\POL@isolzmult@index}}}%
+ {\let\POL@isolzmult@haszero\@ne}%
+ {\let\POL@isolzmult@haszero\z@}%
+}%
+\def\POL@isolzmult@loop@isnotknown{%
+ \edef\POL@isolzmult@loop@A
+ {\POL@xintexprGetVar{\POL@originalsturmname L_\POL@isolzmult@index}}
+ \edef\POL@isolzmult@loop@B
+ {\POL@xintexprGetVar{\POL@originalsturmname
+ R_\POL@isolzmult@index}}
+ % attention that \PolSetToNbOfZerosWithin sets \POL@sturmname to 2nd argument
+ \PolSetToNbOfZerosWithin
+ \POL@isolzmult@haszero % nb of zeros A < x <= B, here 0 or 1
+ \POL@isolzmult@newsturmname
+ \POL@isolzmult@loop@A
+ \POL@isolzmult@loop@B
+}%
+\def\POL@isolzmult@loop@sharedbody{%
+ \ifnum\POL@isolzmult@haszero>\z@
+ \expandafter
+ \xdef
+ \csname POL_ZM\POL@originalsturmname*\POL@isolzmult@index\endcsname
+ {\the\numexpr
+ \csname POL_ZM\POL@originalsturmname
+ *\POL@isolzmult@index\endcsname+\@ne}%
+ \else
+ % multiplicity now known, no need to check this index in future
+ \@namedef{POL@IfMultIsKnown\POL@isolzmult@index}{\xint_firstoftwo}%
+ \edef\POL@isolz@NbOfRoots@with_unknown_mult
+ {\the\numexpr\POL@isolz@NbOfRoots@with_unknown_mult-\@ne}%
+ \fi
+}%
+\def\PolSturmIsolateZeros@{%
+ \POL@chkopt\POL@oPolSturmIsolateZeros@[\empty]%
+}%
+\def\POL@oPolSturmIsolateZeros@[#1]#2{%
+ % #1 optional E such that roots are searched in -10^E < x < 10^E
+ % both -10^E and +10^E must not be roots!
+ % #2 name of Sturm chain (already pre-computed from a given polynomial)
+ % For reasons I have forgotten (no time now) this code **must** be used
+ % with a *normalized* Sturm chain.
+ \edef\POL@sturmname{#2}%
+ \edef\POL@sturmlength{\PolSturmChainLength{#2}}%
+ % attention to constant polynomial, we must redefine the arrays then
+ \ifnum\POL@sturmlength>\z@
+ \ifx\empty#1\relax
+ \POL@isolz@getsignchanges@plusinf
+ \POL@isolz@getsignchanges@minusinf
+ \else
+ \edef\POL@isolz@E{\the\numexpr\xint_zapspaces #1 \xint_gobble_i\relax}%
+ \POL@sturmchain@getSV@at{1[\POL@isolz@E]}%
+ \let\POL@isolz@plusinf@SV \POL@sturmchain@SV
+ \let\POL@isolz@plusinf@sign\POL@sturmchain@sign
+ \POL@sturmchain@getSV@at{-1[\POL@isolz@E]}%
+ \let\POL@isolz@minusinf@SV \POL@sturmchain@SV
+ \let\POL@isolz@minusinf@sign\POL@sturmchain@sign
+ \ifnum\POL@isolz@plusinf@sign=\z@
+ \PackageError{polexpr}%
+{The polynomial #2 vanishes at set upper bound 10^\POL@isolz@E}%
+{Compile again with a bigger exponent in source. (X to abort).}%
+ \fi
+ \ifnum\POL@isolz@minusinf@sign=\z@
+ \PackageError{polexpr}%
+{The polynomial #2 vanishes at set lower bound -10^\POL@isolz@E}%
+{Compile again with a bigger exponent in source. (X to abort).}%
+ \fi
+ \fi
+ \edef\POL@isolz@NbOfRoots
+ {\the\numexpr\POL@isolz@minusinf@SV-\POL@isolz@plusinf@SV}%
+ \else
+ % constant polynomial
+ \def\POL@isolz@NbOfRoots{0}%
+ \fi
+ \ifnum\POL@isolz@NbOfRoots=\z@
+ \begingroup\globaldefs\@ne
+ \expandafter\xintAssignArray\expandafter\to\csname POL_ZL#2*\endcsname
+ \expandafter\xintAssignArray\expandafter\to\csname POL_ZR#2*\endcsname
+ \expandafter\xintAssignArray\expandafter\to\csname POL_ZK#2*\endcsname
+ \endgroup
+ \else
+ \begingroup\globaldefs\@ne
+ \expandafter\POL@initarray\csname POL_ZL#2*\endcsname{0}%
+ \expandafter\POL@initarray\csname POL_ZR#2*\endcsname{0}%
+ \expandafter\POL@initarray\csname POL_ZK#2*\endcsname
+ \xint_stop_atsecondoftwo
+ \endgroup
+ \ifx\empty#1\relax\expandafter\POL@isolz@getaprioribound\fi
+ \expandafter\POL@isolz@main
+ \fi
+}%
+\def\POL@initarray#1#2{%
+% ATTENTION, if only one item, \xintAssignArray UNBRACES IT
+% so we use an \empty trick to avoid that. Maybe considered a bug of xinttools?
+ \expandafter\xintAssignArray\expandafter\empty
+ \romannumeral\xintreplicate{\POL@isolz@NbOfRoots}{{#2}}\to#1%
+}%
+\def\POL@isolz@getsignchanges@plusinf{%
+ % Count number of sign changes at plus infinity in Sturm sequence
+ \def\POL@isolz@plusinf@SV{0}%
+ \edef\POL@isolz@lastsign{\xintiiSgn{\PolLeadingCoeff{\POL@sturmname _0}}}%
+ \let\POL@isolz@plusinf@sign\POL@isolz@lastsign
+ \POL@count\@ne
+ \xintloop
+ \edef\POL@isolz@newsign
+ {\xintiiSgn{\PolLeadingCoeff{\POL@sturmname _\the\POL@count}}}%
+ \unless\ifnum\POL@isolz@newsign=\POL@isolz@lastsign
+ \edef\POL@isolz@plusinf@SV{\the\numexpr\POL@isolz@plusinf@SV+\@ne}%
+ \fi
+ \let\POL@isolz@lastsign=\POL@isolz@newsign
+ \ifnum\POL@sturmlength>\POL@count
+ \advance\POL@count\@ne
+ \repeat
+}%
+\def\POL@isolz@getsignchanges@minusinf{%
+ % Count number of sign changes at minus infinity in Sturm sequence
+ \def\POL@isolz@minusinf@SV{0}%
+ \edef\POL@isolz@lastsign{\xintiiSgn{\PolLeadingCoeff{\POL@sturmname _0}}}%
+ \ifodd\PolDegree{\POL@sturmname _0}
+ \edef\POL@isolz@lastsign{\xintiiOpp{\POL@isolz@lastsign}}%
+ \fi
+ \let\POL@isolz@minusinf@sign\POL@isolz@lastsign
+ \POL@count\@ne
+ \xintloop
+ \edef\POL@isolz@newsign
+ {\xintiiSgn{\PolLeadingCoeff{\POL@sturmname _\the\POL@count}}}%
+ \ifodd\PolDegree{\POL@sturmname _\the\POL@count}
+ \edef\POL@isolz@newsign{\xintiiOpp{\POL@isolz@newsign}}%
+ \fi
+ \unless\ifnum\POL@isolz@newsign=\POL@isolz@lastsign
+ \edef\POL@isolz@minusinf@SV{\the\numexpr\POL@isolz@minusinf@SV+\@ne}%
+ \fi
+ \let\POL@isolz@lastsign=\POL@isolz@newsign
+ \ifnum\POL@sturmlength>\POL@count
+ \advance\POL@count\@ne
+ \repeat
+}%
+% utility macro for a priori bound on root decimal exponent, via Float Rounding
+\def\POL@isolz@updateE #1e#2;%
+ {\unless\ifnum#2<\POL@isolz@E\space\edef\POL@isolz@E{\the\numexpr#2+\@ne}\fi}%
+\def\POL@isolz@getaprioribound{%
+ \PolAssign{\POL@sturmname _0}\toarray\POL@arrayA
+ \edef\POL@isolz@leading{\POL@arrayA{\POL@arrayA{0}}}%
+ \POL@count\z@
+ \xintloop
+ \advance\POL@count\@ne
+ \ifnum\POL@arrayA{0}>\POL@count
+ \expandafter\edef\csname POL@arrayA\the\POL@count\endcsname
+ {\xintDiv{\POL@arrayA\POL@count}\POL@isolz@leading}%
+ \repeat
+ \def\POL@isolz@E{1}% WE SEEK SMALLEST E SUCH HAT -10^E < roots < +10^E
+ \advance\POL@count\m@ne
+ \xintloop
+ \ifnum\POL@count>\z@
+ \expandafter\POL@isolz@updateE
+ % use floating point to get decimal exponent
+ \romannumeral0\xintfloat[4]% should I use with [2] rather? (should work)
+ {\xintAdd{1/1[0]}{\xintAbs{\POL@arrayA\POL@count}}};%
+ \advance\POL@count\m@ne
+ \repeat
+ % \ifxintverbose\xintMessage{polexpr}{Info}%
+ % {Roots a priori bounded in absolute value by 10 to the \POL@isolz@E.}%
+ % \fi
+}%
+\def\POL@IsoRight@raw{\POL@IsoRight@Int/1[\POL@isolz@E]}%
+\def\POL@IsoLeft@raw {\POL@IsoLeft@Int/1[\POL@isolz@E]}%
+\def\POL@IsoRight@rawout{%
+ \ifnum\POL@IsoRightSign=\z@\expandafter\xintREZ\fi\POL@IsoRight@raw
+}%
+\def\POL@IsoLeft@rawout{%
+ \ifnum\POL@IsoRightSign=\z@
+ \expandafter\xint_firstoftwo\else\expandafter\xint_secondoftwo
+ \fi{\xintREZ\POL@IsoRight@raw}%
+ {\POL@IsoLeft@Int/1[\POL@isolz@E]}%
+}%
+\def\POL@isolz@main {%
+% NOTE 2018/02/16. THIS WILL PRESUMABLY BE RE-ORGANIZED IN FUTURE TO DO
+% FIRST POSITIVE ROOTS THEN NEGATIVE ROOTS VIA CHANGE OF VARIABLE TO OPPOSITE.
+ \global\POL@isolz@nextwillneedrefinefalse
+ \def\POL@IsoRight@Int{0}%
+ \POL@sturmchain@getSV@at\POL@IsoRight@raw
+ \let\POL@IsoRightSV \POL@sturmchain@SV
+ \let\POL@IsoRightSign\POL@sturmchain@sign
+ \let\POL@IsoAtZeroSV \POL@IsoRightSV
+ \let\POL@IsoAtZeroSign\POL@IsoRightSign
+ \ifnum\POL@IsoAtZeroSign=\z@
+ \xdef\POL@isolz@IntervalIndex
+ {\the\numexpr\POL@isolz@minusinf@SV-\POL@IsoRightSV}%
+ \POL@refine@storeleftandright % store zero root, \POL@IsoRightSign is zero
+ \edef\POL@IsoRightSV{\the\numexpr\POL@IsoRightSV+\@ne}%
+% subtlety here if original polynomial had multiplicities, but ok. I checked!
+ \edef\POL@IsoRightSign % evaluated twice, but that's not so bad
+ {\xintiiOpp{\xintiiSgn{\POL@eval{\POL@sturmname _1}{0/1[0]}}}}%
+ \fi
+ \def\POL@IsoLeft@Int{-1}% -10^E isn't a root!
+ \let\POL@IsoLeftSV \POL@isolz@minusinf@SV
+ \let\POL@IsoLeftSign\POL@isolz@minusinf@sign
+ % \POL@IsoRight@SV was modified if zero is a root
+ \edef\POL@isolz@NbOfNegRoots{\the\numexpr\POL@IsoLeftSV-\POL@IsoRightSV}%
+ \gdef\POL@isolz@IntervalIndex{0}%
+ \let\POL@isolz@@E\POL@isolz@E
+ \ifnum\POL@isolz@NbOfNegRoots>\z@
+% refactored at 0.7 to fix cases leading to an intervals with zero as end-point
+ \POL@isolz@findroots@neg
+ \fi
+ \let\POL@isolz@E\POL@isolz@@E
+ \def\POL@IsoLeft@Int{0}%
+ \let\POL@IsoLeftSV \POL@IsoAtZeroSV % véritable SV en zéro
+ \let\POL@IsoLeftSign\POL@IsoAtZeroSign% véritable signe en zéro
+ \ifnum\POL@IsoLeftSign=\z@
+ \xdef\POL@isolz@IntervalIndex{\the\numexpr\POL@isolz@IntervalIndex+\@ne}%
+ \fi
+ \let\POL@@IsoRightSV \POL@isolz@plusinf@SV
+ \let\POL@@IsoRightSign\POL@isolz@plusinf@sign % 10^E not a root!
+ \edef\POL@isolz@NbOfPosRoots
+ {\the\numexpr\POL@IsoLeftSV-\POL@@IsoRightSV}% attention @@
+ \ifnum\POL@isolz@NbOfPosRoots>\z@
+ % always do that to avoid zero as end-point whether it is a root or not
+ \global\POL@isolz@nextwillneedrefinetrue
+ \POL@isolz@findroots@pos
+ \fi
+}%
+\def\POL@isolz@findroots@neg{%
+ \def\POL@IsoRight@Int{-1}%
+ \POL@isolz@findnextzeroboundeddecade@neg
+ \def\POL@IsoLeft@Int{-10}%
+ \let\POL@@IsoRightSign\POL@IsoRightSign % a zero there is possible
+ \let\POL@@IsoRightSV \POL@IsoRightSV
+ % this will do possibly recursive \POL@isolz@check's
+ \POL@isolz@explorenexteightsubdecades@neg
+ \ifnum\POL@isolz@IntervalIndex<\POL@isolz@NbOfNegRoots\space
+ % above did not explore -2, -1 for this optimization (SV known at Right)
+ \def\POL@IsoRight@Int{-1}%
+ \let\POL@IsoRightSign\POL@@IsoRightSign
+ \let\POL@IsoRightSV \POL@@IsoRightSV
+ \POL@isolz@check
+ \ifnum\POL@isolz@IntervalIndex<\POL@isolz@NbOfNegRoots\space
+ \def\POL@IsoLeft@Int{-1}%
+ \let\POL@IsoLeftSign\POL@@IsoRightSign
+ \let\POL@IsoLeftSV \POL@@IsoRightSV
+ % I don't like being inside TeX conditionals
+ \expandafter\expandafter\expandafter\POL@isolz@findroots@neg
+ \fi
+ \fi
+}%
+\def\POL@isolz@findnextzeroboundeddecade@neg{%
+ \xintloop
+ \edef\POL@isolz@E{\the\numexpr\POL@isolz@E-\@ne}%
+ \POL@sturmchain@getSV@at\POL@IsoRight@raw
+ \let\POL@IsoRightSV \POL@sturmchain@SV
+ \let\POL@IsoRightSign\POL@sturmchain@sign
+ % would an \ifx test be quicker? (to be checked)
+ \ifnum\POL@IsoRightSV=\POL@IsoLeftSV\space
+ % no roots in-between, iterate
+ \repeat
+}%
+\def\POL@isolz@explorenexteightsubdecades@neg{%
+ \xintloop
+ \edef\POL@IsoRight@Int{\the\numexpr\POL@IsoLeft@Int+\@ne}%
+ % we could arguably do a more efficient dichotomy here
+ \POL@sturmchain@getSV@at\POL@IsoRight@raw
+ \let\POL@IsoRightSV \POL@sturmchain@SV
+ \let\POL@IsoRightSign\POL@sturmchain@sign
+ \POL@isolz@check % may recurse if multiple roots are to be found
+ \ifnum\POL@isolz@IntervalIndex=\POL@isolz@NbOfNegRoots\space
+ \expandafter\xintbreakloop
+ \fi
+ \let\POL@IsoLeft@Int\POL@IsoRight@Int
+ \let\POL@IsoLeftSign\POL@IsoRightSign
+ \let\POL@IsoLeftSV\POL@IsoRightSV
+ \ifnum\POL@IsoRight@Int < -\tw@
+ \repeat
+}%
+\def\POL@isolz@findroots@pos{%
+ % remark (2018/12/08), this needs some refactoring, I hardly understand
+ % the logic and it hides most into the recursion done by \POL@isolz@check
+ % It would probably make more sense to proceed like done for the negative
+ % but here finding the largest roots first.
+ \def\POL@IsoRight@Int{1}%
+ \POL@isolz@findnextzeroboundeddecade@pos
+ \unless\ifnum\POL@IsoRightSV=\POL@IsoLeftSV\space
+ % this actually explores the whole of some interval (0, 10^{e-1}]
+ % in a context where some roots are known to be in (10^{e-1}, 10^{e}]
+ % and none are larger
+ \POL@isolz@check % will recurse inside groups if needed with modified E
+ \fi
+ % we know get the roots in the last 9 decades from 10^{e-1} to 10^{e}
+ % we should arguably do a more efficient dichotomy here
+ \def\POL@IsoLeft@Int{1}%
+ \let\POL@IsoLeftSV\POL@IsoRightSV
+ \let\POL@IsoLeftSign\POL@IsoRightSign
+ \xintloop
+ \edef\POL@IsoRight@Int{\the\numexpr\POL@IsoLeft@Int+\@ne}%
+ \POL@sturmchain@getSV@at\POL@IsoRight@raw
+ \let\POL@IsoRightSV \POL@sturmchain@SV
+ \let\POL@IsoRightSign\POL@sturmchain@sign
+ \POL@isolz@check % recurses in needed
+ \let\POL@IsoLeft@Int\POL@IsoRight@Int
+ \let\POL@IsoLeftSign\POL@IsoRightSign
+ \let\POL@IsoLeftSV\POL@IsoRightSV
+ \ifnum\POL@isolz@IntervalIndex=\POL@isolz@NbOfRoots\space
+ \expandafter\xintbreakloop
+ \fi
+ \ifnum\POL@IsoLeft@Int < \xint_c_ix
+ \repeat
+ \ifnum\POL@isolz@IntervalIndex<\POL@isolz@NbOfRoots\space
+ % get now the last, rightmost, root (or roots)
+ \def\POL@IsoRight@Int{10}%
+ \let\POL@IsoRightSign\POL@@IsoRightSign
+ \let\POL@IsoRightSV\POL@@IsoRightSV
+ \POL@isolz@check
+ \fi
+}%
+\def\POL@isolz@findnextzeroboundeddecade@pos{%
+ \xintloop
+ \edef\POL@isolz@E{\the\numexpr\POL@isolz@E-\@ne}%
+ \POL@sturmchain@getSV@at\POL@IsoRight@raw
+ \let\POL@IsoRightSV \POL@sturmchain@SV
+ \let\POL@IsoRightSign\POL@sturmchain@sign
+ \ifnum\POL@IsoRightSV=\POL@@IsoRightSV\space
+ \let\POL@@IsoRightSign\POL@IsoRightSign % root here possible!
+ \repeat
+}%
+\def\POL@isolz@check{% \POL@IsoRightSign must be ready for use here
+% \ifxintverbose
+% \xintMessage{polexpr}{Info}%
+% {\the\numexpr\POL@IsoLeftSV-\POL@IsoRightSV\relax\space roots
+% in (\POL@IsoLeft@raw,\POL@IsoRight@raw] (E = \POL@isolz@E)}%
+% \fi
+ \ifcase\numexpr\POL@IsoLeftSV-\POL@IsoRightSV\relax
+ % no root in ]left, right]
+ \global\POL@isolz@nextwillneedrefinefalse
+ \or
+ % exactly one root in ]left, right]
+ \xdef\POL@isolz@IntervalIndex{\the\numexpr\POL@isolz@IntervalIndex+\@ne}%
+ \ifnum\POL@IsoRightSign=\z@
+ % if right boundary is a root, ignore previous flag
+ \global\POL@isolz@nextwillneedrefinefalse
+ \fi
+ % if left boundary is known to have been a root we refine interval
+ \ifPOL@isolz@nextwillneedrefine
+ \expandafter\expandafter\expandafter\POL@isolz@refine
+ \else
+ % \POL@IsoRightSign is zero iff root now exactly known
+ \POL@refine@storeleftandright
+ \ifnum\POL@IsoRightSign=\z@
+ \global\POL@isolz@nextwillneedrefinetrue
+ \fi
+ \fi
+ \else
+ % more than one root, we need to recurse
+ \expandafter\POL@isolz@recursedeeper
+ \fi
+}%
+\def\POL@isolz@recursedeeper{%
+% NOTE 2018/02/16. I SHOULD DO A REAL BINARY DICHOTOMY HERE WHICH ON AVERAGE
+% SHOULD BRING SOME GAIN (LIKE WHAT IS ALREADY DONE FOR THE "refine" MACROS.
+% THUS IN FUTURE THIS MIGHT BE REFACTORED.
+\begingroup
+ \edef\POL@isolz@E{\the\numexpr\POL@isolz@E-\@ne}%
+ \edef\POL@@IsoRight@Int{\xintDSL{\POL@IsoRight@Int}}%
+ \let\POL@@IsoRightSign \POL@IsoRightSign
+ \let\POL@@IsoRightSV \POL@IsoRightSV
+ \edef\POL@IsoLeft@Int {\xintDSL{\POL@IsoLeft@Int}}%
+ \xintiloop[1+1]
+ \edef\POL@IsoRight@Int{\xintInc{\POL@IsoLeft@Int}}%
+ \POL@sturmchain@getSV@at\POL@IsoRight@raw
+ \let\POL@IsoRightSV \POL@sturmchain@SV
+ \let\POL@IsoRightSign\POL@sturmchain@sign
+ \POL@isolz@check
+ \let\POL@IsoLeft@Int\POL@IsoRight@Int
+ \let\POL@IsoLeftSV\POL@IsoRightSV
+ \let\POL@IsoLeftSign\POL@IsoRightSign% not used, actually
+ \ifnum\POL@IsoLeftSV=\POL@@IsoRightSV\space
+ \expandafter\xintbreakiloop
+ \fi
+ \ifnum\xintiloopindex < \xint_c_ix
+ \repeat
+ \let\POL@IsoRight@Int\POL@@IsoRight@Int
+ \let\POL@IsoRightSign\POL@@IsoRightSign
+ \let\POL@IsoRightSV \POL@@IsoRightSV
+ % if we exited the loop via breakiloop this is superfluous
+ % but it only costs one \ifnum
+ \POL@isolz@check
+\endgroup
+}%
+\def\POL@isolz@refine{%
+ % starting point is first root = left < unique second root < right
+ % even if we hit exactly via refinement second root, we set flag false as
+ % processing will continue with original right end-point, which isn't a root
+ \global\POL@isolz@nextwillneedrefinefalse
+\begingroup
+ \let\POL@@IsoRightSign\POL@IsoRightSign % already evaluated
+ \xintloop
+ \edef\POL@isolz@E{\the\numexpr\POL@isolz@E-\@ne}%
+ \edef\POL@IsoLeft@Int {\xintDSL{\POL@IsoLeft@Int}}%
+ \edef\POL@IsoRight@Int{\xintInc{\POL@IsoLeft@Int}}%
+ \edef\POL@IsoRightSign
+ {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}%
+ \ifnum\POL@IsoRightSign=\POL@@IsoRightSign\space
+ \repeat
+ % now second root has been separated from the one at left end point
+% we update the storage of the root at left for it to have the same number
+% of digits in mantissa. No, I decided not to do that to avoid complications.
+ % \begingroup
+ % \let\POL@IsoRight@Int\POL@IsoLeft@Int
+ % \def\POL@IsoRightSign{0}%
+ % \edef\POL@isolz@IntervalIndex{\the\numexpr\POL@isolz@IntervalIndex-\@ne}%
+ % \POL@refine@storeleftandright
+ % \endgroup
+ \edef\POL@@IsoRight@Int{\xintDSL{\xintInc{\xintDSR{\POL@IsoLeft@Int}}}}%
+ \let\POL@IsoLeft@Int\POL@IsoRight@Int
+ \let\POL@IsoLeftSign\POL@IsoRightSign
+ \ifnum\POL@IsoRightSign=\z@ % check if new Left is actually a root
+ \else
+ \edef\POL@IsoRight@Int{\xintDec{\POL@@IsoRight@Int}}%
+ \edef\POL@IsoRightSign
+ {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}%
+ \ifnum\POL@IsoRightSign=\POL@@IsoRightSign\space
+ \POL@refine@doonce % we need to locate in interval (1, 9) in local scale
+ \else
+ \let\POL@IsoLeft@Int\POL@IsoRight@Int
+ \ifnum\POL@IsoRightSign=\z@
+ \def\POL@IsoLeftSign{0}%
+ \else
+ \let\POL@IsoRight@Int\POL@@IsoRight@Int
+ % the IsoRightSign is now wrong but here we don't care
+ \fi\fi
+ \fi
+ % on exit, exact root found iff \POL@IsoRightSign is zero
+ \POL@refine@storeleftandright
+\endgroup
+}%
+\def\POL@refine@doonce{% if exact root is found, always in IsoRight on exit
+% NOTE: FUTURE REFACTORING WILL GET RID OF \xintiiAdd WHICH ARE A BIT COSTLY
+% BUT BASICALLY NEEDED TO HANDLE BOTH NEGATIVE AND POSITIVE HERE.
+% I WILL RE-ORGANIZE THE WHOLE THING IN FUTURE TO GET ROOTS STARTING FROM
+% THE ORIGIN AND SIMPLY RE-LABEL THE NEGATIVE ONE AT THE END. 2018/02/16.
+ \let\POL@@IsoRight@Int\POL@IsoRight@Int % 9
+ \let\POL@@IsoRightSign\POL@IsoRightSign
+ \edef\POL@IsoRight@Int{\xintiiAdd{4}{\POL@IsoLeft@Int}}% 5
+ \edef\POL@IsoRightSign
+ {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}%
+ \ifnum\POL@IsoRightSign=\POL@IsoLeftSign\space
+ \let\POL@IsoLeft@Int\POL@IsoRight@Int % 5
+ \edef\POL@IsoRight@Int{\xintiiAdd{2}{\POL@IsoLeft@Int}}%
+ \edef\POL@IsoRightSign
+ {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}%
+ \ifnum\POL@IsoRightSign=\POL@IsoLeftSign\space
+ \let\POL@IsoLeft@Int\POL@IsoRight@Int % 7
+ \edef\POL@IsoRight@Int{\xintInc{\POL@IsoLeft@Int}}%
+ \edef\POL@IsoRightSign
+ {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}%
+ \ifnum\POL@IsoRightSign=\POL@IsoLeftSign\space
+ \let\POL@IsoLeft@Int\POL@IsoRight@Int % 8
+ \let\POL@IsoRight@Int\POL@@IsoRight@Int % 9
+ \let\POL@IsoRightSign\POL@@IsoRightSign % opposite of one at left
+ \fi % else 7, 8 with possible root at 8
+ \else
+ \ifnum\POL@IsoRightSign=\z@
+ \let\POL@IsoLeft@Int\POL@IsoRight@Int % root at 7
+ \def\POL@IsoLeftSign{0}%
+ \else
+ \let\POL@@IsoRight@Int\POL@IsoRight@Int % 7
+ \edef\POL@IsoRight@Int{\xintInc{\POL@IsoLeft@Int}}% 6
+ \edef\POL@IsoRightSign
+ {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}%
+ \ifnum\POL@IsoRightSign=\POL@IsoLeftSign\space
+ \let\POL@IsoLeft@Int\POL@IsoRight@Int % 6
+ \let\POL@IsoRight@Int\POL@@IsoRight@Int % 7
+ \let\POL@IsoRightSign\POL@@IsoRightSign
+ \fi % else 5, 6 with possible root at 6
+ \fi\fi
+ \else
+ \ifnum\POL@IsoRightSign=\z@
+ \let\POL@IsoLeft@Int\POL@IsoRight@Int % root at 5
+ \def\POL@IsoLeftSign{0}%
+ \else
+ \let\POL@@IsoRight@Int\POL@IsoRight@Int % 5
+ \edef\POL@IsoRight@Int{\xintiiAdd{2}{\POL@IsoLeft@Int}}%
+ \edef\POL@IsoRightSign
+ {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}%
+ \ifnum\POL@IsoRightSign=\POL@IsoLeftSign\space
+ \let\POL@IsoLeft@Int\POL@IsoRight@Int % 3
+ \edef\POL@IsoRight@Int{\xintInc{\POL@IsoLeft@Int}}% 4
+ \edef\POL@IsoRightSign
+ {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}%
+ \ifnum\POL@IsoRightSign=\POL@IsoLeftSign\space
+ \let\POL@IsoLeft@Int\POL@IsoRight@Int % 4
+ \let\POL@IsoRight@Int\POL@@IsoRight@Int % 5
+ \let\POL@IsoRightSign\POL@@IsoRightSign
+ \fi % else 3, 4 with possible root at 4
+ \else
+ \ifnum\POL@IsoRightSign=\z@
+ \let\POL@IsoLeft@Int\POL@IsoRight@Int % root at 3
+ \def\POL@IsoLeftSign{0}%
+ \else
+ \let\POL@@IsoRight@Int\POL@IsoRight@Int % 3
+ \edef\POL@IsoRight@Int{\xintInc{\POL@IsoLeft@Int}}% 2
+ \edef\POL@IsoRightSign
+ {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}%
+ \ifnum\POL@IsoRightSign=\POL@IsoLeftSign\space
+ \let\POL@IsoLeft@Int\POL@IsoRight@Int % 2
+ \let\POL@IsoRight@Int\POL@@IsoRight@Int % 3
+ \let\POL@IsoRightSign\POL@@IsoRightSign
+ \fi % else 1, 2 with possible root at 2
+ \fi\fi
+ \fi\fi
+}%
+\def\POL@refine@storeleftandright{%
+ \expandafter
+ \xdef\csname POL_ZL\POL@sturmname*\POL@isolz@IntervalIndex\endcsname
+ {\PolDecToString{\POL@IsoLeft@rawout}}%
+ \expandafter
+ \xdef\csname POL_ZR\POL@sturmname*\POL@isolz@IntervalIndex\endcsname
+ {\PolDecToString{\POL@IsoRight@rawout}}%
+ % added at 0.6
+ \ifnum\POL@IsoRightSign=\z@
+ \global
+ \expandafter
+ \let\csname POL_ZK\POL@sturmname*\POL@isolz@IntervalIndex\endcsname
+ \xint_stop_atfirstoftwo
+ \fi
+ \begingroup\xintglobaldefstrue
+ % skip some overhead of \xintdefvar...
+ % Let me repeat: ATTENTION to change of internal format at xint 1.4
+ \XINT_expr_defvar_one{\POL@sturmname L_\POL@isolz@IntervalIndex}%
+ {{\POL@IsoLeft@rawout}}%
+ \XINT_expr_defvar_one{\POL@sturmname R_\POL@isolz@IntervalIndex}%
+ {{\POL@IsoRight@rawout}}%
+ % added at 0.7
+ \XINT_expr_defvar_one{\POL@sturmname Z_\POL@isolz@IntervalIndex _isknown}%
+ {{\ifnum\POL@IsoRightSign=\z@ 1\else 0\fi}}%
+ \endgroup
+}%
+%% \PolRefineInterval
+%% ATTENTION TO xint 1.4 INTERNAL CHANGES
+\def\POL@xintexprGetVar#1{\expandafter\expandafter\expandafter\xint_firstofone
+ \csname XINT_expr_varvalue_#1\endcsname}%
+% attention, also used by \POL@findrat@loop@a
+\def\POL@get@IsoLeft@rawin{%
+ \edef\POL@IsoLeft@rawin
+ {\POL@xintexprGetVar{\POL@sturmname L_\POL@isolz@IntervalIndex}}%
+}%
+% attention, also used by \POL@findrat@loop@a
+\def\POL@get@IsoRight@rawin{%
+ \edef\POL@IsoRight@rawin
+ {\POL@xintexprGetVar{\POL@sturmname R_\POL@isolz@IntervalIndex}}%
+}%
+% attention, also used by \POL@findrat@loop@a
+\def\POL@get@Int@aux #1/1[#2]#3#4{\edef#3{\xintDSH{#4-#2}{#1}}}%
+\def\POL@get@IsoLeft@Int{%
+ \expandafter\POL@get@Int@aux\POL@IsoLeft@rawin\POL@IsoLeft@Int\POL@isolz@E
+}%
+\def\PolRefineInterval{\POL@ifstar\POL@srefine@start\POL@refine@start}%
+\def\POL@refine@start{%
+ \POL@chkopt\POL@oPOL@refine@start[1]%
+}%
+\def\POL@oPOL@refine@start[#1]#2#3{%
+ \edef\POL@isolz@IntervalIndex{\the\numexpr#3}%
+ \edef\POL@sturmname{#2}%
+ \expandafter\POL@refine@sharedbody\expandafter
+ {\expandafter\POL@refine@loop\expandafter{\the\numexpr#1}}%
+}%
+\def\POL@srefine@start#1#2{%
+ \edef\POL@isolz@IntervalIndex{\the\numexpr#2}%
+ \edef\POL@sturmname{#1}%
+ \POL@refine@sharedbody
+ {\let\POL@refine@left@next\POL@refine@main % we want to recurse if needed
+ \let\POL@refine@right@next\POL@refine@main % we want to recurse if needed
+ \POL@refine@main}%
+}%
+\def\POL@refine@sharedbody#1{%
+ \POL@get@IsoLeft@rawin
+ \edef\POL@IsoLeftSign
+ {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoLeft@rawin}}}%
+ \ifnum\POL@IsoLeftSign=\z@
+ % do nothing if that interval was already a singleton
+ \else
+ % else both end-points are not roots and there is a single one in-between
+ \POL@get@IsoRight@rawin
+ \edef\POL@IsoRightSign{\the\numexpr-\POL@IsoLeftSign}%
+ \edef\POL@isolz@E{\expandafter\POL@refine@getE
+ % je pense que le xintrez ici est superflu
+ \romannumeral0\xintrez{\xintSub{\POL@IsoRight@rawin}{\POL@IsoLeft@rawin}}}%
+ \POL@get@IsoLeft@Int
+ \edef\POL@IsoRight@Int{\xintInc{\POL@IsoLeft@Int}}%
+ #1%
+ \POL@refine@storeleftandright % \POL@IsoRightSign not zero
+ \fi
+}%
+\def\POL@refine@loop#1{%
+ \let\POL@refine@left@next \empty % no recursion at end sub-intervals
+ \let\POL@refine@right@next\empty
+ \xintiloop[1+1]
+ \POL@refine@main
+ \ifnum\POL@IsoRightSign=\z@
+ \expandafter\xintbreakiloop
+ \fi
+ \ifnum\xintiloopindex<#1
+ \repeat
+}%
+\def\POL@refine@main{%
+ \edef\POL@isolz@E{\the\numexpr\POL@isolz@E-\@ne}%
+ \edef\POL@IsoLeft@Int{\xintDSL{\POL@IsoLeft@Int}}%
+ \edef\POL@IsoRight@Int{\xintDSL{\POL@IsoRight@Int}}%
+ \let\POL@@IsoRight@Int\POL@IsoRight@Int
+ \let\POL@@IsoRightSign\POL@IsoRightSign
+ \edef\POL@IsoRight@Int{\xintInc{\POL@IsoLeft@Int}}%
+ \edef\POL@IsoRightSign
+ {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}%
+ \ifnum\POL@IsoRightSign=\z@
+ \let\POL@IsoLeft@Int\POL@IsoRight@Int % root at 1
+ \def\POL@IsoLeftSign{0}%
+ \let\POL@next\empty
+ \else
+ \ifnum\POL@IsoRightSign=\POL@@IsoRightSign\space
+ \let\POL@next\POL@refine@left@next % may be \empty or \POL@refine@main for recursion
+ \let\POL@refine@right@next\empty
+ \else
+ \let\POL@IsoLeft@Int\POL@IsoRight@Int
+ \edef\POL@IsoRight@Int{\xintDec{\POL@@IsoRight@Int}}%
+ \edef\POL@IsoRightSign
+ {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}%
+ \ifnum\POL@IsoRightSign=\z@
+ \let\POL@IsoLeft@Int\POL@IsoRight@Int % root at 9
+ \def\POL@IsoLeftSign{0}%
+ \let\POL@next\empty
+ \else
+ \ifnum\POL@IsoRightSign=\POL@@IsoRightSign\space
+ \let\POL@next\POL@refine@doonce
+ \else
+ \let\POL@IsoLeft@Int\POL@IsoRight@Int
+ \let\POL@IsoRight@Int\POL@@IsoRight@Int
+ \let\POL@IsoRightSign\POL@@IsoRightSign
+ \let\POL@next\POL@refine@right@next
+ \let\POL@refine@left@next\empty
+ \fi
+ \fi
+ \fi\fi
+ \POL@next
+}%
+% lacking pre-defined xintfrac macro here (such as an \xintRawExponent)
+\def\POL@refine@getE#1[#2]{#2}% \xintREZ already applied, for safety
+%
+%
+\def\PolIntervalWidth#1#2{%
+% le \xintRez est à cause des E positifs, car trailing zéros explicites
+% si je travaillais à partir des variables xintexpr directement ne devrait
+% pas être nécessaire, mais trop fragile par rapport à chgt internes possibles
+ \romannumeral0\xintrez{\xintSub{\@nameuse{POL_ZR#1*}{#2}}%
+ {\@nameuse{POL_ZL#1*}{#2}}}
+}%
+\def\PolEnsureIntervalLengths#1#2{% #1 = Sturm chain name,
+ % localize roots in intervals of length at most 10^{#2}
+ \edef\POL@sturmname{#1}%
+ \edef\POL@ensure@targetE{\the\numexpr#2}%
+ \edef\POL@nbofroots{\csname POL_ZL\POL@sturmname*0\endcsname}%
+ \ifnum\POL@nbofroots>\z@
+ \expandafter\POL@ensureintervallengths
+ \fi
+}%
+\def\POL@ensureintervallengths{%
+ \POL@count\z@
+ % \POL@count used by \POL@sturmchain@getSV@at but latter not used
+ \xintloop
+ \advance\POL@count\@ne
+ \edef\POL@isolz@IntervalIndex{\the\POL@count}%
+ \POL@ensure@one
+ \ifnum\POL@nbofroots>\POL@count
+ \repeat
+}%
+\def\PolEnsureIntervalLength#1#2#3{% #1 = Sturm chain name,
+ % #2 = index of interval
+ % localize roots in intervals of length at most 10^{#3}
+ \edef\POL@sturmname{#1}%
+ \edef\POL@ensure@targetE{\the\numexpr#3}%
+ \edef\POL@isolz@IntervalIndex{\the\numexpr#2}%
+% peut-être autoriser -1, -2, ... ?
+ \ifnum\POL@isolz@IntervalIndex>\z@
+% 0.7, add this safeguard but attention means this structure must be in place
+ \ifnum\csname POL_ZL\POL@sturmname*0\endcsname>\z@
+% je ne fais pas les \expandafter mais je préfèrerais ne pas être à l'intérieur
+ \POL@ensure@one
+ \fi
+ \fi
+}%
+\def\POL@ensure@one{%
+ \POL@get@IsoLeft@rawin
+ \POL@get@IsoRight@rawin
+ \edef\POL@ensure@delta{\xintREZ{\xintSub{\POL@IsoRight@rawin}{\POL@IsoLeft@rawin}}}%
+ \xintiiifZero{\POL@ensure@delta}
+ {}
+ {\edef\POL@isolz@E{\expandafter\POL@refine@getE\POL@ensure@delta}%
+ \POL@get@IsoLeft@Int
+ \edef\POL@IsoRight@Int{\xintInc{\POL@IsoLeft@Int}}%
+ \ifnum\POL@isolz@E>\POL@ensure@targetE\space
+ \edef\POL@IsoLeftSign
+ {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoLeft@raw}}}%
+ % at start left and right are not roots, and values of opposite signs
+ % \edef\POL@IsoRightSign{\the\numexpr-\POL@IsoLeftSign}%
+ \xintloop
+ \POL@ensure@Eloopbody % decreases E by one at each iteration
+ % if separation level is still too coarse we recurse at deeper level
+ \ifnum\POL@isolz@E>\POL@ensure@targetE\space
+ \repeat
+ % will check if right is at a zero, it needs \POL@IsoRightSign set up
+ \POL@refine@storeleftandright
+ \fi
+ }%
+}%
+\def\POL@ensure@Eloopbody {%
+ \edef\POL@isolz@E{\the\numexpr\POL@isolz@E-\@ne}%
+ \edef\POL@IsoLeft@Int{\xintDSL{\POL@IsoLeft@Int}}%
+ % this will loop at most ten times
+ \xintloop
+ \edef\POL@IsoRight@Int{\xintInc{\POL@IsoLeft@Int}}%
+ \edef\POL@IsoRightSign
+ {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}%
+ % if we have found a zero at right boundary the \ifnum test will fail
+ % and we exit the loop
+ % else we exit the loop if sign at right boundary is opposite of
+ % sign at left boundary (the latter is +1 or -1, never 0)
+ % this is a bit wasteful if we go ten times to the right, because
+ % we know that there the sign will be opposite, evaluation was superfluous
+ \ifnum\POL@IsoLeftSign=\POL@IsoRightSign\space
+ \let\POL@IsoLeft@Int\POL@IsoRight@Int
+ \repeat
+ % check for case when we exited the inner loop because we actually
+ % found a zero, then we force exit from the main (E decreasing) loop
+ \ifnum\POL@IsoRightSign=\z@
+ \expandafter\xintbreakloop
+ \fi
+}%
+%
+%% \PolPrintIntervals
+\catcode`_ 8
+\catcode`& 4
+\def\PolPrintIntervals{\POL@ifstar{\PolPrintIntervals@@}{\PolPrintIntervals@}}%
+% As explained in the docs, this is an example of customization so is not
+% itself customizable, apart from redefining it entirely!
+\def\PolPrintIntervals@@{%
+ \begingroup
+ \def\POL@AfterPrintIntervals{\endgroup}%
+ \let\PolPrintIntervalsPrintExactZero\POL@@PrintIntervalsPrintExactZero
+ \let\PolPrintIntervalsUnknownRoot\POL@@PrintIntervalsUnknownRoot
+ \let\PolPrintIntervalsKnownRoot\POL@@PrintIntervalsKnownRoot
+\ifdefined\array
+ \def\arraystretch{2}%
+ \def\PolPrintIntervalsBeginEnv{\[\begin{array}{cl}}%\]
+ \def\PolPrintIntervalsEndEnv{\end{array}\]}%
+\else
+ \def\PolPrintIntervalsBeginEnv{$$\tabskip0pt plus 1000pt minus 1000pt
+ \halign to\displaywidth\bgroup
+ \hfil\vrule height 2\ht\strutbox
+ depth 2\dp\strutbox
+ width \z@
+ $####$\tabskip6pt&$####$\hfil
+ \tabskip0pt plus 1000pt minus 1000pt\cr}%$$
+ \def\PolPrintIntervalsEndEnv{\crcr\egroup$$}%$$
+\fi
+ \PolPrintIntervals@
+}%
+\def\PolPrintIntervals@{%
+ \POL@chkopt\POL@oPolPrintIntervals@[Z]%
+}%
+\def\POL@oPolPrintIntervals@[#1]#2{%
+ \def\PolPrintIntervalsTheVar{#1}%
+ \def\PolPrintIntervalsTheSturmName{#2}%
+ \ifnum\@nameuse{POL_ZL#2*}{0}=\z@
+ \PolPrintIntervalsNoRealRoots
+ \else
+ \gdef\PolPrintIntervalsTheIndex{1}%
+ \POL@PrintIntervals@DoDefs
+ \begingroup\edef\POL@tmp{\endgroup
+ \unexpanded\expandafter{\PolPrintIntervalsBeginEnv}%
+ \unexpanded\expandafter{\POL@PrintIntervals@Loop}%
+ \unexpanded\expandafter{\PolPrintIntervalsEndEnv}%
+ }\POL@tmp
+ \fi
+ \POL@AfterPrintIntervals
+ \def\PolPrintIntervalsTheVar{#1}%
+ \def\PolPrintIntervalsTheSturmName{#2}%
+}%
+\let\POL@AfterPrintIntervals\empty
+\let\PolPrintIntervalsNoRealRoots\empty
+\def\PolPrintIntervalsArrayStretch{1}%
+\ifdefined\array
+ \def\PolPrintIntervalsBeginEnv{\[\begin{array}{rcccl}}%
+ \def\PolPrintIntervalsEndEnv{\end{array}\]}%
+\else
+ \def\PolPrintIntervalsBeginEnv
+ {$$\tabskip 0pt plus 1000pt minus 1000pt
+ \halign to\displaywidth\bgroup
+ \hfil\vrule height\PolPrintIntervalsArrayStretch\ht\strutbox
+ depth \PolPrintIntervalsArrayStretch\dp\strutbox
+ width \z@
+ $##$\tabskip 6pt &\hfil $##$\hfil &\hfil $##$\hfil &\hfil $##$\hfil &$##$\hfil
+ \tabskip 0pt plus 1000pt minus 1000pt \cr
+ }%$$
+ \def\PolPrintIntervalsEndEnv{\crcr\egroup$$}%$$
+\fi
+\def\PolPrintIntervalsKnownRoot{%
+ &&\PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}%
+ &=&\PolPrintIntervalsPrintExactZero
+}%
+\def\PolPrintIntervalsUnknownRoot{%
+ \PolPrintIntervalsPrintLeftEndPoint&<&%
+ \PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}&<&%
+ \PolPrintIntervalsPrintRightEndPoint
+}%
+\def\PolPrintIntervalsPrintExactZero {\PolPrintIntervalsTheLeftEndPoint}%
+\def\PolPrintIntervalsPrintLeftEndPoint {\PolPrintIntervalsTheLeftEndPoint}%
+\def\PolPrintIntervalsPrintRightEndPoint{\PolPrintIntervalsTheRightEndPoint}%
+%
+\ifdefined\mbox
+\def\PolPrintIntervalsPrintMultiplicity{(\mbox{mult. }\PolPrintIntervalsTheMultiplicity)}%
+\else
+\def\PolPrintIntervalsPrintMultiplicity{(\hbox{mult. }\PolPrintIntervalsTheMultiplicity)}%
+\fi
+%
+\def\POL@@PrintIntervalsKnownRoot{%
+ \PolPrintIntervalsPrintMultiplicity&%
+ \PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}=%
+ \PolPrintIntervalsPrintExactZero
+}%
+\ifdefined\frac
+\def\POL@@PrintIntervalsPrintExactZero{%
+ \displaystyle
+ \xintSignedFrac{\PolPrintIntervalsTheLeftEndPoint}%
+}%
+\else
+\def\POL@@PrintIntervalsPrintExactZero{%
+ \displaystyle
+ \xintSignedFwOver{\PolPrintIntervalsTheLeftEndPoint}%
+}%
+\fi
+\def\POL@@PrintIntervalsUnknownRoot{%
+ \PolPrintIntervalsPrintMultiplicity&%
+ \xintifSgn{\PolPrintIntervalsTheLeftEndPoint}%
+ {\xintifSgn{\PolPrintIntervalsTheRightEndPoint}
+ {\PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}=%
+ \PolPrintIntervalsPrintRightEndPoint\dots}%
+ {0>\PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}>%
+ \PolPrintIntervalsPrintLeftEndPoint}%
+ {\PolErrorThisShouldNotHappenPleaseReportToAuthorA}}%
+ {\xintifSgn{\PolPrintIntervalsTheRightEndPoint}
+ {\PolErrorThisShouldNotHappenPleaseReportToAuthorB}%
+ {\PolErrorThisShouldNotHappenPleaseReportToAuthorC}%
+ {0<\PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}<%
+ \PolPrintIntervalsPrintRightEndPoint}}%
+ {\xintifSgn{\PolPrintIntervalsTheRightEndPoint}
+ {\PolErrorThisShouldNotHappenPleaseReportToAuthorD}%
+ {\PolErrorThisShouldNotHappenPleaseReportToAuthorE}%
+ {\PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}=%
+ \PolPrintIntervalsPrintLeftEndPoint\dots}}%
+}%
+\catcode`& 7
+\catcode`_ 11
+\def\POL@PrintIntervals@Loop#1{%
+\def\POL@PrintIntervals@Loop{%
+ \POL@SturmIfZeroExactlyKnown\PolPrintIntervalsTheSturmName
+ \PolPrintIntervalsTheIndex
+ \PolPrintIntervalsKnownRoot
+ \PolPrintIntervalsUnknownRoot
+ \xdef\PolPrintIntervalsTheIndex{\the\numexpr\PolPrintIntervalsTheIndex+\@ne}%
+ \unless\ifnum\PolPrintIntervalsTheIndex>
+ \@nameuse{POL_ZL\PolPrintIntervalsTheSturmName*0}
+ \POL@PrintIntervals@DoDefs
+ \xint_afterfi{#1\POL@PrintIntervals@Loop}%
+ \fi
+}}%
+\ifdefined\array\POL@PrintIntervals@Loop{\\}\else\POL@PrintIntervals@Loop{\cr}\fi
+\def\POL@PrintIntervals@DoDefs{%
+ \xdef\PolPrintIntervalsTheLeftEndPoint{%
+ \csname POL_ZL\PolPrintIntervalsTheSturmName*\PolPrintIntervalsTheIndex
+ \endcsname
+ }%
+ \xdef\PolPrintIntervalsTheRightEndPoint{%
+ \csname POL_ZR\PolPrintIntervalsTheSturmName*\PolPrintIntervalsTheIndex
+ \endcsname
+ }%
+ \xdef\PolPrintIntervalsTheMultiplicity{%
+ \ifcsname POL_ZM\PolPrintIntervalsTheSturmName*\PolPrintIntervalsTheIndex
+ \endcsname
+ \csname POL_ZM\PolPrintIntervalsTheSturmName*\PolPrintIntervalsTheIndex
+ \endcsname
+ \else
+ ?% or use 0 ?
+ \fi
+ }%
+}%
+%
+%% Expandable interface
+%
+\def\PolSturmIfZeroExactlyKnown#1#2{% #1 = sturmname, #2=index
+ \romannumeral0\csname POL_ZK#1*\endcsname{#2}%
+}%
+\def\POL@SturmIfZeroExactlyKnown#1#2{% #1 = sturmname, #2=index
+ \romannumeral0\csname POL_ZK#1*\the\numexpr#2\endcsname
+}%
+\def\PolSturmIsolatedZeroMultiplicity#1#2{%
+ \romannumeral`&&@\csname POL_ZM#1*\endcsname{#2}%
+}%
+\def\PolSturmIsolatedZeroLeft#1#2{%
+ \romannumeral`&&@\csname POL_ZL#1*\endcsname{#2}%
+}%
+\def\PolSturmIsolatedZeroRight#1#2{%
+ \romannumeral`&&@\csname POL_ZR#1*\endcsname{#2}%
+}%
+\def\PolSturmNbOfIsolatedZeros#1{%
+ \romannumeral`&&@\csname POL_ZL#1*0\endcsname
+}%
+\def\PolSturmRationalRoot#1#2{%
+ \romannumeral`&&@\csname POL_ZL#1*%
+ \csname POL_RI#1*\endcsname{#2}\endcsname
+}%
+\def\PolSturmRationalRootIndex#1#2{%
+ \romannumeral`&&@\csname POL_RI#1*\endcsname{#2}%
+}%
+\def\PolSturmRationalRootMultiplicity#1#2{%
+ \romannumeral`&&@\csname POL_ZM#1%
+ *\csname POL_RI#1*\endcsname{#2}\endcsname
+}%
+\def\PolSturmNbOfRationalRoots#1{%
+ \romannumeral`&&@\csname POL_RI#1*0\endcsname
+}%
+\def\PolSturmNbOfRationalRootsWithMultiplicities#1{%
+% means the \POL@norr must not have been changed in-between...
+ \the\numexpr\PolDegree{#1}-\PolDegree{#1\POL@norr}\relax
+}%
+\def\PolSturmIntervalIndex#1#2#3{\the\numexpr\POL@eval@fork
+ #2\PolSturmIntervalIndexAt
+ \At\PolSturmIntervalIndexAtExpr\krof {#1}{#3}%
+}%
+\def\PolSturmIntervalIndexAtExpr#1#2{%
+ \PolSturmIntervalIndexAt{#1}{\xinttheexpr#2\relax}%
+}%
+% ! is of catcode 11 in all of polexpr
+\def\PolSturmIntervalIndexAt#1#2{%
+ \expandafter\POL@sturm@index@at\romannumeral`&&@#2!{#1}\xint_bye\relax
+}%
+\def\POL@sturm@index@at#1!#2%
+{%
+ \expandafter\POL@sturm@index@at@iloop
+ \romannumeral`&&@\PolSturmNbOfIsolatedZeros{#2}!{#2}{#1}%
+}%
+% implementation is sub-optimal as it should use some kind of binary tree
+% search rather than comparing to the intervals from right to left as here
+\def\POL@sturm@index@at@iloop #1!%
+{%
+ \ifnum #1=\z@ 0\expandafter\xint_bye\fi
+ \POL@sturm@index@at@iloop@a #1!%
+}%
+\def\POL@sturm@index@at@iloop@a #1!#2#3%
+{% #1 = index, #2 = sturmname, #3 value
+ \PolSturmIfZeroExactlyKnown{#2}{#1}
+ {\xintifCmp{#3}{\POL@xintexprGetVar{#2L_#1}}%
+ {}%
+ {#1\xint_bye}%
+ {0\xint_bye}%
+ }%
+ {\xintifGt{#3}{\POL@xintexprGetVar{#2L_#1}}%
+ {\xintifLt{#3}{\POL@xintexprGetVar{#2R_#1}}%
+ {#1\xint_bye}%
+ {0\xint_bye}%
+ }%
+ {}%
+ }%
+ % attention that catcode of ! is 11 in polexpr.sty
+ \expandafter\POL@sturm@index@at@iloop\the\numexpr#1-\@ne !{#2}{#3}%
+}%
+%
+\def\POL@leq@fork#1\LessThanOrEqualTo#2#3\krof{#2}%
+\def\PolSturmNbOfRootsOf#1#2#3{\romannumeral`&&@\POL@leq@fork
+ #2\PolNbOfRootsLessThanOrEqualTo
+ \LessThanOrEqualTo\PolNbOfRootsLessThanOrEqualToExpr\krof {#1}{#3}%
+}%
+\def\PolNbOfRootsLessThanOrEqualToExpr#1#2
+ {\PolNbOfRootsLessThanOrEqualTo{#1}{\xinttheexpr#2\relax}}%
+\def\PolNbOfRootsLessThanOrEqualTo#1{%
+ \ifnum\PolSturmNbOfIsolatedZeros{#1}=\z@
+ \expandafter\xint_firstofthree\expandafter0%
+ \else
+ \expandafter\PolNbOfRootsLessThanOrEqualTo@%
+ \fi {#1}%
+}%
+\def\PolNbOfRootsLessThanOrEqualTo@ #1#2%
+{%
+ \expandafter\POL@nbofrootsleq@prep\romannumeral`&&@#2!{#1}%
+}%
+\def\POL@nbofrootsleq@prep#1!#2%
+{%
+ \expandafter\POL@nbofrootsleq@iloop\expandafter 1\expandafter !%
+ \romannumeral0\xintsgn{\POL@eval{#2_0}{#1}}!%
+ #1!{#2}%
+}%
+\def\POL@nbofrootsleq@iloop#1!#2!#3!#4%
+{% #1 = index, #2 = sign of evaluation at value, #3 = value, #4 = sturmname
+ \xintifCmp{#3}{\POL@xintexprGetVar{#4L_#1}}%
+ {\POL@nbofrootsleq@return #1-\@ne !}%
+ {\POL@nbofrootsleq@return
+ \PolSturmIfZeroExactlyKnown{#4}{#1}{#1}{#1-\@ne}!%
+ }%
+ % in third branch we are sure that if root is exactly known
+ % the test \xintifLt will be negative
+ {\xintifLt{#3}{\POL@xintexprGetVar{#4R_#1}}%
+ {\POL@nbofrootsleq@return
+ #1\ifnum#2=\xintSgn{\POL@eval{#4_0}{\POL@xintexprGetVar{#4L_#1}}}
+ -\@ne\fi !%
+ }%
+ {\ifnum#1=\PolSturmNbOfIsolatedZeros{#4}
+ \expandafter\POL@nbofrootsleq@rightmost
+ \fi \expandafter\POL@nbofrootsleq@iloop \the\numexpr\@ne+%
+ }%
+ }%
+ #1!#2!#3!{#4}%
+}%
+\def\POL@nbofrootsleq@return #1!#2!#3!#4!#5{\the\numexpr #1\relax}%
+\def\POL@nbofrootsleq@rightmost\expandafter\POL@nbofrootsleq@iloop
+ \the\numexpr\@ne+#1!#2!#3!#4{#1}%
+%
+\def\PolSturmNbWithMultOfRootsOf#1#2#3{%
+ \the\numexpr0\POL@leq@fork
+ #2\PolNbWithMultOfRootsLessThanOrEqualTo
+ \LessThanOrEqualTo\PolNbWithMultOfRootsLessThanOrEqualToExpr\krof {#1}{#3}%
+}%
+\def\PolNbWithMultOfRootsLessThanOrEqualToExpr#1#2{%
+ \PolNbWithMultOfRootsLessThanOrEqualTo{#1}{\xinttheexpr#2\relax}%
+}%
+\def\PolNbWithMultOfRootsLessThanOrEqualTo#1{%
+ \ifnum\PolSturmNbOfIsolatedZeros{#1}=\z@
+ \expandafter\POL@nbwmofroots@noroots
+ \else
+ \expandafter\PolNbWithMultOfRootsLessThanOrEqualTo@%
+ \fi {#1}%
+}%
+\def\POL@nbwmofroots@noroots#1#2{\relax}%
+\def\PolNbWithMultOfRootsLessThanOrEqualTo@ #1#2%
+{%
+ \expandafter\POL@nbwmofrootsleq@prep\romannumeral`&&@#2!{#1}%
+}%
+\def\POL@nbwmofrootsleq@prep#1!#2%
+{%
+ \expandafter\POL@nbwmofrootsleq@iloop\expandafter 1\expandafter !%
+ \romannumeral0\xintsgn{\POL@eval{#2_0}{#1}}!%
+ #1!{#2}%
+}%
+\def\POL@nbwmofrootsleq@iloop#1!#2!#3!#4%
+{% #1 = index, #2 = sign of evaluation at value, #3 = value, #4 = sturmname
+ \xintifCmp{#3}{\POL@xintexprGetVar{#4L_#1}}%
+ {\POL@nbwmofrootsleq@return !}%
+ {\POL@nbwmofrootsleq@return
+ \PolSturmIfZeroExactlyKnown{#4}{#1}%
+ {+\PolSturmIsolatedZeroMultiplicity{#4}{#1}}{}!%
+ }%
+ % in third branch we are sure that if root is exactly known
+ % the test \xintifLt will be negative
+ {\xintifLt{#3}{\POL@xintexprGetVar{#4R_#1}}%
+ {\POL@nbwmofrootsleq@return
+ \unless
+ \ifnum#2=\xintSgn{\POL@eval{#4_0}{\POL@xintexprGetVar{#4L_#1}}}
+ +\PolSturmIsolatedZeroMultiplicity{#4}{#1}\fi !%
+ }%
+ {+\PolSturmIsolatedZeroMultiplicity{#4}{#1}%
+ \ifnum#1=\PolSturmNbOfIsolatedZeros{#4}
+ \expandafter\POL@nbwmofrootsleq@return\expandafter !%
+ \fi
+ \expandafter\POL@nbwmofrootsleq@iloop \the\numexpr\@ne+%
+ }%
+ }%
+ #1!#2!#3!{#4}%
+}%
+\def\POL@nbwmofrootsleq@return #1!#2!#3!#4!#5{#1\relax}%
+\endinput
diff --git a/macros/generic/xint/CHANGES.html b/macros/generic/xint/CHANGES.html
index 32fcfbe4ee..20b940dad7 100644
--- a/macros/generic/xint/CHANGES.html
+++ b/macros/generic/xint/CHANGES.html
@@ -4,7 +4,7 @@
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
- <meta name="author" content="xint 1.4c" />
+ <meta name="author" content="xint 1.4d" />
<title>CHANGE LOG</title>
<style type="text/css">
code{white-space: pre-wrap;}
@@ -25,47 +25,51 @@
<body>
<header>
<h1 class="title">CHANGE LOG</h1>
-<p class="author">xint 1.4c</p>
-<p class="date">2021/02/20</p>
+<p class="author">xint 1.4d</p>
+<p class="date">2021/03/29</p>
</header>
<nav id="TOC">
<ul>
-<li><a href="#c-20210220"><code>1.4c (2021/02/20)</code></a><ul>
+<li><a href="#d-20210329"><code>1.4d (2021/03/29)</code></a><ul>
+<li><a href="#breaking-changes">Breaking changes</a></li>
<li><a href="#bug-fixes">Bug fixes</a></li>
</ul></li>
+<li><a href="#c-20210220"><code>1.4c (2021/02/20)</code></a><ul>
+<li><a href="#bug-fixes-1">Bug fixes</a></li>
+</ul></li>
<li><a href="#b-20200225"><code>1.4b (2020/02/25)</code></a><ul>
<li><a href="#future">Future</a></li>
<li><a href="#new-features">New features</a></li>
-<li><a href="#bug-fixes-1">Bug fixes</a></li>
+<li><a href="#bug-fixes-2">Bug fixes</a></li>
</ul></li>
<li><a href="#a-20200219"><code>1.4a (2020/02/19)</code></a><ul>
-<li><a href="#breaking-changes">Breaking changes</a></li>
+<li><a href="#breaking-changes-1">Breaking changes</a></li>
<li><a href="#new-features-1">New features</a></li>
-<li><a href="#bug-fixes-2">Bug fixes</a></li>
+<li><a href="#bug-fixes-3">Bug fixes</a></li>
</ul></li>
<li><a href="#section"><code>1.4 (2020/01/31)</code></a><ul>
-<li><a href="#breaking-changes-1">Breaking changes</a></li>
+<li><a href="#breaking-changes-2">Breaking changes</a></li>
<li><a href="#improvements-and-new-features">Improvements and new features</a></li>
-<li><a href="#bug-fixes-3">Bug fixes</a></li>
+<li><a href="#bug-fixes-4">Bug fixes</a></li>
<li><a href="#todo">TODO</a></li>
</ul></li>
<li><a href="#f-20190910"><code>1.3f (2019/09/10)</code></a><ul>
<li><a href="#improvements-and-new-features-1">Improvements and new features</a></li>
-<li><a href="#bug-fixes-4">Bug fixes</a></li>
+<li><a href="#bug-fixes-5">Bug fixes</a></li>
</ul></li>
<li><a href="#e-20190405"><code>1.3e (2019/04/05)</code></a><ul>
-<li><a href="#breaking-changes-2">Breaking changes</a></li>
+<li><a href="#breaking-changes-3">Breaking changes</a></li>
<li><a href="#improvements-and-new-features-2">Improvements and new features</a></li>
-<li><a href="#bug-fixes-5">Bug fixes</a></li>
+<li><a href="#bug-fixes-6">Bug fixes</a></li>
</ul></li>
<li><a href="#d-20190106"><code>1.3d (2019/01/06)</code></a><ul>
-<li><a href="#breaking-changes-3">Breaking changes</a></li>
+<li><a href="#breaking-changes-4">Breaking changes</a></li>
<li><a href="#improvements-and-new-features-3">Improvements and new features</a></li>
-<li><a href="#bug-fixes-6">Bug fixes</a></li>
+<li><a href="#bug-fixes-7">Bug fixes</a></li>
</ul></li>
<li><a href="#c-20180617"><code>1.3c (2018/06/17)</code></a><ul>
<li><a href="#improvements-and-new-features-4">Improvements and new features</a></li>
-<li><a href="#bug-fixes-7">Bug fixes</a></li>
+<li><a href="#bug-fixes-8">Bug fixes</a></li>
</ul></li>
<li><a href="#b-20180518"><code>1.3b (2018/05/18)</code></a><ul>
<li><a href="#improvements-and-new-features-5">Improvements and new features</a></li>
@@ -73,85 +77,85 @@
<li><a href="#a-20180307"><code>1.3a (2018/03/07)</code></a><ul>
<li><a href="#removed">Removed</a></li>
<li><a href="#improvements-and-new-features-6">Improvements and new features</a></li>
-<li><a href="#bug-fixes-8">Bug fixes</a></li>
+<li><a href="#bug-fixes-9">Bug fixes</a></li>
</ul></li>
<li><a href="#section-1"><code>1.3 (2018/03/01)</code></a><ul>
-<li><a href="#breaking-changes-4">Breaking changes</a></li>
+<li><a href="#breaking-changes-5">Breaking changes</a></li>
<li><a href="#improvements-and-new-features-7">Improvements and new features</a></li>
</ul></li>
<li><a href="#q-20180206"><code>1.2q (2018/02/06)</code></a><ul>
<li><a href="#improvements-and-new-features-8">Improvements and new features</a></li>
-<li><a href="#bug-fixes-9">Bug fixes</a></li>
+<li><a href="#bug-fixes-10">Bug fixes</a></li>
</ul></li>
<li><a href="#p-20171205"><code>1.2p (2017/12/05)</code></a><ul>
-<li><a href="#breaking-changes-5">Breaking changes</a></li>
+<li><a href="#breaking-changes-6">Breaking changes</a></li>
<li><a href="#improvements-and-new-features-9">Improvements and new features</a></li>
-<li><a href="#bug-fixes-10">Bug fixes</a></li>
+<li><a href="#bug-fixes-11">Bug fixes</a></li>
</ul></li>
<li><a href="#o-20170829"><code>1.2o (2017/08/29)</code></a><ul>
-<li><a href="#breaking-changes-6">Breaking changes</a></li>
+<li><a href="#breaking-changes-7">Breaking changes</a></li>
<li><a href="#deprecated">Deprecated</a></li>
</ul></li>
<li><a href="#n-20170806"><code>1.2n (2017/08/06)</code></a><ul>
-<li><a href="#breaking-changes-7">Breaking changes</a></li>
+<li><a href="#breaking-changes-8">Breaking changes</a></li>
<li><a href="#improvements-and-new-features-10">Improvements and new features</a></li>
</ul></li>
<li><a href="#m-20170731"><code>1.2m (2017/07/31)</code></a><ul>
-<li><a href="#breaking-changes-8">Breaking changes</a></li>
+<li><a href="#breaking-changes-9">Breaking changes</a></li>
<li><a href="#improvements-and-new-features-11">Improvements and new features</a></li>
-<li><a href="#bug-fixes-11">Bug fixes</a></li>
+<li><a href="#bug-fixes-12">Bug fixes</a></li>
</ul></li>
<li><a href="#l-20170726"><code>1.2l (2017/07/26)</code></a><ul>
<li><a href="#removed-1">Removed</a></li>
<li><a href="#improvements-and-new-features-12">Improvements and new features</a></li>
-<li><a href="#bug-fixes-12">Bug fixes</a></li>
+<li><a href="#bug-fixes-13">Bug fixes</a></li>
</ul></li>
<li><a href="#k-20170106"><code>1.2k (2017/01/06)</code></a><ul>
-<li><a href="#breaking-changes-9">Breaking changes</a></li>
+<li><a href="#breaking-changes-10">Breaking changes</a></li>
<li><a href="#improvements-and-new-features-13">Improvements and new features</a></li>
-<li><a href="#bug-fixes-13">Bug fixes</a></li>
+<li><a href="#bug-fixes-14">Bug fixes</a></li>
</ul></li>
<li><a href="#j-20161222"><code>1.2j (2016/12/22)</code></a><ul>
<li><a href="#improvements-and-new-features-14">Improvements and new features</a></li>
-<li><a href="#bug-fixes-14">Bug fixes</a></li>
+<li><a href="#bug-fixes-15">Bug fixes</a></li>
</ul></li>
<li><a href="#i-20161213"><code>1.2i (2016/12/13)</code></a><ul>
-<li><a href="#breaking-changes-10">Breaking changes</a></li>
+<li><a href="#breaking-changes-11">Breaking changes</a></li>
<li><a href="#removed-2">Removed</a></li>
<li><a href="#improvements-and-new-features-15">Improvements and new features</a></li>
-<li><a href="#bug-fixes-15">Bug fixes</a></li>
+<li><a href="#bug-fixes-16">Bug fixes</a></li>
</ul></li>
<li><a href="#h-20161120"><code>1.2h (2016/11/20)</code></a><ul>
<li><a href="#improvements-and-new-features-16">Improvements and new features</a></li>
-<li><a href="#bug-fixes-16">Bug fixes</a></li>
+<li><a href="#bug-fixes-17">Bug fixes</a></li>
</ul></li>
<li><a href="#g-20160319"><code>1.2g (2016/03/19)</code></a><ul>
-<li><a href="#breaking-changes-11">Breaking changes</a></li>
+<li><a href="#breaking-changes-12">Breaking changes</a></li>
<li><a href="#improvements-and-new-features-17">Improvements and new features</a></li>
</ul></li>
<li><a href="#f-20160312"><code>1.2f (2016/03/12)</code></a><ul>
-<li><a href="#breaking-changes-12">Breaking changes</a></li>
+<li><a href="#breaking-changes-13">Breaking changes</a></li>
<li><a href="#improvements-and-new-features-18">Improvements and new features</a></li>
-<li><a href="#bug-fixes-17">Bug fixes</a></li>
+<li><a href="#bug-fixes-18">Bug fixes</a></li>
</ul></li>
<li><a href="#e-20151122"><code>1.2e (2015/11/22)</code></a><ul>
<li><a href="#improvements-and-new-features-19">Improvements and new features</a></li>
-<li><a href="#bug-fixes-18">Bug fixes</a></li>
+<li><a href="#bug-fixes-19">Bug fixes</a></li>
</ul></li>
<li><a href="#d-20151118"><code>1.2d (2015/11/18)</code></a><ul>
<li><a href="#improvements-and-new-features-20">Improvements and new features</a></li>
-<li><a href="#bug-fixes-19">Bug fixes</a></li>
+<li><a href="#bug-fixes-20">Bug fixes</a></li>
</ul></li>
<li><a href="#c-20151116"><code>1.2c (2015/11/16)</code></a><ul>
<li><a href="#improvements-and-new-features-21">Improvements and new features</a></li>
-<li><a href="#bug-fixes-20">Bug fixes</a></li>
+<li><a href="#bug-fixes-21">Bug fixes</a></li>
</ul></li>
<li><a href="#b-20151029"><code>1.2b (2015/10/29)</code></a><ul>
-<li><a href="#bug-fixes-21">Bug fixes</a></li>
+<li><a href="#bug-fixes-22">Bug fixes</a></li>
</ul></li>
<li><a href="#a-20151019"><code>1.2a (2015/10/19)</code></a><ul>
<li><a href="#improvements-and-new-features-22">Improvements and new features</a></li>
-<li><a href="#bug-fixes-22">Bug fixes</a></li>
+<li><a href="#bug-fixes-23">Bug fixes</a></li>
</ul></li>
<li><a href="#section-2"><code>1.2 (2015/10/10)</code></a><ul>
<li><a href="#removed-3">Removed</a></li>
@@ -161,11 +165,11 @@
<li><a href="#b-20150831"><code>1.1b (2015/08/31)</code></a></li>
<li><a href="#a-20141107"><code>1.1a (2014/11/07)</code></a></li>
<li><a href="#section-3"><code>1.1 (2014/10/28)</code></a><ul>
-<li><a href="#breaking-changes-13">Breaking changes</a></li>
+<li><a href="#breaking-changes-14">Breaking changes</a></li>
<li><a href="#removed-4">Removed</a></li>
<li><a href="#deprecated-1">Deprecated</a></li>
<li><a href="#improvements-and-new-features-24">Improvements and new features</a></li>
-<li><a href="#bug-fixes-23">Bug fixes</a></li>
+<li><a href="#bug-fixes-24">Bug fixes</a></li>
</ul></li>
<li><a href="#n-20140401"><code>1.09n (2014/04/01)</code></a></li>
<li><a href="#m-20140226"><code>1.09m (2014/02/26)</code></a></li>
@@ -193,13 +197,26 @@
<li><a href="#section-10"><code>1.0 (2013/03/28)</code></a></li>
</ul>
</nav>
-<pre><code>Source: xint.dtx 1.4c 2021/02/20 (doc 2021/02/20)
+<pre><code>Source: xint.dtx 1.4d 2021/03/29 (doc 2021/03/29)
Author: Jean-Francois Burnol
Info: Expandable operations on big integers, decimals, fractions
License: LPPL 1.3c</code></pre>
-<h2 id="c-20210220"><code>1.4c (2021/02/20)</code></h2>
+<h2 id="d-20210329"><code>1.4d (2021/03/29)</code></h2>
+<h3 id="breaking-changes">Breaking changes</h3>
+<ul>
+<li><p><code>quo()</code> and <code>rem()</code> in <code>\xintiiexpr/\xintiieval</code> renamed to <code>iquo()</code> and <code>irem()</code>.</p></li>
+<li><p>the output of <code>gcd()</code> and <code>lcm()</code> as applied to fractions is now always in lowest terms.</p></li>
+</ul>
<h3 id="bug-fixes">Bug fixes</h3>
<ul>
+<li><p>Ever since <code>1.3</code> the <code>quo()</code> and <code>rem()</code> functions in <code>\xintexpr</code> (not the ones in <code>\xintiiexpr</code>) were broken as their (officially deprecated) support macros had been removed! They had somewhat useless definitions anyway. They have now been officially removed from the syntax. Their siblings in <code>\xintiieval</code> were renamed to <code>iquo()</code> and <code>irem()</code>.</p></li>
+<li><p>Sadly, <code>gcd()</code> was broken in <code>\xintexpr</code> since <code>1.4</code>, if the first argument vanished. And <code>gcd()</code> was broken in <code>\xintiiexpr</code> since <code>1.3d</code> if <em>any</em> argument vanished. I did have a unit test! (which obviously was too limited …)</p>
+<p>Further, the <code>\xintGCDof</code> and <code>\xintLCMof</code> <strong>xintfrac</strong> macros were added at <code>1.4</code> but did not behave like other <strong>xintfrac</strong> macros with respect to parsing their arguments: e.g. <code>\xintGCDof{2}{03}</code> gave an unexpected non-numeric result.</p></li>
+<li><p>The <code>first()</code> and <code>last()</code> functions, if used as arguments to numerical functions such as <code>sqr()</code> inside an <code>\xintdeffunc</code> caused the defined function to be broken.</p></li>
+</ul>
+<h2 id="c-20210220"><code>1.4c (2021/02/20)</code></h2>
+<h3 id="bug-fixes-1">Bug fixes</h3>
+<ul>
<li>Fix <code>1.4</code> regression which broke syntax <code>varname(...)</code> which supposedly is allowed and inserts a tacit multiplication.</li>
</ul>
<h2 id="b-20200225"><code>1.4b (2020/02/25)</code></h2>
@@ -217,13 +234,13 @@ License: LPPL 1.3c</code></pre>
<li><p>Chaining of comparison operators (e.g. <code>x&lt;y&lt;z</code>) as in Python (but all comparisons are done even if one is found false) and l3fp.</p></li>
<li><p>It was possible since <code>1.4</code>’s <code>\xintFracToSciE</code> to configure the separator between mantissas and exponents in the output of <code>\xinteval</code> but strangely there was no way to customize the output of <code>\xintfloateval</code>. The added <code>\xintPFloatE</code> fixes this.</p></li>
</ul>
-<h3 id="bug-fixes-1">Bug fixes</h3>
+<h3 id="bug-fixes-2">Bug fixes</h3>
<ul>
<li><code>\xintieval{[D]...}</code> with a negative <code>D</code> (a feature added at <code>1.4a</code>) used erroneously a catcode 12 <code>e</code> in output, which moreover remained immuned to the <code>\xintFracToSciE</code> setting.</li>
</ul>
<h2 id="a-20200219"><code>1.4a (2020/02/19)</code></h2>
<p>All changes regard the <strong>xintexpr</strong> module.</p>
-<h3 id="breaking-changes">Breaking changes</h3>
+<h3 id="breaking-changes-1">Breaking changes</h3>
<ul>
<li>The macros implementing customization of <code>\xintthealign</code> have modified meanings and names.</li>
</ul>
@@ -233,13 +250,13 @@ License: LPPL 1.3c</code></pre>
<li><p>The optional argument <code>[D]</code> to <code>\xintieval/\xintiexpr</code> can be negative, with the same meaning as the non-negative case, i.e. rounding to an integer multiple of <code>10^(-D)</code>.</p>
<p>The same applies to the functions <code>trunc()</code> and <code>round()</code>. And to the <code>\xintTrunc</code>, <code>\xintRound</code>, <code>\xintiTrunc</code>, and <code>\xintiRound</code> macros of <strong>xintfrac</strong>.</p></li>
</ul>
-<h3 id="bug-fixes-2">Bug fixes</h3>
+<h3 id="bug-fixes-3">Bug fixes</h3>
<ul>
<li><p>Usage of <code>round()</code> and <code>trunc()</code> within <code>\xintdeffunc</code> got broken at <code>1.4</code>.</p></li>
<li><p><code>add()</code> and <code>mul()</code> were supposedly accepting the <code>omit</code>, <code>abort</code> and <code>break()</code> keywords since <code>1.4</code> but this was broken.</p></li>
</ul>
<h2 id="section"><code>1.4 (2020/01/31)</code></h2>
-<h3 id="breaking-changes-1">Breaking changes</h3>
+<h3 id="breaking-changes-2">Breaking changes</h3>
<p>Please note that this list may still be incomplete. If not otherly specified all items regard the <strong>xintexpr</strong> module.</p>
<ul>
<li><p>The <code>\expanded</code> primitive (TeXLive 2019) is <strong>required</strong>. This does not affect the macro layer <strong>xintcore</strong>, <strong>xint</strong>, <strong>xintfrac</strong>, <strong>xinttools</strong> (yet).</p></li>
@@ -285,7 +302,7 @@ License: LPPL 1.3c</code></pre>
<li><p>Function declarations are able to parse a much wider part of the syntax, but some severe limitations remain. Refer to the user manual for related information.</p></li>
<li><p>We have made an effort on some error messages, and when working interactively in a shell it may even be sometimes possible to insert for example a correct variable or function name in place of the not recognized one. But don’t expect miracles when trying to intervene in the midst of a purely expandable expansion…</p></li>
</ul>
-<h3 id="bug-fixes-3">Bug fixes</h3>
+<h3 id="bug-fixes-4">Bug fixes</h3>
<p>Bugs? Those identified in <code>1.3f</code> were almost features. As per <code>1.4</code> the code base of <strong>xintexpr</strong> received multiple successive core refactorings and added numerous new features, and our test suite although significantly enlarged is not yet extensive enough. Please report bugs by mail.</p>
<h3 id="todo">TODO</h3>
<ul>
@@ -301,13 +318,13 @@ License: LPPL 1.3c</code></pre>
<li><p><strong>xintexpr</strong>: add starred variants <code>\xintDigits*</code> and <code>\xintSetDigits*</code> which execute <code>\xintreloadxinttrig</code>.</p>
<p>Revert 1.3e ban on usage of <code>\xinteval</code> et al. inside expressions by <code>\xintdeffunc</code>. And make them usable also inside macro definitions via <code>\xintNewExpr</code>.</p></li>
</ul>
-<h3 id="bug-fixes-4">Bug fixes</h3>
+<h3 id="bug-fixes-5">Bug fixes</h3>
<ul>
<li><p><strong>xintexpr</strong>: fix bug preventing usage of <code>\xintdefefunc</code> to define a function without variables.</p>
<p>Fix some issue with <code>\xintfloatexpr[D]..\relax</code> if used inside an expression parsed by <code>\xintdeffunc</code> et al.</p></li>
</ul>
<h2 id="e-20190405"><code>1.3e (2019/04/05)</code></h2>
-<h3 id="breaking-changes-2">Breaking changes</h3>
+<h3 id="breaking-changes-3">Breaking changes</h3>
<ul>
<li>(<em>reverted at 1.3f</em>) When defining functions, sub-expressions can only use the <code>\xint(float)expr...\relax</code> syntax. One can not use there the <code>\xint(float)eval</code> wrappers.</li>
</ul>
@@ -321,12 +338,12 @@ License: LPPL 1.3c</code></pre>
<li><p><strong>xintexpr</strong>: <code>\xintensuredummy</code>, <code>\xintrestorelettervar</code>.</p></li>
<li><p>The optional argument of <code>\xintfloatexpr</code> or <code>\xintfloateval</code> (it must be at start of braced argument) can be negative; it then means to trim (and round) from the output at float precision that many least significant digits.</p></li>
</ul>
-<h3 id="bug-fixes-5">Bug fixes</h3>
+<h3 id="bug-fixes-6">Bug fixes</h3>
<ul>
<li>Some bugfixes related to user functions with no variables at all; they were dysfunctional.</li>
</ul>
<h2 id="d-20190106"><code>1.3d (2019/01/06)</code></h2>
-<h3 id="breaking-changes-3">Breaking changes</h3>
+<h3 id="breaking-changes-4">Breaking changes</h3>
<ul>
<li><p><strong>xintexpr</strong>: the <code>gcd()</code> and <code>lcm()</code> functions formerly converted their arguments to integers via <code>\xintNum</code>. They now handle general input with no such modification.</p></li>
<li><p><strong>xintexpr</strong>: former <code>\xinteval</code>, <code>\xintieval</code>, <code>\xintiieval</code>, and <code>\xintfloateval</code> renamed to <code>\xintexpro</code>, <code>\xintiexpro</code>, <code>\xintiiexpro</code>, and <code>\xintfloatexpro</code>.</p></li>
@@ -340,7 +357,7 @@ License: LPPL 1.3c</code></pre>
<li><p><strong>xintexpr</strong>: functions <code>isone()</code> and <code>isint()</code>.</p></li>
<li><p><strong>xintexpr</strong>: <code>\xinteval</code>, <code>\xintieval</code>, <code>\xintiieval</code>, and <code>\xintfloateval</code> as synonyms to <code>\xinttheexpr...\relax</code> etc…, but with the (comma-separated) expression as a usual braced macro argument.</p></li>
</ul>
-<h3 id="bug-fixes-6">Bug fixes</h3>
+<h3 id="bug-fixes-7">Bug fixes</h3>
<ul>
<li><strong>xintcore</strong>, <strong>xintexpr</strong> : division in <code>\xintiiexpr</code> was broken for a zero dividend and a one-digit divisor (e.g. <code>0//7</code>) since <code>1.2p</code> due to a bug in <code>\xintiiDivMod</code> for such arguments. The bug was signaled (thanks to Kpym for report) and fixed shortly after <code>1.3c</code> release but I then completely forgot to upload a bugfix release to CTAN at that time, apologies for that.</li>
</ul>
@@ -353,7 +370,7 @@ License: LPPL 1.3c</code></pre>
<li><p><strong>xintexpr</strong>: <code>\xintdefvar</code>, <code>\xintdeffunc</code> and their variants try to set the catcode of the semi-colon which delimits their arguments; of course this will not work if that catcode is already frozen.</p></li>
<li><p><code>\xintUniformDeviate</code> is better documented and <code>sourcexint.pdf</code> is better hyperlinked and includes indices for the macros defined by each package.</p></li>
</ul>
-<h3 id="bug-fixes-7">Bug fixes</h3>
+<h3 id="bug-fixes-8">Bug fixes</h3>
<ul>
<li><strong>xintfrac</strong>: since <code>1.3</code> release, it loaded <strong>xintgcd</strong> in contradiction to what the documentation says (hence also <strong>xintexpr</strong> loaded <strong>xintgcd</strong> automatically). There is no actual dependency so the loading is removed for now.</li>
</ul>
@@ -379,12 +396,12 @@ License: LPPL 1.3c</code></pre>
<li><p><strong>xintfrac</strong>: <code>\xintREZ</code> is faster on inputs having one hundred digits or more.</p></li>
<li><p>Added to the user manual mention of macros such as <code>\xintDivFloor</code>, <code>\xintMod</code>, <code>\xintModTrunc</code>, which had been left out so far.</p></li>
</ul>
-<h3 id="bug-fixes-8">Bug fixes</h3>
+<h3 id="bug-fixes-9">Bug fixes</h3>
<ul>
<li><strong>xintexpr</strong>: the mechanism for adjunction to the expression parsers of user defined functions was refactored and improved at previous release <code>1.3</code>: in particular recursive definitions became possible. But an oversight made these recursive functions quite inefficient (to remain polite.) This release fixes the problem.</li>
</ul>
<h2 id="section-1"><code>1.3 (2018/03/01)</code></h2>
-<h3 id="breaking-changes-4">Breaking changes</h3>
+<h3 id="breaking-changes-5">Breaking changes</h3>
<ul>
<li><p><strong>xintcore</strong>, <strong>xint</strong>, <strong>xintfrac</strong>: all macros deprecated at <code>1.2o</code> got removed.</p></li>
<li><p><strong>xintfrac</strong>: addition and subtraction of <code>a/b</code> and <code>c/d</code> now use the l.c.m. of the denominators. Similarly the macro supporting the modulo operator <code>/:</code> uses a l.c.m. for the denominator of the result.</p></li>
@@ -402,12 +419,12 @@ License: LPPL 1.3c</code></pre>
<ul>
<li><strong>xintexpr</strong>: tacit multiplication extended to cases such as <code>3!4!5!</code> or <code>(1+2)3</code>.</li>
</ul>
-<h3 id="bug-fixes-9">Bug fixes</h3>
+<h3 id="bug-fixes-10">Bug fixes</h3>
<ul>
<li><strong>xintcore</strong>: sadly, refactoring at <code>1.2l</code> of subtraction left an extra character in an inner macro causing breakage in some rare circumstances. This should not have escaped our test suite!</li>
</ul>
<h2 id="p-20171205"><code>1.2p (2017/12/05)</code></h2>
-<h3 id="breaking-changes-5">Breaking changes</h3>
+<h3 id="breaking-changes-6">Breaking changes</h3>
<ul>
<li><p><strong>xintgcd</strong>: <code>\xintBezout{a}{b}</code>’s output consists of <code>{u}{v}{d}</code> with <code>u*a+v*b==d</code>, with <code>d</code> the GCD. Formerly it was <code>{a}{b}{u}{v}{d}</code>, and with <code>u*a-v*b==d</code>.</p></li>
<li><p><strong>xintgcd</strong>: <code>\xintBezout{0}{0}</code> expands to <code>{0}{0}{0}</code>. Formerly (since <code>1.2l</code>) it raised <code>InvalidOperation</code>.</p></li>
@@ -421,7 +438,7 @@ License: LPPL 1.3c</code></pre>
<li><p><strong>xintexpr</strong>: <code>\xintdefvar</code>’s syntax is extended to allow simultaneous assignments. Examples: <code>\xintdefvar x1, x2, x3 := 1, 3**10, 3**20;</code> or <code>\xintdefiivar A, B := B, A 'mod' B;</code> for already defined variables <code>A</code> and <code>B</code>.</p></li>
<li><p><strong>xintexpr</strong>: added <code>divmod()</code> to the built-in functions. It is associated with floored division, like the Python language <code>divmod()</code>. Related support macros added to <strong>xintcore</strong>, and <strong>xintfrac</strong>.</p></li>
</ul>
-<h3 id="bug-fixes-10">Bug fixes</h3>
+<h3 id="bug-fixes-11">Bug fixes</h3>
<ul>
<li><p><strong>xintgcd</strong>: <code>\xintBezout{6}{3}</code> (for example) expanded to <code>{6}{3}{-0}{-1}{3}</code>, but the <code>-0</code> should have been <code>0</code>.</p></li>
<li><p><strong>xintgcd</strong>: it still used macro <code>\xintiAbs</code> although the latter had been deprecated from <strong>xintcore</strong>.</p></li>
@@ -429,7 +446,7 @@ License: LPPL 1.3c</code></pre>
<li><p>various documentation fixes; in particular, the partial dependency of <strong>xintcfrac</strong> on <strong>xinttools</strong> had not been mentioned.</p></li>
</ul>
<h2 id="o-20170829"><code>1.2o (2017/08/29)</code></h2>
-<h3 id="breaking-changes-6">Breaking changes</h3>
+<h3 id="breaking-changes-7">Breaking changes</h3>
<ul>
<li><strong>xint</strong>: <code>\xintAND</code>, <code>\xintOR</code>, … and similar Boolean logic macros do not apply anymore <code>\xintNum</code> (or <code>\xintRaw</code> if <strong>xintfrac</strong> is loaded), to their arguments (often, from internal usage of <code>\xintSgn</code>), but only f-expand them (using e.g. <code>\xintiiSgn</code>). This is kept un-modified even if loading <strong>xintfrac</strong>.</li>
</ul>
@@ -445,7 +462,7 @@ License: LPPL 1.3c</code></pre>
<li><p><strong>xint</strong>: <code>\xintNot</code> was renamed to <code>\xintNOT</code>, former denomination is deprecated. See also item about Boolean logic macros in the <em>Incompatible Changes</em> section.</p></li>
</ul>
<h2 id="n-20170806"><code>1.2n (2017/08/06)</code></h2>
-<h3 id="breaking-changes-7">Breaking changes</h3>
+<h3 id="breaking-changes-8">Breaking changes</h3>
<ul>
<li><strong>xintbinhex</strong> does not load package <strong>xintcore</strong> anymore, but only <strong>xintkernel</strong>.</li>
</ul>
@@ -455,7 +472,7 @@ License: LPPL 1.3c</code></pre>
<li><p>Macros of <strong>xintbinhex</strong> have been improved for speed and increased maximal sizes of allowable inputs.</p></li>
</ul>
<h2 id="m-20170731"><code>1.2m (2017/07/31)</code></h2>
-<h3 id="breaking-changes-8">Breaking changes</h3>
+<h3 id="breaking-changes-9">Breaking changes</h3>
<ul>
<li><p><strong>xintbinhex</strong>: the length of the input is now limited. The maximum size depends on the macro and ranges from about <code>4000</code> to about <code>19900</code> digits.</p></li>
<li><p><strong>xintbinhex</strong>: <code>\xintCHexToBin</code> is now the variant of <code>\xintHexToBin</code> which does not remove leading binary zeroes: <code>N</code> hex-digits give on output exactly <code>4N</code> binary digits.</p></li>
@@ -464,7 +481,7 @@ License: LPPL 1.3c</code></pre>
<ul>
<li><strong>xintbinhex</strong>: all macros have been rewritten using techniques from the 1.2 release (they had remained unmodified since <code>1.08</code> of <code>2013/06/07</code>.) The new macros are faster but limited to a few thousand digits. The <code>1.08</code> routines could handle tens of thousands of digits, but not in a reasonable time.</li>
</ul>
-<h3 id="bug-fixes-11">Bug fixes</h3>
+<h3 id="bug-fixes-12">Bug fixes</h3>
<ul>
<li><p>user manual: the <code>Changes</code> section wrongly stated at <code>1.2l</code> that the macros of <strong>xintbinhex</strong> had been made robust against non terminated input such as <code>\number\mathcode`\-</code>. Unfortunately the author fell into the trap of believing his own documentation and he forgot to actually implement the change. Now done.</p></li>
<li><p>user manual: the PDF bookmarks were messed up.</p></li>
@@ -485,14 +502,14 @@ License: LPPL 1.3c</code></pre>
<p>The situation with expressions is unchanged: syntax such as <code>\xintexpr \numexpr1+2\relax</code> is illegal as the ending <code>\relax</code> token will get swallowed by the <code>\numexpr</code>; but it is needed by the <code>xintexpr</code>-ession parser, hence the parser will expand forward and presumably end with in an “illegal token” error, or provoke some low-level TeX error (N.B.: a closing brace <code>}</code> for example can not terminate an <code>xintexpr</code>-ession, the parser must find a <code>\relax</code> token at some point). Thus there must be in this example a second <code>\relax</code>.</p></li>
<li><p>experimental code for error conditions; there is no complete user interface yet, it is done in preparation for next major release and is completely unstable and undocumented.</p></li>
</ul>
-<h3 id="bug-fixes-12">Bug fixes</h3>
+<h3 id="bug-fixes-13">Bug fixes</h3>
<ul>
<li><p><strong>xintbinhex</strong>: since <code>1.2 (2015/10/10)</code>, <code>\xintHexToDec</code> was broken due to an undefined macro (it was in <code>xint.sty</code>, but the module by itself is supposedly dependent only upon <code>xintcore.sty</code>).</p></li>
<li><p><strong>xintgcd</strong>: macro <code>\xintBezout</code> produced partially wrong output if one of its two arguments was zero.</p></li>
<li><p><strong>xintfrac</strong>: the manual said one could use directly <code>\numexpr</code> compatible expressions in arithmetic macros (without even a <code>\numexpr</code> encapsulation) if they were expressed with up to 8 tokens. There was a bug if these 8 tokens evaluated to zero. The bug has been fixed, and up to 9 tokens are now accepted. But it is simpler to use <code>\the\numexpr</code> prefix and not to worry about the token count… The ending <code>\relax</code> is now un-needed.</p></li>
</ul>
<h2 id="k-20170106"><code>1.2k (2017/01/06)</code></h2>
-<h3 id="breaking-changes-9">Breaking changes</h3>
+<h3 id="breaking-changes-10">Breaking changes</h3>
<ul>
<li><p>macro <code>\xintFloat</code> which rounds its input to a floating point number does <em>not</em> print anymore <code>10.0...0eN</code> to signal an upwards rounding to the next power of ten. The mantissa has in all cases except the zero input exactly one digit before the decimal mark.</p></li>
<li><p>some floating point computations may differ in the least significant digits, due to a change in the rounding algorithm applied to macro arguments expressed as fractions and to an improvement in precision regarding half-integer powers in expressions. See next.</p></li>
@@ -504,7 +521,7 @@ License: LPPL 1.3c</code></pre>
<li><p>added <code>\xintiSqrtR</code>, there was only <code>\xintiiSqrtR</code> alongside <code>\xintiSqrt</code> and <code>\xintiiSqrt</code> (<strong>xint</strong>).</p></li>
<li><p>added non public <code>\xintLastItem:f:csv</code> to <strong>xinttools</strong> for faster <code>last()</code> function, and improved <code>\xintNewExpr</code> compatibility. Also <code>\xintFirstItem:f:csv</code>.</p></li>
</ul>
-<h3 id="bug-fixes-13">Bug fixes</h3>
+<h3 id="bug-fixes-14">Bug fixes</h3>
<ul>
<li><p>the <code>1.2f</code> half-integer powers computed within <code>\xintfloatexpr</code> had a silly rounding to the target precision just <em>before</em> the final square-root extraction, thus possibly losing some precision. The <code>1.2k</code> implementation keeps guard digits for this final square root extraction. As for integer exponents, it is guaranteed that the computed value differs from the exact one by less than <code>0.52 ulp</code> (for inputs having at most <code>\xinttheDigits</code> digits.)</p></li>
<li><p>more regressions from <code>1.2i</code> were fixed: <code>\xintLen</code> (<strong>xint</strong>, <strong>xintfrac</strong>) and <code>\xintDouble</code> (<strong>xintcore</strong>) had forgotten that their argument was allowed to be negative. A regression test suite is now in place and is being slowly expanded to cover more macros.</p></li>
@@ -520,12 +537,12 @@ License: LPPL 1.3c</code></pre>
</ol></li>
<li><p>significant documentations tweaks (inclusive of suppressing things!), and among them two beautiful hyperlinked tables with both horizontal and vertical rules which bring the documentation of the <strong>xintexpr</strong> syntax to a kind of awe-inspiring perfection… except that implementation of some math functions is still lacking.</p></li>
</ul>
-<h3 id="bug-fixes-14">Bug fixes</h3>
+<h3 id="bug-fixes-15">Bug fixes</h3>
<ul>
<li>fix two <code>1.2i</code> regressions caused by undefined macros (<code>\xintNthElt</code> in certain branches and <code>[list][N]</code> item extraction in certain cases.) The test files existed but were not executed prior to release. Automation in progress.</li>
</ul>
<h2 id="i-20161213"><code>1.2i (2016/12/13)</code></h2>
-<h3 id="breaking-changes-10">Breaking changes</h3>
+<h3 id="breaking-changes-11">Breaking changes</h3>
<ul>
<li><code>\xintDecSplit</code> second argument must have no sign (former code replaced it with its absolute value, a sign now may cause an error.)</li>
</ul>
@@ -552,7 +569,7 @@ License: LPPL 1.3c</code></pre>
<li><p>the documentation has again been (slightly) re-organized; it has a new sub-section on the Miller-Rabin primality test, to illustrate some use of <code>\xintNewFunction</code> for recursive definitions.</p></li>
<li><p>the documentation has dropped the LaTeX “command” terminology (which had been used initially in 2013 for some forgotten reasons and should have been removed long ago) and uses only the more apt “macro”, as after all, all of <strong>xint</strong> is about expansion of macros (plus the use of <code>\numexpr</code>).</p></li>
</ul>
-<h3 id="bug-fixes-15">Bug fixes</h3>
+<h3 id="bug-fixes-16">Bug fixes</h3>
<ul>
<li><code>\xintDecSplitL</code> and <code>\xintDecSplitR</code> from <strong>xint</strong> produced their output in a spurious brace pair (bug introduced in <code>1.2f</code>).</li>
</ul>
@@ -562,7 +579,7 @@ License: LPPL 1.3c</code></pre>
<li><p>new macro <code>\xintNewFunction</code> in <strong>xintexpr</strong> which allows to extend the parser syntax with functions in situations where <code>\xintdeffunc</code> is not usable (typically, because dummy variables are used over a not yet determined range of values because it depends on the variables).</p></li>
<li><p>after three years of strict obedience to <code>xint</code> prefix, now <code>\thexintexpr</code>, <code>\thexintiexpr</code>, <code>\thexintfloatexpr</code>, and <code>\thexintiiexpr</code> are provided as synonyms to <code>\xinttheexpr</code>, etc…</p></li>
</ul>
-<h3 id="bug-fixes-16">Bug fixes</h3>
+<h3 id="bug-fixes-17">Bug fixes</h3>
<ul>
<li><p>the <code>(cond)?{foo}{bar}</code> operator from <strong>xintexpr</strong> mis-behaved in certain circumstances (such as an empty <code>foo</code>).</p></li>
<li><p>the <strong>xintexpr</strong> <code>1.2f</code> <code>binomial</code> function (which uses <code>\xintiiBinomial</code> from <strong>xint.sty</strong> or <code>\xintFloatBinomial</code> from <strong>xintfrac.sty</strong>) deliberately raised an error for <code>binomial(x,y)</code> with <code>y&lt;0</code> or <code>x&lt;y</code>. This was unfortunate, and it now simply evaluates to zero in such cases.</p></li>
@@ -570,7 +587,7 @@ License: LPPL 1.3c</code></pre>
<li><p>the <code>add</code> and <code>mul</code> from <strong>xintexpr</strong>, which work with dummy variables since <code>1.1</code>, raised an error since <code>1.2c 2015/11/16</code> when the dummy variable was given an empty range (or list) of values, rather than producing respectively <code>0</code> and <code>1</code> as formerly.</p></li>
</ul>
<h2 id="g-20160319"><code>1.2g (2016/03/19)</code></h2>
-<h3 id="breaking-changes-11">Breaking changes</h3>
+<h3 id="breaking-changes-12">Breaking changes</h3>
<ul>
<li><p>inside expressions, list item selector <code>[L][n]</code> counts starting at zero, not at one. This is more coherent with <code>[L][a:b]</code> which was already exactly like in Python since its introduction. A function len(L) replaces earlier <code>[L][0]</code>.</p></li>
<li><p>former <code>iter</code> keyword now called <code>iterr</code>. Indeed it matched with <code>rrseq</code>, the new <code>iter</code> (which was somehow missing from <code>1.1</code>) is the one matching <code>rseq</code>. Allows to iterate more easily with a “list” variable.</p></li>
@@ -584,7 +601,7 @@ License: LPPL 1.3c</code></pre>
<li><p>the syntax of expressions is described in a devoted chapter of the documentation; an example shows how to implement (expandably) the Brent-Salamin algorithm for computation of Pi using <code>iter</code> in a float expression.</p></li>
</ul>
<h2 id="f-20160312"><code>1.2f (2016/03/12)</code></h2>
-<h3 id="breaking-changes-12">Breaking changes</h3>
+<h3 id="breaking-changes-13">Breaking changes</h3>
<ul>
<li>no more <code>\xintFac</code> macro but <code>\xintiFac/\xintiiFac/\xintFloatFac</code>.</li>
</ul>
@@ -602,7 +619,7 @@ License: LPPL 1.3c</code></pre>
<li><p>(TeXperts only) the macros defined (internally) from <code>\xintdeffunc</code> et al. constructs do not incorporate an initial <code>\romannumeral</code> anymore.</p></li>
<li><p>renewed desperate efforts at improving the documentation by random shuffling of sections and well thought additions; cuts were considered and even performed.</p></li>
</ul>
-<h3 id="bug-fixes-17">Bug fixes</h3>
+<h3 id="bug-fixes-18">Bug fixes</h3>
<ul>
<li><p>squaring macro <code>\xintSqr</code> from <strong>xintfrac.sty</strong> was broken due to a misspelled sub-macro name. Dates back to <code>1.1</code> release of <code>2014/10/28</code> <code>:-((</code>.</p></li>
<li><p><code>1.2c</code>’s fix to the subtraction bug from <code>1.2</code> introduced another bug, which in some cases could create leading zeroes in the output, or even worse. This could invalidate other routines using subtractions, like <code>\xintiiSquareRoot</code>.</p></li>
@@ -616,7 +633,7 @@ License: LPPL 1.3c</code></pre>
<li><p>a space in <code>\xintdeffunc f(x)&lt;space&gt;:= expression ;</code> is now accepted.</p></li>
<li><p>documentation enhancements: the <em>Quick Sort</em> section with its included code samples has been entirely re-written; the <em>Commands of the xintexpr package</em> section has been extended and reviewed entirely.</p></li>
</ul>
-<h3 id="bug-fixes-18">Bug fixes</h3>
+<h3 id="bug-fixes-19">Bug fixes</h3>
<ul>
<li><p>in <strong>xintfrac</strong>: the <code>\xintFloatFac</code> from release <code>1.2</code> parsed its argument only through <code>\numexpr</code> but it should have used <code>\xintNum</code>.</p></li>
<li><p>in <strong>xintexpr</strong>: release <code>1.2d</code> had broken the recognition of sub-expressions immediately after variable names (with tacit multiplication).</p></li>
@@ -629,7 +646,7 @@ License: LPPL 1.3c</code></pre>
<li><p>tacit multiplication applies to more cases, for example (x+y)z, and always ties more than standard * infix operator, e.g. x/2y is like x/(2*y).</p></li>
<li><p>some documentation enhancements, particularly in the chapter on xintexpr.sty, and also in the code source comments.</p></li>
</ul>
-<h3 id="bug-fixes-19">Bug fixes</h3>
+<h3 id="bug-fixes-20">Bug fixes</h3>
<ul>
<li>in <strong>xintcore</strong>: release <code>1.2c</code> had inadvertently broken the <code>\xintiiDivRound</code> macro.</li>
</ul>
@@ -639,12 +656,12 @@ License: LPPL 1.3c</code></pre>
<li><p>macros <code>\xintdeffunc</code>, <code>\xintdefiifunc</code>, <code>\xintdeffloatfunc</code> and boolean <code>\ifxintverbose</code>.</p></li>
<li><p>on-going code improvements and documentation enhancements, but stopped in order to issue this bugfix release.</p></li>
</ul>
-<h3 id="bug-fixes-20">Bug fixes</h3>
+<h3 id="bug-fixes-21">Bug fixes</h3>
<ul>
<li>in <strong>xintcore</strong>: recent release <code>1.2</code> introduced a bug in the subtraction (happened when 00000001 was found under certain circumstances at certain mod 8 locations).</li>
</ul>
<h2 id="b-20151029"><code>1.2b (2015/10/29)</code></h2>
-<h3 id="bug-fixes-21">Bug fixes</h3>
+<h3 id="bug-fixes-22">Bug fixes</h3>
<ul>
<li>in <strong>xintcore</strong>: recent release <code>1.2</code> introduced a bug in the division macros, causing a crash when the divisor started with 99999999 (it was attempted to use with 1+99999999 a subroutine expecting only 8-digits numbers).</li>
</ul>
@@ -655,7 +672,7 @@ License: LPPL 1.3c</code></pre>
<li><p>added <code>\xintiiMaxof/\xintiiMinof</code> (<strong>xint</strong>).</p></li>
<li><p>TeX hackers only: replaced all code uses of <code>\romannumeral-`0</code> by the quicker <code>\romannumeral`&amp;&amp;@</code> (<code>^</code> being used as letter, had to find another character usable with catcode 7).</p></li>
</ul>
-<h3 id="bug-fixes-22">Bug fixes</h3>
+<h3 id="bug-fixes-23">Bug fixes</h3>
<ul>
<li>in <strong>xintexpr</strong>: recent release <code>1.2</code> introduced a bad bug in the parsing of decimal numbers and as a result <code>\xinttheexpr 0.01\relax</code> expanded to <code>0</code> ! (sigh…)</li>
</ul>
@@ -698,7 +715,7 @@ License: LPPL 1.3c</code></pre>
<li><p>various typographical fixes throughout the documentation, and a bit of clean up of the code comments. Improved <code>\Factors</code> example of nested <code>subs</code>, <code>rseq</code>, <code>iter</code> in <code>\xintiiexpr</code>.</p></li>
</ul>
<h2 id="section-3"><code>1.1 (2014/10/28)</code></h2>
-<h3 id="breaking-changes-13">Breaking changes</h3>
+<h3 id="breaking-changes-14">Breaking changes</h3>
<ul>
<li><p>in <code>\xintiiexpr</code>, <code>/</code> does <em>rounded</em> division, rather than the Euclidean division (for positive arguments, this is truncated division). The <code>//</code> operator does truncated division,</p></li>
<li><p>the <code>:</code> operator for three-way branching is gone, replaced with <code>??</code>,</p></li>
@@ -756,7 +773,7 @@ License: LPPL 1.3c</code></pre>
<li><p><code>\xintthecoords</code> converts a comma separated list of an even number of items to the format expected by the <code>TikZ</code> <code>coordinates</code> syntax,</p></li>
<li><p>completely new version <code>\xintNewExpr</code>, <code>protect</code> function to handle external macros. The dollar sign <code>$</code> for place holders is not accepted anymore, only the standard macro parameter <code>#</code>. Not all constructs are compatible with <code>\xintNewExpr</code>.</p></li>
</ul>
-<h3 id="bug-fixes-23">Bug fixes</h3>
+<h3 id="bug-fixes-24">Bug fixes</h3>
<ul>
<li><p><code>\xintZapFirstSpaces</code> hence also <code>\xintZapSpaces</code> from package <strong>xinttools</strong> were buggy when used with an argument either empty or containing only space tokens.</p></li>
<li><p><code>\xintiiexpr</code> did not strip leading zeroes, hence <code>\xinttheiiexpr 001+1\relax</code> did not obtain the expected result …</p></li>
diff --git a/macros/generic/xint/README.md b/macros/generic/xint/README.md
index bb01bbb277..a9dcafa44a 100644
--- a/macros/generic/xint/README.md
+++ b/macros/generic/xint/README.md
@@ -1,8 +1,8 @@
% README
-% xint 1.4c
-% 2021/02/20
+% xint 1.4d
+% 2021/03/29
- Source: xint.dtx 1.4c 2021/02/20 (doc 2021/02/20)
+ Source: xint.dtx 1.4d 2021/03/29 (doc 2021/03/29)
Author: Jean-Francois Burnol
Info: Expandable operations on big integers, decimals, fractions
License: LPPL 1.3c
@@ -101,7 +101,7 @@ is a functionality of all major TeX engines since TeXLive 2019.
License
=======
-Copyright (C) 2013-2020 by Jean-Francois Burnol
+Copyright (C) 2013-2021 by Jean-Francois Burnol
This Work may be distributed and/or modified under the
conditions of the LaTeX Project Public License version 1.3c.
diff --git a/macros/generic/xint/sourcexint.pdf b/macros/generic/xint/sourcexint.pdf
index 6c9a354b0b..0e99479d7c 100644
--- a/macros/generic/xint/sourcexint.pdf
+++ b/macros/generic/xint/sourcexint.pdf
Binary files differ
diff --git a/macros/generic/xint/xint.dtx b/macros/generic/xint/xint.dtx
index 8a6a882ba8..6b5ff7588c 100644
--- a/macros/generic/xint/xint.dtx
+++ b/macros/generic/xint/xint.dtx
@@ -3,28 +3,28 @@
% Extract all files via "etex xint.dtx" and do "make help"
% or follow instructions from extracted README.md.
%<*dtx>
-\def\xintdtxtimestamp {Time-stamp: <20-02-2021 at 20:47:06 CET>}
+\def\xintdtxtimestamp {Time-stamp: <29-03-2021 at 11:06:25 CEST>}
%</dtx>
%<*drv>
%% ---------------------------------------------------------------
-\def\xintdocdate {2021/02/20}
-\def\xintbndldate{2021/02/20}
-\def\xintbndlversion {1.4c}
+\def\xintdocdate {2021/03/29}
+\def\xintbndldate{2021/03/29}
+\def\xintbndlversion {1.4d}
%</drv>
%<readme>% README
%<changes>% CHANGE LOG
-%<readme|changes>% xint 1.4c
-%<readme|changes>% 2021/02/20
+%<readme|changes>% xint 1.4d
+%<readme|changes>% 2021/03/29
%<readme|changes>
-%<readme|changes> Source: xint.dtx 1.4c 2021/02/20 (doc 2021/02/20)
+%<readme|changes> Source: xint.dtx 1.4d 2021/03/29 (doc 2021/03/29)
%<readme|changes> Author: Jean-Francois Burnol
%<readme|changes> Info: Expandable operations on big integers, decimals, fractions
%<readme|changes> License: LPPL 1.3c
%<readme|changes>
%<*!readme&!changes&!dohtmlsh&!makefile>
%% ---------------------------------------------------------------
-%% The xint bundle 1.4c 2021/02/20
-%% Copyright (C) 2013-2020 by Jean-Francois Burnol
+%% The xint bundle 1.4d 2021/03/29
+%% Copyright (C) 2013-2021 by Jean-Francois Burnol
%<xintkernel>%% xintkernel: Paraphernalia for the xint packages
%<xinttools>%% xinttools: Expandable and non-expandable utilities
%<xintcore>%% xintcore: Expandable arithmetic on big integers
@@ -137,7 +137,7 @@ is a functionality of all major TeX engines since TeXLive 2019.
License
=======
-Copyright (C) 2013-2020 by Jean-Francois Burnol
+Copyright (C) 2013-2021 by Jean-Francois Burnol
This Work may be distributed and/or modified under the
conditions of the LaTeX Project Public License version 1.3c.
@@ -161,6 +161,40 @@ See `xint.pdf` for contact information.
%</readme>--------------------------------------------------------
%<*changes>-------------------------------------------------------
+`1.4d (2021/03/29)`
+----
+
+### Breaking changes
+
+ - `quo()` and `rem()` in `\xintiiexpr/\xintiieval` renamed to
+ `iquo()` and `irem()`.
+
+ - the output of `gcd()` and `lcm()` as applied to fractions is now
+ always in lowest terms.
+
+### Bug fixes
+
+ - Ever since `1.3` the `quo()` and `rem()` functions in `\xintexpr`
+ (not the ones in `\xintiiexpr`) were broken as their (officially
+ deprecated) support macros had been removed! They had somewhat
+ useless definitions anyway. They have now been officially removed
+ from the syntax. Their siblings in `\xintiieval` were renamed to
+ `iquo()` and `irem()`.
+
+ - Sadly, `gcd()` was broken in `\xintexpr` since `1.4`, if the first
+ argument vanished. And `gcd()` was broken in `\xintiiexpr` since
+ `1.3d` if *any* argument vanished. I did have a unit test! (which
+ obviously was too limited ...)
+
+ Further, the `\xintGCDof` and `\xintLCMof` **xintfrac** macros were
+ added at `1.4` but did not behave like other **xintfrac** macros with
+ respect to parsing their arguments: e.g. `\xintGCDof{2}{03}` gave an
+ unexpected non-numeric result.
+
+ - The `first()` and `last()` functions, if used as arguments to
+ numerical functions such as `sqr()` inside an `\xintdeffunc`
+ caused the defined function to be broken.
+
`1.4c (2021/02/20)`
----
@@ -3577,6 +3611,8 @@ pdfpagemode=UseNone,%
% ===============
% \ttzfamily done at begin document
+\newcommand\ctanpackage[1]{\href{https://ctan.org/pkg/#1}{#1}}
+
\begin{document}\thispagestyle{empty}
\pdfbookmark[1]{Title page}{TOP}
\def\partname{Part}
@@ -3805,16 +3841,16 @@ pdfpagemode=UseNone,%
\node [right of=kernel] (B) {};
\node [block, below right of=B] (core) {\xintcorename};
\node [block, below left of=A] (tools) {\xinttoolsname};
- \node [block, right of=core, xshift=1cm] (bnumexpr) {\href{https://ctan.org/pkg/bnumexpr}{bnumexpr}};
+ \node [block, right of=core, xshift=1cm] (bnumexpr) {\ctanpackage{bnumexpr}};
\node [block, below of=core] (xint) {\xintname};
\node [block, left of=xint, xshift=-1cm] (gcd) {\xintgcdname};
\node [block, left of=gcd] (binhex) {\xintbinhexname};
\node [block, below of=xint] (frac) {\xintfracname};
\node [block, below of=frac, yshift=-.5cm] (expr) {\xintexprname};
- \node [block, below right of=expr, yshift=-.5cm, xshift=2.25cm] (polexpr) {\href{https://ctan.org/pkg/polexpr}{polexpr}};
+ \node [block, below right of=expr, yshift=-.5cm, xshift=2.25cm] (polexpr) {\ctanpackage{polexpr}};
\node [block, below of=expr, yshift=-.5cm] (trig) {\xinttrigname};
\node [block, left of=trig] (log) {\xintlogname};
- \node [block, left of=log, xshift=-1cm] (poormanlog) {\href{https://ctan.org/pkg/poormanlog}{poormanlog}};
+ \node [block, left of=log, xshift=-1cm] (poormanlog) {\ctanpackage{poormanlog}};
\node [block, below right of=frac, xshift=1cm] (series) {\xintseriesname};
\node [block, right of=series] (cfrac) {\xintcfracname};
% Draw edges
@@ -3857,17 +3893,17 @@ pdfpagemode=UseNone,%
functionalities of the lower module it is thus necessary to use
a suitable |\usepackage| (\LaTeX) or |\input| (Plain \TeX.)\par
- \href{https://ctan.org/pkg/bnumexpr}{bnumexpr} is a
+ \ctanpackage{bnumexpr} is a
separate (\LaTeX{} only) package by the author which uses (by default)
\xintcorename as its mathematical engine.
- \href{https://ctan.org/pkg/polexpr}{polexpr} is a
+ \ctanpackage{polexpr} is a
separate (\LaTeX{} only) package by the author which requires \xintexprname.
\xinttrigname and \xintlogname are loaded automatically by \xintexprname; they
will refuse to be loaded directly (but see \csbxint{reloadxinttrig}).
- \href{https://ctan.org/pkg/poormanlog}{poormanlog} is a \TeX{} and
+ \ctanpackage{poormanlog} is a \TeX{} and
\LaTeX{} package by the author which is loaded automatically by \xintlogname.
\par
\end{addmargin}
@@ -3949,6 +3985,49 @@ quality of the document). Reports welcome.%
\footnote{Thanks to Jürgen Gilg for keeping the author motivated and
helping proof-read the documentation.}
+\subsection{Known bugs/features at \texttt{1.4d}}
+
+\begin{description}
+\item[if(100>0,(100,125),(100,128)) breaks my code:]
+%
+ This is a feature. This is a syntax error, as the comma serves to contatenate
+ "oples" (see \autoref{oples}), so it is parsed to behave as
+\begin{everbatim}
+ if(100>0,100,125,100,128)
+\end{everbatim}
+ which is an error as \func{if} requires exactly three arguments, not
+ five. Use:
+\begin{everbatim}
+ if(100>0,[100,125],[100,128])
+\end{everbatim}
+ which will expand to the "tuple" |[100,125]|.
+\item[{\detokenize{\xintdeffunc foo(x):= gcd((x>0)?{[x,125]}{[x,128]});}
+ creates a broken function:}]
+%
+ Bug. Normally \func{gcd} (and other
+ multi-arguments functions) work both with open lists of arguments or
+ bracketed lists ("nutples") and the above syntax would work perfectly fine
+ in numerical context. But the presence of the \oper{?} breaks in
+ \csbxint{deffunc} context the flexibility of \func{gcd}.
+
+ Currently working alternatives:
+\begin{everbatim}
+\xintdeffunc foo(x) := gcd(if(x>0, [x,125], [x,128]));
+\xintdeffunc foo(x) := if(x>0, gcd(x,125), gcd(x,128));
+\xintdeffunc foo(x) := if(x>0, gcd([x,125]), gcd([x,128]));
+\xintdeffunc foo(x) := gcd((x>0)?{x,125}{x,128});
+\xintdeffunc foo(x) := (x>0)?{gcd(x,125)}{gcd(x,128)};
+\xintdeffunc foo(x) := (x>0)?{gcd([x,125])}{gcd([x,128])};
+\end{everbatim}
+ The same problem will arise with an \oper{??} nested inside \func{gcd} or
+ similar functions, in an \csbxint{deffunc}.
+\end{description}
+
+If the list stops here, it is probably only because I have not tested enough
+yet. But it is already mentioned in the \csbxint{deffunc} documentation that
+it can not parse currently the entirety of the available purely numerical
+syntax, some documented limitations apply.
+
\subsection{Features added since the \texttt{1.4} release}
For bugfixes and possibly more details check |CHANGES.html|:
@@ -4095,7 +4174,8 @@ The rendering here uses extra decoration.
\localtableofcontents
-\subsection{Oples and nut-ples: terminology for the \text{1.4} \xintname generation}
+
+\subsection{Oples and nutples: terminology for the \text{1.4} \xintname generation}\label{oples}
\emph{Skip this on first reading, else you will never start using the
package.} \fbox{SKIP THIS!} (understood?)
@@ -4145,7 +4225,7 @@ input syntax, Python |lists|), or \emph{packing} (as a reverse to Python's
unpacking of sequence type objects).
\item
-A braced \emph{ople} is called a \emph{nut-ple}. Among them $\{nil\}$ is a bit
+A braced \emph{ople} is called a \emph{nutple}. Among them $\{nil\}$ is a bit
special. It is called the \emph{not-ple}. It is not |nil|!
\end{itemize}
@@ -4172,7 +4252,7 @@ Each \emph{ople} has a length which is its cardinality. The |oples| of length
1 are called \emph{one-ples}. There are two types of \emph{one-ples}:
\begin{itemize}
\item \emph{numbers},
-\item packed \emph{oples}: the \emph{nut-ples}.
+\item packed \emph{oples}: the \emph{nutples}.
\end{itemize}
As said before the \emph{not-ple} |{{}}| is special. It can be input as
@@ -4186,7 +4266,7 @@ can associate with any \emph{ople} a tree. The root is the ople. In the case
of the |nil|, there is nothing else than the root, which we then consider also
a \emph{leaf}. Else the children at top level are the successive items of the
ople. Among the items some are \emph{atoms} giving \emph{leaves} of the tree,
-others are \emph{nut-ples} which in turn have children. In the special case of
+others are \emph{nutples} which in turn have children. In the special case of
the \emph{not-ple} we consider it has a child, which is the empty set and this
why we consider the empty set |nil| a \emph{leaf}. We then proceed
recursively. We thus obtain from the root \emph{ople} a tree whose vertices
@@ -4223,21 +4303,21 @@ indicate the shape than display it.
subset. This applies also if it is a \emph{number}. Then it can be sliced only
to itself or to the empty set (indeed it has only one element, which is an
atom). Similarly the \emph{not-ple} can only be sliced to give itself or the
-empty set. And more generally a \emph{nut-ple} is a singleton so also can only
+empty set. And more generally a \emph{nutple} is a singleton so also can only
be set-sliced to either the empty set or itself.
\xintexprname extends «Python-like» slicing to act on \emph{oples}:
\begin{itemize}[nosep]
-\item if they are not \emph{nut-ples} set-theoretical slicing applies,
-\item if they are \emph{nut-ples} (only case having a one-to-one
- correspondance in Python) then the slicing happens \emph{within brackets}:
- i.e. the \emph{nut-ple} is unpacked then the set-theoretical slicing is
- applied, then the result is \emph{repacked} to produce a new \emph{nut-ple}.
+\item if they are not \emph{nutples} set-theoretical slicing applies,
+\item if they are \emph{nutples} (only case having a one-to-one
+ correspondence in Python) then the slicing happens \emph{within brackets}:
+ i.e. the \emph{nutple} is unpacked then the set-theoretical slicing is
+ applied, then the result is \emph{repacked} to produce a new \emph{nutple}.
\end{itemize}
With these conventions the \emph{not-ple} for example is invariant under
slicing: unpacking it gives the empty set, which has only the empty set as
subset and repacking gives back the \emph{not-ple}. Slicing a general
-\emph{nut-ple} returns a \emph{nut-ple} but now of course in general distinct
+\emph{nutple} returns a \emph{nutple} but now of course in general distinct
from the first one.
The syntax for Python slicing is to postfix a variable or a parenthesized ople
@@ -4252,16 +4332,16 @@ a set).
\xintexprname extends «Python-like» indexing to act on \emph{oples}:
\begin{itemize}[nosep]
-\item if they are not \emph{nut-ples} set-theoretical item indexing applies,
-\item if they are \emph{nut-ples} (only case having a one-to-one
- correspondance in Python) then the meaning becomes \emph{extracting}: i.e.
- the \emph{nut-ple} is unpacked then the set-theoretical indexing is applied,
+\item if they are not \emph{nutples} set-theoretical item indexing applies,
+\item if they are \emph{nutples} (only case having a one-to-one
+ correspondence in Python) then the meaning becomes \emph{extracting}: i.e.
+ the \emph{nutple} is unpacked then the set-theoretical indexing is applied,
but the result is \emph{not repacked}.
\end{itemize}
For example when applied to the \emph{not-ple} we always obtain
the |nil|. Whereas as we saw slicing the \emph{not-ple} always gives back the
\emph{not-ple}. Indexing is denoted in the syntax by postfixing by |[N]|. Thus
-for \emph{nut-ples} (which are analogous to Python objects), there is genuine
+for \emph{nutples} (which are analogous to Python objects), there is genuine
difference between the |[N]| extractor and the |[N:N+1]| slicer. But for
\emph{oples} which are either |nil|, a \emph{number}, or of length at least 2,
there is no difference.
@@ -4269,8 +4349,8 @@ there is no difference.
Nested slicing is a concept from NumPy, which is extended by \xintexprname to
trees of varying depths. We have a chain of slicers and extractors. I will
-describe only the case of slicers and letting them act on a |nut-ple|. The
-first slicer gives back a new |nut-ple|. The second slicer will be applied to
+describe only the case of slicers and letting them act on a |nutple|. The
+first slicer gives back a new |nutple|. The second slicer will be applied to
each of one of its remaining items. However some of them may be \emph{atoms}
or the empty set. In the NumPy context all leaves are at the same depth thus
this can happen only when we have reached beyond the last dimension
@@ -4278,19 +4358,19 @@ this can happen only when we have reached beyond the last dimension
does not generate an error. But any attempt to slice an \emph{atom} or the
empty set (as element of its container) removes it. Recall we call them
\emph{leaves}. We can not slice leaves. We can only slice non-leaf items: such
-items are necessarily |nut-ples|. The procedure then applies recursively.
+items are necessarily |nutples|. The procedure then applies recursively.
If we handle an extractor rather than a slicer, the procedure is similar: we
can not extract out of an \emph{atom} or the empty set. They are thus
-removed. Else we have a |nut-ple|. It is thus unpacked and replaced by the
+removed. Else we have a |nutple|. It is thus unpacked and replaced by the
selected item. This item may be an atom or the empty set and any further
-slicer or extractor will remove them, or it is a |nut-ple| and the procedure
+slicer or extractor will remove them, or it is a |nutple| and the procedure
applies with the next slicer/extractor.
\xintexprname allows to apply such a |[a:b,c:d,N,e:f,...]| chain of
-slicing/extracting also to an \emph{ople}, which is not a \emph{nut-ple}. We
+slicing/extracting also to an \emph{ople}, which is not a \emph{nutple}. We
simply apply the first step as has been described previously and successive
-steps will only get applied to either \emph{nut-ples} or \emph{leaves}, the
+steps will only get applied to either \emph{nutples} or \emph{leaves}, the
latter getting silently removed by any attempted operation.
One last thing. In the syntax of \xintexprname, variables as well as functions
@@ -4298,11 +4378,11 @@ have a name and a value. The value is an |ople|. We can always use a variable
whose value is an |ople|
in a function call, it will occupy the place of as many arguments as its
length indicates. But in a function declaration, the variables must stand for
-|one-ples|, i.e. either |numbers| or |nut-ples|.
+|one-ples|, i.e. either |numbers| or |nutples|.
The |*| unpacks a
-|nut-ple|. The last positional argument in a function declaration can have a
-special form |*|\meta{name}. This means that \meta{name} is a |nut-ple| which
+|nutple|. The last positional argument in a function declaration can have a
+special form |*|\meta{name}. This means that \meta{name} is a |nutple| which
receives as items all arguments in the function call beyond the first ones
corresponding to the function declaration.
@@ -4934,29 +5014,43 @@ discussion at each level.
\precdesc{14}
\begin{description}
\operdesc{\lowast} multiplication
-\operdesc{/} division: exact in \csbxint{eval}, correctly rounded in
- \csbxint{floateval} (numerator and denominator are rounded before the
- division is done), and rounded to an integer (like |\numexpr| does:
- half-integers are rounded towards infinity of same sign) in
- \csbxint{iieval}. The division is left-associative:
+
+\operdesc{/} division:
+ \begin{itemize}
+ \item in \csbxint{eval}: exact division in the field of rational numbers (not
+ automatically reduced to lowest terms),
+ \item in \csbxint{floateval}: correct rounding of the exact division; the two
+ operands are, if necessary, float-rounded before the fraction is
+ evaluated and rounded (to obtain the correcty rounded |A/B|
+ without prior rounding of |A| and |B| see \func{qfloat}),
+ \item in \csbxint{iieval}: for compatibility with the legacy behaviour of
+ |/| in |\numexpr|, it rounds the exact fraction \emph{with half-integers
+ going towards the infinity of the same sign}.
+ \end{itemize}
+ The division is left-associative. Example:
\begin{everbatim*}
\xintexpr reduce(100/50/2)\relax
\end{everbatim*}
-\operdesc{//} floored division
+\operdesc{//} floored division (and thus produces an integer, see
+ \func{divmod} for details)
-\operdesc{/:} the associated modulo
+\operdesc{/:} the associated modulo (see \func{divmod} and \func{mod})
Left-associativity applies generally to operators of same precedence.
\begin{everbatim*}
\xintexpr 100000/:13, 100000 'mod' 13\relax\newline
\xintexpr 100000/:13/13\relax
\end{everbatim*}
+
+ Nothing special needs to be done in contexts such as \LaTeX3
+ |\ExplSyntaxOn| where |:| is of catcode letter, but if |:| is an active
+ character (for example in \LaTeX\ with babel+french) with an active |:|,
+ one needs to use input such as |/\string :| (or use \func{mod}).
-\operdesc{'mod'} is same as \oper{/:}.
-
-Note: The enclosing (right) ticks are
-mandatory part of all such infix operator «words».
+ \operdesc{'mod'} is same as \oper{/:}. \fbox{Attention:} with
+ \ctanpackage{polexpr} loaded, which allows |'| in variable and function
+ names, |'mod'| syntax is broken. Use the alternatives.
\end{description}
@@ -5013,8 +5107,10 @@ precedence, use parentheses for disambiguation.
\operdesc{\Ampersand\Ampersand} logical conjunction. Evaluates to \dtt{1} if
both sides are non-zero, to \dtt{0} if not.
- \operdesc{'and'} idem. The (right) ticks are mandatory. See also the
- \func{all} multi-arguments function.
+ \operdesc{'and'} same as \verb+&&+. See
+ also the \func{all} multi-arguments function. \fbox{Attention:} with
+ \ctanpackage{polexpr} loaded, which allows |'| in variable and function
+ names, |'and'| syntax is broken. Use the alternatives.
\end{description}
\precdesc{6}
@@ -5022,10 +5118,16 @@ precedence, use parentheses for disambiguation.
\operdesc{\string|\string|} logical (inclusive) disjunction. Evaluates to
\dtt{1} if one or both sides are non-zero, to \dtt{0} if not.
- \operdesc{'or'} idem. See also the \func{any} multi-arguments function.
+ \operdesc{'or'} same as as \verb+||+. See also the \func{any} multi-arguments
+ function. \fbox{Attention:} with \ctanpackage{polexpr} loaded, which allows
+ |'| in variable and function names, |'or'| syntax is broken. Use the
+ alternatives.
- \operdesc{'xor'} logical (exclusive) disjunction. See also the \func{xor}
- multi-arguments function.
+ \operdesc{'xor'} logical (exclusive) disjunction. \fbox{Attention:} with
+ \ctanpackage{polexpr} loaded, which allows |'| in variable and function
+ names, |'xor'| syntax is broken. Use the multi-arguments \func{xor} function
+ (or suggest to the author some credible alternative ascii notation to use as
+ infix operator).
\operdesc{\strut..}
\operdesc{..[}
@@ -5125,13 +5227,13 @@ binomial, bool,
ceil, cos, cosd, cot, cotd, cotg, csc, cscd,
divmod, even, exp,
factorial, first, flat, float, float\string_, floor, frac, gcd,
-if, ifint, ifone, ifsgn, ilog10, isint, isone, iter, iterr, inv,
+if, ifint, ifone, ifsgn, ilog10, iquo, irem, isint, isone, iter, iterr, inv,
last, lcm, len, log, log10, max, min, mod, mul,
ndmap, ndseq, ndfillraw,
not, num, nuple, odd,
pArg, pArgd, pfactorial, pow, pow10, preduce,
-qfloat, qfrac, qint, qrand, qraw, quo,
-random, randrange, rbit, reduce, rem, reversed, round, rrseq, rseq,
+qfloat, qfrac, qint, qrand, qraw,
+random, randrange, rbit, reduce, reversed, round, rrseq, rseq,
sec, secd, seq, sgn, sin, sinc, sind, sqr, sqrt, sqrtr,
subs, subsm, subsn,
tan, tand, tg, togl, trunc, unpack,
@@ -5474,7 +5576,7 @@ $\xintthefloatexpr subs(((x-1)/x, x/x, (x+1)/x), x=2**30)\relax
allow arbitrarily complicated combinations of various |bool(name)|.
\funcdesc[name]{togl}
returns $1$
- if the \LaTeX{} package \href{https://ctan.org/pkg/etoolbox}{etoolbox}%
+ if the \LaTeX{} package \ctanpackage{etoolbox}%
%
%
%
@@ -5483,7 +5585,7 @@ $\xintthefloatexpr subs(((x-1)/x, x/x, (x+1)/x), x=2**30)\relax
has been used to define a toggle named |name|, and this toggle is
currently set to |true|. Using |togl| in an |\xintexpr..\relax|
without having loaded
- \href{https://ctan.org/pkg/etoolbox}{etoolbox} will result in an
+ \ctanpackage{etoolbox} will result in an
error from |\iftoggle| being a non-defined macro. If |etoolbox| is
loaded but |togl| is used on a name not recognized by |etoolbox|
the error message will be of the type ``ERROR: Missing |\endcsname|
@@ -5650,14 +5752,17 @@ $\xintthefloatexpr subs(((x-1)/x, x/x, (x+1)/x), x=2**30)\relax
% labelwidth=-\fontdimen2\font, labelsep=\fontdimen2\font, labelindent=0pt,
% listparindent=\leftmarginiii]
- \funcdesc[f, g]{quo} first truncates the arguments to convert them to integers then
- computes the Euclidean quotient. Hence it computes an integer.
- \funcdesc[f, g]{rem} first truncates the arguments to convert them to integers then
- computes the Euclidean remainder. Hence it computes an integer.
+ \funcdesc[m, n]{iquo} Only available in |\xintiiexpr/\xintiieval|
+ context. Computes the Euclidean quotient. Matches with the remainder
+ defined in next item. See \csbxint{iiQuo}.
+
+ \funcdesc[m, n]{irem} Only available in |\xintiiexpr/\xintiieval|
+ context. Computes the Euclidean remainder. Attention that, following
+ mathematical definition, it is always non-negative. See \csbxint{iiRem}.
\funcdesc[f, g]{mod} computes |f - g*floor(f/g)|. Hence its output is a
general fraction or floating point number or integer depending on the
- used parser.
+ used parser. If non-zero, it has the same sign as |g|.
Prior to |1.2p| it computed |f - g*trunc(f/g)|.
@@ -5833,15 +5938,23 @@ At |1.4| \func{all}, \func{any}, \func{xor},
\func{max}, \func{min}, \func{gcd}, \func{lcm}, \func{first}, \func{last},
\func{reversed} and \func{len} admit:
\begin{itemize}
-\item at least two arguments, and then operate as expected in backward
- compatible way,
-\item or only one argument,\IMPORTANT{} which then \emph{must} be a |nut-ple|, i.e. a
- variable or explicit bracketed list. In the case of \func{reversed} the output
- is a |nut-ple| if the input was one.
+\item at least two arguments, and then they operate as expected in the backwards
+ compatible way (notice that it is possible in \xintexprname to define
+ variables expanding to an |ople|, i.e. (at user level) an unpacked comma
+ separated list, |foo(ople)| thus falls into this category),
+\item or only one argument,\IMPORTANT{} which then \emph{must} be a |nutple|,
+ i.e. a bracketed list (or a variable defined to hold such a
+ bracketed list, or a function producing such a |nutple|). The argument is then
+ automatically unpacked.
+
+ In the specific case of \func{reversed} the output is then repacked so that
+ the output is a |nutple| if and only if the input was one (the reversal does
+ not propagate to deeper nested |nutple|'s, it applies only at depth one).
\end{itemize}
-Notice that this is breaking change as the functions do not work anymore with
-a single argument being a number (or give funny non-documented results
-depending on internal data representation).
+The arguments of the functions doing computations on the arguments (such as
+\func{gcd}) must be numerical, except if there is only one argument, and then
+it must be a |nutple|. Prior to |1.4|, the functions worked also with a single
+scalar argument, but this is now illegal.
\begin{description}
% [parsep=0pt,align=left,
@@ -5894,45 +6007,57 @@ the resulting logical assertion,
\funcdesc[x, y, ...]{gcd} computes the positive generator of the fractional
ideal of rational numbers $x\mathbb Z + y\mathbb Z + ... \subset \mathbb
-Q$. When the inputs are integers it is advantageous to use a sub
-\csbxint{iiexpr}-ession, as the integer-only macro is more efficient (about
-|6X|) than the
-one accepting general fractional inputs. Notice that this may require some
-\func{num} wrapper when using variables, as they may well be in fraction
-format, and \csbxint{iiexpr} accepts only strict integers. Since |1.3d|, this
-function and \func{lcm} are available whether or not package \xintgcdname is
-loaded. Note that like other operations with fractions it does not always
-produce a fraction in irreducible format. This example shows also how to
-reduce an n-uple to its primitive part: (this example should be revisited)
-\begin{everbatim*}
-\xinttheexpr gcd(7/300, 11/150, 13/60)\relax\newline
+Q$. Since |1.4d| the output is always in lowest terms.
+
+This example shows how to reduce an n-uple to its primitive part:
+\begin{everbatim*}
+\xinteval{gcd(7/300, 11/150, 13/60)}\newline
$(7/300, 11/150, 13/60)\to
-(\xinttheexpr subs(seq(reduce(x/D), x = 7/300, 11/150, 13/60), D=gcd(7/300, 11/150, 13/60))\relax)$\newline
+(\xinteval{subsn(seq(reduce(x/D), x = L), D=gcd(L); L=7/300, 11/150, 13/60)})$\newline
\xintexpr gcd([7/300, 11/150, 13/60])\relax\par
\end{everbatim*}
-
+MEMO
Perhaps a future release will provide a |primpart()| function as built-in
functionality.
+In case of strict integers, using a |\xintiiexpr...\relax| wrapper is
+advantageous as the integer-only |gcd()| is more efficient.
+%
+% ceci semble encore à peu près exact à 1.4d :
+% (about |6X|) than the one accepting general fractional inputs.
+%
+As \csbxint{iiexpr} accepts only strict integers, doing this may require
+wrapping the argument in \func{num}.
+
\funcdesc[x, y, ...]{lcm} computes the positive generator of the
fractional ideal of rational numbers $x\mathbb Z \cap y\mathbb Z \cap ...
-\subset \mathbb Q$. When the inputs are integers it is
-advantageous to use a sub \csbxint{iiexpr}-ession, as the integer-only macro
-is more efficient (about |9X|) than the one accepting general fractional inputs.
+\subset \mathbb Q$.
\begin{everbatim*}
\xinttheexpr lcm([7/300, 11/150, 13/60])\relax
\end{everbatim*}
+As for \func{gcd}, since |1.4d| the output is always in lowest terms.
+% Memo 1.4d: This
+% function got (I did not tests extensively) a |4X| speed gain for inputs being
+% only integers
+For strict integers it is slightly advantageous to use a sub
+\csbxint{iiexpr}-ession.
+%
+% je disais à 1.4:
+% (about |9X|) than the one accepting general fractional inputs.
+% mais à 1.4d c'est seulement 2X : le lcm pour les fractions
+% a quadruplé sa vitesse !
+%
-\funcdesc[x, y, ...]{first} first item of the list or nut-ple argument:
+\funcdesc[x, y, ...]{first} first item of the list or nutple argument:
\begin{everbatim*}
\xintiiexpr first([last(-7..3), [58, 97..105]])\relax
\end{everbatim*}
-\funcdesc[x, y, ...]{last} last item of the list or nut-ple argument:
+\funcdesc[x, y, ...]{last} last item of the list or nutple argument:
\begin{everbatim*}
\xintiiexpr last([-7..3, 58, first(97..105)])\relax
\end{everbatim*}
\funcdesc[x, y, ...]{reversed} reverses the order of the comma separated list
-or inside a nut-ple:
+or inside a nutple:
\begin{everbatim*}
\xintiieval{reversed(reversed(1..5), reversed([1..5]))}
\end{everbatim*}
@@ -5940,16 +6065,16 @@ or inside a nut-ple:
The above is correct as \xintexprname functions may produce oples and this is
the case here.
\funcdesc[x, y, ...]{len} computes the number of items in a comma separated
- list or inside a nut-ple (at first level only: it is not a counter of leaves).
+ list or inside a nutple (at first level only: it is not a counter of leaves).
\begin{everbatim*}
\xinttheiiexpr len(1..50, [101..150], 1001..1050), len([1..10])\relax
\end{everbatim*}
\funcdesc[\lowast nutples]{zip} behaves\NewWith{1.4b} similarly to
- the Python function of the same name: i.e. it produces \emph{an ople of nut-ples,
- where the i-th nut-ple contains the i-th element from each of the argument
- nut-ples. The ople ends when the shortest input nut-ple is exhausted.
- With a single nut-ple argument, it returns an ople of 1-nutples.
+ the Python function of the same name: i.e. it produces \emph{an ople of nutples,
+ where the i-th nutple contains the i-th element from each of the argument
+ nutples. The ople ends when the shortest input nutple is exhausted.
+ With a single nutple argument, it returns an ople of 1-nutples.
With no arguments, it returns the empty ople.}
As there is no exact match in \xintexprname of the concept of «iterator» object,%
@@ -6363,7 +6488,7 @@ In the example above the parentheses serve to disambiguate from the raw
on input. And we used a trick to show that |(7)[-2]| returns |nil|.
The behaviour changes for singleton \emph{oples} which are not
-\emph{numbers}. They are thus \emph{nut-ples}, or equivalently they are the
+\emph{numbers}. They are thus \emph{nutples}, or equivalently they are the
bracketing (bracing, packing) of another \emph{ople}. In this case, the meaning
of the syntax for item indexing is, as in Python, item
\emph{extraction}:
@@ -6379,7 +6504,7 @@ of the syntax for item indexing is, as in Python, item
\xintiiexpr (0..10)[:6]\relax\ and \xintiiexpr (0..10)[:-6]\relax
\end{everbatim*}
-As above, the meaning change for \emph{nut-ples} and fits with expectations
+As above, the meaning change for \emph{nutples} and fits with expectations
from Python regarding its sequence types:
\begin{everbatim*}
\xintiiexpr [0..10][:6]\relax\ and \xintiiexpr [0..10][:-6]\relax
@@ -6391,7 +6516,7 @@ from Python regarding its sequence types:
\xintiiexpr (0..10)[6:]\relax\ and \xintiiexpr (0..10)[-6:]\relax
\end{everbatim*}
-As above, the meaning change for \emph{nut-ples} and fit with expectations
+As above, the meaning change for \emph{nutples} and fit with expectations
from Python with \emph{tuple} or \emph{list} types:
\begin{everbatim*}
\xintiiexpr [0..10][6:]\relax\ and \xintiiexpr [0..10][-6:]\relax
@@ -6414,7 +6539,7 @@ from Python with \emph{tuple} or \emph{list} types:
\end{itemize}
-\subsection{NumPy like nested slicing and indexing for arbitrary oples and nut-ples}
+\subsection{NumPy like nested slicing and indexing for arbitrary oples and nutples}
This is entirely new with |1.4|.\NewWith{1.4}
@@ -6467,6 +6592,21 @@ part, or hexadecimal input), or is looking for an infix operator, and:
\end{enumerate}
\begin{framed}
+ \centeredline{\textcolor{Red}{\textbf{!!!!ATTENTION!!!!}}}
+
+ Explicit digits prefixing a variable, or a function, whose name starts with
+ an |e| or |E| will trap the parser into trying to build a number in
+ scientific notation. So the |*| must be explictly inserted.
+
+\begin{everbatim}
+\xintdefiivar e := (2a+4b+6d+N)/:7;%
+\xintdefiivar f := (c+11d+22*e)//451;% 22e would raise errors
+\end{everbatim}
+
+ I don't think I will fix this anytime soon...
+\end{framed}
+
+\begin{framed}
For example, if |x, y, z| are variables all three of |(x+y)z|, |x(y+z)|,
|(x+y)(x+z)| will create a tacit multiplication.
@@ -7109,7 +7249,7 @@ This section\CHANGED{1.4} has changed significantly at |1.4| due to the new exte
types manipulated by the syntax.
Suppose we want to manipulate 3-dimensional vectors, which will be represented
-as |nut-ples| of length 3. And let's add a bit of matrix algebra.
+as |nutples| of length 3. And let's add a bit of matrix algebra.
\begin{everbatim*}
\xintdeffunc dprod(V, W) := V[0]*W[0] + V[1]*W[1] + V[2]*W[2];
\xintdeffunc cprod(V, W) := [V[1]*W[2] - V[2]*W[1],
@@ -7623,9 +7763,9 @@ This package was first included in release |1.3e| (|2019/04/05|) of
Currently, the functions \func{log10}, \func{pow10}, \func{log}, \func{exp},
and \func{pow} use at their core two fast expandable macros handling base 10
logarithms and powers for mantissas of 9 digit tokens. They are
-defined by package \href{https://ctan.org/pkg/poormanlog}{poormanlog} which is
+defined by package \ctanpackage{poormanlog} which is
automatically imported. The error is believed to be at most \dtt{2ulp} (see
-its |README|). The package \href{https://ctan.org/pkg/poormanlog}{poormanlog}
+its |README|). The package \ctanpackage{poormanlog}
has no dependencies and can be imported by any other \TeX\ macro file.
Although the precision is thus limited to about \dtt{8} or \dtt{9} digits this
@@ -7679,7 +7819,7 @@ first 8 or 9 digits of the output are significant...
\end{everbatim*}
Notice that the last digit of |log(2)| is not the correctly rounded one... I
did say 9 \textbf{or} 8 digits or precision... The documentation of
-\href{https://ctan.org/pkg/poormanlog}{poormanlog} mentions an error of up
+\ctanpackage{poormanlog} mentions an error of up
to 2 units in the ninth digit when computing |log10(x)| for |1<x<10| and
|10^x| for |0<x<1|.
@@ -7783,7 +7923,7 @@ using standard infix notations with \TeX{} integers. But \eTeX{} did not
modify the \TeX{} bound on acceptable integers, and did not add floating point
support.
-The \href{https://ctan.org/pkg/bigintcalc}{bigintcalc} package by
+The \ctanpackage{bigintcalc} package by
\textsc{Heiko Oberdiek} provided expandable macros (using some of |\numexpr|
possibilities, when available) on arbitrarily big integers, beyond the \TeX{}
bound. It does not provide an expression parser.%
@@ -7848,7 +7988,7 @@ Even with the superior \liiibigint{} Karatsuba multiplication it takes about
computations in a document. I have long been thinking that without the
expandability constraint much higher speeds could be achieved, but perhaps I
have not given enough thought to sustain that optimistic stance.\footnote{The
- \href{https://ctan.org/pkg/apnum}{apnum} package implements
+ \ctanpackage{apnum} package implements
(non-expandably) arbitrary precision fixed point algebra and (v1.6)
functions exp, log, sqrt, the trigonometrical direct and inverse functions.}
@@ -8076,7 +8216,7 @@ margin annotation next to the description of the arguments.
package provided conditionals such as \csbxint{ifEq}, \csbxint{ifGt},
\csbxint{ifSgn},\dots\ or, for \LaTeX{} users and when dealing
with short integers the
- \href{https://ctan.org/pkg/etoolbox}{etoolbox}%
+ \ctanpackage{etoolbox}%
%
\footnote{\url{https://ctan.org/pkg/etoolbox}}
expandable conditionals (for small integers only) such as \texttt{\char92
@@ -8617,7 +8757,7 @@ unused branches should not be forgotten.
If these tests are to be applied to standard \TeX{} short integers, it is more
efficient to use (under \LaTeX{}) the equivalent conditional tests from the
-\href{https://ctan.org/pkg/etoolbox}{etoolbox}%
+\ctanpackage{etoolbox}%
%
\footnote{\url{https://ctan.org/pkg/etoolbox}}
package.
@@ -8867,7 +9007,7 @@ early 2014.
This |1.2| release also got its impulse from a fast
``reversing'' macro, which I wrote after my interest got awakened again as a
-result of correspondance with Bruno \textsc{Le Floch} during September 2015:
+result of correspondence with Bruno \textsc{Le Floch} during September 2015:
this new reverse uses a \TeX nique which \emph{requires} the tokens to be
digits. I wrote a routine which works (expandably) in quasi-linear time, but a
less fancy |O(N^2)| variant which I developed concurrently proved to be faster
@@ -11334,8 +11474,11 @@ Prior to |1.4| a macro of the same name existed in \xintgcdname. But
it truncated all its arguments to integers via \csbxint{Num} and then
proceeded with integer only computations.
-See \csbxint{iiGCDof} for the integer only variant (which is about |6X| faster
-than this one for integer arguments).
+See \csbxint{iiGCDof} for the integer only variant.
+
+% Semble encore vrai à 1.4d
+% Mais je n'ai testé que sur un exemple...
+% (which is about |6X| faster than this one for integer arguments).
\subsection{\csh{xintLCMof}}\label{xintLCMof}
@@ -11349,8 +11492,13 @@ output.
Prior to |1.4| a macro of the same name existed in \xintgcdname. But
it truncated all its arguments to integers via \csbxint{Num}.
-See \csbxint{iiLCMof} for the integer only variant (which is about |9X| faster
-than this one for integer arguments).
+See \csbxint{iiLCMof} for the integer only variant.
+
+% Avant 1.4d on avait ceci :
+% (which is about |9X| faster han this one for integer arguments).
+% mais à 1.4d le lcm des fractions est environ 4X fois plus efficace,
+% en ce qui concerne son emploi avec des entiers (testé sur un seul exemple)
+% donc le gain de faire \xintiiexpr n'est plus que 2X !
\subsection{\csh{xintDigits}, \csh{xinttheDigits}}
\label{xintDigits}
@@ -18338,7 +18486,7 @@ math shift catcode.
\fi
\XINT_providespackage
\ProvidesPackage {xintkernel}%
- [2021/02/20 v1.4c Paraphernalia for the xint packages (JFB)]%
+ [2021/03/29 v1.4d Paraphernalia for the xint packages (JFB)]%
% \end{macrocode}
% \subsection{Constants}
% \begin{macrocode}
@@ -18431,6 +18579,7 @@ math shift catcode.
\long\def\xint_firstofone #1{#1}%
\long\def\xint_firstoftwo #1#2{#1}%
\long\def\xint_secondoftwo #1#2{#2}%
+\long\def\xint_thirdofthree#1#2#3{#3}% 1.4d
\let\xint_stop_aftergobble\xint_gob_andstop_i
\long\def\xint_stop_atfirstofone #1{ #1}%
\long\def\xint_stop_atfirstoftwo #1#2{ #1}%
@@ -18462,7 +18611,7 @@ math shift catcode.
\long\def\xint_gob_til_xint:#1\xint:{}%
\long\def\xint_gob_til_^#1^{}%
\def\xint_bracedstopper{\xint:}%
-\long\def\xint_gob_til_exclam #1!{}%
+\long\def\xint_gob_til_exclam #1!{}% documenter le catcode de ! ici
\long\def\xint_gob_til_sc #1;{}%
% \end{macrocode}
% \subsection{\csh{xint_afterfi}}
@@ -19124,7 +19273,7 @@ math shift catcode.
% \begin{macrocode}
\XINT_providespackage
\ProvidesPackage{xinttools}%
- [2021/02/20 v1.4c Expandable and non-expandable utilities (JFB)]%
+ [2021/03/29 v1.4d Expandable and non-expandable utilities (JFB)]%
% \end{macrocode}
% \lverb|\XINT_toks is used in macros such as \xintFor. It is not used
% elsewhere in the xint bundle.|
@@ -21468,7 +21617,7 @@ math shift catcode.
% \begin{macrocode}
\XINT_providespackage
\ProvidesPackage{xintcore}%
- [2021/02/20 v1.4c Expandable arithmetic on big integers (JFB)]%
+ [2021/03/29 v1.4d Expandable arithmetic on big integers (JFB)]%
% \end{macrocode}
% \subsection{(WIP!) Error conditions and exceptions}
% \lverb|As per the Mike Cowlishaw/IBM's General Decimal Arithmetic Specification
@@ -21782,6 +21931,13 @@ math shift catcode.
-{ #1}%
\krof
}%
+\def\XINT_Abs #1%
+{%
+ \xint_UDsignfork
+ #1{}%
+ -{#1}%
+ \krof
+}%
% \end{macrocode}
% \subsection{\csh{xintFDg}}
% \lverb|&
@@ -24770,7 +24926,7 @@ math shift catcode.
% \begin{macrocode}
\XINT_providespackage
\ProvidesPackage{xint}%
- [2021/02/20 v1.4c Expandable operations on big integers (JFB)]%
+ [2021/03/29 v1.4d Expandable operations on big integers (JFB)]%
% \end{macrocode}
% \subsection{More token management}
% \begin{macrocode}
@@ -26946,11 +27102,20 @@ math shift catcode.
\def\xintToggle #1{\romannumeral`&&@\iftoggle{#1}{1}{0}}%
% \end{macrocode}
% \subsection{\csh{xintiiGCD}}
-% Copied over |\xintiiGCD| code from \xintgcdnameimp at |1.3d| in order to
+% |1.3d|: |\xintiiGCD| code from \xintgcdnameimp is copied here to
% support |gcd()| function in \csbxint{iiexpr}.
%
-% At |1.4| original code removed from
-% \xintgcdnameimp as the latter now requires \xintnameimp.
+% |1.4|: removed from \xintgcdnameimp the original caode as now
+% \xintgcdnameimp loads \xintnameimp.
+%
+% \changed{1.4d}{2021/03/22} Damn'ed! Since |1.3d| (2019/01/06) the code was
+% broken if one of the arguments vanished due to a typo in macro names:
+% "AisZero" at one location and "Aiszero" at next, and same for B...
+%
+% How could this not be detected by my tests !?!
+%
+% This caused |\xintiiGCDof| hence the |gcd()| function in |\xintiiexpr| to
+% break as soon as one argument was zero.
% \begin{macrocode}
\def\xintiiGCD {\romannumeral0\xintiigcd }%
\def\xintiigcd #1{\expandafter\XINT_iigcd\romannumeral0\xintiiabs#1\xint:}%
@@ -26968,8 +27133,8 @@ math shift catcode.
\krof
#2%
}%
-\def\XINT_gcd_AisZero #1\xint:#2\xint:{ #1}%
-\def\XINT_gcd_BisZero #1\xint:#2\xint:{ #2}%
+\def\XINT_gcd_Aiszero #1\xint:#2\xint:{ #1}%
+\def\XINT_gcd_Biszero #1\xint:#2\xint:{ #2}%
\def\XINT_gcd_loop #1\xint:#2\xint:
{%
\expandafter\expandafter\expandafter\XINT_gcd_CheckRem
@@ -26982,6 +27147,29 @@ math shift catcode.
}%
\def\XINT_gcd_end0\XINT_gcd_loop #1\xint:#2\xint:{ #2}%
% \end{macrocode}
+% \subsection{\csh{xintiiGCDof}}
+% \lverb|New with 1.09a (was located in xintgcd.sty).
+%
+% 1.2l adds protection against items being non-terminated \the\numexpr.
+%
+% 1.4 renames the macro into \xintiiGCDof and moves it here.
+% Terminator modified to ^ for direct call by \xintiiexpr function.
+%
+% 1.4d fixes breakage inherited since 1.3d rom \xintiiGCD, in case
+% any argument vanished.
+%
+% Currently does not support empty list of arguments.
+% |
+% \begin{macrocode}
+\def\xintiiGCDof {\romannumeral0\xintiigcdof }%
+\def\xintiigcdof #1{\expandafter\XINT_iigcdof_a\romannumeral`&&@#1^}%
+\def\XINT_iiGCDof {\romannumeral0\XINT_iigcdof_a}%
+\def\XINT_iigcdof_a #1{\expandafter\XINT_iigcdof_b\romannumeral`&&@#1!}%
+\def\XINT_iigcdof_b #1!#2{\expandafter\XINT_iigcdof_c\romannumeral`&&@#2!{#1}!}%
+\def\XINT_iigcdof_c #1{\xint_gob_til_^ #1\XINT_iigcdof_e ^\XINT_iigcdof_d #1}%
+\def\XINT_iigcdof_d #1!{\expandafter\XINT_iigcdof_b\romannumeral0\xintiigcd {#1}}%
+\def\XINT_iigcdof_e #1!#2!{ #2}%
+% \end{macrocode}
% \subsection{\csh{xintiiLCM}}
% Copied over |\xintiiLCM| code from \xintgcdnameimp at |1.3d| in order to
% support |lcm()| function in \csbxint{iiexpr}.
@@ -27016,26 +27204,6 @@ math shift catcode.
}%
\def\XINT_lcm_end #1\xint:#2\xint:#3\xint:{\xintiimul {#2}{\xintiiQuo{#3}{#1}}}%
% \end{macrocode}
-% \subsection{\csh{xintiiGCDof}}
-% \lverb|New with 1.09a (xintgcd.sty).
-%
-% 1.2l adds protection against items being non-terminated \the\numexpr.
-%
-% 1.4 renames the macro into \xintiiGCDof and moves it here.
-% Terminator modified to ^ for direct call by \xintiiexpr function.
-% See comments
-% in xintfrac.sty about \xintGCDof macro there.|
-%
-% \begin{macrocode}
-\def\xintiiGCDof {\romannumeral0\xintiigcdof }%
-\def\xintiigcdof #1{\expandafter\XINT_iigcdof_a\romannumeral`&&@#1^}%
-\def\XINT_iiGCDof {\romannumeral0\XINT_iigcdof_a}%
-\def\XINT_iigcdof_a #1{\expandafter\XINT_iigcdof_b\romannumeral`&&@#1!}%
-\def\XINT_iigcdof_b #1!#2{\expandafter\XINT_iigcdof_c\romannumeral`&&@#2!{#1}!}%
-\def\XINT_iigcdof_c #1{\xint_gob_til_^ #1\XINT_iigcdof_e ^\XINT_iigcdof_d #1}%
-\def\XINT_iigcdof_d #1!{\expandafter\XINT_iigcdof_b\romannumeral0\xintiigcd {#1}}%
-\def\XINT_iigcdof_e #1!#2!{ #2}%
-% \end{macrocode}
% \subsection{\csh{xintiiLCMof}}
% \lverb|See comments of \xintiiGCDof|.
% \begin{macrocode}
@@ -27336,7 +27504,7 @@ math shift catcode.
% \begin{macrocode}
\XINT_providespackage
\ProvidesPackage{xintbinhex}%
- [2021/02/20 v1.4c Expandable binary and hexadecimal conversions (JFB)]%
+ [2021/03/29 v1.4d Expandable binary and hexadecimal conversions (JFB)]%
% \end{macrocode}
% \subsection{Constants, etc...}
% \lverb|1.2n switches to \csname-governed expansion at various places.|
@@ -28008,7 +28176,7 @@ math shift catcode.
% \begin{macrocode}
\XINT_providespackage
\ProvidesPackage{xintgcd}%
- [2021/02/20 v1.4c Euclide algorithm with xint package (JFB)]%
+ [2021/03/29 v1.4d Euclide algorithm with xint package (JFB)]%
% \end{macrocode}
% \subsection{\csh{xintBezout}}
% \lverb|&
@@ -28608,7 +28776,7 @@ math shift catcode.
% \begin{macrocode}
\XINT_providespackage
\ProvidesPackage{xintfrac}%
- [2021/02/20 v1.4c Expandable operations on fractions (JFB)]%
+ [2021/03/29 v1.4d Expandable operations on fractions (JFB)]%
% \end{macrocode}
% \subsection{\csh{XINT_cntSgnFork}}
% \lverb|1.09i. Used internally, #1 must expand to \m@ne, \z@, or \@ne or
@@ -30692,7 +30860,11 @@ math shift catcode.
% \end{macrocode}
% \subsection{\csh{xintDivFloor}}
% \lverb|1.1. Changed at 1.2p to not append /1[0] ending but rather output a
-% big integer in strict format, like \xintDivTrunc and \xintDivRound.|
+% big integer in strict format, like \xintDivTrunc and \xintDivRound.
+%
+%
+%
+% |
% \begin{macrocode}
\def\xintDivFloor {\romannumeral0\xintdivfloor }%
\def\xintdivfloor #1#2{\xintifloor{\xintDiv {#1}{#2}}}%
@@ -31200,80 +31372,183 @@ math shift catcode.
\def\xintSgn {\romannumeral0\xintsgn }%
\def\xintsgn #1{\expandafter\XINT_sgn\romannumeral0\xintraw {#1}\xint:}%
% \end{macrocode}
-% \subsection{\csh{xintGCD}, \csh{xintLCM}}
+% \subsection{\csh{xintGCD}}
% \changed{1.4}{}
-% They replace the former \xintgcdnameimp macros of the
-% same names which truncated to integers their arguments.
-% Fraction-producing |gcd()| and |lcm()| functions
-% were available since |1.3d| \xintexprnameimp, with non-public
-% support macros handling comma separated
-% values.
+% They replace the former \xintgcdnameimp macros of the same names which
+% truncated to integers their arguments. Fraction-producing |gcd()| and
+% |lcm()| functions were available since |1.3d| \xintexprnameimp, with
+% non-public support macros handling comma separated values.
+%
+% \changed{1.4d}{}
+% Somewhat strangely \csh{xintGCD} was formerly \csh{xintGCDof} used with only two
+% arguments, as the latter directly implemented a fractionl gcd algorithm
+% using \csh{xintMod} repeatedly for two arguments.
+%
+% Now \csh{xintGCD} contains the pairwise gcd routine and \csh{xintGCDof}
+% is only a wrapper. And the pairwise gcd is reduced to integer-only
+% computations to hopefully reduce fraction overhead.
+%
+% Each input is filtered via |\xintPIrr| and |\xintREZ| to reduce size
+% of maniuplate integers in algebra.
+%
+% But hesitation about applying |\xintPIrr| to output, and/or |\xintREZ|.
+% (as it is applied on input).
+%
+% But as the code is now used for frational lcm's we actually need to do
+% some reduction of output else lcm's of integers will not be necessarily
+% printed by |\xinteval| as integers.
+%
+% Well finally I apply |\xintIrr| (but not |\xintREZ| to output).
+% Hesitations here (thinking of inputs with large [n] parts, the output
+% will have many zeros). So I do this only for the user macro but
+% the core routine as used by |\xintGCDof| will not do it.
+%
+% Also at |1.4d| the code uses |\expanded|.
% \begin{macrocode}
\def\xintGCD {\romannumeral0\xintgcd}%
-\def\xintgcd #1#2{\XINT_fgcdof{#1}{#2}^}%
-\def\xintLCM {\romannumeral0\xintlcm}%
-\def\xintlcm #1#2{\XINT_flcmof{#1}{#2}^}%
+\def\xintgcd #1%
+{%
+ \expandafter\XINT_fgcd_in
+ \romannumeral0\xintrez{\xintPIrr{\xintAbs{#1}}}\xint:
+}%
+\def\XINT_fgcd_in #1#2\xint:#3%
+{%
+ \expandafter\XINT_fgcd_out
+ \romannumeral0\expandafter\XINT_fgcd_chkzeros\expandafter#1%
+ \romannumeral0\xintrez{\xintPIrr{\xintAbs{#3}}}\xint:#1#2\xint:
+}%
+\def\XINT_fgcd_out#1[#2]{\xintirr{#1[#2]}[0]}%
+\def\XINT_fgcd_chkzeros #1#2%
+{%
+ \xint_UDzerofork
+ #1\XINT_fgcd_aiszero
+ #2\XINT_fgcd_biszero
+ 0\XINT_fgcd_main
+ \krof #2%
+}%
+\def\XINT_fgcd_aiszero #1\xint:#2\xint:{ #1}%
+\def\XINT_fgcd_biszero #1\xint:#2\xint:{ #2}%
+\def\XINT_fgcd_main #1/#2[#3]\xint:#4/#5[#6]\xint:
+{%
+ \expandafter\XINT_fgcd_a
+ \romannumeral0\XINT_gcd_loop #2\xint:#5\xint:\xint:
+ #2\xint:#5\xint:#1\xint:#4\xint:#3.#6.%
+}%
+\def\XINT_fgcd_a #1\xint:#2\xint:
+{%
+ \expandafter\XINT_fgcd_b
+ \romannumeral0\xintiiquo{#2}{#1}\xint:#1\xint:#2\xint:
+}%
+\def\XINT_fgcd_b #1\xint:#2\xint:#3\xint:#4\xint:#5\xint:#6\xint:#7.#8.%
+{%
+ \expanded{%
+ \xintiigcd{\xintiiE{\xintiiMul{#5}{\xintiiQuo{#4}{#2}}}{#7-#8}}%
+ {\xintiiE{\xintiiMul{#6}{#1}}{#8-#7}}%
+ /\xintiiMul{#1}{#4}%
+ [\ifnum#7>#8 #8\else #7\fi]%
+ }%
+}%
% \end{macrocode}
% \subsection{\csh{xintGCDof}}
% \changed{1.4}{}
-% This inherits from former non public \xintexprnameimp macro called |\xintGCDof:csv|,
-% handling comma separated items, and former \xintgcdnameimp macro called
-% |\xintGCDof| which handled braced items to which it applied |\xintNum|
-% before handling the computations on integers only. The macro keeps the
-% former name \xintgcdnameimp, and handles fractions presented as braced
-% items. It is now the support macro for the |gcd()| function in |\xintexpr|
-% and |\xintfloatexpr|.
+% This inherits from former non public \xintexprnameimp macro called
+% |\xintGCDof:csv|, which handled comma separated items.
%
-% The support macro for the |gcd()| function in |\xintiiexpr| is
-% \csbxint{iiGCDof} which is located in \xintnameimp.
+% It handles fractions presented as braced items and is the support macro
+% for the |gcd()| function in |\xintexpr| and |\xintfloatexpr|. The support
+% macro for the |gcd()| function in |\xintiiexpr| is \csbxint{iiGCDof}, from
+% \xintnameimp.
%
+% An empty input is allowed but I have some hesitations on the return
+% value of 1.
+%
+% \changed{1.4d}{}
+% Sadly the |1.4| version had multiple problems:
+% \begin{itemize}
+% \item broken if first argument vanished,
+% \item broken if some argument was not in strict format, for example
+% had leading chains of signs or zeros (|\xintGCDof{2}{03}|).
+% This bug originates in the fact the original macro
+% was used only in \xintexprnameimp sanitized context.
+% \end{itemize}
%
+% Also, output is now always an irreducible fraction (ending with |[0]|).
% \begin{macrocode}
\def\xintGCDof {\romannumeral0\xintgcdof}%
\def\xintgcdof #1{\expandafter\XINT_fgcdof\romannumeral`&&@#1^}%
\def\XINT_GCDof{\romannumeral0\XINT_fgcdof}%
-% \end{macrocode}
-% \lverb|This abuses the way \xintiiabs works in order to avoid fetching whole
-% argument again: \xintiiabs ^ raises no error.
-% |
-% \begin{macrocode}
\def\XINT_fgcdof #1%
{%
- \xint_gob_til_^ #1\XINT_fgcdof_empty ^%
- \expandafter\XINT_fgcdof_loop\romannumeral0\xintiiabs#1\xint:
+ \expandafter\XINT_fgcdof_chkempty\romannumeral`&&@#1\xint:
+}%
+\def\XINT_fgcdof_chkempty #1%
+{%
+ \xint_gob_til_^#1\XINT_fgcdof_empty ^\XINT_fgcdof_in #1%
+}%
+\def\XINT_fgcdof_empty #1\xint:{ 1/1[0]}% hesitation, should it be infinity? O?
+\def\XINT_fgcdof_in #1\xint:
+{%
+ \expandafter\XINT_fgcd_out
+ \romannumeral0\expandafter\XINT_fgcdof_loop
+ \romannumeral0\xintrez{\xintPIrr{\xintAbs{#1}}}\xint:
}%
-\def\XINT_fgcdof_empty ^#1\xint:{ 1/1[0]}%
\def\XINT_fgcdof_loop #1\xint:#2%
{%
- \expandafter\XINT_fgcdof_loop_a\romannumeral0\xintiiabs#2\xint:#1\xint:
+ \expandafter\XINT_fgcdof_chkend\romannumeral`&&@#2\xint:#1\xint:\xint:
+}%
+\def\XINT_fgcdof_chkend #1%
+{%
+ \xint_gob_til_^#1\XINT_fgcdof_end ^\XINT_fgcdof_loop_pair #1%
+}%
+\def\XINT_fgcdof_end #1\xint:#2\xint:\xint:{ #2}%
+\def\XINT_fgcdof_loop_pair #1\xint:#2%
+{%
+ \expandafter\XINT_fgcdof_loop
+ \romannumeral0\expandafter\XINT_fgcd_chkzeros\expandafter#2%
+ \romannumeral0\xintrez{\xintPIrr{\xintAbs{#1}}}\xint:#2%
}%
% \end{macrocode}
+% \subsection{\csh{xintLCM}}
+% Same comments as for \csh{xintGCD}.
+% Entirely redone for |1.4d|.
+% Well, actually we can express it in terms of fractional gcd.
% \begin{macrocode}
-\def\XINT_fgcdof_loop_a#1#2\xint:#3\xint:
+\def\xintLCM {\romannumeral0\xintlcm}%
+\def\xintlcm #1%
{%
- \xint_gob_til_^ #1\XINT_fgcdof_end ^%
- \xint_gob_til_zero #1\XINT_fgcdof_skip 0%
- \expandafter\XINT_fgcdof_loop_b\romannumeral0\xintmod{#1#2}{#3}\xint:#3\xint:
+ \expandafter\XINT_flcm_in
+ \romannumeral0\xintrez{\xintPIrr{\xintAbs{#1}}}\xint:
}%
-\def\XINT_fgcdof_end ^#1\xint:#2\xint:{ #2}%
-\def\XINT_fgcdof_skip 0%
- \expandafter\XINT_fgcdof_loop_b\romannumeral0\xintmod#1\xint:
+\def\XINT_flcm_in #1#2\xint:#3%
{%
- \XINT_fgcdof_loop
+ \expandafter\XINT_fgcd_out
+ \romannumeral0\expandafter\XINT_flcm_chkzeros\expandafter#1%
+ \romannumeral0\xintrez{\xintPIrr{\xintAbs{#3}}}\xint:#1#2\xint:
}%
-\def\XINT_fgcdof_loop_b#1#2\xint:#3\xint:
+\def\XINT_flcm_chkzeros #1#2%
{%
- \xint_gob_til_zero #1\XINT_fgcdof_next 0%
- \expandafter\XINT_fgcdof_loop_b\romannumeral0\xintmod{#3}{#1#2}\xint:#1#2\xint:
+ \xint_UDzerofork
+ #1\XINT_flcm_zero
+ #2\XINT_flcm_zero
+ 0\XINT_flcm_main
+ \krof #2%
}%
-\def\XINT_fgcdof_next 0%
- \expandafter\XINT_fgcdof_loop_b\romannumeral0\xintmod#1#2\xint:#3\xint:#4%
+\def\XINT_flcm_zero #1\xint:#2\xint:{ 0/1[0]}%
+\def\XINT_flcm_main #1/#2[#3]\xint:#4/#5[#6]\xint:
{%
- \expandafter\XINT_fgcdof_loop_a\romannumeral0\xintiiabs#4\xint:#1\xint:
+ \xintinv
+ {%
+ \romannumeral0\XINT_fgcd_main #2/#1[-#3]\xint:#5/#4[-#6]\xint:
+ }%
}%
% \end{macrocode}
% \subsection{\csh{xintLCMof}}
-% See comments for |\xintGCDof|. \xintnameimp provides integer only \csbxint{iiLCMof}.
+% See comments for |\xintGCDof|. \xintnameimp provides the integer only
+% \csbxint{iiLCMof}.
+%
+% \changes{1.4d}{}
+% Sadly, although a public \xintfracnameimp macro, it did not (since |1.4|)
+% sanitize its arguments like other \xintfracnameimp macros.
%
% \begin{macrocode}
\def\xintLCMof {\romannumeral0\xintlcmof}%
@@ -31281,50 +31556,39 @@ math shift catcode.
\def\XINT_LCMof{\romannumeral0\XINT_flcmof}%
\def\XINT_flcmof #1%
{%
- \xint_gob_til_^ #1\XINT_flcmof_empty ^%
- \expandafter\XINT_flcmof_loop\romannumeral0\xintiiabs\xintRaw{#1}\xint:
+ \expandafter\XINT_flcmof_chkempty\romannumeral`&&@#1\xint:
}%
-\def\XINT_flcmof_empty ^#1\xint:{ 0/1[0]}%
-% \end{macrocode}
-% \lverb|\XINT_inv expects A/B[N] format which is the case here.|
-% \begin{macrocode}
-\def\XINT_flcmof_loop #1%
+\def\XINT_flcmof_chkempty #1%
{%
- \xint_gob_til_zero #1\XINT_flcmof_zero 0%
- \expandafter\XINT_flcmof_d\romannumeral0\XINT_inv #1%
+ \xint_gob_til_^#1\XINT_flcmof_empty ^\XINT_flcmof_in #1%
}%
-\def\XINT_flcmof_zero #1^{ 0/1[0]}%
-% \end{macrocode}
-% \lverb|\xintRaw{^} would raise an error thus we delay application of
-% \xintRaw to new item. As soon as we hit against a zero item, the l.c.m is
-% known to be zero itself. Else we need to inverse new item, but this requires
-% full A/B[N] raw format, hence the \xintraw.|
-% \begin{macrocode}
-\def\XINT_flcmof_d #1\xint:#2%
+\def\XINT_flcmof_empty #1\xint:{ 0/1[0]}% hesitation
+\def\XINT_flcmof_in #1\xint:
{%
- \expandafter\XINT_flcmof_loop_a\romannumeral0\xintiiabs#2\xint:#1\xint:
+ \expandafter\XINT_fgcd_out
+ \romannumeral0\expandafter\XINT_flcmof_loop
+ \romannumeral0\xintrez{\xintPIrr{\xintAbs{#1}}}\xint:
}%
-\def\XINT_flcmof_loop_a #1#2\xint:%
+\def\XINT_flcmof_loop #1\xint:#2%
{%
- \xint_gob_til_^ #1\XINT_flcmof_end ^%
- \xint_gob_til_zero #1\XINT_flcmof_zero 0%
- \expandafter\XINT_flcmof_loop_b\romannumeral0\expandafter\XINT_inv
- \romannumeral0\xintraw{#1#2}\xint:
+ \expandafter\XINT_flcmof_chkend\romannumeral`&&@#2\xint:#1\xint:\xint:
}%
-\def\XINT_flcmof_end ^#1\xint:#2\xint:{\XINT_inv #2}%
-% \end{macrocode}
-% \lverb|This is Euclide algorithm.|
-% \begin{macrocode}
-\def\XINT_flcmof_loop_b #1#2\xint:#3\xint:
+\def\XINT_flcmof_chkend #1%
{%
- \xint_gob_til_zero #1\XINT_flcmof_next 0%
- \expandafter\XINT_flcmof_loop_b\romannumeral0\xintmod{#3}{#1#2}\xint:#1#2\xint:
+ \xint_gob_til_^#1\XINT_flcmof_end ^\XINT_flcmof_loop_pair #1%
}%
-\def\XINT_flcmof_next 0%
- \expandafter\XINT_flcmof_loop_b\romannumeral0\xintmod#1#2\xint:#3\xint:#4%
+\def\XINT_flcmof_end #1\xint:#2\xint:\xint:{ #2}%
+\def\XINT_flcmof_loop_pair #1\xint:#2%
{%
- \expandafter\XINT_flcmof_loop_a\romannumeral0\xintiiabs#4\xint:#1\xint:
+ \expandafter\XINT_flcmof_chkzero
+ \romannumeral0\expandafter\XINT_flcm_chkzeros\expandafter#2%
+ \romannumeral0\xintrez{\xintPIrr{\xintAbs{#1}}}\xint:#2%
}%
+\def\XINT_flcmof_chkzero #1%
+{%
+ \xint_gob_til_zero#1\XINT_flcmof_zero0\XINT_flcmof_loop#1%
+}%
+\def\XINT_flcmof_zero#1^{ 0/1[0]}%
% \end{macrocode}
% \subsection{Floating point macros}
%
@@ -33797,7 +34061,7 @@ math shift catcode.
% \begin{macrocode}
\XINT_providespackage
\ProvidesPackage{xintseries}%
- [2021/02/20 v1.4c Expandable partial sums with xint package (JFB)]%
+ [2021/03/29 v1.4d Expandable partial sums with xint package (JFB)]%
% \end{macrocode}
% \subsection{\csh{xintSeries}}
% \begin{macrocode}
@@ -34298,7 +34562,7 @@ math shift catcode.
% \begin{macrocode}
\XINT_providespackage
\ProvidesPackage{xintcfrac}%
- [2021/02/20 v1.4c Expandable continued fractions with xint package (JFB)]%
+ [2021/03/29 v1.4d Expandable continued fractions with xint package (JFB)]%
% \end{macrocode}
% \subsection{\csh{xintCFrac}}
% \begin{macrocode}
@@ -35690,7 +35954,7 @@ math shift catcode.
% \begin{macrocode}
\XINT_providespackage
\ProvidesPackage{xintexpr}%
- [2021/02/20 v1.4c Expandable expression parser (JFB)]%
+ [2021/03/29 v1.4d Expandable expression parser (JFB)]%
\catcode`! 11
\let\XINT_Cmp \xintiiCmp
\def\XINTfstop{\noexpand\XINTfstop}%
@@ -35713,7 +35977,10 @@ math shift catcode.
% \subsubsection{Bracketed list rendering with prettifying of leaves from nested
% braced contents}
% \lverb|1.4 The braces in \XINT:expr:toblistwith are there because there is
-% an \expanded trigger.|
+% an \expanded trigger.
+%
+% 1.4d: support for polexpr 0.8 polynomial type.
+% |
% \begin{macrocode}
\def\XINT:expr:toblistwith#1#2%
{%
@@ -35729,8 +35996,13 @@ math shift catcode.
\def\XINT:expr:toblist_a #1{#2%
<%
\if{#2\xint_dothis<[\XINT:expr:toblist_a>\fi
+ \if P#2\xint_dothis<\XINT:expr:toblist_pol>\fi
\xint_orthat\XINT:expr:toblist_b #1#2%
>%
+\def\XINT:expr:toblist_pol #1!#2.{#3}}%
+<%
+ pol([\XINT:expr:toblist_b #1!#3}^])\XINT:expr:toblist_c #1!}%
+>%
\def\XINT:expr:toblist_b #1!#2}%
<%
\if\relax#2\relax\xintexprEmptyItem\else#1<#2>\fi\XINT:expr:toblist_c #1!}%
@@ -36235,7 +36507,6 @@ math shift catcode.
\let\XINT:NEhook:f:one:from:two\expandafter
\let\XINT:NEhook:f:one:from:two:direct\empty
\let\XINT:NEhook:x:one:from:two\empty
-\let\XINT:NEhook:x:one:from:twoandone\empty
\let\XINT:NEhook:f:one:and:opt:direct \empty
\let\XINT:NEhook:f:tacitzeroifone:direct \empty
\let\XINT:NEhook:f:iitacitzeroifone:direct \empty
@@ -36969,10 +37240,6 @@ math shift catcode.
% This means cases like (a+b)/(c+d)(e+f) will first multiply the last two
% parenthesized terms.
%
-% The ! starting a sub-expression must be distinguished from the post-fix !
-% for factorial, thus we must not do a too early \string. In versions < 1.2c,
-% the catcode 11 ! had to be identified in all branches of the number or
-% function scans. Here it is simply treated as a special case of a letter.
%
% 1.2q adds tacit multiplication in cases such as (1+1)3 or 5!7!
%
@@ -37396,11 +37663,11 @@ math shift catcode.
\XINT_expr_defbin_b {flexpr}{xor}{vi}{xii} {xintXOR}%
\XINT_expr_defbin_b {iiexpr}{xor}{vi}{xii} {xintXOR}%
\XINT_expr_defbin_b {expr} {//} {xiv}{xiv}{xintDivFloor}%
-\XINT_expr_defbin_b {flexpr}{//} {xiv}{xiv}{XINTinFloatDivFloor}% "
-\XINT_expr_defbin_b {iiexpr}{//} {xiv}{xiv}{xintiiDivFloor}% "
-\XINT_expr_defbin_b {expr} {/:} {xiv}{xiv}{xintMod}% "
-\XINT_expr_defbin_b {flexpr}{/:} {xiv}{xiv}{XINTinFloatMod}% "
-\XINT_expr_defbin_b {iiexpr}{/:} {xiv}{xiv}{xintiiMod}% "
+\XINT_expr_defbin_b {flexpr}{//} {xiv}{xiv}{XINTinFloatDivFloor}%
+\XINT_expr_defbin_b {iiexpr}{//} {xiv}{xiv}{xintiiDivFloor}%
+\XINT_expr_defbin_b {expr} {/:} {xiv}{xiv}{xintMod}%
+\XINT_expr_defbin_b {flexpr}{/:} {xiv}{xiv}{XINTinFloatMod}%
+\XINT_expr_defbin_b {iiexpr}{/:} {xiv}{xiv}{xintiiMod}%
\XINT_expr_defbin_b {expr} + {xii}{xii}{xintAdd}%
\XINT_expr_defbin_b {flexpr} + {xii}{xii}{XINTinFloatAdd}%
\XINT_expr_defbin_b {iiexpr} + {xii}{xii}{xintiiAdd}%
@@ -38414,7 +38681,7 @@ math shift catcode.
*\unexpanded{\expandafter\expandafter}%
\expandafter\noexpand\csname XINT_expr_var_#1\endcsname(}%
\ifxintverbose\xintMessage{xintexpr}{Info}
- {Variable "#1" \ifxintglobaldefs globally \fi
+ {Variable #1 \ifxintglobaldefs globally \fi
defined with value \csname XINT_expr_varvalue_#1\endcsname.}%
\fi
}%
@@ -39801,7 +40068,7 @@ math shift catcode.
% {float}{sfloat}{ilog10}
% {divmod}{mod}{binomial}{pfactorial}
% {randrange}
-% {quo}{rem}{gcd}{lcm}{max}{min}
+% {iquo}{irem}{gcd}{lcm}{max}{min}
% {`+`}{`*`}
% {all}{any}{xor}
% {len}{first}{last}{reversed}
@@ -40268,27 +40535,13 @@ math shift catcode.
{\xintiiRandRange{#1}}%
{\xintiiRandRangeAtoB{#1}{#2}}%
}%
-\def\XINT_expr_func_quo #1#2#3%
-{%
- \expandafter #1\expandafter #2\expandafter{\romannumeral`&&@%
- \XINT:NEhook:f:one:from:two
- {\romannumeral`&&@\xintiQuo #3}}%
-}%
-\let\XINT_flexpr_func_quo\XINT_expr_func_quo
-\def\XINT_iiexpr_func_quo #1#2#3%
+\def\XINT_iiexpr_func_iquo #1#2#3%
{%
\expandafter #1\expandafter #2\expandafter{\romannumeral`&&@%
\XINT:NEhook:f:one:from:two
{\romannumeral`&&@\xintiiQuo #3}}%
}%
-\def\XINT_expr_func_rem #1#2#3%
-{%
- \expandafter #1\expandafter #2\expandafter{\romannumeral`&&@%
- \XINT:NEhook:f:one:from:two
- {\romannumeral`&&@\xintiRem #3}}%
-}%
-\let\XINT_flexpr_func_rem\XINT_expr_func_rem
-\def\XINT_iiexpr_func_rem #1#2#3%
+\def\XINT_iiexpr_func_irem #1#2#3%
{%
\expandafter #1\expandafter #2\expandafter{\romannumeral`&&@%
\XINT:NEhook:f:one:from:two
@@ -41024,7 +41277,7 @@ math shift catcode.
}}\expandafter\XINT:NE:f:iitacitzeroifone:direct\string#%
\def\XINT:NE:f:iitacitzeroifone_a #1#2&&A#3%
{%
- \detokenize{\romannumeral`-0\expandafter#1\expanded{#2}$XINT_expr_exclam#3}%$
+ \detokenize{\romannumeral`$XINT_expr_null\expandafter#1\expanded{#2}$XINT_expr_exclam#3}%
}%
\def\XINT:NE:f:iitacitzeroifone_b\XINT:expr:f:iitacitzeroifone #1#2#3&&A#4%
{%
@@ -41045,16 +41298,6 @@ math shift catcode.
}}\expandafter\XINT:NE:x:one:from:two_fork\string#%
\def\XINT:NE:x:one:from:two:p #1#2#3%
{~expanded{\detokenize{\expandafter#1}~expanded{{#2}{#3}}}}%
-\def\XINT:NE:x:one:from:twoandone #1#2#3{\XINT:NE:x:one:from:twoandone_a #2#3&&A#1{#2}{#3}}%
-\def\XINT:NE:x:one:from:twoandone_a #1#2{\XINT:NE:x:one:from:twoandone_fork #1&&A#2&&A}%
-\def\XINT:NE:x:one:from:twoandone_fork #1{%
-\def\XINT:NE:x:one:from:twoandone_fork ##1##2&&A##3##4&&A##5##6&&A%
-{%
- \if0\XINT:NE:hastilde ##1##3##5~!\relax\XINT:NE:hashash ##1##3##5#1!\relax 0%
- \else
- \expandafter\XINT:NE:x:one:from:two:p
- \fi
-}}\expandafter\XINT:NE:x:one:from:twoandone_fork\string#%
\def\XINT:NE:x:listsel #1{%
\def\XINT:NE:x:listsel ##1##2&%
{%
@@ -41065,13 +41308,12 @@ math shift catcode.
\fi
##1##2&%
}}\expandafter\XINT:NE:x:listsel\string#%
-\def\XINT:NE:x:listsel:p #1#2&(#3%
+\def\XINT:NE:x:listsel:p #1#2_#3&(#4%
{%
- \detokenize
- {%
- \expanded{\expandafter#1\expanded{#2$XINT_expr_tab({#3}}\expandafter\empty\empty}%$
- }%
+ \detokenize{\expanded\XINT:expr:ListSel{{#3}{#4}}}%
}%
+\def\XINT:expr:ListSel{\expandafter\XINT:expr:ListSel_i\expanded}%
+\def\XINT:expr:ListSel_i #1#2{{\XINT_ListSel_top #2_#1&({#2}}}%
\def\XINT:NE:f:reverse #1{%
\def\XINT:NE:f:reverse ##1^%
{%
@@ -41084,13 +41326,14 @@ math shift catcode.
}}\expandafter\XINT:NE:f:reverse\string#%
\def\XINT:NE:f:reverse:p #1^#2\xint_bye
{%
- \detokenize
- {%
- \romannumeral0\expandafter\XINT:expr:f:reverse
- \expandafter{\expanded\expandafter{\xint_gobble_i#1}}%
- }%
+ \expandafter\XINT:NE:f:reverse:p_i\expandafter{\xint_gobble_i#1}%
}%
-\def\XINT:expr:f:reverse #1%
+\def\XINT:NE:f:reverse:p_i #1%
+{%
+ \detokenize{\romannumeral0\XINT:expr:f:reverse{{#1}}}%
+}%
+\def\XINT:expr:f:reverse{\expandafter\XINT:expr:f:reverse_i\expanded}%
+\def\XINT:expr:f:reverse_i #1%
{%
\XINT_expr_reverse #1^^#1\xint:\xint:\xint:\xint:
\xint:\xint:\xint:\xint:\xint_bye
@@ -41118,7 +41361,7 @@ math shift catcode.
##1{##2}%
}}\expandafter\XINT:NE:f:noeval:from:braced:u\string#%
\def\XINT:NE:f:noeval:from:braced:u:p #1#2%
- {\detokenize{\expandafter#1}~expanded{{#2}}}%
+ {\detokenize{\romannumeral`$XINT_expr_null\expandafter#1}~expanded{{#2}}}%
\catcode`- 11
\def\XINT:NE:exec_? #1#2%
{%
@@ -41518,7 +41761,6 @@ math shift catcode.
\let\XINT:NEhook:f:one:from:two \XINT:NE:f:one:from:two
\let\XINT:NEhook:f:one:from:two:direct \XINT:NE:f:one:from:two:direct
\let\XINT:NEhook:x:one:from:two \XINT:NE:x:one:from:two
- \let\XINT:NEhook:x:one:from:twoandone \XINT:NE:x:one:from:twoandone
\let\XINT:NEhook:f:one:and:opt:direct \XINT:NE:f:one:and:opt:direct
\let\XINT:NEhook:f:tacitzeroifone:direct \XINT:NE:f:tacitzeroifone:direct
\let\XINT:NEhook:f:iitacitzeroifone:direct \XINT:NE:f:iitacitzeroifone:direct
@@ -41678,6 +41920,7 @@ math shift catcode.
\def\XINT_expr_tilde{~}\def\XINT_expr_qmark{?}% catcode 3
\def\XINT_expr_caret{^}\def\XINT_expr_exclam{!}% catcode 11
\def\XINT_expr_tab{&}% catcode 7
+\def\XINT_expr_null{&&@}%
\catcode`~ 13 \catcode`@ 14 \catcode`\% 6 \catcode`# 12 \catcode`$ 11 @ $
\def\XINT_NewExpr_a %1%2%3%4%5@
{@
@@ -41869,10 +42112,10 @@ math shift catcode.
\expandafter\xint_secondoftwo
\fi
{\immediate\write-1{Reloading xinttrig library using Digits=\xinttheDigits.}}%
-{\expandafter\gdef\csname xintlibver@trig\endcsname{2021/02/20 v1.4c}%
+{\expandafter\gdef\csname xintlibver@trig\endcsname{2021/03/29 v1.4d}%
\XINT_providespackage
\ProvidesPackage{xinttrig}%
-[2021/02/20 v1.4c Trigonometrical functions for xintexpr (JFB)]%
+[2021/03/29 v1.4d Trigonometrical functions for xintexpr (JFB)]%
}%
% \end{macrocode}
% \subsection{Ensure used letters are dummy letters}
@@ -42868,7 +43111,7 @@ math shift catcode.
\xintexprSafeCatcodes\catcode`_ 11
\XINT_providespackage
\ProvidesPackage{xintlog}%
-[2021/02/20 v1.4c Logarithms and exponentials for xintexpr (JFB)]%
+[2021/03/29 v1.4d Logarithms and exponentials for xintexpr (JFB)]%
% \end{macrocode}
% \subsection{Loading of \cshn{poormanlog} package}
% \lverb|Attention to catcode regime when loading poormanlog. It matters less
@@ -42882,13 +43125,13 @@ math shift catcode.
\fi
% \end{macrocode}
% \lverb|\XINT_setcatcodes switches to the standard catcode regime of
-% xint*.sty files. And we need the xintexpr catcode for ! too (cf
-% \XINT_expr_func_pow)
+% xint*.sty files. Formerly we needed here the ! of catcode 11 as in
+% xintexpr.sty, which is set by \XINT_setcatcodes but does not apply now.
%
% See the remark above about importance of doing \xintexprRestoreCatcodes if
% \xintexprSafeCatcodes has been used...|
% \begin{macrocode}
-\xintexprRestoreCatcodes\csname XINT_setcatcodes\endcsname\catcode`\! 11
+\xintexprRestoreCatcodes\csname XINT_setcatcodes\endcsname
% \end{macrocode}
% \subsection{The \cshn{log10()} and \cshn{pow10()} functions}
% \lverb|The support macros from poormanlog v0.04 \PoorManLogBaseTen,
@@ -42941,9 +43184,6 @@ math shift catcode.
\romannumeral`&&@\XINT:NEhook:f:one:from:one
{\romannumeral`&&@\XINTinFloatExp#3}}%
}%
-% \end{macrocode}
-% \lverb|Attention that the ! is of catcode 11 here.|
-% \begin{macrocode}
\def\XINT_expr_func_pow #1#2#3%
{%
\expandafter #1\expandafter #2\expandafter{%
@@ -42954,7 +43194,11 @@ math shift catcode.
% \end{macrocode}
% \subsection{\csh{poormanloghack}}
% \lverb|With \poormanloghack{**}, the ** operator will use pow10(y*log10(x)).
-% Same for ^. Sync'd with xintexpr 1.4.|
+% Same for ^. Sync'd with xintexpr 1.4.
+%
+% MEMO: the reason why I need to redefine a lot of stuff is that xintexpr.sty
+% does the job only for ^ and then does a \let for exec_** only. So if now
+% ^ and ** possibly act differently all must be duplicated.|
% \begin{macrocode}
\catcode`\* 11
\def\poormanloghack**
@@ -43064,9 +43308,9 @@ math shift catcode.
xint.sty:205
xintbinhex.sty:53
xintcfrac.sty:183
-xintcore.sty:271
-xintexpr.sty:430
-xintfrac.sty:496
+xintcore.sty:272
+xintexpr.sty:428
+xintfrac.sty:507
xintgcd.sty:41
xintkernel.sty:17
xintlog.sty:9
@@ -43075,15 +43319,15 @@ xinttools.sty:157
xinttrig.sty:31
\fi
% grep -o "^{%" xint*sty | wc -l
-\def\totala{ 1941}
+\def\totala{ 1951}
\iffalse
% grep -c -e "^}%" xint*sty
xint.sty:204
xintbinhex.sty:52
xintcfrac.sty:183
-xintcore.sty:268
-xintexpr.sty:413
-xintfrac.sty:499
+xintcore.sty:269
+xintexpr.sty:412
+xintfrac.sty:510
xintgcd.sty:43
xintkernel.sty:18
xintlog.sty:9
@@ -43092,7 +43336,7 @@ xinttools.sty:156
xinttrig.sty:32
\fi
% grep -o "^}%" xint*sty | wc -l
-\def\totalb{ 1925}
+\def\totalb{ 1936}
\cleardoublepage
\section{Cumulative line count}
@@ -43116,8 +43360,8 @@ xinttrig.sty:32
\TeX\strut. Version {\xintbndlversion} of {\xintbndldate}.\par
}
-\CheckSum {35109}% 1.4c
-% 35103 pour 1.4b, 34648 pour 1.4a, 34575 pour 1.4
+\CheckSum {35184}% 1.4d
+% 35109 pour 1.4c, 35103 pour 1.4b, 34648 pour 1.4a, 34575 pour 1.4
% 33497 pour 1.3f, 33274 pour 1.3e, 31601 pour 1.3d, 31122 pour 1.3c
% 31069 pour 1.3b, 30482 pour 1.3a, 30621 pour 1.3, 30988 pour 1.2q,
% 30982 pour 1.2p, 30524 pour 1.2o, 30303 pour 1.2h, 30403 pour 1.2i,
diff --git a/macros/generic/xint/xint.pdf b/macros/generic/xint/xint.pdf
index 5be576e57e..35ac85b1b0 100644
--- a/macros/generic/xint/xint.pdf
+++ b/macros/generic/xint/xint.pdf
Binary files differ