diff options
-rw-r--r-- | Master/texmf-dist/doc/generic/polexpr/README.md (renamed from Master/texmf-dist/doc/latex/polexpr/README.md) | 95 | ||||
-rw-r--r-- | Master/texmf-dist/doc/generic/polexpr/polexpr.html | 4086 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/polexpr/polexpr.html | 2911 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/polexpr/polexpr.txt | 2598 | ||||
-rw-r--r-- | Master/texmf-dist/tex/generic/polexpr/polexpr.sty | 1057 | ||||
-rw-r--r-- | Master/texmf-dist/tex/generic/polexpr/polexprcore.tex | 1366 | ||||
-rw-r--r-- | Master/texmf-dist/tex/generic/polexpr/polexprexpr.tex | 179 | ||||
-rw-r--r-- | Master/texmf-dist/tex/generic/polexpr/polexprsturm.tex (renamed from Master/texmf-dist/tex/latex/polexpr/polexpr.sty) | 1813 | ||||
-rwxr-xr-x | Master/tlpkg/libexec/ctan2tds | 1 |
9 files changed, 6959 insertions, 7147 deletions
diff --git a/Master/texmf-dist/doc/latex/polexpr/README.md b/Master/texmf-dist/doc/generic/polexpr/README.md index a901b56adc7..b32b8f056df 100644 --- a/Master/texmf-dist/doc/latex/polexpr/README.md +++ b/Master/texmf-dist/doc/generic/polexpr/README.md @@ -1,46 +1,43 @@ Package polexpr README ====================== -License -------- +Usage +----- -Copyright (C) 2018-2020 Jean-François Burnol +The package can be used with TeX based formats incorporating the +e-TeX primitives. The `\expanded` primitive available generally +since TeXLive 2019 is required. -See documentation of package [xint](http://www.ctan.org/pkg/xint) for -contact information. + \input polexpr.sty -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 +with Plain or other non-LaTeX macro formats, or: -> <http://www.latex-project.org/lppl/lppl-1-3c.txt> + \usepackage{polexpr} -and version 1.3 or later is part of all distributions of LaTeX version -2005/12/01 or later. +with the LaTeX macro format. -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 file polexpr.sty, this README.md and -the documentation file polexpr.txt. +The package currently requires xintexpr.sty `1.4d` or later. Abstract -------- -The package provides `\poldef`. This a parser of polynomial expressions -based upon the `\xintdeffunc` mechanism of xintexpr. +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. -The parsed expressions use the operations of algebra (inclusive of -composition of functions) with standard operators, fractional numbers -(possibly in scientific notation) and previously defined polynomial -functions or other constructs as recognized by the `\xintexpr` numerical -parser. +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. -The polynomials are then not only genuine `\xintexpr` (and -`\xintfloatexpr`) numerical functions but additionally are known to the -package via their coefficients. This allows dedicated macros to -implement polynomial algorithmics. +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 -------- @@ -62,7 +59,7 @@ Releases - Main new feature: root localization via [Sturm Theorem](https://en.wikipedia.org/wiki/Sturm%27s_theorem). - 0.4.1 (2018/03/01) - Synced with xint 1.3. + Synced with xintexpr 1.3. - 0.4.2 (2018/03/03) Documentation fix. - 0.5 (2018/04/08) @@ -82,21 +79,45 @@ Releases Bugfix: 20000000000 is too big for \numexpr, shouldn't I know that? Thanks to Jürgen Gilg for report. - 0.7.5 (2020/01/31) - Synced with xint 1.4. Requires it. + 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.7.5 release: +Files of 0.8 release: +- polexpr.sty, polexprcore.tex, polexprexpr.tex, polexprsturm.tex, - README.md, -- polexpr.sty (package file), -- polexpr.txt (documentation), -- polexpr.html (conversion via - [DocUtils](http://docutils.sourceforge.net/docs/index.html) - rst2html.py) +- polexpr.html (documentation) Acknowledgments --------------- Thanks to Jürgen Gilg whose question about -[xint](http://www.ctan.org/pkg/xint) usage for differentiating +[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/Master/texmf-dist/doc/generic/polexpr/polexpr.html b/Master/texmf-dist/doc/generic/polexpr/polexpr.html new file mode 100644 index 00000000000..81cd2b4b7c1 --- /dev/null +++ b/Master/texmf-dist/doc/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"><, >, <=, >=, ==, !=</span></a></p></li> +<li><p><a class="reference internal" href="#pol-nutple-expression" id="id50"><span class="docutils literal"><span class="pre">pol(<nutple</span> expression>)</span></a></p></li> +<li><p><a class="reference internal" href="#xinteval-pol-expr" id="id51"><span class="docutils literal"><span class="pre">\xinteval{<pol.</span> <span class="pre">expr.>}</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(<pol.</span> <span class="pre">expr.>,</span> <pol. expr>)</span></a></p></li> +<li><p><a class="reference internal" href="#deg-pol-expr" id="id53"><span class="docutils literal"><span class="pre">deg(<pol.</span> <span class="pre">expr.>)</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(<pol.</span> <span class="pre">expr.>)</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(<pol.</span> <span class="pre">expr.>,</span> <num. <span class="pre">expr.>)</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(<pol.</span> <span class="pre">expr.>)</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(<pol.</span> <span class="pre">expr.>)</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(<pol.</span> <span class="pre">expr.>)</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(<pol.</span> <span class="pre">expr.>)</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(<pol.</span> <span class="pre">expr.>,</span> <pol. <span class="pre">expr.>)</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(<pol.</span> <span class="pre">expr.>,</span> <pol. <span class="pre">expr.>)</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(<pol.</span> <span class="pre">expr.>,</span> <pol. <span class="pre">expr.>)</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(<pol.</span> expr. 1>, <pol. expr. 2>)</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(<pol.</span> expr. 1>, <pol. expr. 2>)</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(<pol.</span> expr. 1>, <pol. expr. 2>)</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(<pol.</span> expr. 1>, <pol. expr. 2>, <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(<pol.</span> expr. 1>, <pol. expr. 2>)</span></a></p></li> +<li><p><a class="reference internal" href="#disc-pol-expr" id="id68"><span class="docutils literal"><span class="pre">disc(<pol.</span> <span class="pre">expr.>)</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(<pol.</span> expr. 1>, <num. <span class="pre">expr.>,</span> <pol. expr. 2>)</span></a></p></li> +<li><p><a class="reference internal" href="#rdcoeffs-pol-expr" id="id70"><span class="docutils literal"><span class="pre">rdcoeffs(<pol.</span> <span class="pre">expr.>)</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(<pol.</span> <span class="pre">expr.>)</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(<pol.</span> <span class="pre">expr.>)</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(<pol.</span> <span class="pre">expr.>)</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(<pol.</span> expr. P>, <num. expr. n>)</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(<pol.</span> expr. P>)</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(<pol.</span> expr. P>, <pol. expr. c>)</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(<pol.</span> expr. P>, [<pol. expr. a>, <pol. expr. <span class="pre">b>])</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}{<csv>}</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{<pol.</span> <span class="pre">expr.>}</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*{<pol.</span> <span class="pre">expr.>}</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{<pol.</span> <span class="pre">expr.>}</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*{<pol.</span> <span class="pre">expr.>}</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{<pol.</span> <span class="pre">expr.>}</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*{<pol.</span> <span class="pre">expr.>}</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">@</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">@</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">@</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 "ties more", 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)% <--- 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)% <--- 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{<pol. expr.>}</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"><, >, <=, >=, ==, !=</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(<nutple</span> expression>)</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 "nutple".</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 "variable" to refer to +arbitrary expressions used as function arguments, without implying +that we are actually referring to pre-declared variables in the sense +of <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{<pol.</span> <span class="pre">expr.>}</span></span></a></h2> +<blockquote> +<p>This is documented here for lack of a better place: it evaluates the +polynomial expression then outputs the "string" <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 "pol" word uses letter catcodes, which is actually mandatory for +this output to be usable as input, but it does not make sense to use +this inside <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(<pol.</span> <span class="pre">expr.>,</span> <pol. expr>)</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(<pol.</span> <span class="pre">expr.>)</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)<0</span></span> correctly detects the zero polynomial, +and <span class="docutils literal"><span class="pre">deg(P)<=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(<pol.</span> <span class="pre">expr.>)</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(<pol.</span> <span class="pre">expr.>,</span> <num. <span class="pre">expr.>)</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(<pol.</span> <span class="pre">expr.>)</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(<pol.</span> <span class="pre">expr.>)</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(<pol.</span> <span class="pre">expr.>)</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(<pol.</span> <span class="pre">expr.>)</span></span></a></h2> +<blockquote> +<p>The quotient (except for the zero polynomial) by +<span class="docutils literal"><span class="pre">icontent(<pol.</span> <span class="pre">expr.>)</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(<pol.</span> <span class="pre">expr.>,</span> <pol. <span class="pre">expr.>)</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(<pol.</span> <span class="pre">expr.>,</span> <pol. <span class="pre">expr.>)</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(<pol.</span> <span class="pre">expr.>,</span> <pol. <span class="pre">expr.>)</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(<pol.</span> expr. 1>, <pol. expr. 2>)</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)>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)>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(<pol.</span> expr. 1>, <pol. expr. 2>)</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(<pol.</span> expr. 1>, <pol. expr. 2>)</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(<pol.</span> expr. 1>, <pol. expr. 2>, <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 "nutple" 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(<pol.</span> expr. 1>, <pol. expr. 2>)</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(<pol.</span> <span class="pre">expr.>)</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(<pol.</span> expr. 1>, <num. <span class="pre">expr.>,</span> <pol. expr. 2>)</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)>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 > 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(<pol.</span> <span class="pre">expr.>)</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(<pol.</span> <span class="pre">expr.>)</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(<pol.</span> <span class="pre">expr.>)</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(<pol.</span> <span class="pre">expr.>)</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(<pol.</span> expr. P>, <num. expr. n>)</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<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(<pol.</span> expr. P>)</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(<pol.</span> expr. P>, <pol. expr. c>)</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(<pol.</span> expr. P>, [<pol. expr. a>, <pol. expr. <span class="pre">b>])</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{<pol. expr.>}</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}<Z_2<\PolSturmIsolatedZeroRight{f}{2}$$ +And here is the first root with twenty digits after decimal mark: +\PolEnsureIntervalLength{f}{1}{-20} +$$\PolSturmIsolatedZeroLeft{f}{1}<Z_1<\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 < Z_1 < 1.1, 1.10 < Z_2 < 1.11, 1.110 < Z_3 < 1.111, and 1.111 < Z_4 < 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 < Z_1 < 1.06, 1.105 < Z_2 < 1.106, 1.1105 < Z_3 < 1.1106, +% and 1.11105 < Z_4 < 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 = "sturmname" +\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}<x<\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 "polname" as "sturmname" too +\PolSturmIsolateZerosAndGetMultiplicities{f}% use the "sturmname" 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 < x < 0.99 +The multiplicity is 1 for the root such that 0.9991 < x < 0.9992 +The multiplicity is 1 for the root such that 0.9997 < x < 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 < x < 0.9899888033 +The multiplicity is 1 for the root such that 0.9991447980 < x < 0.9991447981 +The multiplicity is 1 for the root such that 0.9997663986 < x < 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 < Z_1 < -1, 0.09 < Z_2 < 0.10, 0.1 < Z_3 < 0.2, 1 < Z_4 < 2 +Let us refine the second and third intervals to separate the corresponding +roots: +\PolRefineInterval*{P}{2}% will refine to 0.0999990 < Z_2 < 0.0999991 +\PolRefineInterval*{P}{3}% will refine to 0.100001 < Z_3 < 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}<Z_2<\PolSturmIsolatedZeroRight{P}{2}$$</pre> +<p>The last line produces:</p> +<pre class="literal-block">0.09999900004999650028 < Z_2 < 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<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{<pol. expr.>}</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}{<csv>}</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{<pol.</span> <span class="pre">expr.>}</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*{<pol.</span> <span class="pre">expr.>}</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 "square-free part" 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 <= 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 < z < 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"><sturmname>L_1</span>, +<span class="docutils literal"><sturmname>L_2</span>, etc..., for the left end-points and +<span class="docutils literal"><sturmname>R_1</span>, <span class="docutils literal"><sturmname>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 "known" 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<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<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"><</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{% + &&\PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}% + &=&\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&<&% + \PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}&<&% + \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@@PrintIntervals...</span></span> macros. We only reproduce here one +definition:</p> +<pre class="literal-block">\newcommand\POL@@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{<pol.</span> <span class="pre">expr.>}</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*{<pol.</span> <span class="pre">expr.>}</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{<pol. expr.>}</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{<pol.</span> <span class="pre">expr.>}</span></span></a></h2> +<blockquote> +<p>Similar to <a class="reference internal" href="#poltoexpr-pol-expr">\PolToExpr{<pol. expr.>}</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*{<pol.</span> <span class="pre">expr.>}</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"><sturmname>_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{<pol. expr.>}</a> and <a class="reference internal" href="#poltofloatexpr-pol-expr">\PolToFloatExpr{<pol. expr.>}</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">"README thinks \numexpr recognizes ^ operator"</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">&&</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 +"ople" 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/Master/texmf-dist/doc/latex/polexpr/polexpr.html b/Master/texmf-dist/doc/latex/polexpr/polexpr.html deleted file mode 100644 index 74963329764..00000000000 --- a/Master/texmf-dist/doc/latex/polexpr/polexpr.html +++ /dev/null @@ -1,2911 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head> -<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> -<meta name="generator" content="Docutils 0.14: http://docutils.sourceforge.net/" /> -<title>Package polexpr documentation</title> -<style type="text/css"> - -/* -:Author: David Goodger (goodger@python.org) -:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $ -:Copyright: This stylesheet has been placed in the public domain. - -Default cascading style sheet for the HTML output of Docutils. - -See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to -customize this style sheet. -*/ - -/* used to remove borders from tables and images */ -.borderless, table.borderless td, table.borderless th { - border: 0 } - -table.borderless td, table.borderless th { - /* Override padding for "table.docutils td" with "! important". - The right padding separates the table cells. */ - padding: 0 0.5em 0 0 ! important } - -.first { - /* Override more specific margin styles with "! important". */ - margin-top: 0 ! important } - -.last, .with-subtitle { - margin-bottom: 0 ! important } - -.hidden { - display: none } - -.subscript { - vertical-align: sub; - font-size: smaller } - -.superscript { - vertical-align: super; - font-size: smaller } - -a.toc-backref { - text-decoration: none ; - color: black } - -blockquote.epigraph { - margin: 2em 5em ; } - -dl.docutils dd { - margin-bottom: 0.5em } - -object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] { - overflow: hidden; -} - -/* Uncomment (and remove this text!) to get bold-faced definition list terms -dl.docutils dt { - font-weight: bold } -*/ - -div.abstract { - margin: 2em 5em } - -div.abstract p.topic-title { - font-weight: bold ; - text-align: center } - -div.admonition, div.attention, div.caution, div.danger, div.error, -div.hint, div.important, div.note, div.tip, div.warning { - margin: 2em ; - border: medium outset ; - padding: 1em } - -div.admonition p.admonition-title, div.hint p.admonition-title, -div.important p.admonition-title, div.note p.admonition-title, -div.tip p.admonition-title { - font-weight: bold ; - font-family: sans-serif } - -div.attention p.admonition-title, div.caution p.admonition-title, -div.danger p.admonition-title, div.error p.admonition-title, -div.warning p.admonition-title, .code .error { - color: red ; - font-weight: bold ; - font-family: sans-serif } - -/* Uncomment (and remove this text!) to get reduced vertical space in - compound paragraphs. -div.compound .compound-first, div.compound .compound-middle { - margin-bottom: 0.5em } - -div.compound .compound-last, div.compound .compound-middle { - margin-top: 0.5em } -*/ - -div.dedication { - margin: 2em 5em ; - text-align: center ; - font-style: italic } - -div.dedication p.topic-title { - font-weight: bold ; - font-style: normal } - -div.figure { - margin-left: 2em ; - margin-right: 2em } - -div.footer, div.header { - clear: both; - font-size: smaller } - -div.line-block { - display: block ; - margin-top: 1em ; - margin-bottom: 1em } - -div.line-block div.line-block { - margin-top: 0 ; - margin-bottom: 0 ; - margin-left: 1.5em } - -div.sidebar { - margin: 0 0 0.5em 1em ; - border: medium outset ; - padding: 1em ; - background-color: #ffffee ; - width: 40% ; - float: right ; - clear: right } - -div.sidebar p.rubric { - font-family: sans-serif ; - font-size: medium } - -div.system-messages { - margin: 5em } - -div.system-messages h1 { - color: red } - -div.system-message { - border: medium outset ; - padding: 1em } - -div.system-message p.system-message-title { - color: red ; - font-weight: bold } - -div.topic { - margin: 2em } - -h1.section-subtitle, h2.section-subtitle, h3.section-subtitle, -h4.section-subtitle, h5.section-subtitle, h6.section-subtitle { - margin-top: 0.4em } - -h1.title { - text-align: center } - -h2.subtitle { - text-align: center } - -hr.docutils { - width: 75% } - -img.align-left, .figure.align-left, object.align-left, table.align-left { - clear: left ; - float: left ; - margin-right: 1em } - -img.align-right, .figure.align-right, object.align-right, table.align-right { - clear: right ; - float: right ; - margin-left: 1em } - -img.align-center, .figure.align-center, object.align-center { - display: block; - margin-left: auto; - margin-right: auto; -} - -table.align-center { - margin-left: auto; - margin-right: auto; -} - -.align-left { - text-align: left } - -.align-center { - clear: both ; - text-align: center } - -.align-right { - text-align: right } - -/* reset inner alignment in figures */ -div.align-right { - text-align: inherit } - -/* div.align-center * { */ -/* text-align: left } */ - -.align-top { - vertical-align: top } - -.align-middle { - vertical-align: middle } - -.align-bottom { - vertical-align: bottom } - -ol.simple, ul.simple { - margin-bottom: 1em } - -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 } - -p.attribution { - text-align: right ; - margin-left: 50% } - -p.caption { - font-style: italic } - -p.credits { - font-style: italic ; - font-size: smaller } - -p.label { - white-space: nowrap } - -p.rubric { - font-weight: bold ; - font-size: larger ; - color: maroon ; - text-align: center } - -p.sidebar-title { - font-family: sans-serif ; - font-weight: bold ; - font-size: larger } - -p.sidebar-subtitle { - font-family: sans-serif ; - font-weight: bold } - -p.topic-title { - font-weight: bold } - -pre.address { - margin-bottom: 0 ; - margin-top: 0 ; - font: inherit } - -pre.literal-block, pre.doctest-block, pre.math, pre.code { - margin-left: 2em ; - margin-right: 2em } - -pre.code .ln { color: grey; } /* line numbers */ -pre.code, code { background-color: #eeeeee } -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} - -span.classifier { - font-family: sans-serif ; - font-style: oblique } - -span.classifier-delimiter { - font-family: sans-serif ; - font-weight: bold } - -span.interpreted { - font-family: sans-serif } - -span.option { - white-space: nowrap } - -span.pre { - white-space: pre } - -span.problematic { - color: red } - -span.section-subtitle { - /* font-size relative to parent (h1..h6 element) */ - font-size: 80% } - -table.citation { - border-left: solid 1px gray; - margin-left: 1px } - -table.docinfo { - margin: 2em 4em } - -table.docutils { - margin-top: 0.5em ; - margin-bottom: 0.5em } - -table.footnote { - border-left: solid 1px black; - margin-left: 1px } - -table.docutils td, table.docutils th, -table.docinfo td, table.docinfo th { - padding-left: 0.5em ; - padding-right: 0.5em ; - vertical-align: top } - -table.docutils th.field-name, table.docinfo th.docinfo-name { - font-weight: bold ; - text-align: left ; - white-space: nowrap ; - padding-left: 0 } - -/* "booktabs" style (no vertical lines) */ -table.docutils.booktabs { - border: 0px; - border-top: 2px solid; - border-bottom: 2px solid; - border-collapse: collapse; -} -table.docutils.booktabs * { - border: 0px; -} -table.docutils.booktabs th { - border-bottom: thin solid; - text-align: left; -} - -h1 tt.docutils, h2 tt.docutils, h3 tt.docutils, -h4 tt.docutils, h5 tt.docutils, h6 tt.docutils { - font-size: 100% } - -ul.auto-toc { - list-style-type: none } - -</style> -</head> -<body> -<div class="document" id="package-polexpr-documentation"> -<h1 class="title">Package polexpr documentation</h1> -<h2 class="subtitle" id="id1">0.7.5 (2020/01/31)</h2> - -<!-- comment: -*- fill-column: 72; mode: rst; -*- --> -<div class="contents topic" id="contents"> -<p class="topic-title first">Contents</p> -<ul class="simple"> -<li><a class="reference internal" href="#basic-syntax" id="id38">Basic syntax</a></li> -<li><a class="reference internal" href="#examples-of-localization-of-roots" id="id39">Examples of localization of roots</a><ul> -<li><a class="reference internal" href="#a-typical-example" id="id40">A typical example</a></li> -<li><a class="reference internal" href="#a-degree-four-polynomial-with-nearby-roots" id="id41">A degree four polynomial with nearby roots</a></li> -<li><a class="reference internal" href="#the-degree-nine-polynomial-with-0-99-0-999-0-9999-as-triple-roots" id="id42">The degree nine polynomial with 0.99, 0.999, 0.9999 as triple roots</a></li> -<li><a class="reference internal" href="#a-degree-five-polynomial-with-three-rational-roots" id="id43">A degree five polynomial with three rational roots</a></li> -<li><a class="reference internal" href="#a-mignotte-type-polynomial" id="id44">A Mignotte type polynomial</a></li> -<li><a class="reference internal" href="#the-wilkinson-polynomial" id="id45">The Wilkinson polynomial</a></li> -<li><a class="reference internal" href="#the-second-wilkinson-polynomial" id="id46">The second Wilkinson polynomial</a></li> -<li><a class="reference internal" href="#the-degree-41-polynomial-with-2-1-9-1-8-0-0-1-1-9-2-as-roots" id="id47">The degree 41 polynomial with -2, -1.9, -1.8, ..., 0, 0.1, ..., 1.9, 2 as roots</a></li> -<li><a class="reference internal" href="#roots-of-chebyshev-polynomials" id="id48">Roots of Chebyshev polynomials</a></li> -</ul> -</li> -<li><a class="reference internal" href="#non-expandable-macros" id="id49">Non-expandable macros</a><ul> -<li><a class="reference internal" href="#poldef-polname-letter-expression-in-letter" id="id50"><tt class="docutils literal">\poldef <span class="pre">polname(letter):=</span> expression in letter;</tt></a></li> -<li><a class="reference internal" href="#poldef-letter-polname-expression-in-letter" id="id51"><tt class="docutils literal"><span class="pre">\PolDef[letter]{polname}{expression</span> in letter}</tt></a></li> -<li><a class="reference internal" href="#polgenfloatvariant-polname" id="id52"><tt class="docutils literal">\PolGenFloatVariant{polname}</tt></a></li> -<li><a class="reference internal" href="#pollet-polname-2-polname-1" id="id53"><tt class="docutils literal"><span class="pre">\PolLet{polname_2}={polname_1}</span></tt></a></li> -<li><a class="reference internal" href="#polgloballet-polname-2-polname-1" id="id54"><tt class="docutils literal"><span class="pre">\PolGlobalLet{polname_2}={polname_1}</span></tt></a></li> -<li><a class="reference internal" href="#polassign-polname-toarray-macro" id="id55"><tt class="docutils literal"><span class="pre">\PolAssign{polname}\toarray\macro</span></tt></a></li> -<li><a class="reference internal" href="#polget-polname-fromarray-macro" id="id56"><tt class="docutils literal"><span class="pre">\PolGet{polname}\fromarray\macro</span></tt></a></li> -<li><a class="reference internal" href="#polfromcsv-polname-csv" id="id57"><tt class="docutils literal"><span class="pre">\PolFromCSV{polname}{<csv>}</span></tt></a></li> -<li><a class="reference internal" href="#poltypeset-polname" id="id58"><tt class="docutils literal">\PolTypeset{polname}</tt></a><ul> -<li><a class="reference internal" href="#poltypesetcmd-raw-coeff" id="id59"><tt class="docutils literal">\PolTypesetCmd{raw_coeff}</tt></a></li> -<li><a class="reference internal" href="#poltypesetone-raw-coeff" id="id60"><tt class="docutils literal">\PolTypesetOne{raw_coeff}</tt></a></li> -<li><a class="reference internal" href="#id6" id="id61"><tt class="docutils literal">\PolTypesetMonomialCmd</tt></a></li> -<li><a class="reference internal" href="#poltypesetcmdprefix-raw-coeff" id="id62"><tt class="docutils literal">\PolTypesetCmdPrefix{raw_coeff}</tt></a></li> -</ul> -</li> -<li><a class="reference internal" href="#id8" id="id63"><tt class="docutils literal"><span class="pre">\PolTypeset*{polname}</span></tt></a></li> -<li><a class="reference internal" href="#poldiff-polname-1-polname-2" id="id64"><tt class="docutils literal"><span class="pre">\PolDiff{polname_1}{polname_2}</span></tt></a></li> -<li><a class="reference internal" href="#poldiff-n-polname-1-polname-2" id="id65"><tt class="docutils literal"><span class="pre">\PolDiff[N]{polname_1}{polname_2}</span></tt></a></li> -<li><a class="reference internal" href="#polantidiff-polname-1-polname-2" id="id66"><tt class="docutils literal"><span class="pre">\PolAntiDiff{polname_1}{polname_2}</span></tt></a></li> -<li><a class="reference internal" href="#polantidiff-n-polname-1-polname-2" id="id67"><tt class="docutils literal"><span class="pre">\PolAntiDiff[N]{polname_1}{polname_2}</span></tt></a></li> -<li><a class="reference internal" href="#poldivide-polname-1-polname-2-polname-q-polname-r" id="id68"><tt class="docutils literal"><span class="pre">\PolDivide{polname_1}{polname_2}{polname_Q}{polname_R}</span></tt></a></li> -<li><a class="reference internal" href="#polquo-polname-1-polname-2-polname-q" id="id69"><tt class="docutils literal"><span class="pre">\PolQuo{polname_1}{polname_2}{polname_Q}</span></tt></a></li> -<li><a class="reference internal" href="#polrem-polname-1-polname-2-polname-r" id="id70"><tt class="docutils literal"><span class="pre">\PolRem{polname_1}{polname_2}{polname_R}</span></tt></a></li> -<li><a class="reference internal" href="#polgcd-polname-1-polname-2-polname-gcd" id="id71"><tt class="docutils literal"><span class="pre">\PolGCD{polname_1}{polname_2}{polname_GCD}</span></tt></a></li> -<li><a class="reference internal" href="#poltosturm-polname-sturmname" id="id72"><tt class="docutils literal"><span class="pre">\PolToSturm{polname}{sturmname}</span></tt></a></li> -<li><a class="reference internal" href="#id10" id="id73"><tt class="docutils literal"><span class="pre">\PolToSturm*{polname}{sturmname}</span></tt></a></li> -<li><a class="reference internal" href="#polsettosturmchainsignchangesat-macro-sturmname-fraction" id="id74"><tt class="docutils literal"><span class="pre">\PolSetToSturmChainSignChangesAt{\macro}{sturmname}{fraction}</span></tt></a></li> -<li><a class="reference internal" href="#polsettonbofzeroswithin-macro-sturmname-value-a-value-b" id="id75"><tt class="docutils literal"><span class="pre">\PolSetToNbOfZerosWithin{\macro}{sturmname}{value_a}{value_b}</span></tt></a></li> -<li><a class="reference internal" href="#polsturmisolatezeros-sturmname" id="id76"><tt class="docutils literal">\PolSturmIsolateZeros{sturmname}</tt></a></li> -<li><a class="reference internal" href="#id12" id="id77"><tt class="docutils literal"><span class="pre">\PolSturmIsolateZeros*{sturmname}</span></tt></a></li> -<li><a class="reference internal" href="#id14" id="id78"><tt class="docutils literal"><span class="pre">\PolSturmIsolateZeros**{sturmname}</span></tt></a></li> -<li><a class="reference internal" href="#polsturmisolatezerosandgetmultiplicities-sturmname" id="id79"><tt class="docutils literal">\PolSturmIsolateZerosAndGetMultiplicities{sturmname}</tt></a></li> -<li><a class="reference internal" href="#polsturmisolatezerosgetmultiplicitiesandrationalroots-sturmname" id="id80"><tt class="docutils literal">\PolSturmIsolateZerosGetMultiplicitiesAndRationalRoots{sturmname}</tt></a></li> -<li><a class="reference internal" href="#polsturmisolatezerosandfindrationalroots-sturmname" id="id81"><tt class="docutils literal">\PolSturmIsolateZerosAndFindRationalRoots{sturmname}</tt></a></li> -<li><a class="reference internal" href="#polrefineinterval-sturmname-index" id="id82"><tt class="docutils literal"><span class="pre">\PolRefineInterval*{sturmname}{index}</span></tt></a></li> -<li><a class="reference internal" href="#polrefineinterval-n-sturmname-index" id="id83"><tt class="docutils literal"><span class="pre">\PolRefineInterval[N]{sturmname}{index}</span></tt></a></li> -<li><a class="reference internal" href="#polensureintervallength-sturmname-index-e" id="id84"><tt class="docutils literal"><span class="pre">\PolEnsureIntervalLength{sturmname}{index}{E}</span></tt></a></li> -<li><a class="reference internal" href="#polensureintervallengths-sturmname-e" id="id85"><tt class="docutils literal"><span class="pre">\PolEnsureIntervalLengths{sturmname}{E}</span></tt></a></li> -<li><a class="reference internal" href="#polprintintervals-varname-sturmname" id="id86"><tt class="docutils literal"><span class="pre">\PolPrintIntervals[varname]{sturmname}</span></tt></a><ul> -<li><a class="reference internal" href="#polprintintervalsnorealroots" id="id87"><tt class="docutils literal">\PolPrintIntervalsNoRealRoots</tt></a></li> -<li><a class="reference internal" href="#polprintintervalsbeginenv" id="id88"><tt class="docutils literal">\PolPrintIntervalsBeginEnv</tt></a></li> -<li><a class="reference internal" href="#polprintintervalsendenv" id="id89"><tt class="docutils literal">\PolPrintIntervalsEndEnv</tt></a></li> -<li><a class="reference internal" href="#polprintintervalsknownroot" id="id90"><tt class="docutils literal">\PolPrintIntervalsKnownRoot</tt></a></li> -<li><a class="reference internal" href="#polprintintervalsunknownroot" id="id91"><tt class="docutils literal">\PolPrintIntervalsUnknownRoot</tt></a></li> -<li><a class="reference internal" href="#id15" id="id92"><tt class="docutils literal">\PolPrintIntervalsPrintExactZero</tt></a></li> -<li><a class="reference internal" href="#id16" id="id93"><tt class="docutils literal">\PolPrintIntervalsPrintLeftEndPoint</tt></a></li> -<li><a class="reference internal" href="#id17" id="id94"><tt class="docutils literal">\PolPrintIntervalsPrintRightEndPoint</tt></a></li> -</ul> -</li> -<li><a class="reference internal" href="#id19" id="id95"><tt class="docutils literal"><span class="pre">\PolPrintIntervals*[varname]{sturmname}</span></tt></a><ul> -<li><a class="reference internal" href="#polprintintervalsprintmultiplicity" id="id96"><tt class="docutils literal">\PolPrintIntervalsPrintMultiplicity</tt></a></li> -</ul> -</li> -<li><a class="reference internal" href="#polmapcoeffs-macro-polname" id="id97"><tt class="docutils literal"><span class="pre">\PolMapCoeffs{\macro}{polname}</span></tt></a></li> -<li><a class="reference internal" href="#polreducecoeffs-polname" id="id98"><tt class="docutils literal">\PolReduceCoeffs{polname}</tt></a></li> -<li><a class="reference internal" href="#id21" id="id99"><tt class="docutils literal"><span class="pre">\PolReduceCoeffs*{polname}</span></tt></a></li> -<li><a class="reference internal" href="#polmakemonic-polname" id="id100"><tt class="docutils literal">\PolMakeMonic{polname}</tt></a></li> -<li><a class="reference internal" href="#polmakeprimitive-polname" id="id101"><tt class="docutils literal">\PolMakePrimitive{polname}</tt></a></li> -</ul> -</li> -<li><a class="reference internal" href="#expandable-macros" id="id102">Expandable macros</a><ul> -<li><a class="reference internal" href="#poleval-polname-atexpr-numerical-expression" id="id103"><tt class="docutils literal"><span class="pre">\PolEval{polname}\AtExpr{numerical</span> expression}</tt></a></li> -<li><a class="reference internal" href="#poleval-polname-at-fraction" id="id104"><tt class="docutils literal"><span class="pre">\PolEval{polname}\At{fraction}</span></tt></a></li> -<li><a class="reference internal" href="#polevalreduced-polname-atexpr-numerical-expression" id="id105"><tt class="docutils literal"><span class="pre">\PolEvalReduced{polname}\AtExpr{numerical</span> expression}</tt></a></li> -<li><a class="reference internal" href="#polevalreduced-polname-at-fraction" id="id106"><tt class="docutils literal"><span class="pre">\PolEvalReduced{polname}\At{fraction}</span></tt></a></li> -<li><a class="reference internal" href="#polfloateval-polname-atexpr-numerical-expression" id="id107"><tt class="docutils literal"><span class="pre">\PolFloatEval{polname}\AtExpr{numerical</span> expression}</tt></a></li> -<li><a class="reference internal" href="#polfloateval-polname-at-fraction" id="id108"><tt class="docutils literal"><span class="pre">\PolFloatEval{polname}\At{fraction}</span></tt></a></li> -<li><a class="reference internal" href="#polifcoeffisplusorminusone-a-b" id="id109"><tt class="docutils literal"><span class="pre">\PolIfCoeffIsPlusOrMinusOne{A}{B}</span></tt></a></li> -<li><a class="reference internal" href="#polleadingcoeff-polname" id="id110"><tt class="docutils literal">\PolLeadingCoeff{polname}</tt></a></li> -<li><a class="reference internal" href="#polnthcoeff-polname-number" id="id111"><tt class="docutils literal"><span class="pre">\PolNthCoeff{polname}{number}</span></tt></a></li> -<li><a class="reference internal" href="#poldegree-polname" id="id112"><tt class="docutils literal">\PolDegree{polname}</tt></a></li> -<li><a class="reference internal" href="#policontent-polname" id="id113"><tt class="docutils literal">\PolIContent{polname}</tt></a></li> -<li><a class="reference internal" href="#poltoexpr-polname" id="id114"><tt class="docutils literal">\PolToExpr{polname}</tt></a><ul> -<li><a class="reference internal" href="#poltoexproneterm-raw-coeff-number" id="id115"><tt class="docutils literal"><span class="pre">\PolToExprOneTerm{raw_coeff}{number}</span></tt></a></li> -<li><a class="reference internal" href="#poltoexpronetermstylea-raw-coeff-number" id="id116"><tt class="docutils literal"><span class="pre">\PolToExprOneTermStyleA{raw_coeff}{number}</span></tt></a></li> -<li><a class="reference internal" href="#poltoexpronetermstyleb-raw-coeff-number" id="id117"><tt class="docutils literal"><span class="pre">\PolToExprOneTermStyleB{raw_coeff}{number}</span></tt></a></li> -<li><a class="reference internal" href="#poltoexprcmd-raw-coeff" id="id118"><tt class="docutils literal">\PolToExprCmd{raw_coeff}</tt></a></li> -<li><a class="reference internal" href="#poltoexprtermprefix-raw-coeff" id="id119"><tt class="docutils literal">\PolToExprTermPrefix{raw_coeff}</tt></a></li> -<li><a class="reference internal" href="#id28" id="id120"><tt class="docutils literal">\PolToExprVar</tt></a></li> -<li><a class="reference internal" href="#id29" id="id121"><tt class="docutils literal">\PolToExprTimes</tt></a></li> -</ul> -</li> -<li><a class="reference internal" href="#id31" id="id122"><tt class="docutils literal"><span class="pre">\PolToExpr*{polname}</span></tt></a></li> -<li><a class="reference internal" href="#poltofloatexpr-polname" id="id123"><tt class="docutils literal">\PolToFloatExpr{polname}</tt></a><ul> -<li><a class="reference internal" href="#poltofloatexproneterm-raw-coeff-number" id="id124"><tt class="docutils literal"><span class="pre">\PolToFloatExprOneTerm{raw_coeff}{number}</span></tt></a></li> -<li><a class="reference internal" href="#poltofloatexprcmd-raw-coeff" id="id125"><tt class="docutils literal">\PolToFloatExprCmd{raw_coeff}</tt></a></li> -</ul> -</li> -<li><a class="reference internal" href="#id35" id="id126"><tt class="docutils literal"><span class="pre">\PolToFloatExpr*{polname}</span></tt></a></li> -<li><a class="reference internal" href="#poltolist-polname" id="id127"><tt class="docutils literal">\PolToList{polname}</tt></a></li> -<li><a class="reference internal" href="#poltocsv-polname" id="id128"><tt class="docutils literal">\PolToCSV{polname}</tt></a></li> -<li><a class="reference internal" href="#polsturmchainlength-sturmname" id="id129"><tt class="docutils literal">\PolSturmChainLength{sturmname}</tt></a></li> -<li><a class="reference internal" href="#polsturmifzeroexactlyknown-sturmname-index-a-b" id="id130"><tt class="docutils literal"><span class="pre">\PolSturmIfZeroExactlyKnown{sturmname}{index}{A}{B}</span></tt></a></li> -<li><a class="reference internal" href="#polsturmisolatedzeroleft-sturmname-index" id="id131"><tt class="docutils literal"><span class="pre">\PolSturmIsolatedZeroLeft{sturmname}{index}</span></tt></a></li> -<li><a class="reference internal" href="#polsturmisolatedzeroright-sturmname-index" id="id132"><tt class="docutils literal"><span class="pre">\PolSturmIsolatedZeroRight{sturmname}{index}</span></tt></a></li> -<li><a class="reference internal" href="#polsturmisolatedzeromultiplicity-sturmname-index" id="id133"><tt class="docutils literal"><span class="pre">\PolSturmIsolatedZeroMultiplicity{sturmname}{index}</span></tt></a></li> -<li><a class="reference internal" href="#polsturmnbofisolatedzeros-sturmname" id="id134"><tt class="docutils literal">\PolSturmNbOfIsolatedZeros{sturmname}</tt></a><ul> -<li><a class="reference internal" href="#polsturmnbofrootsof-sturmname-lessthanorequalto-value" id="id135"><tt class="docutils literal"><span class="pre">\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualTo{value}</span></tt></a></li> -<li><a class="reference internal" href="#polsturmnbofrootsof-sturmname-lessthanorequaltoexpr-expression" id="id136"><tt class="docutils literal"><span class="pre">\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualToExpr{expression}</span></tt></a></li> -<li><a class="reference internal" href="#polsturmnbwithmultofrootsof-sturmname-lessthanorequalto-value" id="id137"><tt class="docutils literal"><span class="pre">\PolSturmNbWithMultOfRootsOf{sturmname}\LessThanOrEqualTo{value}</span></tt></a></li> -<li><a class="reference internal" href="#polsturmnbwithmultofrootsof-sturmname-lessthanorequaltoexpr-expression" id="id138"><tt class="docutils literal"><span class="pre">\PolSturmNbWithMultOfRootsOf{sturmname}\LessThanOrEqualToExpr{expression}</span></tt></a></li> -</ul> -</li> -<li><a class="reference internal" href="#polsturmnbofrationalroots-sturmname" id="id139"><tt class="docutils literal">\PolSturmNbOfRationalRoots{sturmname}</tt></a></li> -<li><a class="reference internal" href="#polsturmnbofrationalrootswithmultiplicities-sturmname" id="id140"><tt class="docutils literal">\PolSturmNbOfRationalRootsWithMultiplicities{sturmname}</tt></a></li> -<li><a class="reference internal" href="#polsturmrationalroot-sturmname-k" id="id141"><tt class="docutils literal"><span class="pre">\PolSturmRationalRoot{sturmname}{k}</span></tt></a></li> -<li><a class="reference internal" href="#polsturmrationalrootindex-sturmname-k" id="id142"><tt class="docutils literal"><span class="pre">\PolSturmRationalRootIndex{sturmname}{k}</span></tt></a></li> -<li><a class="reference internal" href="#polsturmrationalrootmultiplicity-sturmname-k" id="id143"><tt class="docutils literal"><span class="pre">\PolSturmRationalRootMultiplicity{sturmname}{k}</span></tt></a></li> -<li><a class="reference internal" href="#polintervalwidth-sturmname-index" id="id144"><tt class="docutils literal"><span class="pre">\PolIntervalWidth{sturmname}{index}</span></tt></a></li> -<li><a class="reference internal" href="#expandable-macros-for-use-within-execution-of-polprintintervals" id="id145">Expandable macros for use within execution of <tt class="docutils literal">\PolPrintIntervals</tt></a><ul> -<li><a class="reference internal" href="#polprintintervalsthevar" id="id146"><tt class="docutils literal">\PolPrintIntervalsTheVar</tt></a></li> -<li><a class="reference internal" href="#polprintintervalstheindex" id="id147"><tt class="docutils literal">\PolPrintIntervalsTheIndex</tt></a></li> -<li><a class="reference internal" href="#polprintintervalsthesturmname" id="id148"><tt class="docutils literal">\PolPrintIntervalsTheSturmName</tt></a></li> -<li><a class="reference internal" href="#polprintintervalstheleftendpoint" id="id149"><tt class="docutils literal">\PolPrintIntervalsTheLeftEndPoint</tt></a></li> -<li><a class="reference internal" href="#polprintintervalstherightendpoint" id="id150"><tt class="docutils literal">\PolPrintIntervalsTheRightEndPoint</tt></a></li> -<li><a class="reference internal" href="#polprintintervalsthemultiplicity" id="id151"><tt class="docutils literal">\PolPrintIntervalsTheMultiplicity</tt></a></li> -</ul> -</li> -<li><a class="reference internal" href="#poldectostring-decimal-number" id="id152"><tt class="docutils literal">\PolDecToString{decimal number}</tt></a></li> -</ul> -</li> -<li><a class="reference internal" href="#booleans-with-default-setting-as-indicated" id="id153">Booleans (with default setting as indicated)</a><ul> -<li><a class="reference internal" href="#xintverbosefalse" id="id154"><tt class="docutils literal">\xintverbosefalse</tt></a></li> -<li><a class="reference internal" href="#poltypesetallfalse" id="id155"><tt class="docutils literal">\poltypesetallfalse</tt></a></li> -<li><a class="reference internal" href="#poltoexprallfalse" id="id156"><tt class="docutils literal">\poltoexprallfalse</tt></a></li> -</ul> -</li> -<li><a class="reference internal" href="#polexprsetup" id="id157"><tt class="docutils literal">\polexprsetup</tt></a></li> -<li><a class="reference internal" href="#technicalities" id="id158">Technicalities</a></li> -<li><a class="reference internal" href="#change-log" id="id159">CHANGE LOG</a></li> -<li><a class="reference internal" href="#acknowledgments" id="id160">Acknowledgments</a></li> -</ul> -</div> -<div class="section" id="basic-syntax"> -<h1><a class="toc-backref" href="#id38">Basic syntax</a></h1> -<p>The syntax is:</p> -<pre class="literal-block"> -\poldef polname(x):= expression in variable x; -</pre> -<p>where:</p> -<ul class="simple"> -<li>in place of <tt class="docutils literal">x</tt> an arbitrary <em>dummy variable</em> is authorized, -i.e. per default any of <tt class="docutils literal"><span class="pre">[a-z|A-Z]</span></tt> (more letters can be declared -under Unicode engines.)</li> -<li><tt class="docutils literal">polname</tt> consists of letters, digits, and the <tt class="docutils literal">_</tt> and -<tt class="docutils literal">'</tt> characters. It must start with a letter.</li> -</ul> -<div class="admonition attention"> -<p class="first admonition-title">Attention!</p> -<p class="last">The <tt class="docutils literal">'</tt> is authorized since <tt class="docutils literal">0.5.1</tt>. As a result some constructs -recognized by the <tt class="docutils literal">\xintexpr</tt> parser, such as <tt class="docutils literal">var1 'and' var2</tt> -will get misinterpreted and cause errors. However these constructs -are unlikely to be frequently needed in polynomial expressions, and -the <tt class="docutils literal">\xintexpr</tt> syntax offers alternatives, so it was deemed a -small evil. Of course the <tt class="docutils literal">\xintexpr</tt> parser is modified only -temporarily during execution of <tt class="docutils literal">\poldef</tt>.</p> -</div> -<p>One can also issue:</p> -<pre class="literal-block"> -\PolDef{polname}{expression in variable x} -</pre> -<p>which admits an optional first argument to modify the variable letter -from its default <tt class="docutils literal">x</tt>.</p> -<dl class="docutils"> -<dt><tt class="docutils literal">\poldef <span class="pre">f(x):=</span> <span class="pre">1-x+x^2;</span></tt></dt> -<dd>defines polynomial <tt class="docutils literal">f</tt>. Polynomial names must start with a -letter and may contain letters, digits, underscores and the right -tick character. The -variable must be a single letter. The colon character is optional. -The semi-colon at end of expression is mandatory.</dd> -<dt><tt class="docutils literal"><span class="pre">\PolDef{f}{1-x+x^2}</span></tt></dt> -<dd>does the same as <tt class="docutils literal">\poldef <span class="pre">f(x):=</span> <span class="pre">1-x+x^2;</span></tt> To use another letter -than <tt class="docutils literal">x</tt> in the expression, one must pass it as an extra optional -argument to <tt class="docutils literal">\PolDef</tt>. Useful if the semi-colon has been assigned -some non-standard catcode by some package.</dd> -<dt><tt class="docutils literal"><span class="pre">\PolLet{g}={f}</span></tt></dt> -<dd>saves a copy of <tt class="docutils literal">f</tt> under name <tt class="docutils literal">g</tt>. Also usable without <tt class="docutils literal">=</tt>.</dd> -<dt><tt class="docutils literal">\poldef <span class="pre">f(z):=</span> <span class="pre">f(z)^2;</span></tt></dt> -<dd>redefines <tt class="docutils literal">f</tt> in terms of itself.</dd> -<dt><tt class="docutils literal">\poldef <span class="pre">f(T):=</span> <span class="pre">f(f(T));</span></tt></dt> -<dd>again redefines <tt class="docutils literal">f</tt> in terms of its (new) self.</dd> -<dt><tt class="docutils literal">\poldef <span class="pre">k(z):=</span> <span class="pre">f(z)-g(g(z)^2)^2;</span></tt></dt> -<dd>should now define the zero polynomial... Let's check: -<tt class="docutils literal">\[ k(z) = <span class="pre">\PolTypeset[z]{k}</span> \]</tt></dd> -<dt><tt class="docutils literal"><span class="pre">\PolDiff{f}{f'}</span></tt></dt> -<dd>sets <tt class="docutils literal">f'</tt> to the derivative of <tt class="docutils literal">f</tt>. The name doesn't have to be -<tt class="docutils literal">f'</tt> (in fact the <tt class="docutils literal">'</tt> is licit only since <tt class="docutils literal">0.5.1</tt>).</dd> -</dl> -<div class="admonition important"> -<p class="first admonition-title">Important</p> -<p class="last">This is not done automatically. If some new definition needs to use -the derivative of some available polynomial, that derivative -polynomial must have been defined via <tt class="docutils literal">\PolDiff</tt>: something like -<tt class="docutils literal"><span class="pre">T'(x)^2</span></tt> will not work without a prior <tt class="docutils literal"><span class="pre">\PolDiff{T}{T'}</span></tt>.</p> -</div> -<dl class="docutils"> -<dt><tt class="docutils literal"><span class="pre">\PolDiff{f'}{f''}</span></tt></dt> -<dd>obtains second derivative.</dd> -<dt><tt class="docutils literal"><span class="pre">\PolDiff[3]{f}{f'''}</span></tt></dt> -<dd>computes the third derivative.</dd> -</dl> -<pre class="literal-block"> -$f(z) = \PolTypeset[z]{f} $\newline -$f'(z) = \PolTypeset[z]{f'} $\newline -$f''(z) = \PolTypeset[z]{f''} $\newline -$f'''(z)= \PolTypeset[z]{f'''} $\par -</pre> -<div class="admonition important"> -<p class="first admonition-title">Important</p> -<p>The package does not currently know rational functions: <tt class="docutils literal">/</tt> in -a parsed polynomial expression does the Euclidean quotient:</p> -<pre class="literal-block"> -(1-x^2)/(1-x) -</pre> -<p>does give <tt class="docutils literal">1+x</tt> but</p> -<pre class="literal-block"> -(1/(1-x))*(1-x^2) -</pre> -<p>evaluates to zero. This will work as expected:</p> -<pre class="last literal-block"> -\poldef k(x):= (x-1)(x-2)(x-3)(x-4)/(x^2-5x+4); -</pre> -</div> -<div class="admonition attention" id="warningtacit"> -<p class="first admonition-title">Attention!</p> -<p><tt class="docutils literal">1/2 x^2</tt> skips the space and is treated like <tt class="docutils literal"><span class="pre">1/(2*x^2)</span></tt> because -of the tacit multiplication rules of xintexpr. But this means it -gives zero! Thus one must use <tt class="docutils literal">(1/2)x^2</tt> or <tt class="docutils literal">1/2*x^2</tt> or -<tt class="docutils literal"><span class="pre">(1/2)*x^2</span></tt> for disambiguation: <tt class="docutils literal">x - 1/2*x^2 + <span class="pre">1/3*x^3...</span></tt>. It is -even simpler to move the denominator to the right: <tt class="docutils literal">x - x^2/2 + -x^3/3 - ...</tt>.</p> -<p class="last">It is worth noting that <tt class="docutils literal"><span class="pre">1/2(x-1)(x-2)</span></tt> suffers the same issue: -<a class="reference external" href="http://www.ctan.org/pkg/xint">xint</a> tacit multiplication always "ties more", hence this gets -interpreted as <tt class="docutils literal"><span class="pre">1/(2*(x-1)*(x-2))</span></tt> which gives zero by polynomial -division. Thus, use one of <tt class="docutils literal"><span class="pre">(1/2)(x-1)(x-2)</span></tt>, <tt class="docutils literal"><span class="pre">1/2*(x-1)(x-2)</span></tt> or -<tt class="docutils literal"><span class="pre">(x-1)(x-2)/2</span></tt>.</p> -</div> -<p>After:</p> -<pre class="literal-block"> -\poldef f_1(x):= 25(x-1)(x^2-2)(x-3)(x-4)(x-5);% -\poldef f_2(x):= 37(x-1)(x^2-2)(x-6)(x-7)(x-8);% -</pre> -<p>the macro call <tt class="docutils literal"><span class="pre">\PolGCD{f_1}{f_2}{k}</span></tt> sets <tt class="docutils literal">k</tt> to the (unitary) GCD of -<tt class="docutils literal">f_1</tt> and <tt class="docutils literal">f_2</tt> (hence to the expansion of <tt class="docutils literal"><span class="pre">(x-1)(x^2-2)</span></tt>.)</p> -<dl class="docutils"> -<dt><tt class="docutils literal">\PolToExpr{k}</tt></dt> -<dd>will (expandably) give in this case <tt class="docutils literal"><span class="pre">x^3-x^2-2*x+2</span></tt>. This is -useful for console or file output (the syntax is Maple- and -PSTricks-compatible; the letter used in output can be -(non-expandably) changed via a redefinition of <a class="reference internal" href="#poltoexprvar">\PolToExprVar</a>.)</dd> -<dt><tt class="docutils literal"><span class="pre">\PolToExpr*{k}</span></tt></dt> -<dd>gives ascending powers: <tt class="docutils literal"><span class="pre">2-2*x-x^2+x^3</span></tt>.</dd> -</dl> -</div> -<div class="section" id="examples-of-localization-of-roots"> -<h1><a class="toc-backref" href="#id39">Examples of localization of roots</a></h1> -<ul> -<li><p class="first">To make printed decimal numbers more enjoyable than via -<tt class="docutils literal">\xintSignedFrac</tt>:</p> -<pre class="literal-block"> -\renewcommand\PolTypesetOne[1]{\PolDecToString{\xintREZ{#1}}}% -</pre> -<p><tt class="docutils literal">\PolDecToString</tt> will use decimal notation to incorporate the power -of ten part; and the <tt class="docutils literal">\xintREZ</tt> 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"> -\renewcommand\PolToExprCmd[1]{\PolDecToString{\xintREZ{#1}}}% -</pre> -<p>to modify output of <a class="reference internal" href="#poltoexpr-polname">\PolToExpr{polname}</a>.</p> -</li> -<li><p class="first">For extra info in log file use <tt class="docutils literal">\xintverbosetrue</tt>.</p> -</li> -<li><p class="first">Only for some of these examples is the output included here.</p> -</li> -</ul> -<div class="section" id="a-typical-example"> -<h2><a class="toc-backref" href="#id40">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}<Z_2<\PolSturmIsolatedZeroRight{f}{2}\] -And here is the first root with twenty digits after decimal mark: -\PolEnsureIntervalLength{f}{1}{-20} -\[\PolSturmIsolatedZeroLeft{f}{1}<Z_1<\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="#id41">A degree four polynomial with nearby roots</a></h2> -<p>Notice that this example is a bit outdated as <tt class="docutils literal">0.7</tt> release has -added <tt class="docutils literal"><span class="pre">\PolSturmIsolateZeros**{sturmname}</span></tt> 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 < Z_1 < 1.1, 1.10 < Z_2 < 1.11, 1.110 < Z_3 < 1.111, and 1.111 < Z_4 < 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 < Z_1 < 1.06, 1.105 < Z_2 < 1.106, 1.1105 < Z_3 < 1.1106, -% and 1.11105 < Z_4 < 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="#id42">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) -\newcommand\showmultiplicities[1]{% #1 = "sturmname" -\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}<x<\PolSturmIsolatedZeroRight{#1}{##1}$} - \par -}}% -\PolDef{f}{(x-0.99)^3(x-0.999)^3(x-0.9999)^3} -\renewcommand\PolTypesetOne[1]{\PolDecToString{\xintREZ{#1}}} -\PolTypeset{f}\par -\PolToSturm{f}{f}% it is allowed to use "polname" as "sturmname" too -\PolSturmIsolateZerosAndGetMultiplicities{f}% use the "sturmname" 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 <tt class="docutils literal">\PolSturmIsolateZeros**</tt> 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 < x < 0.99 -The multiplicity is 1 for the root such that 0.9991 < x < 0.9992 -The multiplicity is 1 for the root such that 0.9997 < x < 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 < x < 0.9899888033 -The multiplicity is 1 for the root such that 0.9991447980 < x < 0.9991447981 -The multiplicity is 1 for the root such that 0.9997663986 < x < 0.9997663987 -</pre> -</div> -<div class="section" id="a-degree-five-polynomial-with-three-rational-roots"> -<h2><a class="toc-backref" href="#id43">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} -%\begin{flushleft} - \renewcommand\PolTypesetCmdPrefix[1]{\allowbreak\xintiiifSgn{#1}{}{+}{+}}% - $Q_0(x) = \PolTypeset{Q_0}$ -%\end{flushleft} -\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 -\renewcommand\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="#id44">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 < Z_1 < -1, 0.09 < Z_2 < 0.10, 0.1 < Z_3 < 0.2, 1 < Z_4 < 2 -Let us refine the second and third intervals to separate the corresponding -roots: -\PolRefineInterval*{P}{2}% will refine to 0.0999990 < Z_2 < 0.0999991 -\PolRefineInterval*{P}{3}% will refine to 0.100001 < Z_3 < 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}<Z_2<\PolSturmIsolatedZeroRight{P}{2}\] -</pre> -<p>The last line produces:</p> -<pre class="literal-block"> -0.09999900004999650028 < Z_2 < 0.09999900004999650029 -</pre> -</div> -<div class="section" id="the-wilkinson-polynomial"> -<h2><a class="toc-backref" href="#id45">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"> -\documentclass{article} -\usepackage{polexpr} -\begin{document} -%\xintverbosetrue % for the curious... - -\poldef f(x) := mul((x - i), i = 1..20); - -\renewcommand\PolTypesetCmdPrefix[1]{\allowbreak\xintiiifSgn{#1}{}{+}{+}}% -\renewcommand\PolTypesetOne[1]{\xintDecToString{#1}}% - -\noindent\PolTypeset{f} - -\PolToSturm{f}{f} -\PolSturmIsolateZeros{f} -\PolPrintIntervals{f} - -\clearpage - -\poldef g(x) := f(x) - 2**{-23} x**19; - -% be patient! -\PolToSturm{g}{g} -\noindent\PolTypeset{g_0}% integer coefficient primitive polynomial - -\PolSturmIsolateZeros{g} -\PolEnsureIntervalLengths{g}{-10} - -\renewcommand\PolPrintIntervalsPrintMultiplicity{} -\PolPrintIntervals*{g} - -\end{document} -</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 (a few seconds), but the modified one <tt class="docutils literal">f(x) - -<span class="pre">2**-23</span> <span class="pre">x**19</span></tt> takes about 20x longer (the Sturm chain polynomials -have integer coefficients with up to 321 digits, whereas (surprisingly -perhaps) those of the Sturm chain polynomials derived from <tt class="docutils literal">f</tt> 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 -<tt class="docutils literal">f(x) - <span class="pre">2**-23</span> <span class="pre">x**19</span></tt> 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="#id46">The second Wilkinson polynomial</a></h2> -<pre class="literal-block"> -\documentclass{article} -\usepackage{polexpr} -\begin{document} -\poldef f(x) := mul(x - 2^-i, i = 1..20); - -%\PolTypeset{f} - -\PolToSturm{f}{f} -\PolSturmIsolateZeros**{f} -\PolPrintIntervals{f} -\end{document} -</pre> -<p>This takes more time than the polynomial with 1, 2, .., 20 as roots but -less than the latter modified by the <tt class="docutils literal"><span class="pre">2**-23</span></tt> change in one -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 <tt class="docutils literal">\xintIrr</tt> 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="#id47">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 <tt class="docutils literal">i/10</tt> but this gives -less efficient internal form for the coefficients (the <tt class="docutils literal">10</tt>'s end up -in denominators). Using <tt class="docutils literal">\PolToExpr{P}</tt> after having done</p> -<pre class="literal-block"> -\renewcommand\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 <tt class="docutils literal">xint + polexpr</tt>, 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="first admonition-title">Note</p> -<p>Release <tt class="docutils literal">0.5</tt> has <em>experimental</em> addition of optional argument -<tt class="docutils literal">E</tt> to <tt class="docutils literal">\PolSturmIsolateZeros</tt>. It instructs to search roots only -in interval <tt class="docutils literal"><span class="pre">(-10^E,</span> 10^E)</tt>. Important: the extremities are -<em>assumed to not be roots</em>. In this example, the <tt class="docutils literal">[1]</tt> in -<tt class="docutils literal"><span class="pre">\PolSturmIsolateZeros[1]{S}</span></tt> gives some speed gain; without it, it -turns out in this case that <tt class="docutils literal">polexpr</tt> would have started with -<tt class="docutils literal"><span class="pre">(-10^6,</span> 10^6)</tt> interval.</p> -<p class="last">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="#id48">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<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="#id49">Non-expandable macros</a></h1> -<div class="section" id="poldef-polname-letter-expression-in-letter"> -<span id="poldef"></span><h2><a class="toc-backref" href="#id50"><tt class="docutils literal">\poldef <span class="pre">polname(letter):=</span> expression in letter;</tt></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, -under the user-chosen <tt class="docutils literal">polname</tt>. Of course the <em>expression</em> can -use other previously defined polynomials. Names must start with a -letter and are constituted of letters, digits, underscores and -(since <tt class="docutils literal">0.5.1</tt>) the right tick <tt class="docutils literal">'</tt>. -The whole <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> syntax is authorized:</p> -<pre class="literal-block"> -\poldef sin(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>As a side effect the function <tt class="docutils literal">polname()</tt> is recognized as a -genuine <tt class="docutils literal"><span class="pre">\xintexpr...\relax</span></tt> function for (exact) numerical -evaluation (or within an <tt class="docutils literal">\xintdefvar</tt> assignment.) It computes -values not according to the original expression but via the Horner -scheme corresponding to the polynomial coefficients.</p> -<div class="admonition attention"> -<p class="first admonition-title">Attention!</p> -<p>Release <tt class="docutils literal">0.3</tt> also did the necessary set-up to let the -polynomial be known to the <tt class="docutils literal">\xintfloatexpr</tt> (or -<tt class="docutils literal">\xintdeffloatvar</tt>) parser.</p> -<p>Since <tt class="docutils literal">0.4</tt> this isn't done automatically. Even more, a -previously existing floating point variant 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 <tt class="docutils literal">\poldef</tt> or <tt class="docutils literal">\PolDef</tt> but as -a product of the other package macros.</p> -<p class="last">See <a class="reference internal" href="#polgenfloatvariant-polname">\PolGenFloatVariant{polname}</a>.</p> -</div> -<p>The original expression is lost after parsing, and in particular -the package provides no way to typeset it. This has to be done -manually, if needed.</p> -</blockquote> -</div> -<div class="section" id="poldef-letter-polname-expression-in-letter"> -<span id="id2"></span><h2><a class="toc-backref" href="#id51"><tt class="docutils literal"><span class="pre">\PolDef[letter]{polname}{expression</span> in letter}</tt></a></h2> -<blockquote> -Does the same as <a class="reference external" 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 -<tt class="docutils literal">[letter]</tt> optional argument, the variable is assumed to be <tt class="docutils literal">x</tt>.</blockquote> -</div> -<div class="section" id="polgenfloatvariant-polname"> -<span id="polgenfloatvariant"></span><h2><a class="toc-backref" href="#id52"><tt class="docutils literal">\PolGenFloatVariant{polname}</tt></a></h2> -<blockquote> -<p>Makes the polynomial also usable in the <tt class="docutils literal">\xintfloatexpr</tt> 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-polname">\PolToFloatExpr{polname}</a>.</p> -<div class="admonition attention"> -<p class="first admonition-title">Attention!</p> -<p>Release <tt class="docutils literal">0.3</tt> did this automatically on <tt class="docutils literal">\PolDef</tt> and -<tt class="docutils literal">\poldef</tt> but this was removed at <tt class="docutils literal">0.4</tt> for optimization.</p> -<p class="last">Any operation, for example generating the derivative polynomial, -or dividing two polynomials or using the <tt class="docutils literal">\PolLet</tt>, <strong>must</strong> be -followed by explicit usage of <tt class="docutils literal">\PolGenFloatVariant{polname}</tt> if -the new polynomial is to be used in <tt class="docutils literal">\xintfloatexpr</tt> or alike -context.</p> -</div> -</blockquote> -</div> -<div class="section" id="pollet-polname-2-polname-1"> -<span id="pollet"></span><h2><a class="toc-backref" href="#id53"><tt class="docutils literal"><span class="pre">\PolLet{polname_2}={polname_1}</span></tt></a></h2> -<blockquote> -Makes a copy of the already defined polynomial <tt class="docutils literal">polname_1</tt> to a -new one <tt class="docutils literal">polname_2</tt>. Same effect as -<tt class="docutils literal"><span class="pre">\PolDef{polname_2}{polname_1(x)}</span></tt> but with less overhead. The -<tt class="docutils literal">=</tt> is optional.</blockquote> -</div> -<div class="section" id="polgloballet-polname-2-polname-1"> -<span id="polgloballet"></span><h2><a class="toc-backref" href="#id54"><tt class="docutils literal"><span class="pre">\PolGlobalLet{polname_2}={polname_1}</span></tt></a></h2> -<blockquote> -Acts globally.</blockquote> -</div> -<div class="section" id="polassign-polname-toarray-macro"> -<span id="polassign"></span><h2><a class="toc-backref" href="#id55"><tt class="docutils literal"><span class="pre">\PolAssign{polname}\toarray\macro</span></tt></a></h2> -<blockquote> -<p>Defines a one-argument expandable macro <tt class="docutils literal"><span class="pre">\macro{#1}</span></tt> which expands -to the (raw) #1th polynomial coefficient.</p> -<ul class="simple"> -<li>Attention, coefficients here are indexed starting at 1.</li> -<li>With #1=-1, -2, ..., <tt class="docutils literal"><span class="pre">\macro{#1}</span></tt> returns leading coefficients.</li> -<li>With #1=0, returns the number of coefficients, i.e. <tt class="docutils literal">1 + deg f</tt> -for non-zero polynomials.</li> -<li>Out-of-range #1's return <tt class="docutils literal">0/1[0]</tt>.</li> -</ul> -<p>See also <a class="reference internal" href="#polnthcoeff-polname-number">\PolNthCoeff{polname}{number}</a>. The main difference is that -with <tt class="docutils literal">\PolAssign</tt>, <tt class="docutils literal">\macro</tt> is made a prefix to <tt class="docutils literal">1 + deg f</tt> -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 <tt class="docutils literal">Nth</tt> coefficient, and due to -expandability can not store it in a macro for future usage (of course, -it can be an argument in an <tt class="docutils literal">\edef</tt>.) 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="#id56"><tt class="docutils literal"><span class="pre">\PolGet{polname}\fromarray\macro</span></tt></a></h2> -<blockquote> -<p>Does the converse operation to -<tt class="docutils literal"><span class="pre">\PolAssign{polname}\toarray\macro</span></tt>. Each individual -<tt class="docutils literal">\macro{number}</tt> gets expanded in an <tt class="docutils literal">\edef</tt> and then normalized -via <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a>'s macro <tt class="docutils literal">\xintRaw</tt>.</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 <tt class="docutils literal">f</tt> as would have <tt class="docutils literal">\poldef <span class="pre">f(x):=1-2x+5x^2-3x^3;</span></tt>.</p> -<div class="admonition note"> -<p class="first admonition-title">Note</p> -<p class="last">Prior to <tt class="docutils literal">0.5</tt>, coefficients were not normalized via -<tt class="docutils literal">\xintRaw</tt> for internal storage.</p> -</div> -</blockquote> -</div> -<div class="section" id="polfromcsv-polname-csv"> -<span id="polfromcsv"></span><h2><a class="toc-backref" href="#id57"><tt class="docutils literal"><span class="pre">\PolFromCSV{polname}{<csv>}</span></tt></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 <tt class="docutils literal">\edef</tt> and then put into normalized -form via <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a>'s macro <tt class="docutils literal">\xintRaw</tt>.</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="first admonition-title">Note</p> -<p class="last">Prior to <tt class="docutils literal">0.5</tt>, coefficients were not normalized via -<tt class="docutils literal">\xintRaw</tt> for internal storage.</p> -</div> -</blockquote> -</div> -<div class="section" id="poltypeset-polname"> -<span id="poltypeset"></span><h2><a class="toc-backref" href="#id58"><tt class="docutils literal">\PolTypeset{polname}</tt></a></h2> -<blockquote> -<p>Typesets in descending powers in math mode. It uses letter <tt class="docutils literal">x</tt> but -this can be changed via an optional argument:</p> -<pre class="literal-block"> -\PolTypeset[z]{polname} -</pre> -<p>By default zero coefficients are skipped (issue <tt class="docutils literal">\poltypesetalltrue</tt> -to get all of them in output).</p> -<p>These commands (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="#id59"><tt class="docutils literal">\PolTypesetCmd{raw_coeff}</tt></a></h3> -<blockquote> -<p>Checks if the coefficient is <tt class="docutils literal">1</tt> or <tt class="docutils literal"><span class="pre">-1</span></tt> and then skips printing -the <tt class="docutils literal">1</tt>, 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="#id60"><tt class="docutils literal">\PolTypesetOne{raw_coeff}</tt></a></h3> -<blockquote> -<p>The default is <tt class="docutils literal">\xintSignedFrac</tt> but this macro is annoying as it -insists to use a power of ten, and not decimal notation.</p> -<p>One can do things such as for example: <a class="footnote-reference" href="#id5" id="id4">[1]</a></p> -<pre class="literal-block"> -\renewcommand\PolTypesetOne[1]{\num{\xintPFloat[5]{#1}}} -\renewcommand\PolTypesetOne[1]{\num{\xintRound{4}{#1}}} -</pre> -<p>where e.g. we used the <tt class="docutils literal">\num</tt> macro of <tt class="docutils literal">siunitx</tt> as it -understands floating point notation.</p> -<table class="docutils footnote" frame="void" id="id5" rules="none"> -<colgroup><col class="label" /><col /></colgroup> -<tbody valign="top"> -<tr><td class="label"><a class="fn-backref" href="#id4">[1]</a></td><td>the difference in the syntaxes of <tt class="docutils literal">\xintPFloat</tt> and -<tt class="docutils literal">\xintRound</tt> is explained from the fact that -<tt class="docutils literal">\xintPFloat</tt> by default uses the prevailing precision -hence the extra argument like here <tt class="docutils literal">5</tt> is an optional one.</td></tr> -</tbody> -</table> -<p>One can also give a try to using <a class="reference internal" href="#poldectostring-decimal-number">\PolDecToString{decimal number}</a> -which uses decimal notation (at least for the numerator part).</p> -</blockquote> -</div> -<div class="section" id="id6"> -<span id="poltypesetmonomialcmd"></span><h3><a class="toc-backref" href="#id61"><tt class="docutils literal">\PolTypesetMonomialCmd</tt></a></h3> -<blockquote> -This decides how a monomial (in variable <tt class="docutils literal">\PolVar</tt> and with -exponent <tt class="docutils literal">\PolIndex</tt>) is to be printed. The default does nothing -for the constant term, <tt class="docutils literal">\PolVar</tt> for the first degree and -<tt class="docutils literal"><span class="pre">\PolVar^{\PolIndex}</span></tt> for higher degrees monomials. Beware that -<tt class="docutils literal">\PolIndex</tt> expands to digit tokens and needs termination in -<tt class="docutils literal">\ifnum</tt> tests.</blockquote> -</div> -<div class="section" id="poltypesetcmdprefix-raw-coeff"> -<span id="poltypesetcmdprefix"></span><h3><a class="toc-backref" href="#id62"><tt class="docutils literal">\PolTypesetCmdPrefix{raw_coeff}</tt></a></h3> -<blockquote> -Expands to a <tt class="docutils literal">+</tt> if the <tt class="docutils literal">raw_coeff</tt> is zero or positive, and to -nothing if <tt class="docutils literal">raw_coeff</tt> is negative, as in latter case the -<tt class="docutils literal">\xintSignedFrac</tt> used by <a class="reference internal" href="#poltypesetcmd-raw-coeff">\PolTypesetCmd{raw_coeff}</a> will put -the <tt class="docutils literal">-</tt> 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.</blockquote> -</div> -</div> -<div class="section" id="id8"> -<span id="id7"></span><h2><a class="toc-backref" href="#id63"><tt class="docutils literal"><span class="pre">\PolTypeset*{polname}</span></tt></a></h2> -<blockquote> -Typesets in ascending powers. Use e.g. <tt class="docutils literal">[h]</tt> optional argument -(after the <tt class="docutils literal">*</tt>) to use letter <tt class="docutils literal">h</tt> rather than <tt class="docutils literal">x</tt>.</blockquote> -</div> -<div class="section" id="poldiff-polname-1-polname-2"> -<span id="poldiff"></span><h2><a class="toc-backref" href="#id64"><tt class="docutils literal"><span class="pre">\PolDiff{polname_1}{polname_2}</span></tt></a></h2> -<blockquote> -<p>This sets <tt class="docutils literal">polname_2</tt> to the first derivative of <tt class="docutils literal">polname_1</tt>. It -is allowed to issue <tt class="docutils literal"><span class="pre">\PolDiff{f}{f}</span></tt>, effectively replacing <tt class="docutils literal">f</tt> -by <tt class="docutils literal">f'</tt>.</p> -<p>Coefficients of the result <tt class="docutils literal">polname_2</tt> 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="#id65"><tt class="docutils literal"><span class="pre">\PolDiff[N]{polname_1}{polname_2}</span></tt></a></h2> -<blockquote> -This sets <tt class="docutils literal">polname_2</tt> to the <tt class="docutils literal">N</tt>-th derivative of <tt class="docutils literal">polname_1</tt>. -Identical arguments is allowed. With <tt class="docutils literal">N=0</tt>, same effect as -<tt class="docutils literal"><span class="pre">\PolLet{polname_2}={polname_1}</span></tt>. With negative <tt class="docutils literal">N</tt>, switches to -using <tt class="docutils literal">\PolAntiDiff</tt>.</blockquote> -</div> -<div class="section" id="polantidiff-polname-1-polname-2"> -<span id="polantidiff"></span><h2><a class="toc-backref" href="#id66"><tt class="docutils literal"><span class="pre">\PolAntiDiff{polname_1}{polname_2}</span></tt></a></h2> -<blockquote> -<p>This sets <tt class="docutils literal">polname_2</tt> to the primitive of <tt class="docutils literal">polname_1</tt> vanishing -at zero.</p> -<p>Coefficients of the result <tt class="docutils literal">polname_2</tt> 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="#id67"><tt class="docutils literal"><span class="pre">\PolAntiDiff[N]{polname_1}{polname_2}</span></tt></a></h2> -<blockquote> -This sets <tt class="docutils literal">polname_2</tt> to the result of <tt class="docutils literal">N</tt> successive integrations on -<tt class="docutils literal">polname_1</tt>. With negative <tt class="docutils literal">N</tt>, it switches to using <tt class="docutils literal">\PolDiff</tt>.</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="#id68"><tt class="docutils literal"><span class="pre">\PolDivide{polname_1}{polname_2}{polname_Q}{polname_R}</span></tt></a></h2> -<blockquote> -This sets <tt class="docutils literal">polname_Q</tt> and <tt class="docutils literal">polname_R</tt> to be the quotient and -remainder in the Euclidean division of <tt class="docutils literal">polname_1</tt> by -<tt class="docutils literal">polname_2</tt>.</blockquote> -</div> -<div class="section" id="polquo-polname-1-polname-2-polname-q"> -<span id="polquo"></span><h2><a class="toc-backref" href="#id69"><tt class="docutils literal"><span class="pre">\PolQuo{polname_1}{polname_2}{polname_Q}</span></tt></a></h2> -<blockquote> -This sets <tt class="docutils literal">polname_Q</tt> to be the quotient in the Euclidean division -of <tt class="docutils literal">polname_1</tt> by <tt class="docutils literal">polname_2</tt>.</blockquote> -</div> -<div class="section" id="polrem-polname-1-polname-2-polname-r"> -<span id="polrem"></span><h2><a class="toc-backref" href="#id70"><tt class="docutils literal"><span class="pre">\PolRem{polname_1}{polname_2}{polname_R}</span></tt></a></h2> -<blockquote> -This sets <tt class="docutils literal">polname_R</tt> to be the remainder in the Euclidean division -of <tt class="docutils literal">polname_1</tt> by <tt class="docutils literal">polname_2</tt>.</blockquote> -</div> -<div class="section" id="polgcd-polname-1-polname-2-polname-gcd"> -<span id="polgcd"></span><h2><a class="toc-backref" href="#id71"><tt class="docutils literal"><span class="pre">\PolGCD{polname_1}{polname_2}{polname_GCD}</span></tt></a></h2> -<blockquote> -This sets <tt class="docutils literal">polname_GCD</tt> to be the (monic) GCD of the two first -polynomials. It is a unitary polynomial except if both <tt class="docutils literal">polname_1</tt> -and <tt class="docutils literal">polname_2</tt> vanish, then <tt class="docutils literal">polname_GCD</tt> is the zero -polynomial.</blockquote> -<!-- ``\PolIGCD{polname_1}{polname_2}{polname_iGCD}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - **NOT YET** - - This **assumes** that the two polynomials have integer coefficients. - It then computes the greatest common divisor in the integer - polynomial ring, normalized to have a positive leading coefficient - (if the inputs are not both zero). - -``\PolIContent{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~ - - **NOT YET** - - This computes a positive rational number such that dividing the - polynomial with it returns an integer coefficients polynomial with - no common factor among the coefficients. --> -</div> -<div class="section" id="poltosturm-polname-sturmname"> -<span id="poltosturm"></span><h2><a class="toc-backref" href="#id72"><tt class="docutils literal"><span class="pre">\PolToSturm{polname}{sturmname}</span></tt></a></h2> -<blockquote> -<p>With <tt class="docutils literal">polname</tt> being for example <tt class="docutils literal">P</tt>, the macro starts by -computing polynomials <tt class="docutils literal">P</tt> and <tt class="docutils literal">P'</tt>, then computes the (opposite -of the) remainder in euclidean division, iteratively.</p> -<p>The last non-zero remainder <tt class="docutils literal">P_N_</tt> (where <tt class="docutils literal">N</tt> is obtainable as -<a class="reference internal" href="#polsturmchainlength-sturmname">\PolSturmChainLength{sturmname}</a>) is up to a factor -the GCD of <tt class="docutils literal">P</tt> and <tt class="docutils literal">P'</tt> hence it is a constant if and only if -<tt class="docutils literal">P</tt> is square-free.</p> -<div class="admonition note"> -<p class="first admonition-title">Note</p> -<ul class="last simple"> -<li>Since <tt class="docutils literal">0.5</tt> 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 <tt class="docutils literal">1</tt> or <tt class="docutils literal"><span class="pre">-1</span></tt>.</li> -<li>After this normalization to primitive polynomials, they are -stored internally as <tt class="docutils literal">sturmname_k_</tt>, <tt class="docutils literal">k=0,1, ...</tt>.</li> -<li>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="#id9">PolToSturm*</a>.</li> -</ul> -</div> -<div class="admonition note"> -<p class="first admonition-title">Note</p> -<p class="last">It is perfectly allowed to use the polynomial name as Sturm chain name: -<tt class="docutils literal"><span class="pre">\PolToSturm{f}(f}</span></tt>.</p> -</div> -<p>The macro then declares <tt class="docutils literal">sturmname_0</tt>, <tt class="docutils literal">sturmname_1</tt>, ..., which are -the (non-declared) <tt class="docutils literal">sturmname_k_</tt> divided by the last one. Division is -not done if this last one is the constant <tt class="docutils literal">1</tt> or <tt class="docutils literal"><span class="pre">-1</span></tt>, 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 <tt class="docutils literal">sturmname_0</tt> has exactly the same real and complex roots as -polynomial <tt class="docutils literal">polname</tt>, but with each root now of multiplicity one: -i.e. it is the "square-free part" of original polynomial <tt class="docutils literal">polname</tt>.</p> -<p>Notice that <tt class="docutils literal">sturmname_1</tt> isn't necessarily the derivative of -<tt class="docutils literal">sturmname_0</tt> due to the various normalizations.</p> -<p>The polynomials <tt class="docutils literal">sturmname_k</tt> main utility is for the execution of -<a class="reference internal" href="#polsturmisolatezeros-sturmname">\PolSturmIsolateZeros{sturmname}</a>. Be careful not to use these -names <tt class="docutils literal">sturmname_0</tt>, <tt class="docutils literal">sturmname_1</tt>, etc... for defining other -polynomials after having done <tt class="docutils literal"><span class="pre">\PolToSturm{polname}{sturmname}</span></tt> and -before executing <tt class="docutils literal">\PolSturmIsolateZeros{sturmname}</tt> 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="id10"> -<span id="id9"></span><h2><a class="toc-backref" href="#id73"><tt class="docutils literal"><span class="pre">\PolToSturm*{polname}{sturmname}</span></tt></a></h2> -<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 <tt class="docutils literal">sturmname_k_</tt>, <tt class="docutils literal">k=0,1, <span class="pre">...,</span> N</tt>, with -<tt class="docutils literal">N</tt> being <a class="reference internal" href="#polsturmchainlength-sturmname">\PolSturmChainLength{sturmname}</a>.</p> -<div class="admonition note"> -<p class="first admonition-title">Note</p> -<p class="last">This behaviour was modified at <tt class="docutils literal">0.6</tt>, anyhow the macro was -broken at <tt class="docutils literal">0.5</tt>.</p> -</div> -<div class="admonition hint"> -<p class="first admonition-title">Hint</p> -<p class="last">The square-free part of <tt class="docutils literal">polname</tt> is <tt class="docutils literal">sturmname_0</tt>, and their -quotient is the polynomial with name -<tt class="docutils literal">sturname_\PolSturmChainLength{sturmname}_</tt>. 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 <tt class="docutils literal">f</tt> as -a product <tt class="docutils literal">c f_1 f_2 f_3 ...</tt> of a constant and square-free (primitive) -polynomials, where each <tt class="docutils literal">f_i</tt> divides its predecessor.</p> -</div> -</blockquote> -</div> -<div class="section" id="polsettosturmchainsignchangesat-macro-sturmname-fraction"> -<span id="polsettosturmchainsignchangesat"></span><h2><a class="toc-backref" href="#id74"><tt class="docutils literal"><span class="pre">\PolSetToSturmChainSignChangesAt{\macro}{sturmname}{fraction}</span></tt></a></h2> -<blockquote> -<p>Sets macro <tt class="docutils literal">\macro</tt> to the number of sign changes in the Sturm -chain with name prefix <tt class="docutils literal">sturmname</tt>, at location <tt class="docutils literal">fraction</tt> -(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="first admonition-title">Note</p> -<p>The author was lazy and did not provide rather an expandable -variant, where one would do <tt class="docutils literal"><span class="pre">\edef\macro{\PolNbOf...}</span></tt>.</p> -<p>This will presumably get added in a future release.</p> -<p class="last">After some hesitation it was decided the macro would by default -act globally. To make the scope of its macro definition local, -use <tt class="docutils literal">[\empty]</tt> as extra optional argument.</p> -</div> -</blockquote> -</div> -<div class="section" id="polsettonbofzeroswithin-macro-sturmname-value-a-value-b"> -<span id="polsettonbofzeroswithin"></span><h2><a class="toc-backref" href="#id75"><tt class="docutils literal"><span class="pre">\PolSetToNbOfZerosWithin{\macro}{sturmname}{value_a}{value_b}</span></tt></a></h2> -<blockquote> -<p>Applies the <a class="reference external" href="https://en.wikipedia.org/wiki/Sturm%27s_theorem">Sturm Theorem</a> to set <tt class="docutils literal">\macro</tt> to the exact number -of <strong>distinct</strong> roots of <tt class="docutils literal">sturmname_0</tt> in the interval <tt class="docutils literal">(value_a, -value_b]</tt> (the macro first re-orders the value for <tt class="docutils literal">value_a <= -value_b</tt> to hold).</p> -<div class="admonition note"> -<p class="first admonition-title">Note</p> -<p>The author was lazy and did not provide rather an expandable -variant, where one would do <tt class="docutils literal"><span class="pre">\edef\macro{\PolNbOf...}</span></tt>.</p> -<p>This will presumably get added in future.</p> -<p class="last">After some hesitation it was decided the macro would by default -act globally. To make the scope of its macro definition local, -use <tt class="docutils literal">[\empty]</tt> 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 <tt class="docutils literal">\numexpr</tt>) 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="#id11">\PolSturmIsolateZeros*</a>.</p> -</blockquote> -</div> -<div class="section" id="polsturmisolatezeros-sturmname"> -<span id="polsturmisolatezeros"></span><h2><a class="toc-backref" href="#id76"><tt class="docutils literal">\PolSturmIsolateZeros{sturmname}</tt></a></h2> -<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="first 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 <tt class="docutils literal"><span class="pre">\PolToSturm{f}{f}</span></tt> is perfectly legal (the -<tt class="docutils literal">sturmname</tt> can be same as the <tt class="docutils literal">polname</tt>): it defines -polynomials <tt class="docutils literal">f_0</tt>, <tt class="docutils literal">f_1</tt>, ... having <tt class="docutils literal">f</tt> has name prefix.</p> -<p class="last">Such a prior call -to <tt class="docutils literal">\PolToSturm</tt> must have been made at any rate for -<tt class="docutils literal">\PolSturmIsolateZeros</tt> 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>singleton <tt class="docutils literal">{a}</tt>: then <tt class="docutils literal">a</tt> is a root, (necessarily a decimal -number, but not all such decimal numbers are exactly identified yet).</li> -<li>open intervals <tt class="docutils literal">(a,b)</tt>: then there is exactly one root <tt class="docutils literal">z</tt> -such that <tt class="docutils literal">a < z < b</tt>, and the end points are guaranteed to not -be roots.</li> -</ul> -<p>The interval boundaries are decimal numbers, originating -in iterated decimal subdivision from initial intervals -<tt class="docutils literal"><span class="pre">(-10^E,</span> 0)</tt> and <tt class="docutils literal">(0, 10^E)</tt> with <tt class="docutils literal">E</tt> 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 <tt class="docutils literal">(a/10^f, <span class="pre">(a+1)/10^f)</span></tt> with <tt class="docutils literal">a</tt> an integer, which is -neither <tt class="docutils literal">0</tt> nor <tt class="docutils literal"><span class="pre">-1</span></tt>. Hence either <tt class="docutils literal">a</tt> and <tt class="docutils literal">a+1</tt> 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="first 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 class="last">See <a class="reference internal" href="#polrefineinterval-sturmname-index">\PolRefineInterval*{sturmname}{index}</a> which addresses -this issue.</p> -</div> -<!-- This procedure is covariant -with the independent variable ``x`` becoming ``-x``. -Hmm, pas sûr et trop fatigué --> -<p>The interval boundaries (and exactly found roots) are made available -for future computations in <tt class="docutils literal">\xintexpr</tt>-essions or polynomial -definitions as variables <tt class="docutils literal"><sturmname>L_1</tt>, -<tt class="docutils literal"><sturmname>L_2</tt>, etc..., for the left end-points and -<tt class="docutils literal"><sturmname>R_1</tt>, <tt class="docutils literal"><sturmname>R_2</tt>, ..., for the right -end-points.</p> -<p>Thus for example, if <tt class="docutils literal">sturmname</tt> is <tt class="docutils literal">f</tt>, one can use the -<a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> variables <tt class="docutils literal">fL_1</tt>, <tt class="docutils literal">fL_2</tt>, ... 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 <tt class="docutils literal">fZ_1_isknown</tt> -will have value <tt class="docutils literal">1</tt> if the root in the first interval is known, -and <tt class="docutils literal">0</tt> 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="first admonition-title">Important</p> -<p class="last">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 <tt class="docutils literal">k</tt>-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 <tt class="docutils literal">value</tt> or <tt class="docutils literal">expression</tt>, and the same but with -multiplicities.</p> -<div class="admonition note"> -<p class="first admonition-title">Note</p> -<p class="last">In the current implementation 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 are globally defined. On the -other hand the Sturm sequence polynomials obey the current scope.</p> -</div> -<div class="admonition note"> -<p class="first 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 class="last">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="id12"> -<span id="id11"></span><h2><a class="toc-backref" href="#id77"><tt class="docutils literal"><span class="pre">\PolSturmIsolateZeros*{sturmname}</span></tt></a></h2> -<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 <tt class="docutils literal">index</tt>-th -interval (intervals are enumerated from left to right, with index -starting at <tt class="docutils literal">1</tt>).</p> -<p>Furthermore, if for example the <tt class="docutils literal">sturmname</tt> is <tt class="docutils literal">f</tt>, <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> -variables <tt class="docutils literal">fM_1</tt>, <tt class="docutils literal">fM_2</tt>... hold the multiplicities thus -computed.</p> -<div class="admonition note"> -<p class="first admonition-title">Note</p> -<p class="last">It is <strong>not</strong> necessary to have executed the <a class="reference internal" href="#id9">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="id14"> -<span id="id13"></span><h2><a class="toc-backref" href="#id78"><tt class="docutils literal"><span class="pre">\PolSturmIsolateZeros**{sturmname}</span></tt></a></h2> -<blockquote> -<p>The macro does the same as <a class="reference internal" href="#id12">\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="first admonition-title">Note</p> -<p class="last">After execution of this macro, a root is "known" if and only if -it is rational.</p> -</div> -<p>Furthermore, primitive polynomial <tt class="docutils literal">sturmname_sqf_norr</tt> is created -to match the (square-free) <tt class="docutils literal">sturmname_0</tt> 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 <tt class="docutils literal">sturmname_norr</tt> is <tt class="docutils literal">sturmname_0_</tt> 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><h2><a class="toc-backref" href="#id79"><tt class="docutils literal">\PolSturmIsolateZerosAndGetMultiplicities{sturmname}</tt></a></h2> -<blockquote> -This is another name for <a class="reference internal" href="#id12">\PolSturmIsolateZeros*{sturmname}</a>.</blockquote> -</div> -<div class="section" id="polsturmisolatezerosgetmultiplicitiesandrationalroots-sturmname"> -<span id="polsturmisolatezerosgetmultiplicitiesandrationalroots"></span><h2><a class="toc-backref" href="#id80"><tt class="docutils literal">\PolSturmIsolateZerosGetMultiplicitiesAndRationalRoots{sturmname}</tt></a></h2> -<blockquote> -This is another name for <a class="reference internal" href="#id14">\PolSturmIsolateZeros**{sturmname}</a>.</blockquote> -</div> -<div class="section" id="polsturmisolatezerosandfindrationalroots-sturmname"> -<h2><a class="toc-backref" href="#id81"><tt class="docutils literal">\PolSturmIsolateZerosAndFindRationalRoots{sturmname}</tt></a></h2> -<blockquote> -<p>This works exactly like <a class="reference internal" href="#id14">\PolSturmIsolateZeros**{sturmname}</a> -(inclusive of declaring the polynomials <tt class="docutils literal">sturmname_sqf_norr</tt> and -<tt class="docutils literal">sturmname_norr</tt> 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="first admonition-title">Note</p> -<p class="last">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="first 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 -<tt class="docutils literal">sturmnameM_1</tt>, <tt class="docutils literal">sturmnameM_2</tt>, ... 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="#id18">\PolPrintIntervals*</a> for example will be -erroneous for the intervals with irrational roots.</p> -<p class="last">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><h2><a class="toc-backref" href="#id82"><tt class="docutils literal"><span class="pre">\PolRefineInterval*{sturmname}{index}</span></tt></a></h2> -<blockquote> -The <tt class="docutils literal">index</tt>-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 <tt class="docutils literal">k</tt>th root is then -strictly separated from the other roots.</blockquote> -</div> -<div class="section" id="polrefineinterval-n-sturmname-index"> -<span id="polrefineinterval-n"></span><h2><a class="toc-backref" href="#id83"><tt class="docutils literal"><span class="pre">\PolRefineInterval[N]{sturmname}{index}</span></tt></a></h2> -<blockquote> -The <tt class="docutils literal">index</tt>-th interval (starting count at one) is further -subdivided once, reducing its length by a factor of 10. This is done -<tt class="docutils literal">N</tt> times if the optional argument <tt class="docutils literal">[N]</tt> is present.</blockquote> -</div> -<div class="section" id="polensureintervallength-sturmname-index-e"> -<span id="polensureintervallength"></span><h2><a class="toc-backref" href="#id84"><tt class="docutils literal"><span class="pre">\PolEnsureIntervalLength{sturmname}{index}{E}</span></tt></a></h2> -<blockquote> -The <tt class="docutils literal">index</tt>-th interval is subdivided until its length becomes at -most <tt class="docutils literal">10^E</tt>. This means (for <tt class="docutils literal">E<0</tt>) that the first <tt class="docutils literal"><span class="pre">-E</span></tt> digits -after decimal mark of the <tt class="docutils literal">k</tt>th root will then be known exactly.</blockquote> -</div> -<div class="section" id="polensureintervallengths-sturmname-e"> -<span id="polensureintervallengths"></span><h2><a class="toc-backref" href="#id85"><tt class="docutils literal"><span class="pre">\PolEnsureIntervalLengths{sturmname}{E}</span></tt></a></h2> -<blockquote> -<p>The intervals as obtained from <tt class="docutils literal">\PolSturmIsolateZeros</tt> are (if -necessary) subdivided further by (base 10) dichotomy in order for -each of them to have length at most <tt class="docutils literal">10^E</tt> (length will be shorter -than <tt class="docutils literal">10^E</tt> 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 -<tt class="docutils literal"><span class="pre">-E</span></tt> digits (for <tt class="docutils literal">E<0</tt>) after decimal mark.</p> -</blockquote> -</div> -<div class="section" id="polprintintervals-varname-sturmname"> -<span id="polprintintervals"></span><h2><a class="toc-backref" href="#id86"><tt class="docutils literal"><span class="pre">\PolPrintIntervals[varname]{sturmname}</span></tt></a></h2> -<blockquote> -<p>This is a convenience macro which prints the bounds for the roots -<tt class="docutils literal">Z_1</tt>, <tt class="docutils literal">Z_2</tt>, ... (the optional argument <tt class="docutils literal">varname</tt> allows to -specify a replacement for the default <tt class="docutils literal">Z</tt>). This will be done (by -default) in a -math mode <tt class="docutils literal">array</tt>, one interval per row, and pattern <tt class="docutils literal">rcccl</tt>, -where the second and fourth column hold the <tt class="docutils literal"><</tt> sign, except when -the interval reduces to a singleton, which means the root is known -exactly.</p> -<div class="admonition attention"> -<p class="first admonition-title">Attention!</p> -<p class="last">This macro was refactored at 0.7, its default output remained -identical but the ways to customize it got completely -modified.</p> -</div> -<p>See next macros which govern its output.</p> -</blockquote> -<div class="section" id="polprintintervalsnorealroots"> -<h3><a class="toc-backref" href="#id87"><tt class="docutils literal">\PolPrintIntervalsNoRealRoots</tt></a></h3> -<blockquote> -<p>Executed in place of an <tt class="docutils literal">array</tt> environment, when there are no -real roots. Default definition:</p> -<pre class="literal-block"> -\newcommand\PolPrintIntervalsNoRealRoots{} -</pre> -</blockquote> -</div> -<div class="section" id="polprintintervalsbeginenv"> -<h3><a class="toc-backref" href="#id88"><tt class="docutils literal">\PolPrintIntervalsBeginEnv</tt></a></h3> -<blockquote> -<p>Default definition:</p> -<pre class="literal-block"> -\newcommand\PolPrintIntervalsBeginEnv{\[\begin{array}{rcccl}} -</pre> -</blockquote> -</div> -<div class="section" id="polprintintervalsendenv"> -<h3><a class="toc-backref" href="#id89"><tt class="docutils literal">\PolPrintIntervalsEndEnv</tt></a></h3> -<blockquote> -<p>Default definition:</p> -<pre class="literal-block"> -\newcommand\PolPrintIntervalsEndEnv{\end{array}\]} -</pre> -</blockquote> -</div> -<div class="section" id="polprintintervalsknownroot"> -<h3><a class="toc-backref" href="#id90"><tt class="docutils literal">\PolPrintIntervalsKnownRoot</tt></a></h3> -<blockquote> -<p>Default definition:</p> -<pre class="literal-block"> -\newcommand\PolPrintIntervalsKnownRoot{% - &&\PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}% - &=&\PolPrintIntervalsPrintExactZero -} -</pre> -</blockquote> -</div> -<div class="section" id="polprintintervalsunknownroot"> -<h3><a class="toc-backref" href="#id91"><tt class="docutils literal">\PolPrintIntervalsUnknownRoot</tt></a></h3> -<blockquote> -<p>Default definition:</p> -<pre class="literal-block"> -\newcommand\PolPrintIntervalsUnknownRoot{% - \PolPrintIntervalsPrintLeftEndPoint&<&% - \PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}&<&% - \PolPrintIntervalsPrintRightEndPoint -} -</pre> -</blockquote> -</div> -<div class="section" id="id15"> -<span id="polprintintervalsprintexactzero"></span><h3><a class="toc-backref" href="#id92"><tt class="docutils literal">\PolPrintIntervalsPrintExactZero</tt></a></h3> -<blockquote> -<p>Default definition:</p> -<pre class="literal-block"> -\newcommand\PolPrintIntervalsPrintExactZero{\PolPrintIntervalsTheLeftEndPoint} -</pre> -</blockquote> -</div> -<div class="section" id="id16"> -<span id="polprintintervalsprintleftendpoint"></span><h3><a class="toc-backref" href="#id93"><tt class="docutils literal">\PolPrintIntervalsPrintLeftEndPoint</tt></a></h3> -<blockquote> -<p>Default definition:</p> -<pre class="literal-block"> -\newcommand\PolPrintIntervalsPrintLeftEndPoint{\PolPrintIntervalsTheLeftEndPoint} -</pre> -</blockquote> -</div> -<div class="section" id="id17"> -<span id="polprintintervalsprintrightendpoint"></span><h3><a class="toc-backref" href="#id94"><tt class="docutils literal">\PolPrintIntervalsPrintRightEndPoint</tt></a></h3> -<blockquote> -<p>Default definition is:</p> -<pre class="literal-block"> -\newcommand\PolPrintIntervalsPrintRightEndPoint{\PolPrintIntervalsTheRightEndPoint} -</pre> -</blockquote> -</div> -</div> -<div class="section" id="id19"> -<span id="id18"></span><h2><a class="toc-backref" href="#id95"><tt class="docutils literal"><span class="pre">\PolPrintIntervals*[varname]{sturmname}</span></tt></a></h2> -<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 -<tt class="docutils literal"><span class="pre">\POL@@PrintIntervals...</span></tt> macros. We only reproduce here one -definition:</p> -<pre class="literal-block"> -\newcommand\POL@@PrintIntervalsPrintExactZero{% - \displaystyle - \xintSignedFrac{\PolPrintIntervalsTheLeftEndPoint}% -}% -</pre> -<p>Multiplicities are printed using this auxiliary macro:</p> -</blockquote> -<div class="section" id="polprintintervalsprintmultiplicity"> -<h3><a class="toc-backref" href="#id96"><tt class="docutils literal">\PolPrintIntervalsPrintMultiplicity</tt></a></h3> -<blockquote> -<p>whose default definition is:</p> -<pre class="literal-block"> -\newcommand\PolPrintIntervalsPrintMultiplicity{(\mbox{mult. }\PolPrintIntervalsTheMultiplicity)} -</pre> -</blockquote> -</div> -</div> -<div class="section" id="polmapcoeffs-macro-polname"> -<span id="polmapcoeffs"></span><h2><a class="toc-backref" href="#id97"><tt class="docutils literal"><span class="pre">\PolMapCoeffs{\macro}{polname}</span></tt></a></h2> -<blockquote> -<p>It modifies ('in-place': original coefficients get lost) each -coefficient of the defined polynomial via the <em>expandable</em> macro -<tt class="docutils literal">\macro</tt>. The degree is adjusted as necessary if some leading -coefficients vanish after the operation. In replacement text of -<tt class="docutils literal">\macro</tt>, <tt class="docutils literal">\index</tt> expands to the coefficient index (which is -defined to be zero for the constant term).</p> -<p>Notice that <tt class="docutils literal">\macro</tt> will have to handle inputs of the shape -<tt class="docutils literal">A/B[N]</tt> (<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 <tt class="docutils literal"><span class="pre">\xintSqr{\index}</span></tt>) to replace <tt class="docutils literal">n</tt>-th coefficient -<tt class="docutils literal">f_n</tt> by <tt class="docutils literal">f_n*n^2</tt>.</p> -</blockquote> -</div> -<div class="section" id="polreducecoeffs-polname"> -<span id="polreducecoeffs"></span><h2><a class="toc-backref" href="#id98"><tt class="docutils literal">\PolReduceCoeffs{polname}</tt></a></h2> -<blockquote> -About the same as <tt class="docutils literal"><span class="pre">\PolMapCoeffs{\xintIrr}{polname}</span></tt> (but -maintaining a <tt class="docutils literal">[0]</tt> 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'.</blockquote> -</div> -<div class="section" id="id21"> -<span id="id20"></span><h2><a class="toc-backref" href="#id99"><tt class="docutils literal"><span class="pre">\PolReduceCoeffs*{polname}</span></tt></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 <tt class="docutils literal">A/B[N]</tt>, then <tt class="docutils literal">A/B</tt> is reduced to -smallest terms, but the <tt class="docutils literal">10^N</tt> 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 <tt class="docutils literal">1.5e7</tt>; the macro will anyhow always first do the -needed conversion to strict format <tt class="docutils literal">A/B[N]</tt>.</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="#id100"><tt class="docutils literal">\PolMakeMonic{polname}</tt></a></h2> -<blockquote> -Divides by the leading coefficient. It is recommended to execute -<a class="reference internal" href="#id21">\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.</blockquote> -</div> -<div class="section" id="polmakeprimitive-polname"> -<span id="polmakeprimitive"></span><h2><a class="toc-backref" href="#id101"><tt class="docutils literal">\PolMakePrimitive{polname}</tt></a></h2> -<blockquote> -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.</blockquote> -</div> -</div> -<div class="section" id="expandable-macros"> -<h1><a class="toc-backref" href="#id102">Expandable macros</a></h1> -<p>All these macros expand completely in two steps except <tt class="docutils literal">\PolToExpr</tt> -and <tt class="docutils literal">\PolToFloatExpr</tt> (and their auxiliaries) which need a -<tt class="docutils literal">\write</tt>, <tt class="docutils literal">\edef</tt> or a <tt class="docutils literal"><span class="pre">\csname...\endcsname</span></tt> context.</p> -<div class="section" id="poleval-polname-atexpr-numerical-expression"> -<span id="polevalatexpr"></span><h2><a class="toc-backref" href="#id103"><tt class="docutils literal"><span class="pre">\PolEval{polname}\AtExpr{numerical</span> expression}</tt></a></h2> -<blockquote> -It boils down to -<tt class="docutils literal">\xinttheexpr polname(numerical <span class="pre">expression)\relax</span></tt>.</blockquote> -</div> -<div class="section" id="poleval-polname-at-fraction"> -<span id="polevalat"></span><h2><a class="toc-backref" href="#id104"><tt class="docutils literal"><span class="pre">\PolEval{polname}\At{fraction}</span></tt></a></h2> -<blockquote> -Evaluates the polynomial at value <tt class="docutils literal">fraction</tt> 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.</blockquote> -</div> -<div class="section" id="polevalreduced-polname-atexpr-numerical-expression"> -<span id="polevalreducedatexpr"></span><h2><a class="toc-backref" href="#id105"><tt class="docutils literal"><span class="pre">\PolEvalReduced{polname}\AtExpr{numerical</span> expression}</tt></a></h2> -<blockquote> -Boils down to <tt class="docutils literal">\xinttheexpr reduce(polname(numerical <span class="pre">expression))\relax</span></tt>.</blockquote> -</div> -<div class="section" id="polevalreduced-polname-at-fraction"> -<span id="polevalreducedat"></span><h2><a class="toc-backref" href="#id106"><tt class="docutils literal"><span class="pre">\PolEvalReduced{polname}\At{fraction}</span></tt></a></h2> -<blockquote> -Evaluates the polynomial at value <tt class="docutils literal">fraction</tt> 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.</blockquote> -</div> -<div class="section" id="polfloateval-polname-atexpr-numerical-expression"> -<span id="polfloatevalatexpr"></span><h2><a class="toc-backref" href="#id107"><tt class="docutils literal"><span class="pre">\PolFloatEval{polname}\AtExpr{numerical</span> expression}</tt></a></h2> -<blockquote> -<p>Boils down to <tt class="docutils literal">\xintthefloatexpr polname(numerical <span class="pre">expression)\relax</span></tt>.</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" href="#id24" id="id22">[2]</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" href="#id25" id="id23">[3]</a></p> -<pre class="literal-block"> -\xintthefloatexpr 3.27*\xintexpr f(2.53)\relax^2\relax -</pre> -<p>The <tt class="docutils literal">f(2.53)</tt> is exactly computed then rounded at the time of -getting raised to the power <tt class="docutils literal">2</tt>. Moving the <tt class="docutils literal">^2</tt> inside, that -operation would also be treated exactly.</p> -<table class="docutils footnote" frame="void" id="id24" rules="none"> -<colgroup><col class="label" /><col /></colgroup> -<tbody valign="top"> -<tr><td class="label"><a class="fn-backref" href="#id22">[2]</a></td><td>Anyway each floating point operation starts by rounding its -operands to the floating point precision.</td></tr> -</tbody> -</table> -<table class="docutils footnote" frame="void" id="id25" rules="none"> -<colgroup><col class="label" /><col /></colgroup> -<tbody valign="top"> -<tr><td class="label"><a class="fn-backref" href="#id23">[3]</a></td><td>The <tt class="docutils literal">\xintexpr</tt> here could be <tt class="docutils literal">\xinttheexpr</tt> but that -would be less efficient. Cf. <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> documentation about -nested expressions.</td></tr> -</tbody> -</table> -</blockquote> -</div> -<div class="section" id="polfloateval-polname-at-fraction"> -<span id="polfloatevalat"></span><h2><a class="toc-backref" href="#id108"><tt class="docutils literal"><span class="pre">\PolFloatEval{polname}\At{fraction}</span></tt></a></h2> -<blockquote> -Evaluates the polynomial at value <tt class="docutils literal">fraction</tt> 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.</blockquote> -</div> -<div class="section" id="polifcoeffisplusorminusone-a-b"> -<span id="polifcoeffisplusorminusone"></span><h2><a class="toc-backref" href="#id109"><tt class="docutils literal"><span class="pre">\PolIfCoeffIsPlusOrMinusOne{A}{B}</span></tt></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 <tt class="docutils literal">\cdot</tt> in front of <tt class="docutils literal"><span class="pre">\PolVar^{\PolIndex}</span></tt> if -the coefficient is not plus or minus one.</p> -<p>The macro will execute <tt class="docutils literal">A</tt> if the coefficient has been found to be -plus or minus one, and <tt class="docutils literal">B</tt> if not.</p> -</blockquote> -</div> -<div class="section" id="polleadingcoeff-polname"> -<span id="polleadingcoeff"></span><h2><a class="toc-backref" href="#id110"><tt class="docutils literal">\PolLeadingCoeff{polname}</tt></a></h2> -<blockquote> -Expands to the leading coefficient.</blockquote> -</div> -<div class="section" id="polnthcoeff-polname-number"> -<span id="polnthcoeff"></span><h2><a class="toc-backref" href="#id111"><tt class="docutils literal"><span class="pre">\PolNthCoeff{polname}{number}</span></tt></a></h2> -<blockquote> -It expands to the raw <tt class="docutils literal">N</tt>-th coefficient (<tt class="docutils literal">0/1[0]</tt> if the index -number is out of range). With <tt class="docutils literal"><span class="pre">N=-1</span></tt>, <tt class="docutils literal"><span class="pre">-2</span></tt>, ... expands to the -leading coefficients.</blockquote> -</div> -<div class="section" id="poldegree-polname"> -<span id="poldegree"></span><h2><a class="toc-backref" href="#id112"><tt class="docutils literal">\PolDegree{polname}</tt></a></h2> -<blockquote> -It expands to the degree. This is <tt class="docutils literal"><span class="pre">-1</span></tt> if zero polynomial but this -may change in future. Should it then expand to <tt class="docutils literal"><span class="pre">-\infty</span></tt> ?</blockquote> -</div> -<div class="section" id="policontent-polname"> -<span id="policontent"></span><h2><a class="toc-backref" href="#id113"><tt class="docutils literal">\PolIContent{polname}</tt></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-polname"> -<span id="poltoexpr"></span><h2><a class="toc-backref" href="#id114"><tt class="docutils literal">\PolToExpr{polname}</tt></a></h2> -<blockquote> -<p>Expands <a class="footnote-reference" href="#id27" id="id26">[4]</a> to <tt class="docutils literal"><span class="pre">coeff_N*x^N+...</span></tt> (descending powers.)</p> -<table class="docutils footnote" frame="void" id="id27" rules="none"> -<colgroup><col class="label" /><col /></colgroup> -<tbody valign="top"> -<tr><td class="label"><a class="fn-backref" href="#id26">[4]</a></td><td>in a <tt class="docutils literal">\write</tt>, <tt class="docutils literal">\edef</tt>, or <tt class="docutils literal"><span class="pre">\csname...\endcsname</span></tt>, but -not under <tt class="docutils literal"><span class="pre">\romannumeral-`0</span></tt>.</td></tr> -</tbody> -</table> -<p>By default zero coefficients are skipped (issue <tt class="docutils literal">\poltoexpralltrue</tt> to -get all of them in output).</p> -<p>By default, no <tt class="docutils literal">+</tt> sign before negative coefficients, for -compliance with Maple input format (but see -<a class="reference internal" href="#poltoexprtermprefix-raw-coeff">\PolToExprTermPrefix{raw_coeff}</a>.) Also, like the default -behaviour of <a class="reference internal" href="#poltypeset-polname">\PolTypeset{polname}</a>, does not print (for the non -constant terms) coefficients equal to plus or minus one. The degree -one monomial is output as <tt class="docutils literal">x</tt>, not <tt class="docutils literal">x^1</tt>. Complete customization is -possible, see next macros.</p> -<p>Of course <tt class="docutils literal">\PolToExpr{f}</tt> can be inserted in a <tt class="docutils literal">\poldef</tt>, as the -latter expands token by token, hence will force complete expansion -of <tt class="docutils literal">\PolToExpr{f}</tt>, but a simple <tt class="docutils literal">f(x)</tt> is more efficient for -the identical result.</p> -</blockquote> -<div class="section" id="poltoexproneterm-raw-coeff-number"> -<span id="poltoexproneterm"></span><h3><a class="toc-backref" href="#id115"><tt class="docutils literal"><span class="pre">\PolToExprOneTerm{raw_coeff}{number}</span></tt></a></h3> -<blockquote> -<p>This two argument expandable command takes care of the monomial and -its coefficient. The default definition is done in order for -coefficients of absolute value <tt class="docutils literal">1</tt> not be printed explicitely -(except of course for the constant term). Also by default, the -monomial of degree one is <tt class="docutils literal">x</tt> not <tt class="docutils literal">x^1</tt>, and <tt class="docutils literal">x^0</tt> is skipped.</p> -<p>For compatibility with Maple input requirements, by default a <tt class="docutils literal">*</tt> -always precedes the <tt class="docutils literal">x^number</tt>, except if the coefficient is a one -or a minus one. See <a class="reference internal" href="#poltoexprtimes">\PolToExprTimes</a>.</p> -</blockquote> -</div> -<div class="section" id="poltoexpronetermstylea-raw-coeff-number"> -<span id="poltoexpronetermstylea"></span><h3><a class="toc-backref" href="#id116"><tt class="docutils literal"><span class="pre">\PolToExprOneTermStyleA{raw_coeff}{number}</span></tt></a></h3> -<blockquote> -Holds the default package meaning of -<a class="reference internal" href="#poltoexproneterm-raw-coeff-number">\PolToExprOneTerm{raw_coeff}{number}</a>.</blockquote> -</div> -<div class="section" id="poltoexpronetermstyleb-raw-coeff-number"> -<span id="poltoexpronetermstyleb"></span><h3><a class="toc-backref" href="#id117"><tt class="docutils literal"><span class="pre">\PolToExprOneTermStyleB{raw_coeff}{number}</span></tt></a></h3> -<blockquote> -<p>For output in this style:</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>issue <tt class="docutils literal">\let\PolToExprOneTerm\PolToExprOneTermStyleB</tt> before usage of -<tt class="docutils literal">\PolToExpr</tt>. Note that then <tt class="docutils literal">\PolToExprCmd</tt> isn't used at all. -To revert to package default, issue -<tt class="docutils literal">\let\PolToExprOneTerm\PolToExprOneTermStyleA</tt>.</p> -<p>To suppress the <tt class="docutils literal">*</tt>'s, cf. <a class="reference internal" href="#poltoexprtimes">\PolToExprTimes</a>.</p> -</blockquote> -</div> -<div class="section" id="poltoexprcmd-raw-coeff"> -<span id="poltoexprcmd"></span><h3><a class="toc-backref" href="#id118"><tt class="docutils literal">\PolToExprCmd{raw_coeff}</tt></a></h3> -<blockquote> -It is the one-argument macro used by the package definition of -<tt class="docutils literal">\PolToExprOneTerm</tt> for the coefficients themselves (when not -equal to plus or minus one), and it defaults to -<tt class="docutils literal"><span class="pre">\xintPRaw{\xintRawWithZeros{#1}}</span></tt>. One will have to redefine it -to <tt class="docutils literal"><span class="pre">\xintIrr{#1}</span></tt> or to <tt class="docutils literal"><span class="pre">\xintPRaw{\xintIrr{#1}}</span></tt> to obtain in the -output forcefully reduced coefficients.</blockquote> -</div> -<div class="section" id="poltoexprtermprefix-raw-coeff"> -<span id="poltoexprtermprefix"></span><h3><a class="toc-backref" href="#id119"><tt class="docutils literal">\PolToExprTermPrefix{raw_coeff}</tt></a></h3> -<blockquote> -Defined identically as <a class="reference internal" href="#poltypesetcmdprefix-raw-coeff">\PolTypesetCmdPrefix{raw_coeff}</a>. It -prefixes with a plus sign for non-negative coefficients, because -they don't carry one by themselves.</blockquote> -</div> -<div class="section" id="id28"> -<span id="poltoexprvar"></span><h3><a class="toc-backref" href="#id120"><tt class="docutils literal">\PolToExprVar</tt></a></h3> -<blockquote> -This expands to the variable to use in output (it does not have to -be a single letter, may be an expandable macro.) Initial definition -is <tt class="docutils literal">x</tt>.</blockquote> -</div> -<div class="section" id="id29"> -<span id="poltoexprtimes"></span><h3><a class="toc-backref" href="#id121"><tt class="docutils literal">\PolToExprTimes</tt></a></h3> -<blockquote> -This expands to the symbol used for multiplication of an -<tt class="docutils literal"><span class="pre">x^{number}</span></tt> by the corresponding coefficient. The default is -<tt class="docutils literal">*</tt>. Redefine the macro to expand to nothing to get rid of it (but -this will give output incompatible with some professional computer -algebra software).</blockquote> -</div> -</div> -<div class="section" id="id31"> -<span id="id30"></span><h2><a class="toc-backref" href="#id122"><tt class="docutils literal"><span class="pre">\PolToExpr*{polname}</span></tt></a></h2> -<blockquote> -Expands to <tt class="docutils literal"><span class="pre">coeff_0+coeff_1*x+coeff_2*x^2+...</span></tt> (ascending powers). -Customizable like <a class="reference internal" href="#poltoexpr-polname">\PolToExpr{polname}</a> via the same macros.</blockquote> -</div> -<div class="section" id="poltofloatexpr-polname"> -<span id="poltofloatexpr"></span><h2><a class="toc-backref" href="#id123"><tt class="docutils literal">\PolToFloatExpr{polname}</tt></a></h2> -<blockquote> -<p>Similar to <a class="reference internal" href="#poltoexpr-polname">\PolToExpr{polname}</a> but uses <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="first admonition-title">Note</p> -<p>It is not necessary to have issued -<a class="reference internal" href="#polgenfloatvariant-polname">\PolGenFloatVariant{polname}</a>. The rounded coefficients are -not easily recoverable from the <tt class="docutils literal">\xintfloatexpr</tt> polynomial -function hence <tt class="docutils literal">\PolToFloatExprCmd</tt> operates from the <em>exact</em> -coefficients anew.</p> -<p class="last">Attention that both macros obey the prevailing float precision. -If it is changed between those macro calls, then a mismatch -exists between the coefficients as used in <tt class="docutils literal">\xintfloatexpr</tt> and -those output by <tt class="docutils literal">\PolToFloatExpr{polname}</tt>.</p> -</div> -</blockquote> -<div class="section" id="poltofloatexproneterm-raw-coeff-number"> -<span id="poltofloatexproneterm"></span><h3><a class="toc-backref" href="#id124"><tt class="docutils literal"><span class="pre">\PolToFloatExprOneTerm{raw_coeff}{number}</span></tt></a></h3> -<blockquote> -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.</blockquote> -</div> -<div class="section" id="poltofloatexprcmd-raw-coeff"> -<span id="id33"></span><h3><a class="toc-backref" href="#id125"><tt class="docutils literal">\PolToFloatExprCmd{raw_coeff}</tt></a></h3> -<blockquote> -<p>It is the one-argument macro used by <tt class="docutils literal">\PolToFloatExprOneTerm</tt>. -Its package definition is <tt class="docutils literal"><span class="pre">\xintFloat{#1}</span></tt>.</p> -<div class="admonition caution"> -<p class="first admonition-title">Caution!</p> -<p>Currently (<a class="reference external" href="http://www.ctan.org/pkg/xint">xint</a> <tt class="docutils literal">1.3c</tt>) <tt class="docutils literal">\xintFloat{0}</tt> outputs <tt class="docutils literal">0.e0</tt> -which is perfectly acceptable input for Python, but not for -Maple. Thus, one should better leave the <a class="reference internal" href="#poltoexprallfalse">\poltoexprallfalse</a> -toggle to its default <tt class="docutils literal">\iffalse</tt> state, 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 class="last">Usage of <tt class="docutils literal">\xintiiifZero</tt> and not <tt class="docutils literal">\xintifZero</tt> is only for -optimization (I can't help it) because <tt class="docutils literal">#1</tt> is known to be -in <tt class="docutils literal">xintfrac</tt> raw format.</p> -</div> -</blockquote> -</div> -</div> -<div class="section" id="id35"> -<span id="id34"></span><h2><a class="toc-backref" href="#id126"><tt class="docutils literal"><span class="pre">\PolToFloatExpr*{polname}</span></tt></a></h2> -<blockquote> -Typesets in ascending powers.</blockquote> -</div> -<div class="section" id="poltolist-polname"> -<span id="poltolist"></span><h2><a class="toc-backref" href="#id127"><tt class="docutils literal">\PolToList{polname}</tt></a></h2> -<blockquote> -Expands to <tt class="docutils literal"><span class="pre">{coeff_0}{coeff_1}...{coeff_N}</span></tt> with <tt class="docutils literal">N</tt> = degree, and -<tt class="docutils literal">coeff_N</tt> the leading coefficient -(the zero polynomial does give <tt class="docutils literal">{0/1[0]}</tt> and not an -empty output.)</blockquote> -</div> -<div class="section" id="poltocsv-polname"> -<span id="poltocsv"></span><h2><a class="toc-backref" href="#id128"><tt class="docutils literal">\PolToCSV{polname}</tt></a></h2> -<blockquote> -Expands to <tt class="docutils literal">coeff_0, coeff_1, coeff_2, <span class="pre">.....,</span> coeff_N</tt>, starting -with constant term and ending with leading coefficient. Converse -to <a class="reference internal" href="#polfromcsv-polname-csv">\PolFromCSV</a>.</blockquote> -</div> -<div class="section" id="polsturmchainlength-sturmname"> -<span id="polsturmchainlength"></span><h2><a class="toc-backref" href="#id129"><tt class="docutils literal">\PolSturmChainLength{sturmname}</tt></a></h2> -<blockquote> -<p>Returns the integer <tt class="docutils literal">N</tt> such that <tt class="docutils literal">sturmname_N</tt> is the last one -in the Sturm chain <tt class="docutils literal">sturmname_0</tt>, <tt class="docutils literal">sturmname_1</tt>, ...</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><h2><a class="toc-backref" href="#id130"><tt class="docutils literal"><span class="pre">\PolSturmIfZeroExactlyKnown{sturmname}{index}{A}{B}</span></tt></a></h2> -<blockquote> -<p>Executes <tt class="docutils literal">A</tt> if the <tt class="docutils literal">index</tt>-th interval reduces to a singleton, -i.e. the root is known exactly, else <tt class="docutils literal">B</tt>.</p> -<div class="admonition note"> -<p class="first admonition-title">Note</p> -<p class="last"><tt class="docutils literal">index</tt> is allowed to be something like <tt class="docutils literal">1+2*3</tt> as it is fed -to <tt class="docutils literal"><span class="pre">\the\numexpr...\relax</span></tt>.</p> -</div> -</blockquote> -</div> -<div class="section" id="polsturmisolatedzeroleft-sturmname-index"> -<span id="polsturmisolatedzeroleft"></span><h2><a class="toc-backref" href="#id131"><tt class="docutils literal"><span class="pre">\PolSturmIsolatedZeroLeft{sturmname}{index}</span></tt></a></h2> -<blockquote> -<p>Expands to the left end-point for the <tt class="docutils literal">index</tt>-th interval, as -computed by some earlier <a class="reference internal" href="#polsturmisolatezeros-sturmname">\PolSturmIsolateZeros{sturmname}</a>.</p> -<div class="admonition note"> -<p class="first admonition-title">Note</p> -<p class="last">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><h2><a class="toc-backref" href="#id132"><tt class="docutils literal"><span class="pre">\PolSturmIsolatedZeroRight{sturmname}{index}</span></tt></a></h2> -<blockquote> -<p>Expands to the right end-point for the <tt class="docutils literal">index</tt>-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><h2><a class="toc-backref" href="#id133"><tt class="docutils literal"><span class="pre">\PolSturmIsolatedZeroMultiplicity{sturmname}{index}</span></tt></a></h2> -<blockquote> -<p>Expands to the multiplicity of the unique root contained in the -<tt class="docutils literal">index</tt>-th interval.</p> -<div class="admonition attention"> -<p class="first admonition-title">Attention!</p> -<p class="last">A prior execution of <a class="reference internal" href="#id12">\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><h2><a class="toc-backref" href="#id134"><tt class="docutils literal">\PolSturmNbOfIsolatedZeros{sturmname}</tt></a></h2> -<blockquote> -Expands to the number of real roots of the polynomial -<tt class="docutils literal"><sturmname>_0</tt>, 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>.</blockquote> -<div class="admonition warning"> -<p class="first admonition-title">Warning</p> -<p class="last">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 class="section" id="polsturmnbofrootsof-sturmname-lessthanorequalto-value"> -<h3><a class="toc-backref" href="#id135"><tt class="docutils literal"><span class="pre">\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualTo{value}</span></tt></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 <tt class="docutils literal">value</tt> (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="first admonition-title">Attention!</p> -<p><a class="reference internal" href="#polsturmisolatezeros-sturmname">\PolSturmIsolateZeros{sturmname}</a> must have been executed -beforehand.</p> -<p class="last">And the argument is a <tt class="docutils literal">sturmname</tt>, not a <tt class="docutils literal">polname</tt> (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="#id136"><tt class="docutils literal"><span class="pre">\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualToExpr{expression}</span></tt></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 <tt class="docutils literal">expression</tt>.</p> -<div class="admonition attention"> -<p class="first admonition-title">Attention!</p> -<p class="last"><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="#id137"><tt class="docutils literal"><span class="pre">\PolSturmNbWithMultOfRootsOf{sturmname}\LessThanOrEqualTo{value}</span></tt></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 <tt class="docutils literal">value</tt>.</p> -<div class="admonition attention"> -<p class="first admonition-title">Attention!</p> -<p class="last"><a class="reference internal" href="#id12">\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="#id138"><tt class="docutils literal"><span class="pre">\PolSturmNbWithMultOfRootsOf{sturmname}\LessThanOrEqualToExpr{expression}</span></tt></a></h3> -<blockquote> -<p>Expands to the total number of roots (counted with multiplicities) -which are less than or equal to the given <tt class="docutils literal">expression</tt>.</p> -<div class="admonition attention"> -<p class="first admonition-title">Attention!</p> -<p class="last"><a class="reference internal" href="#id12">\PolSturmIsolateZeros*{sturmname}</a> (or the double starred -variant) must have been executed beforehand.</p> -</div> -</blockquote> -</div> -</div> -<div class="section" id="polsturmnbofrationalroots-sturmname"> -<h2><a class="toc-backref" href="#id139"><tt class="docutils literal">\PolSturmNbOfRationalRoots{sturmname}</tt></a></h2> -<blockquote> -<p>Expands to the number of rational roots (without multiplicities).</p> -<div class="admonition attention"> -<p class="first admonition-title">Attention!</p> -<p class="last"><a class="reference internal" href="#id14">\PolSturmIsolateZeros**{sturmname}</a> must have been executed -beforehand.</p> -</div> -</blockquote> -</div> -<div class="section" id="polsturmnbofrationalrootswithmultiplicities-sturmname"> -<h2><a class="toc-backref" href="#id140"><tt class="docutils literal">\PolSturmNbOfRationalRootsWithMultiplicities{sturmname}</tt></a></h2> -<blockquote> -<p>Expands to the number of rational roots (counted with multiplicities).</p> -<div class="admonition attention"> -<p class="first admonition-title">Attention!</p> -<p class="last"><a class="reference internal" href="#id14">\PolSturmIsolateZeros**{sturmname}</a> must have been executed -beforehand.</p> -</div> -</blockquote> -</div> -<div class="section" id="polsturmrationalroot-sturmname-k"> -<h2><a class="toc-backref" href="#id141"><tt class="docutils literal"><span class="pre">\PolSturmRationalRoot{sturmname}{k}</span></tt></a></h2> -<blockquote> -<p>Expands to the <tt class="docutils literal">k</tt>th rational root (they are ordered and indexed -starting at 1 for the most negative).</p> -<div class="admonition attention"> -<p class="first admonition-title">Attention!</p> -<p class="last"><a class="reference internal" href="#id14">\PolSturmIsolateZeros**{sturmname}</a> must have been executed -beforehand.</p> -</div> -</blockquote> -</div> -<div class="section" id="polsturmrationalrootindex-sturmname-k"> -<h2><a class="toc-backref" href="#id142"><tt class="docutils literal"><span class="pre">\PolSturmRationalRootIndex{sturmname}{k}</span></tt></a></h2> -<blockquote> -<p>Expands to <tt class="docutils literal">index</tt> of the <tt class="docutils literal">k</tt>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="first admonition-title">Attention!</p> -<p class="last"><a class="reference internal" href="#id14">\PolSturmIsolateZeros**{sturmname}</a> must have been executed -beforehand.</p> -</div> -</blockquote> -</div> -<div class="section" id="polsturmrationalrootmultiplicity-sturmname-k"> -<h2><a class="toc-backref" href="#id143"><tt class="docutils literal"><span class="pre">\PolSturmRationalRootMultiplicity{sturmname}{k}</span></tt></a></h2> -<blockquote> -<p>Expands to the multiplicity of the <tt class="docutils literal">k</tt>th rational root.</p> -<div class="admonition attention"> -<p class="first admonition-title">Attention!</p> -<p class="last"><a class="reference internal" href="#id14">\PolSturmIsolateZeros**{sturmname}</a> must have been executed -beforehand.</p> -</div> -</blockquote> -</div> -<div class="section" id="polintervalwidth-sturmname-index"> -<span id="polintervalwidth"></span><h2><a class="toc-backref" href="#id144"><tt class="docutils literal"><span class="pre">\PolIntervalWidth{sturmname}{index}</span></tt></a></h2> -<blockquote> -The <tt class="docutils literal">10^E</tt> width of the current <tt class="docutils literal">index</tt>-th root localization -interval. Output is in <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a> raw <tt class="docutils literal">1/1[E]</tt> format (if not zero).</blockquote> -</div> -<div class="section" id="expandable-macros-for-use-within-execution-of-polprintintervals"> -<h2><a class="toc-backref" href="#id145">Expandable macros for use within execution of <tt class="docutils literal">\PolPrintIntervals</tt></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="first admonition-title">Attention!</p> -<p class="last">Some macros formerly mentioned here got removed at 0.7: -<tt class="docutils literal">\PolPrintIntervalsTheEndPoint</tt>, -<tt class="docutils literal"><span class="pre">\PolIfEndPointIsPositive{A}{B}</span></tt>, -<tt class="docutils literal"><span class="pre">\PolIfEndPointIsNegative{A}{B}</span></tt>, -<tt class="docutils literal"><span class="pre">\PolIfEndPointIsZero{A}{B}</span></tt>.</p> -</div> -<div class="section" id="polprintintervalsthevar"> -<h3><a class="toc-backref" href="#id146"><tt class="docutils literal">\PolPrintIntervalsTheVar</tt></a></h3> -<blockquote> -Expands to the name (default <tt class="docutils literal">Z</tt>) used for representing the roots, -which was passed as optional argument <tt class="docutils literal">varname</tt> to -<a class="reference internal" href="#polprintintervals-varname-sturmname">\PolPrintIntervals[varname]{sturmname}</a>.</blockquote> -</div> -<div class="section" id="polprintintervalstheindex"> -<h3><a class="toc-backref" href="#id147"><tt class="docutils literal">\PolPrintIntervalsTheIndex</tt></a></h3> -<blockquote> -Expands to the index of the considered interval (indexing starting -at 1 for the leftmost interval).</blockquote> -</div> -<div class="section" id="polprintintervalsthesturmname"> -<h3><a class="toc-backref" href="#id148"><tt class="docutils literal">\PolPrintIntervalsTheSturmName</tt></a></h3> -<blockquote> -Expands to the argument which was passed as <tt class="docutils literal">sturmname</tt> to -<a class="reference internal" href="#polprintintervals-varname-sturmname">\PolPrintIntervals[varname]{sturmname}</a>.</blockquote> -</div> -<div class="section" id="polprintintervalstheleftendpoint"> -<h3><a class="toc-backref" href="#id149"><tt class="docutils literal">\PolPrintIntervalsTheLeftEndPoint</tt></a></h3> -<blockquote> -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>.</blockquote> -</div> -<div class="section" id="polprintintervalstherightendpoint"> -<h3><a class="toc-backref" href="#id150"><tt class="docutils literal">\PolPrintIntervalsTheRightEndPoint</tt></a></h3> -<blockquote> -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.</blockquote> -</div> -<div class="section" id="polprintintervalsthemultiplicity"> -<h3><a class="toc-backref" href="#id151"><tt class="docutils literal">\PolPrintIntervalsTheMultiplicity</tt></a></h3> -<blockquote> -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.</blockquote> -</div> -</div> -<div class="section" id="poldectostring-decimal-number"> -<span id="poldectostring"></span><h2><a class="toc-backref" href="#id152"><tt class="docutils literal">\PolDecToString{decimal number}</tt></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 <tt class="docutils literal">1.3</tt> of <tt class="docutils literal">2018/03/01</tt>) under -the name <tt class="docutils literal">\xintDecToString</tt>, and the <tt class="docutils literal">polexpr</tt> macro is simply -now an alias to it.</p> -<p>For example -<tt class="docutils literal"><span class="pre">\PolDecToString{123.456e-8}</span></tt> will expand to <tt class="docutils literal">0.00000123456</tt> -and <tt class="docutils literal"><span class="pre">\PolDecToString{123.450e-8}</span></tt> to <tt class="docutils literal">0.00000123450</tt> which -illustrates that trailing zeros are not trimmed. To trim trailing -zeroes, one can use <tt class="docutils literal"><span class="pre">\PolDecToString{\xintREZ{#1}}</span></tt>.</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">xint</a>.</p> -</blockquote> -</div> -</div> -<div class="section" id="booleans-with-default-setting-as-indicated"> -<h1><a class="toc-backref" href="#id153">Booleans (with default setting as indicated)</a></h1> -<div class="section" id="xintverbosefalse"> -<h2><a class="toc-backref" href="#id154"><tt class="docutils literal">\xintverbosefalse</tt></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 -<tt class="docutils literal">true</tt> triggers the writing of information to the log when new -polynomials are defined.</p> -<div class="admonition caution"> -<p class="first admonition-title">Caution!</p> -<p class="last">The macro meanings as written to the log are to be considered -unstable and undocumented internal structures.</p> -</div> -</blockquote> -</div> -<div class="section" id="poltypesetallfalse"> -<h2><a class="toc-backref" href="#id155"><tt class="docutils literal">\poltypesetallfalse</tt></a></h2> -<blockquote> -If <tt class="docutils literal">true</tt>, <a class="reference internal" href="#poltypeset-polname">\PolTypeset{polname}</a> will also typeset the vanishing -coefficients.</blockquote> -</div> -<div class="section" id="poltoexprallfalse"> -<h2><a class="toc-backref" href="#id156"><tt class="docutils literal">\poltoexprallfalse</tt></a></h2> -<blockquote> -If <tt class="docutils literal">true</tt>, <a class="reference internal" href="#poltoexpr-polname">\PolToExpr{polname}</a> and <a class="reference internal" href="#poltofloatexpr-polname">\PolToFloatExpr{polname}</a> will -also include the vanishing coefficients in their outputs.</blockquote> -</div> -</div> -<div class="section" id="polexprsetup"> -<h1><a class="toc-backref" href="#id157"><tt class="docutils literal">\polexprsetup</tt></a></h1> -<blockquote> -<p>Serves to customize the package. Currently only two keys are -recognized:</p> -<ul class="simple"> -<li><tt class="docutils literal">norr</tt>: the postfix that <a class="reference internal" href="#id14">\PolSturmIsolateZeros**{sturmname}</a> -should append to <tt class="docutils literal">sturmname</tt> to declare the primitive polynomial -obtained from original one after removal of all rational roots. -The default value is <tt class="docutils literal">_norr</tt> (standing for “no rational roots”).</li> -<li><tt class="docutils literal">sqfnorr</tt>: the postfix that <a class="reference internal" href="#id14">\PolSturmIsolateZeros**{sturmname}</a> -should append to <tt class="docutils literal">sturmname</tt> to declare the primitive polynomial -obtained from original one after removal of all rational roots and -suppression of all multiplicities. -The default value is <tt class="docutils literal">_sqf_norr</tt> (standing for “square-free with -no rational roots”).</li> -</ul> -<p>The package executes <tt class="docutils literal">\polexprsetup{norr=_norr, -sqfnorr=_sqf_norr}</tt> as default.</p> -</blockquote> -</div> -<div class="section" id="technicalities"> -<h1><a class="toc-backref" href="#id158">Technicalities</a></h1> -<ul> -<li><p class="first">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="#id2">\PolDef{f}{P(x)}</a> -rather. The colon in <tt class="docutils literal">:=</tt> may be active with no consequences.</p> -</li> -<li><p class="first">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" href="#id37" id="id36">[5]</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(x)Q(x); -</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 -<tt class="docutils literal">\PolToExpr{PQ}</tt> outputs the <tt class="docutils literal">6/6*x^3</tt> as <tt class="docutils literal">x^3</tt> because (by -default) it recognizes and filters out coefficients equal to one or -minus one (since release <tt class="docutils literal">0.3</tt>). One can use for example -<tt class="docutils literal">\PolToCSV{PQ}</tt> to see the internally stored coefficients.</p> -<table class="docutils footnote" frame="void" id="id37" rules="none"> -<colgroup><col class="label" /><col /></colgroup> -<tbody valign="top"> -<tr><td class="label"><a class="fn-backref" href="#id36">[5]</a></td><td><p class="first last">prior to <tt class="docutils literal">0.4.1</tt>, <tt class="docutils literal">polexpr</tt> 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">xint</a> at release <tt class="docutils literal">1.3</tt>.</p> -</td></tr> -</tbody> -</table> -</li> -<li><p class="first"><a class="reference internal" href="#poldiff-polname-1-polname-2">\PolDiff{polname_1}{polname_2}</a> always applies <tt class="docutils literal">\xintIrr</tt> to the -resulting coefficients, except that the <em>power of ten</em> part <tt class="docutils literal">[N]</tt> -(for example an input in scientific notation such as <tt class="docutils literal">1.23e5</tt> gives -<tt class="docutils literal">123/1[3]</tt> 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 class="first">Currently, the package stores all coefficients from index <tt class="docutils literal">0</tt> 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 <tt class="docutils literal">\poldef -<span class="pre">f(x):=x^1000</span> + x^500;</tt> the subsequent definition <tt class="docutils literal">\poldef <span class="pre">g(x):=</span> -<span class="pre">f(x)^2;</span></tt> 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 class="first">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="#id159">CHANGE LOG</a></h1> -<ul> -<li><p class="first">v0.1 (2018/01/11): initial release. Features:</p> -<ul class="simple"> -<li>The <a class="reference internal" href="#poldef">\poldef</a> parser itself,</li> -<li>Differentiation and anti-differentiation,</li> -<li>Euclidean division and GCDs,</li> -<li>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>, ...</li> -</ul> -<p>Only one-variable polynomials so far.</p> -</li> -<li><p class="first">v0.2 (2018/01/14)</p> -<ul class="simple"> -<li>Fix: <tt class="docutils literal">"README thinks \numexpr recognizes ^ operator"</tt>.</li> -<li>Convert README to reStructuredText markup.</li> -<li>Move main documentation from README to separate <tt class="docutils literal">polexpr.txt</tt> file.</li> -<li>Provide <tt class="docutils literal">polexpr.html</tt> as obtained via <a class="reference external" href="http://docutils.sourceforge.net/docs/index.html">DocUtils</a> <tt class="docutils literal">rst2html.py</tt>.</li> -<li>Convert README to (CTAN compatible) Markdown markup.</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 class="first">v0.3 (2018/01/17)</p> -<ul> -<li><p class="first">bug fixes:</p> -<ul> -<li><p class="first">the <tt class="docutils literal">0.1</tt> <a class="reference internal" href="#polevalat">\PolEval</a> accepted expressions for its second -argument, but this was removed by mistake at <tt class="docutils literal">0.2</tt>. Restored.</p> -<p><strong>Attention</strong>: at <tt class="docutils literal">0.4</tt> 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 class="first">incompatible or breaking changes:</p> -<ul class="simple"> -<li><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="#id30">\PolToExpr*</a> for <em>ascending</em> powers.</li> -<li><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 <tt class="docutils literal">\xintRound</tt> or <tt class="docutils literal">\xintFloat</tt>, this step has been -removed; the former meaning is available as <a class="reference internal" href="#polevalreducedat">\PolEvalReduced</a>.</li> -</ul> -</li> -<li><p class="first">new (or newly documented) macros:</p> -<ul class="simple"> -<li><a class="reference internal" href="#poltypesetcmd">\PolTypesetCmd</a></li> -<li><a class="reference internal" href="#poltypesetcmdprefix">\PolTypesetCmdPrefix</a></li> -<li><a class="reference internal" href="#poltypesetmonomialcmd">\PolTypesetMonomialCmd</a></li> -<li><a class="reference internal" href="#polevalreducedat">\PolEvalReducedAt</a></li> -<li><a class="reference internal" href="#poltofloatexpr">\PolToFloatExpr</a></li> -<li><a class="reference internal" href="#poltoexproneterm">\PolToExprOneTerm</a></li> -<li><a class="reference internal" href="#poltofloatexproneterm">\PolToFloatExprOneTerm</a></li> -<li><a class="reference internal" href="#poltoexprcmd">\PolToExprCmd</a></li> -<li><a class="reference internal" href="#id33">\PolToFloatExprCmd</a></li> -<li><a class="reference internal" href="#poltoexprtermprefix">\PolToExprTermPrefix</a></li> -<li><a class="reference internal" href="#poltoexprvar">\PolToExprVar</a></li> -<li><a class="reference internal" href="#poltoexprtimes">\PolToExprTimes</a></li> -</ul> -</li> -<li><p class="first">improvements:</p> -<ul> -<li><p class="first">documentation has a table of contents, internal hyperlinks, -standardized signature notations and added explanations.</p> -</li> -<li><p class="first">one can do <tt class="docutils literal"><span class="pre">\PolLet{g}={f}</span></tt> or <tt class="docutils literal"><span class="pre">\PolLet{g}{f}</span></tt>.</p> -</li> -<li><p class="first"><tt class="docutils literal">\PolToExpr{f}</tt> is highly customizable.</p> -</li> -<li><p class="first"><a class="reference internal" href="#poldef">\poldef</a> and other defining macros prepare the polynomial -functions for usage within <tt class="docutils literal">\xintthefloatexpr</tt> (or -<tt class="docutils literal">\xintdeffloatvar</tt>). 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 <tt class="docutils literal">0.4</tt>. 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 class="first">v0.3.1 (2018/01/18)</p> -<p>Fixes two typos in example code included in the documentation.</p> -</li> -<li><p class="first">v0.4 (2018/02/16)</p> -<ul> -<li><p class="first">bug fixes:</p> -<ul class="simple"> -<li>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>.</li> -<li><a class="reference internal" href="#polgcd">\PolGCD</a> was buggy in case of first polynomial being -of lesser degree than the second one.</li> -</ul> -</li> -<li><p class="first">breaking changes:</p> -<ul> -<li><p class="first">formerly <a class="reference internal" href="#polevalat">\PolEval{P}\At{foo}</a> allowed <tt class="docutils literal">foo</tt> to -be an expression, which was transparently handled via -<tt class="docutils literal">\xinttheexpr</tt>. Now, <tt class="docutils literal">foo</tt> must be a fraction (or a macro -expanding to such) in the format acceptable by <tt class="docutils literal">xintfrac.sty</tt> -macros. Use <a class="reference internal" href="#polevalatexpr">\PolEval{P}\AtExpr{foo}</a> for more -general arguments using expression syntax. E.g., if <tt class="docutils literal">foo</tt> is the -name of a variable known to <tt class="docutils literal">\xintexpr</tt>.</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 class="first">the <tt class="docutils literal">3.0</tt> 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 class="first">new non-expandable macros:</p> -<ul class="simple"> -<li><a class="reference internal" href="#polgenfloatvariant">\PolGenFloatVariant</a></li> -<li><a class="reference internal" href="#polgloballet">\PolGlobalLet</a></li> -<li><a class="reference internal" href="#poltypesetone">\PolTypesetOne</a></li> -<li><a class="reference internal" href="#polquo">\PolQuo</a></li> -<li><a class="reference internal" href="#polrem">\PolRem</a></li> -<li><a class="reference internal" href="#poltosturm">\PolToSturm</a></li> -<li><a class="reference internal" href="#id9">\PolToSturm*</a></li> -<li><a class="reference internal" href="#polsettosturmchainsignchangesat">\PolSetToSturmChainSignChangesAt</a></li> -<li><a class="reference internal" href="#polsettonbofzeroswithin">\PolSetToNbOfZerosWithin</a></li> -<li><a class="reference internal" href="#polsturmisolatezeros">\PolSturmIsolateZeros</a></li> -<li><a class="reference internal" href="#polrefineinterval">\PolRefineInterval*</a></li> -<li><a class="reference internal" href="#polrefineinterval-n">\PolRefineInterval[N]</a></li> -<li><a class="reference internal" href="#polensureintervallength">\PolEnsureIntervalLength</a></li> -<li><a class="reference internal" href="#polensureintervallengths">\PolEnsureIntervalLengths</a></li> -<li><a class="reference internal" href="#polprintintervals">\PolPrintIntervals</a></li> -<li><a class="reference internal" href="#polprintintervalsprintexactzero">\PolPrintIntervalsPrintExactZero</a></li> -<li><a class="reference internal" href="#polprintintervalsprintleftendpoint">\PolPrintIntervalsPrintLeftEndPoint</a></li> -<li><a class="reference internal" href="#polprintintervalsprintrightendpoint">\PolPrintIntervalsPrintRightEndPoint</a></li> -<li><a class="reference internal" href="#id20">\PolReduceCoeffs*</a></li> -<li><a class="reference internal" href="#polmakemonic">\PolMakeMonic</a></li> -</ul> -</li> -<li><p class="first">new expandable macros:</p> -<ul class="simple"> -<li><a class="reference internal" href="#poltoexpronetermstylea">\PolToExprOneTermStyleA</a></li> -<li><a class="reference internal" href="#polifcoeffisplusorminusone">\PolIfCoeffIsPlusOrMinusOne</a></li> -<li><a class="reference internal" href="#polleadingcoeff">\PolLeadingCoeff</a></li> -<li><a class="reference internal" href="#polsturmchainlength">\PolSturmChainLength</a></li> -<li><a class="reference internal" href="#polsturmnbofisolatedzeros">\PolSturmNbOfIsolatedZeros</a></li> -<li><a class="reference internal" href="#polsturmifzeroexactlyknown">\PolSturmIfZeroExactlyKnown</a></li> -<li><a class="reference internal" href="#polsturmisolatedzeroleft">\PolSturmIsolatedZeroLeft</a></li> -<li><a class="reference internal" href="#polsturmisolatedzeroright">\PolSturmIsolatedZeroRight</a></li> -<li><tt class="docutils literal">\PolPrintIntervalsTheEndPoint</tt> (removed at 0.7)</li> -<li><a class="reference internal" href="#polprintintervalstheindex">\PolPrintIntervalsTheIndex</a></li> -<li><tt class="docutils literal">\PolIfEndPointIsPositive</tt> (removed at 0.7)</li> -<li><tt class="docutils literal">\PolIfEndPointIsNegative</tt> (removed at 0.7)</li> -<li><tt class="docutils literal">\PolIfEndPointIsZero</tt> (removed at 0.7)</li> -<li><a class="reference internal" href="#polintervalwidth">\PolIntervalWidth</a></li> -<li><a class="reference internal" href="#poldectostring">\PolDecToString</a></li> -</ul> -</li> -<li><p class="first">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 class="first">v0.4.1 (2018/03/01)</p> -<p>Synced with xint 1.3.</p> -</li> -<li><p class="first">v0.4.2 (2018/03/03)</p> -<p>Documentation fix.</p> -</li> -<li><p class="first">v0.5 (2018/04/08)</p> -<ul class="simple"> -<li>bug fixes:<ul> -<li><a class="reference internal" href="#polget-polname-fromarray-macro">\PolGet{polname}\fromarray\macro</a> crashed when <tt class="docutils literal">\macro</tt> 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.</li> -</ul> -</li> -<li>breaking changes:<ul> -<li><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.</li> -<li>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 <tt class="docutils literal">\xintRaw</tt>.</li> -</ul> -</li> -<li>experimental change:<ul> -<li>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.</li> -</ul> -</li> -<li>new non-expandable macro:<ul> -<li><a class="reference internal" href="#polmakeprimitive">\PolMakePrimitive</a></li> -</ul> -</li> -<li>new expandable macro:<ul> -<li><a class="reference internal" href="#policontent">\PolIContent</a></li> -</ul> -</li> -</ul> -</li> -<li><p class="first">v0.5.1 (2018/04/22)</p> -<ul class="simple"> -<li>new feature:<ul> -<li>the character <tt class="docutils literal">'</tt> can be used in polynomial names.</li> -</ul> -</li> -</ul> -</li> -<li><p class="first">v0.6 (2018/11/20)</p> -<ul class="simple"> -<li>bugfix:<ul> -<li>the starred variant <a class="reference internal" href="#id10">\PolToSturm*{polname}{sturmname}</a> was -broken. On the occasion of the fix, its meaning has been modified, -see its documentation.</li> -<li>using <a class="reference internal" href="#poltosturm">\PolToSturm</a> with a constant polynomial -caused a division by zero error.</li> -</ul> -</li> -<li>new macro:<ul> -<li><a class="reference internal" href="#id11">\PolSturmIsolateZeros*</a> -acts like the <a class="reference internal" href="#polsturmisolatezeros">non-starred variant</a> then computes all the multiplicities.</li> -</ul> -</li> -<li>new expandable macros:<ul> -<li><a class="reference internal" href="#polsturmisolatedzeromultiplicity-sturmname-index">\PolSturmIsolatedZeroMultiplicity{sturmname}{index}</a></li> -<li><a class="reference internal" href="#polsturmnbofrootsof-sturmname-lessthanorequalto-value">\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualTo{value}</a></li> -<li><a class="reference internal" href="#polsturmnbofrootsof-sturmname-lessthanorequaltoexpr-expression">\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualToExpr{expression}</a></li> -<li><a class="reference internal" href="#polsturmnbwithmultofrootsof-sturmname-lessthanorequalto-value">\PolSturmNbWithMultOfRootsOf{sturmname}\LessThanOrEqualTo{value}</a></li> -<li><a class="reference internal" href="#polsturmnbwithmultofrootsof-sturmname-lessthanorequaltoexpr-expression">\PolSturmNbWithMultOfRootsOf{sturmname}\LessThanOrEqualToExpr{expression}</a></li> -</ul> -</li> -</ul> -</li> -<li><p class="first">v0.7 (2018/12/08), v0.7.1 (bugfix), v0.7.2 (2nd bugfix) (2018/12/09)</p> -<ul class="simple"> -<li>breaking changes:<ul> -<li>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: <tt class="docutils literal">\PolPrintIntervalsTheEndPoint</tt>, -<tt class="docutils literal"><span class="pre">\PolIfEndPointIsPositive{A}{B}</span></tt>, -<tt class="docutils literal"><span class="pre">\PolIfEndPointIsNegative{A}{B}</span></tt>, and -<tt class="docutils literal"><span class="pre">\PolIfEndPointIsZero{A}{B}</span></tt>.</li> -</ul> -</li> -<li>bugfix:<ul> -<li>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,</li> -<li><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,</li> -<li><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).</li> -</ul> -</li> -<li>new macros:<ul> -<li><a class="reference internal" href="#id14">\PolSturmIsolateZeros**{sturmname}</a></li> -<li><a class="reference internal" href="#polsturmisolatezerosgetmultiplicitiesandrationalroots-sturmname">\PolSturmIsolateZerosGetMultiplicitiesAndRationalRoots{sturmname}</a></li> -<li><a class="reference internal" href="#polsturmisolatezerosandfindrationalroots-sturmname">\PolSturmIsolateZerosAndFindRationalRoots{sturmname}</a></li> -<li><a class="reference internal" href="#polexprsetup">\polexprsetup</a></li> -<li><a class="reference internal" href="#id18">\PolPrintIntervals*</a></li> -<li><a class="reference internal" href="#polprintintervalsnorealroots">\PolPrintIntervalsNoRealRoots</a></li> -<li><a class="reference internal" href="#polprintintervalsbeginenv">\PolPrintIntervalsBeginEnv</a></li> -<li><a class="reference internal" href="#polprintintervalsendenv">\PolPrintIntervalsEndEnv</a></li> -<li><a class="reference internal" href="#polprintintervalsknownroot">\PolPrintIntervalsKnownRoot</a></li> -<li><a class="reference internal" href="#polprintintervalsunknownroot">\PolPrintIntervalsUnknownRoot</a></li> -<li><a class="reference internal" href="#polprintintervalsprintmultiplicity">\PolPrintIntervalsPrintMultiplicity</a></li> -</ul> -</li> -<li>new expandable macros:<ul> -<li><a class="reference internal" href="#polsturmnbofrationalroots-sturmname">\PolSturmNbOfRationalRoots{sturmname}</a></li> -<li><a class="reference internal" href="#polsturmnbofrationalrootswithmultiplicities-sturmname">\PolSturmNbOfRationalRootsWithMultiplicities{sturmname}</a></li> -<li><a class="reference internal" href="#polsturmrationalroot-sturmname-k">\PolSturmRationalRoot{sturmname}{k}</a></li> -<li><a class="reference internal" href="#polsturmrationalrootindex-sturmname-k">\PolSturmRationalRootIndex{sturmname}{k}</a></li> -<li><a class="reference internal" href="#polsturmrationalrootmultiplicity-sturmname-k">\PolSturmRationalRootMultiplicity{sturmname}{k}</a></li> -<li><a class="reference internal" href="#polprintintervalsthevar">\PolPrintIntervalsTheVar</a></li> -<li><a class="reference internal" href="#polprintintervalsthesturmname">\PolPrintIntervalsTheSturmName</a></li> -<li><a class="reference internal" href="#polprintintervalsthemultiplicity">\PolPrintIntervalsTheMultiplicity</a></li> -</ul> -</li> -</ul> -</li> -<li><p class="first">v0.7.3 (2019/02/04)</p> -<ul class="simple"> -<li>bugfix:<ul> -<li>Debugging information not destined to user showed in log if root -finding was done under <tt class="docutils literal">\xintverbosetrue</tt> regime.</li> -<li><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="#id18">\PolPrintIntervals*</a> (reported by Jürgen Gilg). Now remains -defined in both cases, and <a class="reference internal" href="#polprintintervalsthesturmname">\PolPrintIntervalsTheSturmName</a> -also.</li> -<li>Polynomial names ending in digits caused errors (reported by Thomas -Söll).</li> -</ul> -</li> -</ul> -</li> -<li><p class="first">v0.7.4 (2019/02/12)</p> -<ul class="simple"> -<li>bugfix:<ul> -<li>20000000000 is too big for <tt class="docutils literal">\numexpr</tt>, shouldn't I know that? -Thanks to Jürgen Gilg for report.</li> -</ul> -</li> -</ul> -</li> -<li><p class="first">v0.7.5 (2020/01/31)</p> -<p>Synced with xint 1.4. Requires it.</p> -</li> -</ul> -</div> -<div class="section" id="acknowledgments"> -<h1><a class="toc-backref" href="#id160">Acknowledgments</a></h1> -<p>Thanks to Jürgen Gilg whose question about <a class="reference external" href="http://www.ctan.org/pkg/xint">xint</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 <tt class="docutils literal">0.6</tt> and <tt class="docutils literal">0.7</tt> releases for their -continued interest.</p> -<p>See README.md for the License.</p> -</div> -</div> -</body> -</html> diff --git a/Master/texmf-dist/doc/latex/polexpr/polexpr.txt b/Master/texmf-dist/doc/latex/polexpr/polexpr.txt deleted file mode 100644 index 898375926b0..00000000000 --- a/Master/texmf-dist/doc/latex/polexpr/polexpr.txt +++ /dev/null @@ -1,2598 +0,0 @@ -.. comment: -*- fill-column: 72; mode: rst; -*- - -=============================== - Package polexpr documentation -=============================== - -0.7.5 (2020/01/31) -================== - -.. contents:: - -Basic syntax ------------- - -The syntax is:: - - \poldef polname(x):= expression in variable x; - -where: - -- in place of ``x`` an arbitrary *dummy variable* is authorized, - i.e. per default any of ``[a-z|A-Z]`` (more letters can be declared - under Unicode engines.) - -- ``polname`` consists of letters, digits, and the ``_`` and - ``'`` characters. It must start with a letter. - -.. attention:: - - The ``'`` is authorized since ``0.5.1``. As a result some constructs - recognized by the ``\xintexpr`` parser, such as ``var1 'and' var2`` - will get misinterpreted and cause errors. However these constructs - are unlikely to be frequently needed in polynomial expressions, and - the ``\xintexpr`` syntax offers alternatives, so it was deemed a - small evil. Of course the ``\xintexpr`` parser is modified only - temporarily during execution of ``\poldef``. - -One can also issue:: - - \PolDef{polname}{expression in variable x} - -which admits an optional first argument to modify the variable letter -from its default ``x``. - -``\poldef f(x):= 1-x+x^2;`` - defines polynomial ``f``. Polynomial names must start with a - letter and may contain letters, digits, underscores and the right - tick character. The - variable must be a single letter. The colon character is optional. - The semi-colon at end of expression is mandatory. - -``\PolDef{f}{1-x+x^2}`` - does the same as ``\poldef f(x):= 1-x+x^2;`` To use another letter - than ``x`` in the expression, one must pass it as an extra optional - argument to ``\PolDef``. Useful if the semi-colon has been assigned - some non-standard catcode by some package. - -``\PolLet{g}={f}`` - saves a copy of ``f`` under name ``g``. Also usable without ``=``. - -``\poldef f(z):= f(z)^2;`` - redefines ``f`` in terms of itself. - -``\poldef f(T):= f(f(T));`` - again redefines ``f`` in terms of its (new) self. - -``\poldef k(z):= f(z)-g(g(z)^2)^2;`` - should now define the zero polynomial... Let's check: - ``\[ k(z) = \PolTypeset[z]{k} \]`` - -``\PolDiff{f}{f'}`` - sets ``f'`` to the derivative of ``f``. The name doesn't have to be - ``f'`` (in fact the ``'`` is licit only since ``0.5.1``). - -.. important:: - - This is not done automatically. If some new definition needs to use - the derivative of some available polynomial, that derivative - polynomial must have been defined via ``\PolDiff``: something like - ``T'(x)^2`` will not work without a prior ``\PolDiff{T}{T'}``. - -``\PolDiff{f'}{f''}`` - obtains second derivative. - -``\PolDiff[3]{f}{f'''}`` - computes the third derivative. - -:: - - $f(z) = \PolTypeset[z]{f} $\newline - $f'(z) = \PolTypeset[z]{f'} $\newline - $f''(z) = \PolTypeset[z]{f''} $\newline - $f'''(z)= \PolTypeset[z]{f'''} $\par - -.. important:: - - The package does not currently know rational functions: ``/`` in - a parsed polynomial expression does the Euclidean quotient:: - - (1-x^2)/(1-x) - - does give ``1+x`` but :: - - (1/(1-x))*(1-x^2) - - evaluates to zero. This will work as expected:: - - \poldef k(x):= (x-1)(x-2)(x-3)(x-4)/(x^2-5x+4); - -.. _warningtacit: - -.. attention:: - - ``1/2 x^2`` skips the space and is treated like ``1/(2*x^2)`` because - of the tacit multiplication rules of \xintexpr. But this means it - gives zero! Thus one must use ``(1/2)x^2`` or ``1/2*x^2`` or - ``(1/2)*x^2`` for disambiguation: ``x - 1/2*x^2 + 1/3*x^3...``. It is - even simpler to move the denominator to the right: ``x - x^2/2 + - x^3/3 - ...``. - - It is worth noting that ``1/2(x-1)(x-2)`` suffers the same issue: - xint_ tacit multiplication always "ties more", hence this gets - interpreted as ``1/(2*(x-1)*(x-2))`` which gives zero by polynomial - division. Thus, use one of ``(1/2)(x-1)(x-2)``, ``1/2*(x-1)(x-2)`` or - ``(x-1)(x-2)/2``. - -After:: - - \poldef f_1(x):= 25(x-1)(x^2-2)(x-3)(x-4)(x-5);% - \poldef f_2(x):= 37(x-1)(x^2-2)(x-6)(x-7)(x-8);% - -the macro call ``\PolGCD{f_1}{f_2}{k}`` sets ``k`` to the (unitary) GCD of -``f_1`` and ``f_2`` (hence to the expansion of ``(x-1)(x^2-2)``.) - -``\PolToExpr{k}`` - will (expandably) give in this case ``x^3-x^2-2*x+2``. This is - useful for console or file output (the syntax is Maple- and - PSTricks-compatible; the letter used in output can be - (non-expandably) changed via a redefinition of `\\PolToExprVar`_.) - -``\PolToExpr*{k}`` - gives ascending powers: ``2-2*x-x^2+x^3``. - -Examples of localization of roots ---------------------------------- - -- To make printed decimal numbers more enjoyable than via - ``\xintSignedFrac``:: - - \renewcommand\PolTypesetOne[1]{\PolDecToString{\xintREZ{#1}}}% - - ``\PolDecToString`` will use decimal notation to incorporate the power - of ten part; and the ``\xintREZ`` 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:: - - \renewcommand\PolToExprCmd[1]{\PolDecToString{\xintREZ{#1}}}% - - to modify output of `\\PolToExpr{polname}`_. - -- For extra info in log file use ``\xintverbosetrue``. - -- Only for some of these examples is the output included here. - - -A typical example -~~~~~~~~~~~~~~~~~ - -In this example the polynomial is square-free. - -:: - - \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}<Z_2<\PolSturmIsolatedZeroRight{f}{2}\] - And here is the first root with twenty digits after decimal mark: - \PolEnsureIntervalLength{f}{1}{-20} - \[\PolSturmIsolatedZeroLeft{f}{1}<Z_1<\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$! - -A degree four polynomial with nearby roots -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Notice that this example is a bit outdated as ``0.7`` release has -added ``\PolSturmIsolateZeros**{sturmname}`` which would find exactly -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. - - -:: - - \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 < Z_1 < 1.1, 1.10 < Z_2 < 1.11, 1.110 < Z_3 < 1.111, and 1.111 < Z_4 < 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 < Z_1 < 1.06, 1.105 < Z_2 < 1.106, 1.1105 < Z_3 < 1.1106, - % and 1.11105 < Z_4 < 1.11106. - \PolEnsureIntervalLengths{Q}{-6} - \PolPrintIntervals{Q} - % of course finds here all roots exactly - - -The degree nine polynomial with 0.99, 0.999, 0.9999 as triple roots -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - % define a user command (xinttools is loaded automatically by polexpr) - \newcommand\showmultiplicities[1]{% #1 = "sturmname" - \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}<x<\PolSturmIsolatedZeroRight{#1}{##1}$} - \par - }}% - \PolDef{f}{(x-0.99)^3(x-0.999)^3(x-0.9999)^3} - \renewcommand\PolTypesetOne[1]{\PolDecToString{\xintREZ{#1}}} - \PolTypeset{f}\par - \PolToSturm{f}{f}% it is allowed to use "polname" as "sturmname" too - \PolSturmIsolateZerosAndGetMultiplicities{f}% use the "sturmname" here - % or \PolSturmIsolateZeros*{f} which is exactly the same, but shorter.. - - \showmultiplicities{f} - -In this example, the output will look like this (but using math mode):: - - 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 - -On first pass, these rational roots were found (due to their relative -magnitudes, using ``\PolSturmIsolateZeros**`` was not needed here). But -multiplicity computation works also with (decimal) roots not yet -identified or with non-decimal or irrational roots. - -It is fun to modify only a tiny bit the polynomial and see if polexpr -survives:: - - \PolDef{g}{f(x)+1e-27} - \PolTypeset{g}\par - \PolToSturm{g}{g} - \PolSturmIsolateZeros*{g} - - \showmultiplicities{g} - -This produces:: - - 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 < x < 0.99 - The multiplicity is 1 for the root such that 0.9991 < x < 0.9992 - The multiplicity is 1 for the root such that 0.9997 < x < 0.9998 - -Which means that the multiplicity-3 roots each became a real and a pair of -complex ones. Let's see them better:: - - \PolEnsureIntervalLengths{g}{-10} - - \showmultiplicities{g} - -which produces:: - - The multiplicity is 1 for the root such that 0.9899888032 < x < 0.9899888033 - The multiplicity is 1 for the root such that 0.9991447980 < x < 0.9991447981 - The multiplicity is 1 for the root such that 0.9997663986 < x < 0.9997663987 - -A degree five polynomial with three rational roots -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - \poldef Q(x) := 1581755751184441 x^5 - -14907697165025339 x^4 - +48415668972339336 x^3 - -63952057791306264 x^2 - +46833913221154895 x - -49044360626280925; - - \PolToSturm{Q}{Q} - %\begin{flushleft} - \renewcommand\PolTypesetCmdPrefix[1]{\allowbreak\xintiiifSgn{#1}{}{+}{+}}% - $Q_0(x) = \PolTypeset{Q_0}$ - %\end{flushleft} - \PolSturmIsolateZeros**{Q} - \PolPrintIntervals{Q} - - $Q_{norr}(x) = \PolTypeset{Q_norr}$ - -Here, all real roots are rational:: - - Z_1 = 833719/265381 - Z_2 = 165707065/52746197 - Z_3 = 355/113 - - Q_norr(x) = x^2 + 1 - -And let's get their decimal expansion too:: - - % print decimal expansion of the found roots - \renewcommand\PolPrintIntervalsPrintExactZero - {\xintTrunc{20}{\PolPrintIntervalsTheLeftEndPoint}\dots} - \PolPrintIntervals{Q} - - Z_1 = 3.14159265358107777120... - Z_2 = 3.14159265358979340254... - Z_3 = 3.14159292035398230088... - - -A Mignotte type polynomial -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - \PolDef{P}{x^10 - (10x-1)^2}% - \PolTypeset{P} % prints it in expanded form - \PolToSturm{P}{P} % we can use same prefix for Sturm chain - \PolSturmIsolateZeros{P} % finds 4 real roots - This polynomial has \PolSturmNbOfIsolatedZeros{P} distinct real roots: - \PolPrintIntervals{P}% - % reports -2 < Z_1 < -1, 0.09 < Z_2 < 0.10, 0.1 < Z_3 < 0.2, 1 < Z_4 < 2 - Let us refine the second and third intervals to separate the corresponding - roots: - \PolRefineInterval*{P}{2}% will refine to 0.0999990 < Z_2 < 0.0999991 - \PolRefineInterval*{P}{3}% will refine to 0.100001 < Z_3 < 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}<Z_2<\PolSturmIsolatedZeroRight{P}{2}\] - -The last line produces:: - - 0.09999900004999650028 < Z_2 < 0.09999900004999650029 - - -The Wilkinson polynomial -~~~~~~~~~~~~~~~~~~~~~~~~ - -See `Wilkinson polynomial`_. - -:: - - \documentclass{article} - \usepackage{polexpr} - \begin{document} - %\xintverbosetrue % for the curious... - - \poldef f(x) := mul((x - i), i = 1..20); - - \renewcommand\PolTypesetCmdPrefix[1]{\allowbreak\xintiiifSgn{#1}{}{+}{+}}% - \renewcommand\PolTypesetOne[1]{\xintDecToString{#1}}% - - \noindent\PolTypeset{f} - - \PolToSturm{f}{f} - \PolSturmIsolateZeros{f} - \PolPrintIntervals{f} - - \clearpage - - \poldef g(x) := f(x) - 2**{-23} x**19; - - % be patient! - \PolToSturm{g}{g} - \noindent\PolTypeset{g_0}% integer coefficient primitive polynomial - - \PolSturmIsolateZeros{g} - \PolEnsureIntervalLengths{g}{-10} - - \renewcommand\PolPrintIntervalsPrintMultiplicity{} - \PolPrintIntervals*{g} - - \end{document} - - -The first polynomial:: - - 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 - -is handled fast enough (a few seconds), but the modified one ``f(x) - -2**-23 x**19`` takes about 20x longer (the Sturm chain polynomials -have integer coefficients with up to 321 digits, whereas (surprisingly -perhaps) those of the Sturm chain polynomials derived from ``f`` never -have more than 21 digits ...). - -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 -``f(x) - 2**-23 x**19`` as computed by the code above:: - - 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... - -The second Wilkinson polynomial -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - \documentclass{article} - \usepackage{polexpr} - \begin{document} - \poldef f(x) := mul(x - 2^-i, i = 1..20); - - %\PolTypeset{f} - - \PolToSturm{f}{f} - \PolSturmIsolateZeros**{f} - \PolPrintIntervals{f} - \end{document} - -This takes more time than the polynomial with 1, 2, .., 20 as roots but -less than the latter modified by the ``2**-23`` change in one -coefficient. - -Here is the output (with release 0.7.2):: - - 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 - -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 ``\xintIrr`` before storage of the found root. -This may evolve in future. - - -The degree 41 polynomial with -2, -1.9, -1.8, ..., 0, 0.1, ..., 1.9, 2 as roots -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - \PolDef{P}{mul((x-i*1e-1), i=-20..20)}% i/10 is same but less efficient - -In the defining expression we could have used ``i/10`` but this gives -less efficient internal form for the coefficients (the ``10``'s end up -in denominators). Using ``\PolToExpr{P}`` after having done - -:: - - \renewcommand\PolToExprCmd[1]{\PolDecToString{\xintREZ{#1}}} - -we get this expanded form:: - - 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 - -which shows coefficients with up to 36 significant digits... - -Stress test: not a hard challenge to ``xint + polexpr``, but be a bit patient! - -:: - - \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? - -.. note:: - - Release ``0.5`` has *experimental* addition of optional argument - ``E`` to ``\PolSturmIsolateZeros``. It instructs to search roots only - in interval ``(-10^E, 10^E)``. Important: the extremities are - *assumed to not be roots*. In this example, the ``[1]`` in - ``\PolSturmIsolateZeros[1]{S}`` gives some speed gain; without it, it - turns out in this case that ``polexpr`` would have started with - ``(-10^6, 10^6)`` interval. - - 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. - -Roots of Chebyshev polynomials -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - \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<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} - - -Non-expandable macros ---------------------- - -.. _poldef;: - -``\poldef polname(letter):= expression in letter;`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This evaluates the *polynomial expression* and stores the coefficients - in a private structure accessible later via other package macros, - under the user-chosen ``polname``. Of course the *expression* can - use other previously defined polynomials. Names must start with a - letter and are constituted of letters, digits, underscores and - (since ``0.5.1``) the right tick ``'``. - The whole xintexpr_ syntax is authorized:: - - \poldef sin(z) := add((-1)^i z^(2i+1)/(2i+1)!, i = 0..10); - - With fractional coefficients, beware the `tacit multiplication issue - <warningtacit_>`_. - - As a side effect the function ``polname()`` is recognized as a - genuine ``\xintexpr...\relax`` function for (exact) numerical - evaluation (or within an ``\xintdefvar`` assignment.) It computes - values not according to the original expression but via the Horner - scheme corresponding to the polynomial coefficients. - - .. attention:: - - Release ``0.3`` also did the necessary set-up to let the - polynomial be known to the ``\xintfloatexpr`` (or - ``\xintdeffloatvar``) parser. - - Since ``0.4`` this isn't done automatically. Even more, a - previously existing floating point variant of the same name will - be let undefined again, to avoid hard to debug mismatches between - exact and floating point polynomials. This also applies when the - polynomial is produced not via ``\poldef`` or ``\PolDef`` but as - a product of the other package macros. - - See `\\PolGenFloatVariant{polname}`_. - - The original expression is lost after parsing, and in particular - the package provides no way to typeset it. This has to be done - manually, if needed. - -.. _PolDef: - -``\PolDef[letter]{polname}{expression in letter}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Does the same as `\\poldef <poldef;>`_ in an undelimited macro - format (thus avoiding potential problems with the catcode of the - semi-colon in presence of some packages.) In absence of the - ``[letter]`` optional argument, the variable is assumed to be ``x``. - -.. _PolGenFloatVariant: - -``\PolGenFloatVariant{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Makes the polynomial also usable in the ``\xintfloatexpr`` parser. - It will therein evaluates via an Horner scheme with coefficients - already pre-rounded to the float precision. - - See also `\\PolToFloatExpr{polname}`_. - - .. attention:: - - Release ``0.3`` did this automatically on ``\PolDef`` and - ``\poldef`` but this was removed at ``0.4`` for optimization. - - Any operation, for example generating the derivative polynomial, - or dividing two polynomials or using the ``\PolLet``, **must** be - followed by explicit usage of ``\PolGenFloatVariant{polname}`` if - the new polynomial is to be used in ``\xintfloatexpr`` or alike - context. - -.. _PolLet: - -``\PolLet{polname_2}={polname_1}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Makes a copy of the already defined polynomial ``polname_1`` to a - new one ``polname_2``. Same effect as - ``\PolDef{polname_2}{polname_1(x)}`` but with less overhead. The - ``=`` is optional. - -.. _PolGlobalLet: - -``\PolGlobalLet{polname_2}={polname_1}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Acts globally. - -.. _PolAssign: - -``\PolAssign{polname}\toarray\macro`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Defines a one-argument expandable macro ``\macro{#1}`` which expands - to the (raw) #1th polynomial coefficient. - - - Attention, coefficients here are indexed starting at 1. - - - With #1=-1, -2, ..., ``\macro{#1}`` returns leading coefficients. - - - With #1=0, returns the number of coefficients, i.e. ``1 + deg f`` - for non-zero polynomials. - - - Out-of-range #1's return ``0/1[0]``. - - See also `\\PolNthCoeff{polname}{number}`_. The main difference is that - with ``\PolAssign``, ``\macro`` is made a prefix to ``1 + deg f`` - already defined (hidden to user) macros holding individually the - coefficients but `\\PolNthCoeff{polname}{number}`_ does each time the job - to expandably recover the ``Nth`` coefficient, and due to - expandability can not store it in a macro for future usage (of course, - it can be an argument in an ``\edef``.) The other difference - is the shift by one in indexing, mentioned above (negative - indices act the same in both.) - -.. _PolGet: - -``\PolGet{polname}\fromarray\macro`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Does the converse operation to - ``\PolAssign{polname}\toarray\macro``. Each individual - ``\macro{number}`` gets expanded in an ``\edef`` and then normalized - via xintfrac_\ 's macro ``\xintRaw``. - - The leading zeros are removed from the polynomial. - - (contrived) Example:: - - \xintAssignArray{1}{-2}{5}{-3}\to\foo - \PolGet{f}\fromarray\foo - - This will define ``f`` as would have ``\poldef f(x):=1-2x+5x^2-3x^3;``. - - .. note:: - - Prior to ``0.5``, coefficients were not normalized via - ``\xintRaw`` for internal storage. - -.. _PolFromCSV: - -``\PolFromCSV{polname}{<csv>}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Defines a polynomial directly from the comma separated list of values - (or a macro expanding to such a list) of its coefficients, the *first - item* gives the constant term, the *last item* gives the leading - coefficient, except if zero, then it is dropped (iteratively). List - items are each expanded in an ``\edef`` and then put into normalized - form via xintfrac_\ 's macro ``\xintRaw``. - - As leading zero coefficients are removed:: - - \PolFromCSV{f}{0, 0, 0, 0, 0, 0, 0, 0, 0, 0} - - defines the zero polynomial, which holds only one coefficient. - - See also expandable macro `\\PolToCSV <\\PolToCSV{polname}_>`_. - - .. note:: - - Prior to ``0.5``, coefficients were not normalized via - ``\xintRaw`` for internal storage. - -.. _PolTypeset: - -``\PolTypeset{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~~ - - Typesets in descending powers in math mode. It uses letter ``x`` but - this can be changed via an optional argument:: - - \PolTypeset[z]{polname} - - By default zero coefficients are skipped (issue ``\poltypesetalltrue`` - to get all of them in output). - - These commands (whose meanings will be found in the package code) - can be re-defined for customization. Their default definitions are - expandable, but this is not a requirement. - -.. _PolTypesetCmd: - -``\PolTypesetCmd{raw_coeff}`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Checks if the coefficient is ``1`` or ``-1`` and then skips printing - the ``1``, except for the constant term. Also it sets conditional - `\\PolIfCoeffIsPlusOrMinusOne{A}{B}`_. - - The actual printing of the coefficients, when not equal to plus or - minus one is handled by `\\PolTypesetOne{raw_coeff}`_. - -.. _PolTypesetOne: - -``\PolTypesetOne{raw_coeff}`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - The default is ``\xintSignedFrac`` but this macro is annoying as it - insists to use a power of ten, and not decimal notation. - - One can do things such as for example: [#]_ - - :: - - \renewcommand\PolTypesetOne[1]{\num{\xintPFloat[5]{#1}}} - \renewcommand\PolTypesetOne[1]{\num{\xintRound{4}{#1}}} - - where e.g. we used the ``\num`` macro of ``siunitx`` as it - understands floating point notation. - - .. [#] the difference in the syntaxes of ``\xintPFloat`` and - ``\xintRound`` is explained from the fact that - ``\xintPFloat`` by default uses the prevailing precision - hence the extra argument like here ``5`` is an optional one. - - One can also give a try to using `\\PolDecToString{decimal number}`_ - which uses decimal notation (at least for the numerator part). - -.. _PolTypesetMonomialCmd: - -``\PolTypesetMonomialCmd`` -^^^^^^^^^^^^^^^^^^^^^^^^^^ - - This decides how a monomial (in variable ``\PolVar`` and with - exponent ``\PolIndex``) is to be printed. The default does nothing - for the constant term, ``\PolVar`` for the first degree and - ``\PolVar^{\PolIndex}`` for higher degrees monomials. Beware that - ``\PolIndex`` expands to digit tokens and needs termination in - ``\ifnum`` tests. - -.. _PolTypesetCmdPrefix: - -``\PolTypesetCmdPrefix{raw_coeff}`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Expands to a ``+`` if the ``raw_coeff`` is zero or positive, and to - nothing if ``raw_coeff`` is negative, as in latter case the - ``\xintSignedFrac`` used by `\\PolTypesetCmd{raw_coeff}`_ will put - the ``-`` sign in front of the fraction (if it is a fraction) and - this will thus serve as separator in the typeset formula. Not used - for the first term. - -.. _PolTypeset*: - -``\PolTypeset*{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~ - - Typesets in ascending powers. Use e.g. ``[h]`` optional argument - (after the ``*``) to use letter ``h`` rather than ``x``. - -.. _PolDiff: - -``\PolDiff{polname_1}{polname_2}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This sets ``polname_2`` to the first derivative of ``polname_1``. It - is allowed to issue ``\PolDiff{f}{f}``, effectively replacing ``f`` - by ``f'``. - - Coefficients of the result ``polname_2`` are irreducible fractions - (see `Technicalities`_ for the whole story.) - -.. _PolDiff[N]: - -``\PolDiff[N]{polname_1}{polname_2}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This sets ``polname_2`` to the ``N``-th derivative of ``polname_1``. - Identical arguments is allowed. With ``N=0``, same effect as - ``\PolLet{polname_2}={polname_1}``. With negative ``N``, switches to - using ``\PolAntiDiff``. - -.. _PolAntiDiff: - -``\PolAntiDiff{polname_1}{polname_2}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This sets ``polname_2`` to the primitive of ``polname_1`` vanishing - at zero. - - Coefficients of the result ``polname_2`` are irreducible fractions - (see `Technicalities`_ for the whole story.) - -.. _PolAntiDiff[N]: - -``\PolAntiDiff[N]{polname_1}{polname_2}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This sets ``polname_2`` to the result of ``N`` successive integrations on - ``polname_1``. With negative ``N``, it switches to using ``\PolDiff``. - -.. _PolDivide: - -``\PolDivide{polname_1}{polname_2}{polname_Q}{polname_R}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This sets ``polname_Q`` and ``polname_R`` to be the quotient and - remainder in the Euclidean division of ``polname_1`` by - ``polname_2``. - -.. _PolQuo: - -``\PolQuo{polname_1}{polname_2}{polname_Q}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This sets ``polname_Q`` to be the quotient in the Euclidean division - of ``polname_1`` by ``polname_2``. - -.. _PolRem: - -``\PolRem{polname_1}{polname_2}{polname_R}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This sets ``polname_R`` to be the remainder in the Euclidean division - of ``polname_1`` by ``polname_2``. - -.. _PolGCD: - -``\PolGCD{polname_1}{polname_2}{polname_GCD}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This sets ``polname_GCD`` to be the (monic) GCD of the two first - polynomials. It is a unitary polynomial except if both ``polname_1`` - and ``polname_2`` vanish, then ``polname_GCD`` is the zero - polynomial. - -.. ``\PolIGCD{polname_1}{polname_2}{polname_iGCD}`` - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - **NOT YET** - - This **assumes** that the two polynomials have integer coefficients. - It then computes the greatest common divisor in the integer - polynomial ring, normalized to have a positive leading coefficient - (if the inputs are not both zero). - - ``\PolIContent{polname}`` - ~~~~~~~~~~~~~~~~~~~~~~~~~ - - **NOT YET** - - This computes a positive rational number such that dividing the - polynomial with it returns an integer coefficients polynomial with - no common factor among the coefficients. - -.. _PolToSturm: - -``\PolToSturm{polname}{sturmname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - With ``polname`` being for example ``P``, the macro starts by - computing polynomials ``P`` and ``P'``, then computes the (opposite - of the) remainder in euclidean division, iteratively. - - The last non-zero remainder ``P_N_`` (where ``N`` is obtainable as - `\\PolSturmChainLength{sturmname}`_) is up to a factor - the GCD of ``P`` and ``P'`` hence it is a constant if and only if - ``P`` is square-free. - - .. note:: - - - Since ``0.5`` 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 ``1`` or ``-1``. - - - After this normalization to primitive polynomials, they are - stored internally as ``sturmname_k_``, ``k=0,1, ...``. - - - These polynomials are used internally only. To keep them as - genuine declared polynomials also after the macro call, use the - starred variant `PolToSturm*`_. - - .. note:: - - It is perfectly allowed to use the polynomial name as Sturm chain name: - ``\PolToSturm{f}(f}``. - - The macro then declares ``sturmname_0``, ``sturmname_1``, ..., which are - the (non-declared) ``sturmname_k_`` divided by the last one. Division is - not done if this last one is the constant ``1`` or ``-1``, i.e. if the - original polynomial was square-free. These polynomials are primitive - polynomials too, i.e. with integer coefficients having no common factor. - - Thus ``sturmname_0`` has exactly the same real and complex roots as - polynomial ``polname``, but with each root now of multiplicity one: - i.e. it is the "square-free part" of original polynomial ``polname``. - - Notice that ``sturmname_1`` isn't necessarily the derivative of - ``sturmname_0`` due to the various normalizations. - - The polynomials ``sturmname_k`` main utility is for the execution of - `\\PolSturmIsolateZeros{sturmname}`_. Be careful not to use these - names ``sturmname_0``, ``sturmname_1``, etc... for defining other - polynomials after having done ``\PolToSturm{polname}{sturmname}`` and - before executing ``\PolSturmIsolateZeros{sturmname}`` else the - latter will behave erroneously. - - `\\PolSturmChainLength{sturmname}`_ gives the index of the last - element of the Sturm chain. - -.. _PolToSturm*: - -``\PolToSturm*{polname}{sturmname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Does the same as `un-starred version <PolToSturm_>`_ and additionally it - keeps for user usage the memory of the *un-normalized* Sturm chain - polynomials ``sturmname_k_``, ``k=0,1, ..., N``, with - ``N`` being `\\PolSturmChainLength{sturmname}`_. - - .. note:: - - This behaviour was modified at ``0.6``, anyhow the macro was - broken at ``0.5``. - - .. hint:: - - The square-free part of ``polname`` is ``sturmname_0``, and their - quotient is the polynomial with name - ``sturname_\PolSturmChainLength{sturmname}_``. It thus easy to - set-up a loop iteratively computing the latter until the last one - is a constant, thus obtaining the decomposition of an ``f`` as - a product ``c f_1 f_2 f_3 ...`` of a constant and square-free (primitive) - polynomials, where each ``f_i`` divides its predecessor. - -.. _PolSetToSturmChainSignChangesAt: - -``\PolSetToSturmChainSignChangesAt{\macro}{sturmname}{fraction}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Sets macro ``\macro`` to the number of sign changes in the Sturm - chain with name prefix ``sturmname``, at location ``fraction`` - (which must be in format as acceptable by the xintfrac_ macros.) - - .. note:: - - The author was lazy and did not provide rather an expandable - variant, where one would do ``\edef\macro{\PolNbOf...}``. - - This will presumably get added in a future release. - - After some hesitation it was decided the macro would by default - act globally. To make the scope of its macro definition local, - use ``[\empty]`` as extra optional argument. - -.. _PolSetToNbOfZerosWithin: - -``\PolSetToNbOfZerosWithin{\macro}{sturmname}{value_a}{value_b}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Applies the `Sturm Theorem`_ to set ``\macro`` to the exact number - of **distinct** roots of ``sturmname_0`` in the interval ``(value_a, - value_b]`` (the macro first re-orders the value for ``value_a <= - value_b`` to hold). - - .. note:: - - The author was lazy and did not provide rather an expandable - variant, where one would do ``\edef\macro{\PolNbOf...}``. - - This will presumably get added in future. - - After some hesitation it was decided the macro would by default - act globally. To make the scope of its macro definition local, - use ``[\empty]`` as extra optional argument. - - See also the expandable - `\\PolSturmNbOfRootsOf{sturmname}\\LessThanOrEqualTo{value}`_, from - which it is immediate (with ``\numexpr``) to create an expandable - variant of this macro. However the difference is that this macro - requires only `\\PolToSturm <PolToSturm_>`_ to have been executed, - whereas the expandable variant requires prior execution of - `\\PolSturmIsolateZeros <PolSturmIsolateZeros_>`_. - - See also the expandable - `\\PolSturmNbWithMultOfRootsOf{sturmname}\\LessThanOrEqualTo{value}`_ - which requires prior execution of - `\\PolSturmIsolateZeros* <PolSturmIsolateZeros*_>`_. - - -.. _PolSturmIsolateZeros: - -``\PolSturmIsolateZeros{sturmname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - The macros locates, using `Sturm theorem`_, as many disjoint - intervals as there are (real) roots. - - .. important:: - - The Sturm chain must have been produced by an earlier - `\\PolToSturm{polname}{sturmname}`_. - - 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. - - Notice that ``\PolToSturm{f}{f}`` is perfectly legal (the - ``sturmname`` can be same as the ``polname``): it defines - polynomials ``f_0``, ``f_1``, ... having ``f`` has name prefix. - - Such a prior call - to ``\PolToSturm`` must have been made at any rate for - ``\PolSturmIsolateZeros`` to be usable. - - After its execution they are two types of such intervals (stored in - memory and accessible via macros or xintexpr_ variables, see below): - - - singleton ``{a}``: then ``a`` is a root, (necessarily a decimal - number, but not all such decimal numbers are exactly identified yet). - - - open intervals ``(a,b)``: then there is exactly one root ``z`` - such that ``a < z < b``, and the end points are guaranteed to not - be roots. - - The interval boundaries are decimal numbers, originating - in iterated decimal subdivision from initial intervals - ``(-10^E, 0)`` and ``(0, 10^E)`` with ``E`` chosen initially large - enough so that all roots are enclosed; if zero is a root it is always - identified as such. The non-singleton intervals are of the - type ``(a/10^f, (a+1)/10^f)`` with ``a`` an integer, which is - neither ``0`` nor ``-1``. Hence either ``a`` and ``a+1`` are both positive - or they are both negative. - - One does not *a priori* know what will be the lengths of these - intervals (except that they are always powers of ten), they - vary depending on how many digits two successive roots have in - common in their respective decimal expansions. - - .. important:: - - If some two consecutive intervals share an end-point, no - information is yet gained about the separation between the two - roots which could at this stage be arbitrarily small. - - See `\\PolRefineInterval*{sturmname}{index}`_ which addresses - this issue. - - .. This procedure is covariant - with the independent variable ``x`` becoming ``-x``. - Hmm, pas sûr et trop fatigué - - The interval boundaries (and exactly found roots) are made available - for future computations in ``\xintexpr``-essions or polynomial - definitions as variables ``<sturmname>L_1``, - ``<sturmname>L_2``, etc..., for the left end-points and - ``<sturmname>R_1``, ``<sturmname>R_2``, ..., for the right - end-points. - - Thus for example, if ``sturmname`` is ``f``, one can use the - xintexpr_ variables ``fL_1``, ``fL_2``, ... to refer in expressions - to the left end-points (or to the exact root, if left and right end - points coincide). Additionally, xintexpr_ variable ``fZ_1_isknown`` - will have value ``1`` if the root in the first interval is known, - and ``0`` otherwise. And similarly for the other intervals. - - Also, macros `\\PolSturmIsolatedZeroLeft{sturmname}{index}`_ and - `\\PolSturmIsolatedZeroRight{sturmname}{index}`_ are provided which - expand to these same values, written in decimal notation (i.e. - pre-processed by `\\PolDecToString <PolDecToString_>`_.) And there - is also `\\PolSturmIfZeroExactlyKnown{sturmname}{index}{A}{B}`_. - - .. important:: - - Trailing zeroes in the stored decimal numbers accessible via the - macros are significant: they are also present in the decimal - expansion of the exact root. - - These variables and macros are automatically updated when one next - uses macros such as `\\PolRefineInterval*{sturmname}{index}`_. - - The start of decimal expansion of a positive ``k``-th root is given - by `\\PolSturmIsolatedZeroLeft{sturmname}{k} - <PolSturmIsolatedZeroLeft_>`_, and for a negative root it is given - by `\PolSturmIsolatedZeroRight{sturmname}{k} - <PolSturmIsolatedZeroRight_>`_. These two decimal - numbers are either both zero or both of the same sign. - - The number of distinct roots is obtainable expandably as - `\\PolSturmNbOfIsolatedZeros{sturmname}`_. - - Furthermore - `\\PolSturmNbOfRootsOf{sturmname}\\LessThanOrEqualTo{value}`_ and - `\\PolSturmNbOfRootsOf{sturmname}\\LessThanOrEqualToExpr{expression}`_. - will expandably compute respectively the number of real roots at - most equal to ``value`` or ``expression``, and the same but with - multiplicities. - - .. note:: - - In the current implementation the xintexpr_ variables - and xinttools_ arrays are globally defined. On the - other hand the Sturm sequence polynomials obey the current scope. - - .. note:: - - As all computations are done *exactly* there can be no errors... - apart those due to bad coding by author. The results are exact - bounds for the mathematically exact real roots. - - Future releases will perhaps also provide macros based on Newton - or Regula Falsi methods. Exact computations with such methods - lead however quickly to very big fractions, and this forces usage - of some rounding scheme for the abscissas if computation times - are to remain reasonable. This raises issues of its own, which - are studied in numerical mathematics. - -.. _PolSturmIsolateZeros*: - -``\PolSturmIsolateZeros*{sturmname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - The macro does the same as `\\PolSturmIsolateZeros{sturmname}`_ and - then in addition it does the extra work to determine all - multiplicities (of the real roots): - after executing this macro, - `\\PolSturmIsolatedZeroMultiplicity{sturmname}{index}`_ will expand - to the multiplicity of the root located in the ``index``\ -th - interval (intervals are enumerated from left to right, with index - starting at ``1``). - - Furthermore, if for example the ``sturmname`` is ``f``, xintexpr_ - variables ``fM_1``, ``fM_2``... hold the multiplicities thus - computed. - - .. note:: - - It is **not** necessary to have executed the `PolToSturm*`_ starred - variant, as the non-starred variant keeps internally the memory of the - original GCD (and even of the full non-normalized original Sturm - chain), even though it does not make the declarations as *user-level* - genuine polynomials. - - See `The degree nine polynomial with 0.99, 0.999, 0.9999 as triple - roots`_ for an example. - -.. _PolSturmIsolateZeros**: - -``\PolSturmIsolateZeros**{sturmname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - The macro does the same as `\\PolSturmIsolateZeros*{sturmname}`_ and - in addition it does the extra work to determine all the *rational* - roots. - - .. note:: - - After execution of this macro, a root is "known" if and only if - it is rational. - - Furthermore, primitive polynomial ``sturmname_sqf_norr`` is created - to match the (square-free) ``sturmname_0`` from which all rational - roots have been removed (see `\\polexprsetup`_ for customizing this - name). The number of distinct rational roots is thus the difference - between the degrees of these two polynomials (see also - `\\PolSturmNbOfRationalRoots{sturmname}`_). - - And ``sturmname_norr`` is ``sturmname_0_`` from which all rational - roots have been removed (see `\\polexprsetup`_), i.e. it contains - the irrational roots of the original polynomial, with the same - multiplicities. - - See `A degree five polynomial with three rational - roots`_ for an example. - -.. _PolSturmIsolateZerosAndGetMultiplicities: - -``\PolSturmIsolateZerosAndGetMultiplicities{sturmname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This is another name for `\\PolSturmIsolateZeros*{sturmname}`_. - -.. _PolSturmIsolateZerosGetMultiplicitiesAndRationalRoots: - -``\PolSturmIsolateZerosGetMultiplicitiesAndRationalRoots{sturmname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This is another name for `\\PolSturmIsolateZeros**{sturmname}`_. - - -``\PolSturmIsolateZerosAndFindRationalRoots{sturmname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This works exactly like `\\PolSturmIsolateZeros**{sturmname}`_ - (inclusive of declaring the polynomials ``sturmname_sqf_norr`` and - ``sturmname_norr`` with no rational roots) except that it does *not* - compute the multiplicities of the *non-rational* roots. - - .. note:: - - There is no macro to find the rational roots but not compute - their multiplicities at the same time. - - .. attention:: - - This macro does *not* define xintexpr_ variables - ``sturmnameM_1``, ``sturmnameM_2``, ... holding the - multiplicities and it leaves the multiplicity array (whose accessor - is `\\PolSturmIsolatedZeroMultiplicity{sturmname}{index}`_) into - a broken state, as all non-rational roots will supposedly have - multiplicity one. This means that the output of - `\\PolPrintIntervals* <PolPrintIntervals*_>`_ for example will be - erroneous for the intervals with irrational roots. - - I decided to document it because finding multiplicities of the - non rational roots is somewhat costly, and one may be interested - only into finding the rational roots (of course random - polynomials with integer coefficients will not have *any* - rational root anyhow). - - -.. _PolRefineInterval*: - -``\PolRefineInterval*{sturmname}{index}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - The ``index``\ -th interval (starting indexing at one) is further - subdivided as many times as is necessary in order for the newer - interval to have both its end-points distinct from the end-points of - the original interval. This means that the ``k``\ th root is then - strictly separated from the other roots. - -.. _PolRefineInterval[N]: - -``\PolRefineInterval[N]{sturmname}{index}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - The ``index``\ -th interval (starting count at one) is further - subdivided once, reducing its length by a factor of 10. This is done - ``N`` times if the optional argument ``[N]`` is present. - -.. _PolEnsureIntervalLength: - -``\PolEnsureIntervalLength{sturmname}{index}{E}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - The ``index``\ -th interval is subdivided until its length becomes at - most ``10^E``. This means (for ``E<0``) that the first ``-E`` digits - after decimal mark of the ``k``\ th root will then be known exactly. - -.. _PolEnsureIntervalLengths: - -``\PolEnsureIntervalLengths{sturmname}{E}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - The intervals as obtained from ``\PolSturmIsolateZeros`` are (if - necessary) subdivided further by (base 10) dichotomy in order for - each of them to have length at most ``10^E`` (length will be shorter - than ``10^E`` in output only if it did not change or became zero.) - - This means that decimal expansions of all roots will be known with - ``-E`` digits (for ``E<0``) after decimal mark. - -.. _PolPrintIntervals: - -``\PolPrintIntervals[varname]{sturmname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This is a convenience macro which prints the bounds for the roots - ``Z_1``, ``Z_2``, ... (the optional argument ``varname`` allows to - specify a replacement for the default ``Z``). This will be done (by - default) in a - math mode ``array``, one interval per row, and pattern ``rcccl``, - where the second and fourth column hold the ``<`` sign, except when - the interval reduces to a singleton, which means the root is known - exactly. - - .. attention:: - - This macro was refactored at 0.7, its default output remained - identical but the ways to customize it got completely - modified. - - See next macros which govern its output. - -``\PolPrintIntervalsNoRealRoots`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Executed in place of an ``array`` environment, when there are no - real roots. Default definition:: - - \newcommand\PolPrintIntervalsNoRealRoots{} - -``\PolPrintIntervalsBeginEnv`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Default definition:: - - \newcommand\PolPrintIntervalsBeginEnv{\[\begin{array}{rcccl}} - -``\PolPrintIntervalsEndEnv`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Default definition:: - - \newcommand\PolPrintIntervalsEndEnv{\end{array}\]} - -``\PolPrintIntervalsKnownRoot`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Default definition:: - - \newcommand\PolPrintIntervalsKnownRoot{% - &&\PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}% - &=&\PolPrintIntervalsPrintExactZero - } - -``\PolPrintIntervalsUnknownRoot`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Default definition:: - - \newcommand\PolPrintIntervalsUnknownRoot{% - \PolPrintIntervalsPrintLeftEndPoint&<&% - \PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}&<&% - \PolPrintIntervalsPrintRightEndPoint - } - - -.. _PolPrintIntervalsPrintExactZero: - -``\PolPrintIntervalsPrintExactZero`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Default definition:: - - \newcommand\PolPrintIntervalsPrintExactZero{\PolPrintIntervalsTheLeftEndPoint} - - -.. _PolPrintIntervalsPrintLeftEndPoint: - -``\PolPrintIntervalsPrintLeftEndPoint`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Default definition:: - - \newcommand\PolPrintIntervalsPrintLeftEndPoint{\PolPrintIntervalsTheLeftEndPoint} - -.. _PolPrintIntervalsPrintRightEndPoint: - -``\PolPrintIntervalsPrintRightEndPoint`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Default definition is:: - - \newcommand\PolPrintIntervalsPrintRightEndPoint{\PolPrintIntervalsTheRightEndPoint} - -.. _PolPrintIntervals*: - -``\PolPrintIntervals*[varname]{sturmname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This starred variant produces an alternative output (which - displays the root multiplicity), and is provided as an - example of customization. - - As replacement for `\\PolPrintIntervalsKnownRoot`_, - `\\PolPrintIntervalsPrintExactZero`_, - `\\PolPrintIntervalsUnknownRoot`_ it uses its own - ``\POL@@PrintIntervals...`` macros. We only reproduce here one - definition:: - - \newcommand\POL@@PrintIntervalsPrintExactZero{% - \displaystyle - \xintSignedFrac{\PolPrintIntervalsTheLeftEndPoint}% - }% - - Multiplicities are printed using this auxiliary macro: - -``\PolPrintIntervalsPrintMultiplicity`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - whose default definition is:: - - \newcommand\PolPrintIntervalsPrintMultiplicity{(\mbox{mult. }\PolPrintIntervalsTheMultiplicity)} - - -.. _PolMapCoeffs: - -``\PolMapCoeffs{\macro}{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - It modifies ('in-place': original coefficients get lost) each - coefficient of the defined polynomial via the *expandable* macro - ``\macro``. The degree is adjusted as necessary if some leading - coefficients vanish after the operation. In replacement text of - ``\macro``, ``\index`` expands to the coefficient index (which is - defined to be zero for the constant term). - - Notice that ``\macro`` will have to handle inputs of the shape - ``A/B[N]`` (xintfrac_ internal notation). This means that it probably - will have to be expressed in terms of macros from xintfrac_ package. - - Example:: - - \def\foo#1{\xintMul{#1}{\the\numexpr\index*\index\relax}} - - (or with ``\xintSqr{\index}``) to replace ``n``-th coefficient - ``f_n`` by ``f_n*n^2``. - -.. _PolReduceCoeffs: - -``\PolReduceCoeffs{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - About the same as ``\PolMapCoeffs{\xintIrr}{polname}`` (but - maintaining a ``[0]`` postfix for speedier xintfrac_ parsing when - polynomial function is used for computations.) This is a - one-argument macro, working 'in-place'. - -.. _PolReduceCoeffs*: - -``\PolReduceCoeffs*{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This starred variant leaves un-touched the decimal exponent in the - internal representation of the fractional coefficients, i.e. if a - coefficient is internally ``A/B[N]``, then ``A/B`` is reduced to - smallest terms, but the ``10^N`` part is kept as is. Note: if the - polynomial is freshly defined directly via `\\PolFromCSV - <PolFromCSV_>`_ its coefficients might still be internally in some - format like ``1.5e7``; the macro will anyhow always first do the - needed conversion to strict format ``A/B[N]``. - - Evaluations with polynomials treated by this can be much faster than - with those handled by the non-starred variant - `\\PolReduceCoeffs{polname}`_: as the numerators and denominators - remain smaller, this proves very beneficial in favorable cases - (especially when the coefficients are decimal numbers) to the - expansion speed of the xintfrac_ macros used internally by - `\\PolEval <PolEvalAt_>`_. - -.. _PolMakeMonic: - -``\PolMakeMonic{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Divides by the leading coefficient. It is recommended to execute - `\\PolReduceCoeffs*{polname}`_ immediately afterwards. This is not - done automatically, due to the case the original polynomial had integer - coefficients and we want to keep the leading one as common - denominator. - -.. _PolMakePrimitive: - -``\PolMakePrimitive{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Divides by the integer content see (`\\PolIContent - <PolIContent_>`_). This thus produces a polynomial with integer - coefficients having no common factor. The sign of the leading - coefficient is not modified. - -Expandable macros ------------------ - -All these macros expand completely in two steps except ``\PolToExpr`` -and ``\PolToFloatExpr`` (and their auxiliaries) which need a -``\write``, ``\edef`` or a ``\csname...\endcsname`` context. - -.. _PolEvalAtExpr: - -``\PolEval{polname}\AtExpr{numerical expression}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - It boils down to - ``\xinttheexpr polname(numerical expression)\relax``. - -.. _PolEvalAt: - -``\PolEval{polname}\At{fraction}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Evaluates the polynomial at value ``fraction`` which must be in (or - expand to) a format acceptable to the xintfrac_ macros. - -.. _PolEvalReducedAtExpr: - -``\PolEvalReduced{polname}\AtExpr{numerical expression}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Boils down to ``\xinttheexpr reduce(polname(numerical expression))\relax``. - -.. _PolEvalReducedAt: - -``\PolEvalReduced{polname}\At{fraction}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Evaluates the polynomial at value ``fraction`` which must be in (or - expand to) a format acceptable to the xintfrac_ macros, and produce - an irreducible fraction. - -.. _PolFloatEvalAtExpr: - -``\PolFloatEval{polname}\AtExpr{numerical expression}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Boils down to ``\xintthefloatexpr polname(numerical expression)\relax``. - - This is done via a Horner Scheme (see `\\poldef <poldef;_>`_ and - `\\PolGenFloatVariant{polname}`_), with already rounded - coefficients. [#]_ To use the *exact coefficients* with *exactly - executed* additions and multiplications, just insert it in the float - expression as in this example: [#]_ - - :: - - \xintthefloatexpr 3.27*\xintexpr f(2.53)\relax^2\relax - - The ``f(2.53)`` is exactly computed then rounded at the time of - getting raised to the power ``2``. Moving the ``^2`` inside, that - operation would also be treated exactly. - - - .. [#] Anyway each floating point operation starts by rounding its - operands to the floating point precision. - - .. [#] The ``\xintexpr`` here could be ``\xinttheexpr`` but that - would be less efficient. Cf. xintexpr_ documentation about - nested expressions. - -.. _PolFloatEvalAt: - -``\PolFloatEval{polname}\At{fraction}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Evaluates the polynomial at value ``fraction`` which must be in (or - expand to) a format acceptable to the xintfrac_ macros, and produces - a floating point number. - -.. _PolIfCoeffIsPlusOrMinusOne: - -``\PolIfCoeffIsPlusOrMinusOne{A}{B}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This macro is a priori undefined. - - It is defined via the default `\\PolTypesetCmd{raw_coeff}`_ to be - used if needed in the execution of `\\PolTypesetMonomialCmd`_, - e.g. to insert a ``\cdot`` in front of ``\PolVar^{\PolIndex}`` if - the coefficient is not plus or minus one. - - The macro will execute ``A`` if the coefficient has been found to be - plus or minus one, and ``B`` if not. - -.. _PolLeadingCoeff: - -``\PolLeadingCoeff{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Expands to the leading coefficient. - -.. _PolNthCoeff: - -``\PolNthCoeff{polname}{number}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - It expands to the raw ``N``-th coefficient (``0/1[0]`` if the index - number is out of range). With ``N=-1``, ``-2``, ... expands to the - leading coefficients. - -.. _PolDegree: - -``\PolDegree{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~ - - It expands to the degree. This is ``-1`` if zero polynomial but this - may change in future. Should it then expand to ``-\infty`` ? - -.. _PolIContent: - -``\PolIContent{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~ - - It expands to the contents of the polynomial, i.e. to the positive - fraction such that dividing by this fraction produces a polynomial - with integer coefficients having no common prime divisor. - - See `\\PolMakePrimitive <PolMakePrimitive_>`_. - -.. _PolToExpr: - -``\PolToExpr{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~ - - Expands [#]_ to ``coeff_N*x^N+...`` (descending powers.) - - .. [#] in a ``\write``, ``\edef``, or ``\csname...\endcsname``, but - not under ``\romannumeral-`0``. - - By default zero coefficients are skipped (issue ``\poltoexpralltrue`` to - get all of them in output). - - By default, no ``+`` sign before negative coefficients, for - compliance with Maple input format (but see - `\\PolToExprTermPrefix{raw_coeff}`_.) Also, like the default - behaviour of `\\PolTypeset{polname}`_, does not print (for the non - constant terms) coefficients equal to plus or minus one. The degree - one monomial is output as ``x``, not ``x^1``. Complete customization is - possible, see next macros. - - Of course ``\PolToExpr{f}`` can be inserted in a ``\poldef``, as the - latter expands token by token, hence will force complete expansion - of ``\PolToExpr{f}``, but a simple ``f(x)`` is more efficient for - the identical result. - -.. _PolToExprOneTerm: - -``\PolToExprOneTerm{raw_coeff}{number}`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - This two argument expandable command takes care of the monomial and - its coefficient. The default definition is done in order for - coefficients of absolute value ``1`` not be printed explicitely - (except of course for the constant term). Also by default, the - monomial of degree one is ``x`` not ``x^1``, and ``x^0`` is skipped. - - For compatibility with Maple input requirements, by default a ``*`` - always precedes the ``x^number``, except if the coefficient is a one - or a minus one. See `\\PolToExprTimes`_. - -.. _PolToExprOneTermStyleA: - -``\PolToExprOneTermStyleA{raw_coeff}{number}`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Holds the default package meaning of - `\\PolToExprOneTerm{raw_coeff}{number}`_. - -.. _PolToExprOneTermStyleB: - -``\PolToExprOneTermStyleB{raw_coeff}{number}`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - For output in this style:: - - 2*x^11/3+3*x^8/7-x^5-x^4/4-x^3-x^2/2-2*x+1 - - issue ``\let\PolToExprOneTerm\PolToExprOneTermStyleB`` before usage of - ``\PolToExpr``. Note that then ``\PolToExprCmd`` isn't used at all. - To revert to package default, issue - ``\let\PolToExprOneTerm\PolToExprOneTermStyleA``. - - To suppress the ``*``'s, cf. `\\PolToExprTimes`_. - -.. _PolToExprCmd: - -``\PolToExprCmd{raw_coeff}`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - It is the one-argument macro used by the package definition of - ``\PolToExprOneTerm`` for the coefficients themselves (when not - equal to plus or minus one), and it defaults to - ``\xintPRaw{\xintRawWithZeros{#1}}``. One will have to redefine it - to ``\xintIrr{#1}`` or to ``\xintPRaw{\xintIrr{#1}}`` to obtain in the - output forcefully reduced coefficients. - -.. _PolToExprTermPrefix: - -``\PolToExprTermPrefix{raw_coeff}`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Defined identically as `\\PolTypesetCmdPrefix{raw_coeff}`_. It - prefixes with a plus sign for non-negative coefficients, because - they don't carry one by themselves. - -.. _PolToExprVar: - -``\PolToExprVar`` -^^^^^^^^^^^^^^^^^ - - This expands to the variable to use in output (it does not have to - be a single letter, may be an expandable macro.) Initial definition - is ``x``. - -.. _PolToExprTimes: - -``\PolToExprTimes`` -^^^^^^^^^^^^^^^^^^^ - - This expands to the symbol used for multiplication of an - ``x^{number}`` by the corresponding coefficient. The default is - ``*``. Redefine the macro to expand to nothing to get rid of it (but - this will give output incompatible with some professional computer - algebra software). - -.. _PolToExpr*: - -``\PolToExpr*{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~~ - - Expands to ``coeff_0+coeff_1*x+coeff_2*x^2+...`` (ascending powers). - Customizable like `\\PolToExpr{polname}`_ via the same macros. - -.. _PolToFloatExpr: - -``\PolToFloatExpr{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Similar to `\\PolToExpr{polname}`_ but uses `\\PolToFloatExprCmd - <\\PolToFloatExprCmd{raw_coeff}>`_ - which by default rounds and converts the coefficients to floating - point format. - - .. note:: - - It is not necessary to have issued - `\\PolGenFloatVariant{polname}`_. The rounded coefficients are - not easily recoverable from the ``\xintfloatexpr`` polynomial - function hence ``\PolToFloatExprCmd`` operates from the *exact* - coefficients anew. - - Attention that both macros obey the prevailing float precision. - If it is changed between those macro calls, then a mismatch - exists between the coefficients as used in ``\xintfloatexpr`` and - those output by ``\PolToFloatExpr{polname}``. - -.. _PolToFloatExprOneTerm: - -``\PolToFloatExprOneTerm{raw_coeff}{number}`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Similar to `\\PolToExprOneTerm - <\\PolToExprOneTerm{raw_coeff}{number}>`_. But does not treat - especially coefficients equal to plus or minus one. - -.. _PolToFloatExprCmd: - -``\PolToFloatExprCmd{raw_coeff}`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - It is the one-argument macro used by ``\PolToFloatExprOneTerm``. - Its package definition is ``\xintFloat{#1}``. - - .. caution:: - - Currently (xint_ ``1.3c``) ``\xintFloat{0}`` outputs ``0.e0`` - which is perfectly acceptable input for Python, but not for - Maple. Thus, one should better leave the `\\poltoexprallfalse`_ - toggle to its default ``\iffalse`` state, if one intends to use - the output in a Maple worksheet. - - But even then the zero polynomial will cause a problem. Workaround:: - - \renewcommand\PolToFloatExprCmd[1]{\xintiiifZero{#1}{0.0}{\xintFloat{#1}}} - - Usage of ``\xintiiifZero`` and not ``\xintifZero`` is only for - optimization (I can't help it) because ``#1`` is known to be - in ``xintfrac`` raw format. - -.. _PolToFloatExpr*: - -``\PolToFloatExpr*{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Typesets in ascending powers. - -.. _PolToList: - -``\PolToList{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~ - - Expands to ``{coeff_0}{coeff_1}...{coeff_N}`` with ``N`` = degree, and - ``coeff_N`` the leading coefficient - (the zero polynomial does give ``{0/1[0]}`` and not an - empty output.) - -.. _PolToCSV: - -``\PolToCSV{polname}`` -~~~~~~~~~~~~~~~~~~~~~~ - - Expands to ``coeff_0, coeff_1, coeff_2, ....., coeff_N``, starting - with constant term and ending with leading coefficient. Converse - to `\\PolFromCSV <\\PolFromCSV{polname}{\<csv\>}_>`_. - -.. _PolSturmChainLength: - -``\PolSturmChainLength{sturmname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Returns the integer ``N`` such that ``sturmname_N`` is the last one - in the Sturm chain ``sturmname_0``, ``sturmname_1``, ... - - See `\\PolToSturm{polname}{sturmname}`_. - -.. _PolSturmIfZeroExactlyKnown: - -``\PolSturmIfZeroExactlyKnown{sturmname}{index}{A}{B}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Executes ``A`` if the ``index``\ -th interval reduces to a singleton, - i.e. the root is known exactly, else ``B``. - - .. note:: - - ``index`` is allowed to be something like ``1+2*3`` as it is fed - to ``\the\numexpr...\relax``. - -.. _PolSturmIsolatedZeroLeft: - -``\PolSturmIsolatedZeroLeft{sturmname}{index}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Expands to the left end-point for the ``index``\ -th interval, as - computed by some earlier `\\PolSturmIsolateZeros{sturmname}`_. - - .. note:: - - Of course, this is kept updated by macros such as - `\\PolRefineInterval{sturmname}{index} <PolRefineInterval[N]_>`_. - - The value is pre-formatted using `\\PolDecTostring - <PolDecToString_>`_. - -.. _PolSturmIsolatedZeroRight: - -``\PolSturmIsolatedZeroRight{sturmname}{index}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Expands to the right end-point for the ``index``\ -th interval as - computed by some earlier `\\PolSturmIsolateZeros{sturmname}`_ and - possibly refined afterwards. - - The value is pre-formatted using `\\PolDecTostring - <PolDecToString_>`_. - -.. _PolSturmIsolatedZeroMultiplicity: - -``\PolSturmIsolatedZeroMultiplicity{sturmname}{index}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Expands to the multiplicity of the unique root contained in the - ``index``\ -th interval. - - .. attention:: - - A prior execution of `\\PolSturmIsolateZeros*{sturmname}`_ is mandatory. - - See `The degree nine polynomial with 0.99, 0.999, 0.9999 as triple - roots`_ for an example of use. - -.. _PolSturmNbOfIsolatedZeros: - -``\PolSturmNbOfIsolatedZeros{sturmname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Expands to the number of real roots of the polynomial - ``<sturmname>_0``, i.e. the number of distinct real roots of the - polynomial originally used to create the Sturm chain via - `\\PolToSturm{polname}{sturmname}`_. - -.. warning:: - - The next few macros counting roots, with or without multiplicities, - less than or equal to some value, are under evaluation and may be - removed from the package if their utility is judged to be not high - enough. They can be re-coded at user level on the basis of the other - documented package macros anyway. - -``\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualTo{value}`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Expands to the number of distinct roots (of the polynomial used to - create the Sturm chain) less than or equal to the ``value`` (i.e. a - number of fraction recognizable by the xintfrac_ macros). - - .. attention:: - - `\\PolSturmIsolateZeros{sturmname}`_ must have been executed - beforehand. - - And the argument is a ``sturmname``, not a ``polname`` (this is - why the macro contains Sturm in its name), simply to be reminded - of the above constraint. - -``\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualToExpr{expression}`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - 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 ``expression``. - - .. attention:: - - `\\PolSturmIsolateZeros{sturmname}`_ must have been executed - beforehand. - -``\PolSturmNbWithMultOfRootsOf{sturmname}\LessThanOrEqualTo{value}`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Expands to the number counted with multiplicities of the roots (of - the polynomial used to create the Sturm chain) which are less than - or equal to the given ``value``. - - .. attention:: - - `\\PolSturmIsolateZeros*{sturmname}`_ (or the double starred - variant) must have been executed beforehand. - -``\PolSturmNbWithMultOfRootsOf{sturmname}\LessThanOrEqualToExpr{expression}`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Expands to the total number of roots (counted with multiplicities) - which are less than or equal to the given ``expression``. - - .. attention:: - - `\\PolSturmIsolateZeros*{sturmname}`_ (or the double starred - variant) must have been executed beforehand. - -``\PolSturmNbOfRationalRoots{sturmname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Expands to the number of rational roots (without multiplicities). - - .. attention:: - - `\\PolSturmIsolateZeros**{sturmname}`_ must have been executed - beforehand. - -``\PolSturmNbOfRationalRootsWithMultiplicities{sturmname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Expands to the number of rational roots (counted with multiplicities). - - .. attention:: - - `\\PolSturmIsolateZeros**{sturmname}`_ must have been executed - beforehand. - -``\PolSturmRationalRoot{sturmname}{k}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Expands to the ``k``\ th rational root (they are ordered and indexed - starting at 1 for the most negative). - - .. attention:: - - `\\PolSturmIsolateZeros**{sturmname}`_ must have been executed - beforehand. - -``\PolSturmRationalRootIndex{sturmname}{k}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Expands to ``index`` of the ``k``\ th rational root as part of the - ordered real roots (without multiplicities). I.e., above macro - `\\PolSturmRationalRoot{sturmname}{k}`_ is equivalent to this - nested call:: - - \PolSturmIsolatedZeroLeft{sturmname}{\PolSturmRationalRootIndex{sturmname}{k}} - - .. attention:: - - `\\PolSturmIsolateZeros**{sturmname}`_ must have been executed - beforehand. - -``\PolSturmRationalRootMultiplicity{sturmname}{k}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Expands to the multiplicity of the ``k``\ th rational root. - - .. attention:: - - `\\PolSturmIsolateZeros**{sturmname}`_ must have been executed - beforehand. - -.. _PolIntervalWidth: - -``\PolIntervalWidth{sturmname}{index}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - The ``10^E`` width of the current ``index``\ -th root localization - interval. Output is in xintfrac_ raw ``1/1[E]`` format (if not zero). - -Expandable macros for use within execution of ``\PolPrintIntervals`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -These macros are for usage within custom user redefinitions of -`\\PolPrintIntervalsKnownRoot`_, `\\PolPrintIntervalsUnknownRoot`_, or -in redefinitions of `\PolPrintIntervalsPrintExactZero`_ (used in the -default for the former) and of `\\PolPrintIntervalsPrintLeftEndPoint`_, -`\\PolPrintIntervalsPrintRightEndPoint`_ (used in the default for the -latter). - -.. attention:: - - Some macros formerly mentioned here got removed at 0.7: - ``\PolPrintIntervalsTheEndPoint``, - ``\PolIfEndPointIsPositive{A}{B}``, - ``\PolIfEndPointIsNegative{A}{B}``, - ``\PolIfEndPointIsZero{A}{B}``. - -``\PolPrintIntervalsTheVar`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Expands to the name (default ``Z``) used for representing the roots, - which was passed as optional argument ``varname`` to - `\\PolPrintIntervals[varname]{sturmname}`_. - -``\PolPrintIntervalsTheIndex`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Expands to the index of the considered interval (indexing starting - at 1 for the leftmost interval). - -``\PolPrintIntervalsTheSturmName`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Expands to the argument which was passed as ``sturmname`` to - `\\PolPrintIntervals[varname]{sturmname}`_. - -``\PolPrintIntervalsTheLeftEndPoint`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - The left end point of the interval, as would be produced by - `\\PolSturmIsolatedZeroLeft <PolSturmIsolatedZeroLeft_>`_ if it was - used with arguments the Sturm chain name and interval index returned - by `\\PolPrintIntervalsTheSturmName`_ and - `\\PolPrintIntervalsTheIndex`_. - -``\PolPrintIntervalsTheRightEndPoint`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - The right end point of the interval, as would be produced by - `\\\PolSturmIsolatedZeroRight <PolSturmIsolatedZeroRight_>`_ for - this Sturm chain name and index. - -``\PolPrintIntervalsTheMultiplicity`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - The multiplicity of the unique root within the interval of index - `\\PolPrintIntervalsTheIndex`_. Makes sense only if the starred (or - double-starred) variant of `\\PolSturmIsolateZeros - <PolSturmIsolateZeros_>`_ was used earlier. - -.. _PolDecToString: - -``\PolDecToString{decimal number}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This is a utility macro to print decimal numbers. It has been - backported to xintfrac_ (release ``1.3`` of ``2018/03/01``) under - the name ``\xintDecToString``, and the ``polexpr`` macro is simply - now an alias to it. - - For example - ``\PolDecToString{123.456e-8}`` will expand to ``0.00000123456`` - and ``\PolDecToString{123.450e-8}`` to ``0.00000123450`` which - illustrates that trailing zeros are not trimmed. To trim trailing - zeroes, one can use ``\PolDecToString{\xintREZ{#1}}``. - - The precise behaviour of this macro may evolve in future releases of - xint_. - -Booleans (with default setting as indicated) --------------------------------------------- - -``\xintverbosefalse`` -~~~~~~~~~~~~~~~~~~~~~ - - This is actually an xintexpr_ configuration. Setting it to - ``true`` triggers the writing of information to the log when new - polynomials are defined. - - .. caution:: - - The macro meanings as written to the log are to be considered - unstable and undocumented internal structures. - -``\poltypesetallfalse`` -~~~~~~~~~~~~~~~~~~~~~~~ - - If ``true``, `\\PolTypeset{polname}`_ will also typeset the vanishing - coefficients. - - -``\poltoexprallfalse`` -~~~~~~~~~~~~~~~~~~~~~~ - - If ``true``, `\\PolToExpr{polname}`_ and `\\PolToFloatExpr{polname}`_ will - also include the vanishing coefficients in their outputs. - -``\polexprsetup`` ------------------ - - Serves to customize the package. Currently only two keys are - recognized: - - - ``norr``: the postfix that `\\PolSturmIsolateZeros**{sturmname}`_ - should append to ``sturmname`` to declare the primitive polynomial - obtained from original one after removal of all rational roots. - The default value is ``_norr`` (standing for “no rational roots”). - - - ``sqfnorr``: the postfix that `\\PolSturmIsolateZeros**{sturmname}`_ - should append to ``sturmname`` to declare the primitive polynomial - obtained from original one after removal of all rational roots and - suppression of all multiplicities. - The default value is ``_sqf_norr`` (standing for “square-free with - no rational roots”). - - The package executes ``\polexprsetup{norr=_norr, - sqfnorr=_sqf_norr}`` as default. - -Technicalities --------------- - -- The catcode of the semi-colon is reset temporarily by `\\poldef - <poldef;_>`_ macro in case some other package (for example the French - babel module) may have made it active. This will fail though if the - whole thing was already part of a macro argument, in such cases one - can use `\\PolDef{f}{P(x)} <PolDef_>`_ - rather. The colon in ``:=`` may be active with no consequences. - -- As a consequence of xintfrac_ addition and subtraction always using - least common multiples for the denominators [#]_, user-chosen common - denominators survive additions and multiplications. For example, this:: - - \poldef P(x):= 1/2 + 2/2*x + 3/2*x^3 + 4/2*x^4; - \poldef Q(x):= 1/3 + (2/3)x + (3/3)x^3 + (4/3)x^4; - \poldef PQ(x):= P(x)Q(x); - - gives internally the polynomial:: - - 1/6+4/6*x^1+4/6*x^2+6/6*x^3+20/6*x^4+16/6*x^5+9/6*x^6+24/6*x^7+16/6*x^8 - - where all coefficients have the same denominator 6. Notice though that - ``\PolToExpr{PQ}`` outputs the ``6/6*x^3`` as ``x^3`` because (by - default) it recognizes and filters out coefficients equal to one or - minus one (since release ``0.3``). One can use for example - ``\PolToCSV{PQ}`` to see the internally stored coefficients. - - .. [#] prior to ``0.4.1``, ``polexpr`` used to temporarily patch - during the parsing of polynomials the xintfrac_ macros. This - patch was backported to xint_ at release ``1.3``. - -- `\\PolDiff{polname_1}{polname_2}`_ always applies ``\xintIrr`` to the - resulting coefficients, except that the *power of ten* part ``[N]`` - (for example an input in scientific notation such as ``1.23e5`` gives - ``123/1[3]`` internally in xintfrac) is not taken into account in the - reduction of the fraction. This is tentative and may change. - - Same remark for `\\PolAntiDiff{polname_1}{polname_2}`_. - -- Currently, the package stores all coefficients from index ``0`` to - index equal to the polynomial degree inside a single macro, as a list. - This data structure is obviously very inefficient for polynomials of - high degree and few coefficients (as an example with ``\poldef - f(x):=x^1000 + x^500;`` the subsequent definition ``\poldef g(x):= - f(x)^2;`` will do of the order of 1,000,000 multiplications and - additions involvings only zeroes... which does take time). This - may change in the future. - -- As is to be expected internal structures of the package are barely - documented and unstable. Don't use them. - - -CHANGE LOG ----------- - -- v0.1 (2018/01/11): initial release. Features: - - * The `\\poldef <poldef;_>`_ parser itself, - * Differentiation and anti-differentiation, - * Euclidean division and GCDs, - * Various utilities such as `\\PolFromCSV <PolFromCSV_>`_, - `\\PolMapCoeffs <PolMapCoeffs_>`_, - `\\PolToCSV <PolToCSV_>`_, `\\PolToExpr <PolToExpr_>`_, ... - - Only one-variable polynomials so far. - -- v0.2 (2018/01/14) - - * Fix: ``"README thinks \numexpr recognizes ^ operator"``. - * Convert README to reStructuredText markup. - * Move main documentation from README to separate ``polexpr.txt`` file. - * Provide ``polexpr.html`` as obtained via DocUtils_ ``rst2html.py``. - * Convert README to (CTAN compatible) Markdown markup. - - Due to lack of available time the test suite might not be extensive - enough. Bug reports are very welcome! - -- v0.3 (2018/01/17) - - * bug fixes: - - - the ``0.1`` `\\PolEval <PolEvalAt_>`_ accepted expressions for its second - argument, but this was removed by mistake at ``0.2``. Restored. - - **Attention**: at ``0.4`` this has been reverted again, and - `\\PolEval{P}\\AtExpr{foo} <PolEvalAtExpr_>`_ syntax is needed for - using expressions in the second argument. - * incompatible or breaking changes: - - - `\\PolToExpr <PolToExpr_>`_ now by default uses *descending* - powers (it also treats differently coefficients equal to 1 or -1.) - Use `\\PolToExpr* <PolToExpr*_>`_ for *ascending* powers. - - `\\PolEval <PolEvalAt_>`_ reduced the output to smallest terms, - but as this is costly with big fractions and not needed if e.g. - wrapped in an ``\xintRound`` or ``\xintFloat``, this step has been - removed; the former meaning is available as `\\PolEvalReduced - <PolEvalReducedAt_>`_. - * new (or newly documented) macros: - - - `\\PolTypesetCmd <PolTypesetCmd_>`_ - - `\\PolTypesetCmdPrefix <PolTypesetCmdPrefix_>`_ - - `\\PolTypesetMonomialCmd <PolTypesetMonomialCmd_>`_ - - `\\PolEvalReducedAt <PolEvalReducedAt_>`_ - - `\\PolToFloatExpr <PolToFloatExpr_>`_ - - `\\PolToExprOneTerm <PolToExprOneTerm_>`_ - - `\\PolToFloatExprOneTerm <PolToFloatExprOneTerm_>`_ - - `\\PolToExprCmd <PolToExprCmd_>`_ - - `\\PolToFloatExprCmd <PolToFloatExprCmd_>`_ - - `\\PolToExprTermPrefix <PolToExprTermPrefix_>`_ - - `\\PolToExprVar <PolToExprVar_>`_ - - `\\PolToExprTimes <PolToExprTimes_>`_ - * improvements: - - - documentation has a table of contents, internal hyperlinks, - standardized signature notations and added explanations. - - one can do ``\PolLet{g}={f}`` or ``\PolLet{g}{f}``. - - ``\PolToExpr{f}`` is highly customizable. - - `\\poldef <poldef;_>`_ and other defining macros prepare the polynomial - functions for usage within ``\xintthefloatexpr`` (or - ``\xintdeffloatvar``). 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. - - **Attention**: this has been reverted at ``0.4``. The macro - `\\PolGenFloatVariant <PolGenFloatVariant_>`_ must be used for - generation floating point polynomial functions. - -- v0.3.1 (2018/01/18) - - Fixes two typos in example code included in the documentation. - -- v0.4 (2018/02/16) - - * bug fixes: - - - 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 `\\PolMapCoeffs <PolMapCoeffs_>`_. - - `\\PolGCD <PolGCD_>`_ was buggy in case of first polynomial being - of lesser degree than the second one. - * breaking changes: - - - formerly `\\PolEval{P}\\At{foo} <PolEvalAt_>`_ allowed ``foo`` to - be an expression, which was transparently handled via - ``\xinttheexpr``. Now, ``foo`` must be a fraction (or a macro - expanding to such) in the format acceptable by ``xintfrac.sty`` - macros. Use `\\PolEval{P}\\AtExpr{foo} <PolEvalAtExpr_>`_ for more - general arguments using expression syntax. E.g., if ``foo`` is the - name of a variable known to ``\xintexpr``. - - The same holds for `\\PolEvalReduced <PolEvalReducedAt_>`_ - and `\\PolFloatEval <PolFloatEvalAt_>`_. - - the ``3.0`` automatic generation of floating point variants has - been reverted. Not only do *not* the package macros automatically - generate floating point variants of newly created polynomials, - they actually make pre-existing such variant undefined. - - See `\\PolGenFloatVariant <PolGenFloatVariant_>`_. - * new non-expandable macros: - - - `\\PolGenFloatVariant <PolGenFloatVariant_>`_ - - `\\PolGlobalLet <PolGlobalLet_>`_ - - `\\PolTypesetOne <PolTypesetOne_>`_ - - `\\PolQuo <PolQuo_>`_ - - `\\PolRem <PolRem_>`_ - - `\\PolToSturm <PolToSturm_>`_ - - `\\PolToSturm\* <PolToSturm*_>`_ - - `\\PolSetToSturmChainSignChangesAt <PolSetToSturmChainSignChangesAt_>`_ - - `\\PolSetToNbOfZerosWithin <PolSetToNbOfZerosWithin_>`_ - - `\\PolSturmIsolateZeros <PolSturmIsolateZeros_>`_ - - `\\PolRefineInterval* <PolRefineInterval*_>`_ - - `\\PolRefineInterval[N] <PolRefineInterval[N]_>`_ - - `\\PolEnsureIntervalLength <PolEnsureIntervalLength_>`_ - - `\\PolEnsureIntervalLengths <PolEnsureIntervalLengths_>`_ - - `\\PolPrintIntervals <PolPrintIntervals_>`_ - - `\\PolPrintIntervalsPrintExactZero <PolPrintIntervalsPrintExactZero_>`_ - - `\\PolPrintIntervalsPrintLeftEndPoint <PolPrintIntervalsPrintLeftEndPoint_>`_ - - `\\PolPrintIntervalsPrintRightEndPoint <PolPrintIntervalsPrintRightEndPoint_>`_ - - `\\PolReduceCoeffs* <PolReduceCoeffs*_>`_ - - `\\PolMakeMonic <PolMakeMonic_>`_ - * new expandable macros: - - - `\\PolToExprOneTermStyleA <PolToExprOneTermStyleA_>`_ - - `\\PolIfCoeffIsPlusOrMinusOne <PolIfCoeffIsPlusOrMinusOne_>`_ - - `\\PolLeadingCoeff <PolLeadingCoeff_>`_ - - `\\PolSturmChainLength <PolSturmChainLength_>`_ - - `\\PolSturmNbOfIsolatedZeros <PolSturmNbOfIsolatedZeros_>`_ - - `\\PolSturmIfZeroExactlyKnown <PolSturmIfZeroExactlyKnown_>`_ - - `\\PolSturmIsolatedZeroLeft <PolSturmIsolatedZeroLeft_>`_ - - `\\PolSturmIsolatedZeroRight <PolSturmIsolatedZeroRight_>`_ - - ``\PolPrintIntervalsTheEndPoint`` (removed at 0.7) - - `\\PolPrintIntervalsTheIndex`_ - - ``\PolIfEndPointIsPositive`` (removed at 0.7) - - ``\PolIfEndPointIsNegative`` (removed at 0.7) - - ``\PolIfEndPointIsZero`` (removed at 0.7) - - `\\PolIntervalWidth <PolIntervalWidth_>`_ - - `\\PolDecToString <PolDecToString_>`_ - * improvements: - - The main new feature is implementation of the `Sturm algorithm`_ - for localization of the real roots of polynomials. - -- v0.4.1 (2018/03/01) - - Synced with xint 1.3. - -- v0.4.2 (2018/03/03) - - Documentation fix. - -- v0.5 (2018/04/08) - - * bug fixes: - - - `\\PolGet{polname}\\fromarray\\macro`_ crashed when ``\macro`` was - an xinttools_ array macro with no items. It now produces the zero - polynomial. - * breaking changes: - - - `\\PolToSturm`_ creates primitive integer coefficients polynomials. - This speeds up localization of roots via - `\\PolSturmIsolateZeros`_. In case of user protests the author - will make available again the code producing the bona fide Sturm - polynomials as used formerly. - - polynomials created from `\\PolFromCSV`_ or `\\PolGet <PolGet_>`_ - get their coefficients normalized via xintfrac_\ 's ``\xintRaw``. - * experimental change: - - - optional argument to `\\PolSturmIsolateZeros`_ (see `The - degree 41 polynomial with -2, -1.9, -1.8, ..., 0, 0.1, ..., 1.9, 2 - as roots`_ for usage). It will presumably be replaced in future by - an interval specification. - * new non-expandable macro: - - - `\\PolMakePrimitive`_ - * new expandable macro: - - - `\\PolIContent`_ - -- v0.5.1 (2018/04/22) - - * new feature: - - - the character ``'`` can be used in polynomial names. - -- v0.6 (2018/11/20) - - * bugfix: - - - the starred variant `\\PolToSturm*{polname}{sturmname}`_ was - broken. On the occasion of the fix, its meaning has been modified, - see its documentation. - - - using `\\PolToSturm <PolToSturm_>`_ with a constant polynomial - caused a division by zero error. - - * new macro: - - - `\\PolSturmIsolateZeros* <PolSturmIsolateZeros*_>`_ - acts like the `non-starred variant - <PolSturmIsolateZeros_>`_ then computes all the multiplicities. - - * new expandable macros: - - - `\\PolSturmIsolatedZeroMultiplicity{sturmname}{index}`_ - - `\\PolSturmNbOfRootsOf{sturmname}\\LessThanOrEqualTo{value}`_ - - `\\PolSturmNbOfRootsOf{sturmname}\\LessThanOrEqualToExpr{expression}`_ - - `\\PolSturmNbWithMultOfRootsOf{sturmname}\\LessThanOrEqualTo{value}`_ - - `\\PolSturmNbWithMultOfRootsOf{sturmname}\\LessThanOrEqualToExpr{expression}`_ - -- v0.7 (2018/12/08), v0.7.1 (bugfix), v0.7.2 (2nd bugfix) (2018/12/09) - - * breaking changes: - - - although `\\PolPrintIntervals[varname]{sturmname}`_ default output - remains the same, some auxiliary macros for user-customization - have been removed: ``\PolPrintIntervalsTheEndPoint``, - ``\PolIfEndPointIsPositive{A}{B}``, - ``\PolIfEndPointIsNegative{A}{B}``, and - ``\PolIfEndPointIsZero{A}{B}``. - - * bugfix: - - - it could happen that, contrarily to documentation, an interval - computed by `\\PolSturmIsolateZeros{sturmname}`_ had zero as an - endpoint, - - `\\PolEnsureIntervalLength{sturmname}{index}{E}`_ could under - certain circumstances erroneously replace a non-zero root by - zero, - - `\\PolEnsureIntervalLengths{sturmname}{E}`_ crashed when used with - a polynomial with no real roots, hence for which no isolation intervals - existed (thanks to Thomas Söll for report). - - * new macros: - - - `\\PolSturmIsolateZeros**{sturmname}`_ - - `\\PolSturmIsolateZerosGetMultiplicitiesAndRationalRoots{sturmname}`_ - - `\\PolSturmIsolateZerosAndFindRationalRoots{sturmname}`_ - - `\\polexprsetup`_ - - `\\PolPrintIntervals* <PolPrintIntervals*_>`_ - - `\\PolPrintIntervalsNoRealRoots`_ - - `\\PolPrintIntervalsBeginEnv`_ - - `\\PolPrintIntervalsEndEnv`_ - - `\\PolPrintIntervalsKnownRoot`_ - - `\\PolPrintIntervalsUnknownRoot`_ - - `\\PolPrintIntervalsPrintMultiplicity`_ - - * new expandable macros: - - - `\\PolSturmNbOfRationalRoots{sturmname}`_ - - `\\PolSturmNbOfRationalRootsWithMultiplicities{sturmname}`_ - - `\\PolSturmRationalRoot{sturmname}{k}`_ - - `\\PolSturmRationalRootIndex{sturmname}{k}`_ - - `\\PolSturmRationalRootMultiplicity{sturmname}{k}`_ - - `\\PolPrintIntervalsTheVar`_ - - `\\PolPrintIntervalsTheSturmName`_ - - `\\PolPrintIntervalsTheMultiplicity`_ - -- v0.7.3 (2019/02/04) - - * bugfix: - - - Debugging information not destined to user showed in log if root - finding was done under ``\xintverbosetrue`` regime. - - `\\PolPrintIntervalsTheVar`_ remained defined after - `\\PolPrintIntervals`_ but was left undefined after - `\\PolPrintIntervals*`_ (reported by Jürgen Gilg). Now remains - defined in both cases, and `\\PolPrintIntervalsTheSturmName`_ - also. - - Polynomial names ending in digits caused errors (reported by Thomas - Söll). - -- v0.7.4 (2019/02/12) - - * bugfix: - - - 20000000000 is too big for ``\numexpr``, shouldn't I know that? - Thanks to Jürgen Gilg for report. - -- v0.7.5 (2020/01/31) - - Synced with xint 1.4. Requires it. - - -Acknowledgments ---------------- - -Thanks to Jürgen Gilg whose question about xint_ 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. - -Renewed thanks to them on occasion of the ``0.6`` and ``0.7`` releases for their -continued interest. - -See README.md for the License. - -.. _xinttools: -.. _xintfrac: -.. _xintexpr: -.. _xint: http://www.ctan.org/pkg/xint - -.. _Wilkinson polynomial: https://en.wikipedia.org/wiki/Wilkinson%27s_polynomial - -.. _Sturm algorithm: -.. _Sturm Theorem: https://en.wikipedia.org/wiki/Sturm%27s_theorem - -.. _DocUtils: http://docutils.sourceforge.net/docs/index.html diff --git a/Master/texmf-dist/tex/generic/polexpr/polexpr.sty b/Master/texmf-dist/tex/generic/polexpr/polexpr.sty new file mode 100644 index 00000000000..c94a4e8d61d --- /dev/null +++ b/Master/texmf-dist/tex/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/Master/texmf-dist/tex/generic/polexpr/polexprcore.tex b/Master/texmf-dist/tex/generic/polexpr/polexprcore.tex new file mode 100644 index 00000000000..e071729e42b --- /dev/null +++ b/Master/texmf-dist/tex/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/Master/texmf-dist/tex/generic/polexpr/polexprexpr.tex b/Master/texmf-dist/tex/generic/polexpr/polexprexpr.tex new file mode 100644 index 00000000000..9b60e7bab00 --- /dev/null +++ b/Master/texmf-dist/tex/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/Master/texmf-dist/tex/latex/polexpr/polexpr.sty b/Master/texmf-dist/tex/generic/polexpr/polexprsturm.tex index 30fef289141..3fa1861558d 100644 --- a/Master/texmf-dist/tex/latex/polexpr/polexpr.sty +++ b/Master/texmf-dist/tex/generic/polexpr/polexprsturm.tex @@ -1,893 +1,4 @@ -% author: Jean-François Burnol -% License: LPPL 1.3c (author-maintained) -\ProvidesPackage{polexpr}% - [2020/01/31 v0.7.5 Polynomial expressions with rational coefficients (JFB)]% -\RequirePackage{xintexpr}[2020/01/31]% xint 1.4 -\edef\POL@restorecatcodes % TODO: think better about what is reasonable here - {\catcode`\noexpand\_ \the\catcode`\_ % - \catcode`\noexpand\! \the\catcode`\! % - \catcode`\noexpand\* \the\catcode`\* % - \catcode`\noexpand\~ \the\catcode`\~ % - \catcode`\noexpand\: \the\catcode`\: % - \catcode0 \the\catcode0\relax}% -\catcode`\_ 11 \catcode0 12 \catcode`\* 12 -\long\def\xint_stop_atfirstoftwo #1#2{ #1}% not yet in xint 1.3c -\long\def\xint_stop_atsecondoftwo #1#2{ #2}% - -%% 0.7.5 VERY SERIOUS TROUBLES TO GET polexpr TO WORK WITH xintexpr 1.4 - -%% I hesitated about incorporating it directly into xint 1.4 -%% Don't do this at home, only xint gurus are allowed. -\let\POL@originalXINT_expr_redefinemacros\XINT_expr_redefinemacros -\def\XINT_expr_redefinemacros -{% - \POL@originalXINT_expr_redefinemacros - \POL@activateNEhook -}% -%% Using \def's and not \let's to get better readable trace -%% in case I need to debug but this never happens -\def\POL@activateNEhook@xint % done in a group -{% - \def\POL@NEhook@polfunc{\POL@NE@polfunc}% -}% -\def\POL@activateNEhook@pol -{% - \def\POL@NEhook@polfunc{\POL@NP@polfunc}% -}% -\def\POL@activateNEhook{\POL@activateNEhook@xint}% -% -% -\catcode`~ 12 -\catcode`! 11 -\catcode`: 11 -% We drop consideration of \XINT_global matters -% because we have other more urgent and arduous problems -\def\POL@defpolfunc #1#2% -{% - \expandafter\POL@defpolfunc_a - \csname XINT_#2_func_#1\expandafter\endcsname - \csname XINT_#2_polfunc_#1\endcsname {#1}{#2}% -}% -\def\POL@defpolfunc_a #1#2#3#4% -{% - \protected % xintexpr 1.4 does things such as \expandafter\xintAdd\expanded - \expandafter\def\expandafter#2\expandafter##\expandafter1\expandafter - {% - #2{##1}% - }% - \def#1##1##2##3% - {% - % put it directly at the correct level of bracing - % don't worry for now about minimizing how many times ##3 is grabbed - \expandafter##1\expandafter##2\expandafter{\expandafter - {\romannumeral`^^@\POL@NEhook@polfunc{XINT_#4_polfunc_#3}#2{##3}}}% - }% -}% -% -\def\POL@polfunc@go #1#2#3{#2#3}% brace stripping intentional -\def\POL@NEhook@polfunc{\POL@polfunc@go}% default for pure numerics -% -% Hook for expansion in \poldef -\def\POL@NP@polfunc #1{% -\def\POL@NP@polfunc ##1##2##3% -{% - \if0\expandafter\XINT:NE:hastilde\detokenize{##3}~!\relax - \expandafter\XINT:NE:hashash\detokenize{##3}#1!\relax 0% - \expandafter\POL@polfunc@go - \else - \expandafter\POL:NP:polfunc:p - \fi {##1}{##2}{##3}% -}}\expandafter\POL@NP@polfunc\string#% -\def\POL:NP:polfunc:p #1#2#3% -{% - ~romannumeral~POL:usepolfunc:pol{#1}{#3}% -}% -\def\POL:usepolfunc:pol #1%#2% -{% -% Here we are in the core of \poldef and we really -% need to get rid of some \expanded tokens so -% we accept being exposed to \expanded but arrange to -% remain invariant. Then we will try to speed up -% polynomial composition (at this time the \#1 -% is a nested Horner type macro) by «pre-expanding» -% the argument, but this means using the \POL@get -% methods inside an \hbox -% -% \POL@applypolfunc will be defined \protected -% - \expandafter\xint_c_\expandafter\POL@applypolfunc -% This will be \protected - \csname#1\endcsname -% #2% brace stripping is deliberate -}% -% -% Hook for expansion in \xintexpr -\def\POL@NE@polfunc #1{% -\def\POL@NE@polfunc ##1##2##3% -{% - \if0\expandafter\XINT:NE:hastilde\detokenize{##3}~!\relax - \expandafter\XINT:NE:hashash\detokenize{##3}#1!\relax 0% - \expandafter\POL@polfunc@go - \else - \expandafter\POL:NE:polfunc:p - \fi {##1}{##2}{##3}% -}}\expandafter\POL@NE@polfunc\string#% -\def\POL:NE:polfunc:p #1#2#3% -{% - ~romannumeral~POL:usepolfunc:xint{#1}{#3}% -}% -\def\POL:usepolfunc:xint #1% -{% -% This is done to overcome \protected and is useful -% in case the polynomial function ends up nested -% in some non-polynomial user declared function -% as the latter (and other things) tries to pre-expand -% its arguments (as they may be used multiple time) -% using \expanded, but \#1 is protected. -% And this works recursively. We are inside braces. -% However we have a very big problem with constant -% polynomial functions. We have to handle them -% in a special way. - -`0\csname#1\expandafter\endcsname\expanded -}% -\catcode`~ 13 -\catcode`: 12 - - -%% Start defining some \protected ones here -\protected\def\POL@empty{}% -\newif\ifPOL@pol -\protected\def\POL@polglobaltrue {\global\let\ifPOL@pol\iftrue}% -\protected\def\POL@polglobalfalse{\global\let\ifPOL@pol\iffalse}% - - -%% Patch xintexpr to authorize ' in names (0.5.1) -%% Adapted 0.7.5 to follow-up on xintexpr 1.4 internal changes -%% (much simpler than previous stuff...) -%% This allows ' as a character in a polynomial name (not initial one) -\def\POL@XINT_expr_scanfunc_b #1% -{% - \ifcat \relax#1\xint_dothis{\iffalse{\fi}(_#1}\fi - \if (#1\xint_dothis{\iffalse{\fi}(`}\fi - \if 1\ifcat a#10\fi - \ifnum\xint_c_ix<1\string#1 0\fi - \if @#10\fi - \if _#10\fi - \if '#10\fi - 1% - \xint_dothis{\iffalse{\fi}(_#1}\fi - \xint_orthat {#1\XINT_expr_scanfunc_a}% -}% - - -%% Activate polexp's modified xintexpr (only during definitions -%% of polynomials) -\def\POL@hackxintexpr {% - \let\POL@originalXINT_expr_scanfunc_b\XINT_expr_scanfunc_b - \let\XINT_expr_scanfunc_b\POL@XINT_expr_scanfunc_b - \def\POL@activateNEhook{\POL@activateNEhook@pol}% -}% -\def\POL@restorexintexpr {% - \let\XINT_expr_scanfunc_b\POL@originalXINT_expr_scanfunc_b - \def\POL@activateNEhook{\POL@activateNEhook@xint}% -}% - - -%% AUXILIARIES -\catcode`! 3 -%% added at 0.7 -\newcommand\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 -}% -\catcode`! 11 -\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} - -\newcount\POL@count -\newif\ifxintveryverbose -\newif\ifpoltypesetall -\newif\ifPOL@tosturm@makefirstprimitive -\POL@tosturm@makefirstprimitivetrue -\newif\ifPOL@isolz@nextwillneedrefine -\newif\ifpoltoexprall -%% the main exchange structure (stored in macros \POLuserpol@<name>) -%% is: degree.\POL@empty{coeff0}{coeff1}....{coeffN} -%% (degree=N except zero polynomial recognized from degree set to -1 -%% but it has always the {0/1[0]} coeff0.) -\def\POL@ifZero#1{\expandafter\POL@ifZero@aux#1;}% -\def\POL@ifZero@aux #1#2;{\if-#1\expandafter\xint_firstoftwo - \else\expandafter\xint_secondoftwo - \fi}% -\def\POL@split#1.#2;#3#4% separates degree and list of coefficients -% The \expandafter chain removes the \empty token - {\def#3{#1}\expandafter\def\expandafter#4\expandafter{#2}}% -% -\def\POL@resultfromarray #1{% ATTENTION, **MUST** be executed with -% \count@ set to 1 + degree (\count@ = 0 for zero polynomial) -% Attention to the \protected here at 0.7.5 -% They are many all over the place - \protected\edef\POL@result{\ifnum\count@>\z@ - \the\numexpr\count@-\@ne.\POL@empty - \xintiloop [1+1]% - \expandafter\POL@braceit\csname POL@array#1\xintiloopindex\endcsname - \ifnum\xintiloopindex<\count@ - \repeat -% Attention to this \protected\POL@empty -% They are many all over the place - \else-1.\POL@empty{0/1[0]}\fi}% -}% -\def\POL@braceit#1{{#1}}% needed as \xintiloopindex can not "see" through braces - - -\newcommand\PolDef[3][x]{\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@tmp{\ifxintverbose1\else0\fi}% - \unless\ifxintveryverbose\xintverbosefalse\fi - \POL@hackxintexpr - \xintdeffunc __pol(#2):=0+(#4);% force conversion to raw if a constant - \POL@restorexintexpr - \if1\POL@tmp\xintverbosetrue\fi - \edef\POL@polname{\xint_zapspaces #1 \xint_gobble_i}% - \begingroup - \setbox0\hbox{% - \let\xintScalarAdd\xintAdd - \let\xintScalarSub\xintSub - \let\xintScalarMul\xintMul - \let\xintScalarDiv\xintDiv - \let\xintScalarPow\xintPow - \let\xintScalarOpp\xintOpp - \let\xintAdd\POL@add - \let\xintMul\POL@mul - \let\xintDiv\POL@div - \let\xintPow\POL@pow - \let\xintOpp\POL@opp - \def\xintSub ##1##2{\xintAdd{##1}{\xintOpp{##2}}}% - % \xintAdd{0} to get \POL@result defined even if numerical only expression - % I could also test \ifPOL@pol, but this is anyhow small overhead -% Attention that xintexpr 1.4 has braces all over the place - \expandafter\xintAdd\expandafter{\expandafter0\expandafter}% - \romannumeral0\csname XINT_expr_userfunc___pol\endcsname - {\POL@polglobaltrue\protected\def\POL@result{1.\POL@empty{0/1[0]}{1/1[0]}}}% - \expandafter}\expandafter - \endgroup\expandafter - \def\csname POLuserpol@\POL@polname\expandafter\endcsname - \expandafter{\POL@result}% - \expandafter\POL@newpol\expandafter{\POL@polname}% -}% -% - - -\def\POL@newpol#1{% -%% We must handle specially constant polynomials because they must -%% be made to work expandably in \poldef of other polynomials due -%% to complicated matters having to do with the \POL@ifpol conditional - \ifnum\PolDegree{#1}<\@ne - % non-zero constant - % I am defining this one only for the Info message, no time now - \expandafter\edef\csname XINT_expr_polfunc_#1\endcsname - ##1{\PolNthCoeff{#1}{0}}% - % No hooks here! - \expandafter\edef\csname XINT_expr_func_#1\endcsname ##1##2##3% - {##1##2{{\PolNthCoeff{#1}{0}}}}% - \else - % polynomial of degree at least 1. This means that mechanism - % to get \POL@result will get activated and we must be very careful - % to never \edef when the Horner macro will be converted to - % a polynomial - \POL@newpolhorner{#1}% - \POL@defpolfunc{#1}{expr}% - \fi - \expandafter\let\csname XINT_flexpr_func_#1\endcsname\@undefined - \ifxintverbose\POL@info{#1}\fi -}% -\def\POL@newfloatpol#1{% -%% We must handle specially constant polynomials because they must -%% be made to work expandably in \poldef of other polynomials due -%% to complicated matters having to do with the \POL@ifpol conditional - \ifnum\PolDegree{#1}<\@ne - % non-zero constant - % I am defining this one only for the Info message, no time now - \expandafter\edef\csname XINT_flexpr_polfunc_#1\endcsname - ##1{\PolNthCoeff{#1}{0}}% - % No hooks here! - \expandafter\edef\csname XINT_flexpr_func_#1\endcsname ##1##2##3% - {##1##2{{\PolNthCoeff{#1}{0}}}}% - \else - % polynomial of degree at least 1. This means that mechanism - % to get \POL@result will get activated and we must be very careful - % to never \edef when the Horner macro will be converted to - % a polynomial - \POL@newfloatpolhorner{#1}% - \POL@defpolfunc{#1}{flexpr}% - \fi - \ifxintverbose\POL@floatinfo{#1}\fi -}% -\def\POL@info #1{% - \xintMessage {polexpr}{Info}% - {Function #1 for the \string\xintexpr\space parser is - associated to \string\XINT_expr_polfunc_#1\space - whose meaning uses Horner scheme: - \expandafter\meaning - \csname XINT_expr_polfunc_#1\endcsname}% -}% -\def\POL@floatinfo #1{% - \xintMessage {polexpr}{Info}% - {Function #1 for the \string\xintfloatexpr\space parser is - associated to \string\XINT_flexpr_polfunc_#1\space - whose meaning uses Horner scheme: - \expandafter\meaning - \csname XINT_flexpr_polfunc_#1\endcsname}% -}% -% -\def\POL@newpolhorner#1{% - %% redefine function to expand by Horner scheme. Is this useful? - %% perhaps bad idea for numerical evaluation of thing such as (1+x)^10? -% note: I added {0/1[0]} item to zero polynomial also to facilitate this - \expandafter\expandafter\expandafter\POL@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\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\xintAdd\relax\let\xintMul\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} - {\@firstofone}{\xintAdd{#1}}% - {\xintMul{##1}{\POL@tmp{##1}}}}% - \POL@newpol@horner@loop.% -}% -\def\POL@newpol@floathorner#1{\let\XINTinFloatAdd\relax\let\XINTinFloatMul\relax - \def\xintAdd{\XINTinFloatAdd}\def\xintMul{\XINTinFloatMul}% - \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} - {\@firstofone}{\xintAdd{\XINTinFloatdigits{#1}}}% - {\xintMul{##1}{\POL@tmp{##1}}}}% - \POL@newpol@floathorner@loop.% -}% - - -\newcommand\PolGenFloatVariant[1]{\POL@newfloatpol{#1}}% - - -\newcommand\PolLet[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{% - \expandafter\let\csname POLuserpol@#1\expandafter\endcsname - \csname POLuserpol@#2\endcsname - \expandafter\let\csname XINT_expr_polfunc_#1\expandafter\endcsname - \csname XINT_expr_polfunc_#2\endcsname - \POL@defpolfunc{#1}{expr}% - \ifxintverbose\POL@info{#1}\fi -}% -\newcommand\PolGlobalLet[2]{\begingroup - \globaldefs\@ne - \if=\noexpand#2\expandafter\xint_firstoftwo - \else\expandafter\xint_secondoftwo\fi -% do I need to check something here relative to \xintNewExpr? - \POL@@globallet\POL@globallet {#1}{#2}}% -\def\POL@@globallet#1#2#3{\POL@globallet{#1}{#3}}% -\def\POL@globallet#1#2{\POL@let{#1}{#2}\endgroup}% - -\newcommand\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}{ }% -}% - - -\newcommand\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@ - \protected\def\POL@result{-1.\POL@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 -% dans le cas particulier d'un array avec que des éléments nuls, \count@ est -% ici devenu 0 et la boucle s'est arrêtée car #2{0} était au moins 1. De plus -% \POL@tmparray1 est bien 0/1[0] donc ok pour polynôme nul dans \POL@result - \count\tw@\count@ - \xintloop -% on mouline tous les coeffs via \xintRaw - \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}}% - \protected\edef\POL@result{\the\numexpr\count@-\@ne.\POL@empty - \xintiloop[1+1]% - \expandafter\POL@tmp\xintiloopindex.% - \ifnum\xintiloopindex<\count@ - \repeat}% - \fi - \expandafter - \endgroup - \expandafter - \def\csname POLuserpol@#1\expandafter\endcsname - \expandafter{\POL@result}% -}% - - -\newcommand\PolFromCSV[2]{% - \begingroup % closed in \POL@getfromarray - \xintAssignArray\xintCSVtoList{#2}\to\POL@arrayA - \POL@getfromarray{#1}\POL@arrayA - \POL@newpol{#1}% -% semble un peu indirect et sous-optimal -% mais je veux élaguer les coefficients nuls. Peut-être à revoir. -}% - - -\newcommand\PolTypesetCmdPrefix[1]{\xintiiifSgn{#1}{}{+}{+}}% -\newcommand\PolTypesetCmd[1]{\xintifOne{\xintiiAbs{#1}}% - {\ifnum\PolIndex=\z@\xintiiSgn{#1}\else - \xintiiifSgn{#1}{-}{}{}\fi - \let\PolIfCoeffIsPlusOrMinusOne\@firstoftwo}% - {\PolTypesetOne{#1}% - \let\PolIfCoeffIsPlusOrMinusOne\@secondoftwo}% - }% -\newcommand\PolTypesetOne{\xintSignedFrac}% -\newcommand\PolTypesetMonomialCmd{% - \ifcase\PolIndex\space - % - \or\PolVar - \else\PolVar^{\PolIndex}% - \fi -}% -\newcommand\PolTypeset{\@ifstar - {\def\POL@ts@ascending{1}\POL@Typeset}% - {\def\POL@ts@ascending{0}\POL@Typeset}% -}% -\newcommand\POL@Typeset[2][x]{% LaTeX \newcommand forces optional argument first - \ensuremath{% - \expandafter\expandafter\expandafter\POL@split - \csname POLuserpol@#2\endcsname;\POL@var@deg\POL@var@coeffs - \if\POL@ts@ascending1% - \def\PolIndex{0}% - \let\POL@ts@reverse\@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 - }% -}% -\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.% -}% - - -\newcommand\PolMapCoeffs[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 - \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]}% -\newcommand\PolReduceCoeffs{\@ifstar\POL@sreducecoeffs\POL@reducecoeffs}% -\def\POL@reducecoeffs#1{\PolMapCoeffs{\POL@xintIrr}{#1}}% -\def\POL@sreducecoeffs#1{\PolMapCoeffs{\xintPIrr}{#1}}% - - -%% EUCLIDEAN DIVISION -\newcommand\PolDivide[4]{% #3=quotient, #4=remainder of #1 by #2 - \POL@divide{#1}{#2}% - \expandafter\let\csname POLuserpol@#3\endcsname\POL@Q - \POL@newpol{#3}% - \expandafter\let\csname POLuserpol@#4\endcsname\POL@R - \POL@newpol{#4}% -}% -\newcommand\PolQuo[3]{% #3=quotient of #1 by #2 - \POL@divide{#1}{#2}% - \expandafter\let\csname POLuserpol@#3\endcsname\POL@Q - \POL@newpol{#3}% -}% -\newcommand\PolRem[3]{% #3=remainder of #1 by #2 - \POL@divide{#1}{#2}% - \expandafter\let\csname POLuserpol@#3\endcsname\POL@R - \POL@newpol{#3}% -}% -\newcommand\POL@divide[2]{% - \begingroup - \let\xintScalarSub\xintSub - \let\xintScalarAdd\xintAdd - \let\xintScalarMul\xintMul - \let\xintScalarDiv\xintDiv - \expandafter\let\expandafter\POL@A\csname POLuserpol@#1\endcsname - \expandafter\let\expandafter\POL@B\csname POLuserpol@#2\endcsname - \POL@div@c - \let\POL@Q\POL@result - \ifnum\POL@degQ<\z@ - \let\POL@R\POL@A - \else - \count@\numexpr\POL@degR+\@ne\relax - \POL@resultfromarray R% - \let\POL@R\POL@result - \fi - \expandafter - \endgroup - \expandafter - \def\csname POL@Q\expandafter\expandafter\expandafter\endcsname - \expandafter\expandafter\expandafter{\expandafter\POL@Q\expandafter}% - \expandafter - \def\csname POL@R\expandafter\endcsname\expandafter{\POL@R}% -}% - - -%% GCD -\newcommand\PolGCD[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 - \let\xintScalarSub\xintSub - \let\xintScalarAdd\xintAdd - \let\xintScalarMul\xintMul - \let\xintScalarDiv\xintDiv - \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 - {\protected\def\POL@result{-1.\POL@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\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{\xintScalarDiv - {\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 - {\xintScalarSub - {\csname POL@array#1\the\count4\endcsname}% - {\xintScalarMul - {\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% -}% - - -%% TODO: BEZOUT - - -%% 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.% -}% -\newcommand\PolDiff[1][1]{% - % optional parameter is how many times to derivate - % first mandatory arg is name of polynomial function to derivate, - % same name as in \NewPolExpr - % second mandatory arg name of derivative - \edef\POL@iterindex{\the\numexpr#1\relax}% - \ifnum\POL@iterindex<\z@ - \expandafter\@firstoftwo - \else - \expandafter\@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 - \@namedef{POLuserpol@#2}{-1.\POL@empty{0/1[0]}}% - \else - \edef\POL@var@coeffs{\expandafter\POL@diff\POL@var@coeffs\relax}% - \expandafter\edef\csname POLuserpol@#2\endcsname - {\the\numexpr\POL@var@deg-\@ne.\POL@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 - \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.% -}% -\newcommand\PolAntiDiff[1][1]{% - % optional parameter is how many times to derivate - % first mandatory arg is name of polynomial function to derivate, - % same name as in \NewPolExpr - % second mandatory arg name of derivative - \edef\POL@iterindex{\the\numexpr#1\relax}% - \ifnum\POL@iterindex<\z@ - \expandafter\@firstoftwo - \else - \expandafter\@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@ - \@namedef{POLuserpol@#2}{-1.\POL@empty{0/1[0]}}% - \else - \edef\POL@var@coeffs{\expandafter\POL@antidiff\POL@var@coeffs\relax}% - \expandafter\edef\csname POLuserpol@#2\endcsname - {\the\numexpr\POL@var@deg+\@ne.\POL@empty{0/1[0]}\POL@var@coeffs}% - \fi -}% - -%% IContent and \PolMakePrimitive (0.5) -\def\POL@aux@mgcd@loop#1#2{% - \if\relax#2\expandafter\POL@aux@mgcd@exit\fi - \expandafter - \POL@aux@mgcd@loop\romannumeral0\POL@aux@gcd#1.#2.% -}% -\def\POL@aux@mgcd@exit - \expandafter - \POL@aux@mgcd@loop\romannumeral0\POL@aux@gcd#1.\relax.{\xintiiabs{#1}}% -\def\POL@aux@gcd#1.#2.{% - \if0\xintiiSgn{#1}\expandafter\POL@aux@gcd@exit\fi - \expandafter\POL@aux@gcd\romannumeral0\xintmod {#2}{#1}.#1.}% -\def\POL@aux@gcd@exit - \expandafter\POL@aux@gcd\romannumeral0\xintmod #1#2.#3.{{#1}}% - -\def\POL@icontent #1{\romannumeral0\expandafter - \POL@aux@mgcd@loop\romannumeral`^^@#1\relax}% - -\newcommand\PolIContent[1]{\romannumeral0\expandafter - \POL@aux@mgcd@loop\romannumeral`^^@\PolToList{#1}\relax}% - - -\def\POL@makeprim@macro#1% - {\xintREZ{\xintNum{\xintDiv{#1}{\POL@makeprim@icontent}}}}% -\newcommand\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}% -}% - - +%% 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. @@ -898,7 +9,16 @@ %% holding the coefficients in memory %% 0.6 fixes the case of a constant polynomial P which caused division %% by zero error from P'. -\newcommand\PolToSturm{\@ifstar{\PolToSturm@@}{\PolToSturm@}}% +%% 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 @@ -914,7 +34,7 @@ \POL@count\z@ % if I applied the same as for positive degree, I should make it -1 % if constant is negative. I also don't worry if polynomial is zero. - \@namedef{POLuserpol@\POL@sturmname _0}{0.\POL@empty{1/1[0]}}% + \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 @@ -945,12 +65,13 @@ \POL@makeprimitive{\POL@sturmname _1_}% does not do \POL@newpol \POL@count\@ne \xintloop - \POL@divide{\POL@sturmname _\the\numexpr\POL@count-\@ne\relax _}% - {\POL@sturmname _\the\POL@count _}% + % 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 - \expandafter\let + \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 @@ -964,18 +85,18 @@ \advance\POL@count\m@ne \POL@divide{\POL@sturmname _\the\POL@count _}% {\POL@sturmname _\POL@sturm@N _}% - \expandafter - \let\csname POLuserpol@\POL@sturmname _\the\POL@count\endcsname\POL@Q + \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 - \@namedef{POLuserpol@\POL@sturmname _\POL@sturm@N}{0.\POL@empty{1/1[0]}}% + \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 - \expandafter\let + \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@ @@ -983,10 +104,13 @@ \fi % Back to \PolToSturm@, \POL@count holds 0 }% -\newcommand\PolSturmChainLength[1] - {\romannumeral`^^@\csname PolSturmChainLength_#1\endcsname}% - -\newcommand\PolSetToSturmChainSignChangesAt[4][\global]{% +\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}}% @@ -1014,7 +138,10 @@ \fi \repeat }% -\newcommand\PolSetToNbOfZerosWithin[5][\global]{% +\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}% @@ -1029,23 +156,25 @@ #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 -\newcommand\PolSturmIsolateZeros{\@ifstar +\def\PolSturmIsolateZeros{\POL@ifstar {\PolSturmIsolateZerosAndGetMultiplicities}% {\PolSturmIsolateZeros@}% }% -\newcommand\PolSturmIsolateZerosAndGetMultiplicities{\@ifstar +\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}% + {\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}}% -\newcommand\PolSturmIsolateZerosGetMultiplicitiesAndRationalRoots[2][\empty]{% +% +\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 @@ -1056,7 +185,10 @@ \fi }% % added at 0.7 -\newcommand\PolSturmIsolateZerosAndFindRationalRoots[2][\empty]{% +\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) @@ -1078,9 +210,11 @@ % 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 @@ -1161,7 +295,7 @@ \POL@findrat@xN\POL@findrat@xD\POl@_ % we can't move this to updatequotients because other branch will % need to do the division first anyhow - \edef\POLuserpol@_findrat@oneterm{1.\POL@empty + \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 @@ -1295,7 +429,7 @@ % zero should never occur here \POL@findrat@ifnegative{\edef\POL@findrat@x{-\POL@findrat@x}}{}% \POL@xintfrac@getNDE\POL@findrat@x\POL@findrat@xN\POL@findrat@xD\POL@_ - \edef\POLuserpol@_findrat@oneterm{1.\POL@empty + \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 @@ -1362,7 +496,7 @@ % safer to do the edef as \POL@findrat@x used later in storeit \edef\POL@findrat@x{\xintIrr{\xintDiv\POL@findrat@Num\POL@findrat@D}[0]}% \POL@xintfrac@getNDE\POL@findrat@x\POL@findrat@xN\POL@findrat@xD\POL@_ - \edef\POLuserpol@_findrat@oneterm{1.\POL@empty + \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 @@ -1385,23 +519,24 @@ \let\csname POL_ZK\POL@sturmname*\POL@findrat@index\endcsname \xint_stop_atfirstoftwo \begingroup\xintglobaldefstrue - % skip some overhead of \xintdefvar... + % 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}% + {{\POL@findrat@x}}% \XINT_expr_defvar_one{\POL@sturmname R_\POL@findrat@index}% - {\POL@findrat@x}% + {{\POL@findrat@x}}% \XINT_expr_defvar_one{\POL@sturmname Z_\POL@findrat@index _isknown}% - {1}% + {{1}}% \endgroup }% \def\POL@findrat@loop@updatequotients{% % attention last division must have been one testing vanishing of\POL@sqfnorr - \expandafter\let\csname POLuserpol@\POL@sturmname\POL@sqfnorr\endcsname\POL@Q + \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}% - \expandafter\let\csname POLuserpol@\POL@sturmname\POL@norr\endcsname\POL@Q + \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 }% @@ -1411,7 +546,7 @@ \POL@divide{\POL@sturmname\POL@norr}{_findrat@oneterm}% \expandafter\POL@split\POL@R;\POL@degR\POL@polR \ifnum\POL@degR=\m@ne % yes - \expandafter\let\csname POLuserpol@\POL@sturmname\POL@norr\endcsname\POL@Q + \XINT_global\expandafter\let\csname POLuserpol@\POL@sturmname\POL@norr\endcsname\POL@Q \POL@mapcoeffs\POL@aux@toint{\POL@sturmname\POL@norr}% \expandafter \xdef @@ -1451,14 +586,19 @@ \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 }% - - -\newcommand\PolSturmIsolateZerosAndGetMultiplicities@[2][\empty]{% +\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) @@ -1487,7 +627,11 @@ % store Sturm chain name, it is needed and altered in isolzmult@loop \let\POL@originalsturmname\POL@sturmname \POL@tosturm@makefirstprimitivefalse - \POL@isolzmult@loop +\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 @@ -1502,8 +646,9 @@ \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}% + {{\csname POL_ZM\POL@sturmname*\x\endcsname}}% \edef\x{\the\numexpr\x-\@ne}% \ifnum\x>\z@ \repeat @@ -1586,9 +731,10 @@ {\the\numexpr\POL@isolz@NbOfRoots@with_unknown_mult-\@ne}% \fi }% - - -\newcommand\PolSturmIsolateZeros@[2][\empty]{% +\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) @@ -2077,17 +1223,20 @@ \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}% + {{\POL@IsoLeft@rawout}}% \XINT_expr_defvar_one{\POL@sturmname R_\POL@isolz@IntervalIndex}% - {\POL@IsoRight@rawout}% + {{\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}% + {{\ifnum\POL@IsoRightSign=\z@ 1\else 0\fi}}% \endgroup }% %% \PolRefineInterval -\def\POL@xintexprGetVar#1{\csname XINT_expr_varvalue_#1\endcsname}% +%% 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 @@ -2103,8 +1252,11 @@ \def\POL@get@IsoLeft@Int{% \expandafter\POL@get@Int@aux\POL@IsoLeft@rawin\POL@IsoLeft@Int\POL@isolz@E }% -\newcommand\PolRefineInterval{\@ifstar\POL@srefine@start\POL@refine@start}% -\newcommand\POL@refine@start[3][1]{% +\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 @@ -2138,8 +1290,8 @@ \fi }% \def\POL@refine@loop#1{% - \let\POL@refine@left@next \@empty % no recursion at end sub-intervals - \let\POL@refine@right@next\@empty + \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@ @@ -2160,11 +1312,11 @@ \ifnum\POL@IsoRightSign=\z@ \let\POL@IsoLeft@Int\POL@IsoRight@Int % root at 1 \def\POL@IsoLeftSign{0}% - \let\POL@next\@empty + \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 + \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}}% @@ -2173,7 +1325,7 @@ \ifnum\POL@IsoRightSign=\z@ \let\POL@IsoLeft@Int\POL@IsoRight@Int % root at 9 \def\POL@IsoLeftSign{0}% - \let\POL@next\@empty + \let\POL@next\empty \else \ifnum\POL@IsoRightSign=\POL@@IsoRightSign\space \let\POL@next\POL@refine@doonce @@ -2182,7 +1334,7 @@ \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 + \let\POL@refine@left@next\empty \fi \fi \fi\fi @@ -2190,18 +1342,16 @@ }% % lacking pre-defined xintfrac macro here (such as an \xintRawExponent) \def\POL@refine@getE#1[#2]{#2}% \xintREZ already applied, for safety - - -\newcommand\PolIntervalWidth[2]{% +% +% +\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}}} }% - - -\newcommand\PolEnsureIntervalLengths[2]{% #1 = Sturm chain name, +\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}% @@ -2220,7 +1370,7 @@ \ifnum\POL@nbofroots>\POL@count \repeat }% -\newcommand\PolEnsureIntervalLength[3]{% #1 = Sturm chain name, +\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}% @@ -2230,7 +1380,7 @@ \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èrerai ne pas être à l'intérieur +% je ne fais pas les \expandafter mais je préfèrerais ne pas être à l'intérieur \POL@ensure@one \fi \fi @@ -2282,24 +1432,39 @@ \expandafter\xintbreakloop \fi }% - - +% +%% \PolPrintIntervals \catcode`_ 8 -\newcommand\PolPrintIntervals - {\@ifstar{\PolPrintIntervals@@}{\PolPrintIntervals@}}% -\newcommand\PolPrintIntervals@@{% +\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}% - \def\arraystretch{2}% \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@ }% -\newcommand\PolPrintIntervals@[2][Z]{\POL@PrintIntervals{#1}{#2}}% -\newcommand\POL@PrintIntervals[2]{% +\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@ @@ -2317,34 +1482,60 @@ \def\PolPrintIntervalsTheVar{#1}% \def\PolPrintIntervalsTheSturmName{#2}% }% -\let\POL@AfterPrintIntervals\@empty -\newcommand\PolPrintIntervalsNoRealRoots{}% -\newcommand\PolPrintIntervalsBeginEnv{\[\begin{array}{rcccl}}% -\newcommand\PolPrintIntervalsEndEnv{\end{array}\]}% -\newcommand\PolPrintIntervalsKnownRoot{% +\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 }% -\newcommand\PolPrintIntervalsUnknownRoot{% +\def\PolPrintIntervalsUnknownRoot{% \PolPrintIntervalsPrintLeftEndPoint&<&% \PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}&<&% \PolPrintIntervalsPrintRightEndPoint }% -\newcommand\PolPrintIntervalsPrintExactZero {\PolPrintIntervalsTheLeftEndPoint}% -\newcommand\PolPrintIntervalsPrintLeftEndPoint {\PolPrintIntervalsTheLeftEndPoint}% -\newcommand\PolPrintIntervalsPrintRightEndPoint{\PolPrintIntervalsTheRightEndPoint}% -\newcommand\PolPrintIntervalsPrintMultiplicity{(\mbox{mult. }\PolPrintIntervalsTheMultiplicity)}% +\def\PolPrintIntervalsPrintExactZero {\PolPrintIntervalsTheLeftEndPoint}% +\def\PolPrintIntervalsPrintLeftEndPoint {\PolPrintIntervalsTheLeftEndPoint}% +\def\PolPrintIntervalsPrintRightEndPoint{\PolPrintIntervalsTheRightEndPoint}% +% +\ifdefined\mbox +\def\PolPrintIntervalsPrintMultiplicity{(\mbox{mult. }\PolPrintIntervalsTheMultiplicity)}% +\else +\def\PolPrintIntervalsPrintMultiplicity{(\hbox{mult. }\PolPrintIntervalsTheMultiplicity)}% +\fi % -\newcommand\POL@@PrintIntervalsKnownRoot{% +\def\POL@@PrintIntervalsKnownRoot{% \PolPrintIntervalsPrintMultiplicity&% \PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}=% \PolPrintIntervalsPrintExactZero }% -\newcommand\POL@@PrintIntervalsPrintExactZero{% +\ifdefined\frac +\def\POL@@PrintIntervalsPrintExactZero{% \displaystyle \xintSignedFrac{\PolPrintIntervalsTheLeftEndPoint}% }% -\newcommand\POL@@PrintIntervalsUnknownRoot{% +\else +\def\POL@@PrintIntervalsPrintExactZero{% + \displaystyle + \xintSignedFwOver{\PolPrintIntervalsTheLeftEndPoint}% +}% +\fi +\def\POL@@PrintIntervalsUnknownRoot{% \PolPrintIntervalsPrintMultiplicity&% \xintifSgn{\PolPrintIntervalsTheLeftEndPoint}% {\xintifSgn{\PolPrintIntervalsTheRightEndPoint} @@ -2364,8 +1555,9 @@ {\PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}=% \PolPrintIntervalsPrintLeftEndPoint\dots}}% }% -% +\catcode`& 7 \catcode`_ 11 +\def\POL@PrintIntervals@Loop#1{% \def\POL@PrintIntervals@Loop{% \POL@SturmIfZeroExactlyKnown\PolPrintIntervalsTheSturmName \PolPrintIntervalsTheIndex @@ -2375,9 +1567,10 @@ \unless\ifnum\PolPrintIntervalsTheIndex> \@nameuse{POL_ZL\PolPrintIntervalsTheSturmName*0} \POL@PrintIntervals@DoDefs - \xint_afterfi{\\\POL@PrintIntervals@Loop}% + \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 @@ -2397,492 +1590,60 @@ \fi }% }% - - -\newcommand\PolSturmIfZeroExactlyKnown[2]{% #1 = sturmname, #2=index +% +%% Expandable interface +% +\def\PolSturmIfZeroExactlyKnown#1#2{% #1 = sturmname, #2=index \romannumeral0\csname POL_ZK#1*\endcsname{#2}% }% -\newcommand\POL@SturmIfZeroExactlyKnown[2]{% #1 = sturmname, #2=index +\def\POL@SturmIfZeroExactlyKnown#1#2{% #1 = sturmname, #2=index \romannumeral0\csname POL_ZK#1*\the\numexpr#2\endcsname }% -\newcommand\PolSturmIsolatedZeroMultiplicity[2]{% - \romannumeral`^^@\csname POL_ZM#1*\endcsname{#2}% +\def\PolSturmIsolatedZeroMultiplicity#1#2{% + \romannumeral`&&@\csname POL_ZM#1*\endcsname{#2}% }% -\newcommand\PolSturmIsolatedZeroLeft[2]{% - \romannumeral`^^@\csname POL_ZL#1*\endcsname{#2}% +\def\PolSturmIsolatedZeroLeft#1#2{% + \romannumeral`&&@\csname POL_ZL#1*\endcsname{#2}% }% -\newcommand\PolSturmIsolatedZeroRight[2]{% - \romannumeral`^^@\csname POL_ZR#1*\endcsname{#2}% +\def\PolSturmIsolatedZeroRight#1#2{% + \romannumeral`&&@\csname POL_ZR#1*\endcsname{#2}% }% -\newcommand\PolSturmNbOfIsolatedZeros[1]{% - \romannumeral`^^@\csname POL_ZL#1*0\endcsname +\def\PolSturmNbOfIsolatedZeros#1{% + \romannumeral`&&@\csname POL_ZL#1*0\endcsname }% -\newcommand\PolSturmRationalRoot[2]{% - \romannumeral`^^@\csname POL_ZL#1*% +\def\PolSturmRationalRoot#1#2{% + \romannumeral`&&@\csname POL_ZL#1*% \csname POL_RI#1*\endcsname{#2}\endcsname }% -\newcommand\PolSturmRationalRootIndex[2]{% - \romannumeral`^^@\csname POL_RI#1*\endcsname{#2}% +\def\PolSturmRationalRootIndex#1#2{% + \romannumeral`&&@\csname POL_RI#1*\endcsname{#2}% }% -\newcommand\PolSturmRationalRootMultiplicity[2]{% - \romannumeral`^^@\csname POL_ZM#1% +\def\PolSturmRationalRootMultiplicity#1#2{% + \romannumeral`&&@\csname POL_ZM#1% *\csname POL_RI#1*\endcsname{#2}\endcsname }% -\newcommand\PolSturmNbOfRationalRoots[1]{% - \romannumeral`^^@\csname POL_RI#1*0\endcsname +\def\PolSturmNbOfRationalRoots#1{% + \romannumeral`&&@\csname POL_RI#1*0\endcsname }% -\newcommand\PolSturmNbOfRationalRootsWithMultiplicities[1]{% +\def\PolSturmNbOfRationalRootsWithMultiplicities#1{% % means the \POL@norr must not have been changed in-between... \the\numexpr\PolDegree{#1}-\PolDegree{#1\POL@norr}\relax }% - - -\let\PolDecToString\xintDecToString - - -\newcommand\PolMakeMonic[1]{% - \edef\POL@leadingcoeff{\PolLeadingCoeff{#1}}% - \edef\POL@leadingcoeff@inverse{\xintDiv{1/1[0]}{\POL@leadingcoeff}}% - \PolMapCoeffs{\xintMul{\POL@leadingcoeff@inverse}}{#1}% -}% - - -%% CORE ALGEBRA MACROS -%% We do this non-expandably, but in a nestable way... this is the whole -%% point because \xintdeffunc as used by \poldef creates a big nested macro. -%% The idea is to execute it with another meaning given to \xintAdd etc.., -%% so that it operates on "polynomials". This is a mixture of expandable -%% and non-expandable techniques. -%% -%% And it was complicated to let it work with xintexpr 1.4 -%% -\def\POL@get#1#2#3{% - \relax %!! part de la tambouille pour fonctionner en xint 1.4 - \POL@polglobalfalse - \begingroup - \protected\def\POL@result{#3}% - #3% - \expandafter - \endgroup - \expandafter\def\expandafter#1\expandafter{\POL@result}% - \unless\ifPOL@pol - % avoid expanding more than twice #3 - % #3 must be purely numerical or at least compatible with \edef - % this is why at 0.7.5 I had to handle especially constant - % polynomial functions to remove any protection from them - % (because the protection triggers the COMPOSITION when - % the polynomial is found as argument of another one and - % this is not expandable) - \edef#1{#3}% - \xintiiifZero{#1}% - {\def#1{-1.\POL@empty{0/1[0]}}}% - {\edef#1{0.\POL@empty{#1}}}% - \fi - #2% -}% - -%% COMPOSITION -%% This did not exist before 0.7.5 and is part of its adaptation to xint 1.4 -%% We thus took up this opportunity to speed up substantially composition. -%% Very serious difficulties with constant polynomials. Had to handle them -%% especially. -%% OK, that was really tough, but advantage now is that composition -%% at 0.7.5 should be more efficient than before. However when polynomials -%% become big via composition, coefficients also are big and the time -%% taken by arithmetic dominates. No time to test really, though, relieved -%% I can release xint 1.4 at last. My basic polexpr test suite passes, -%% but it goes back already to old releases. -\protected\def\POL@applypolfunc#1#2% -{% -% This #2 may be also invoing \POL@applypolfunc... - \POL@get\POL@A\POL@applypolfunc@b#2#1% -}% -\def\POL@applypolfunc@b #1% -{% -% and now the have our Horner scheme nested macro -% which hopefully will do its job with \POL@add, \POL@mul etc... - \POL@polglobalfalse - \expandafter#1\expanded - {{\POL@polglobaltrue\protected\def\noexpand\POL@result{\POL@A}}}% - \unless\ifPOL@pol - \odef\POL@result{#1{0}}% - \xintiiifZero{\POL@result}% - {\protected\def\POL@result{-1.\POL@empty{0/1[0]}}}% - {\protected\edef\POL@result{0.\POL@empty{\POL@result}}}% - \fi -}% - -%% ADDITION -\def\POL@add {\POL@get\POL@A\POL@add@b}% -\def\POL@add@b{\POL@get\POL@B\POL@add@c}% -\def\POL@add@c{% - \POL@polglobaltrue - \POL@ifZero\POL@A - {\let\POL@result\POL@B}% - {\POL@ifZero\POL@B - {\let\POL@result\POL@A}% - {\POL@@add}}% -}% -\def\POL@@add{% - \expandafter\POL@split\POL@A;\POL@degA\POL@polA - \expandafter\POL@split\POL@B;\POL@degB\POL@polB - \ifnum\POL@degA>\POL@degB\relax - \xintAssignArray\POL@polA\to\POL@arrayA - \xintAssignArray\POL@polB\to\POL@arrayB - \else - \xintAssignArray\POL@polB\to\POL@arrayA - \xintAssignArray\POL@polA\to\POL@arrayB - \let\POL@tmp\POL@degB\let\POL@degB\POL@degA\let\POL@degA\POL@tmp - \fi - \count@\z@ - \xintloop - \advance\count@\@ne - \expandafter\edef\csname POL@arrayA\the\count@\endcsname - {\xintScalarAdd{\@nameuse{POL@arrayA\the\count@}}% - {\@nameuse{POL@arrayB\the\count@}}}% - \unless\ifnum\POL@degB<\count@ - \repeat - \count@\@nameuse{POL@arrayA0} % 1+\POL@degA - % trim zero leading coefficients (we could check for equal degrees, - % but would not bring much as anyhow loop exists immediately if not) - \xintloop - % this abuses that \POL@arrayA0 is never zero - \xintiiifZero{\@nameuse{POL@arrayA\the\count@}}% - {\iftrue}% - {\iffalse}% - \advance\count@\m@ne - \repeat - \POL@resultfromarray A% attention that \POL@arrayA0 not updated -}% - -%% MULTIPLICATION -\def\POL@mul {\POL@get\POL@A\POL@mul@b}% -\def\POL@mul@b{\POL@get\POL@B\POL@mul@c}% -\def\POL@mul@c{% - \POL@polglobaltrue - \POL@ifZero\POL@A - {\protected\def\POL@result{-1.\POL@empty{0/1[0]}}}% - {\POL@ifZero\POL@B - {\protected\def\POL@result{-1.\POL@empty{0/1[0]}}}% - {\POL@@mul}}% -}% -\def\POL@@mul{% - \expandafter\POL@split\POL@A;\POL@degA\POL@polA - \expandafter\POL@split\POL@B;\POL@degB\POL@polB - \ifnum\POL@degA>\POL@degB\relax - \xintAssignArray\POL@polA\to\POL@arrayA - \xintAssignArray\POL@polB\to\POL@arrayB - \else - \xintAssignArray\POL@polB\to\POL@arrayA - \xintAssignArray\POL@polA\to\POL@arrayB - \let\POL@tmp\POL@degB - \let\POL@degB\POL@degA - \let\POL@degA\POL@tmp - \fi - \count@\z@ - \xintloop - \POL@@mul@phaseIloopbody - \unless\ifnum\POL@degB<\count@ - \repeat - \xintloop - \unless\ifnum\POL@degA<\count@ % car attention au cas de mêmes degrés - \POL@@mul@phaseIIloopbody - \repeat - \edef\POL@degC{\the\numexpr\POL@degA+\POL@degB}% - \xintloop - \unless\ifnum\POL@degC<\count@ - \POL@@mul@phaseIIIloopbody - \repeat - %\count@\the\numexpr\POL@degC+\@ne\relax % never zero polynomial here - \POL@resultfromarray C% -}% -\def\POL@@mul@phaseIloopbody{% - \advance\count@\@ne - \def\POL@tmp{0[0]}% - \count\tw@\z@ - \xintloop - \advance\count\tw@\@ne - \edef\POL@tmp{% - \xintScalarAdd - {\POL@tmp}% - {\xintScalarMul - {\@nameuse{POL@arrayA\the\count\tw@}}% - {\@nameuse{POL@arrayB\the\numexpr\count@+\@ne-\count\tw@}}% - }% - }% - \ifnum\count\tw@<\count@ - \repeat - \expandafter\let\csname POL@arrayC\the\count@\endcsname\POL@tmp -}% -\def\POL@@mul@phaseIIloopbody{% - \advance\count@\@ne - \def\POL@tmp{0[0]}% - \count\tw@\count@ - \advance\count\tw@-\@nameuse{POL@arrayB0} % - \xintloop - \ifnum\count\tw@<\count@ - \advance\count\tw@\@ne - \edef\POL@tmp{% - \xintScalarAdd - {\POL@tmp}% - {\xintScalarMul - {\@nameuse{POL@arrayA\the\count\tw@}}% - {\@nameuse{POL@arrayB\the\numexpr\count@+\@ne-\count\tw@}}% - }% - }% - \repeat - \expandafter\let\csname POL@arrayC\the\count@\endcsname\POL@tmp -}% -\def\POL@@mul@phaseIIIloopbody{% - \advance\count@\@ne - \def\POL@tmp{0[0]}% - \count\tw@\count@ - \advance\count\tw@-\@nameuse{POL@arrayB0} % - \xintloop - \advance\count\tw@\@ne - \edef\POL@tmp{% - \xintScalarAdd{\POL@tmp}% - {\xintScalarMul - {\@nameuse{POL@arrayA\the\count\tw@}}% - {\@nameuse{POL@arrayB\the\numexpr\count@+\@ne-\count\tw@}}% - }% - }% - \ifnum\@nameuse{POL@arrayA0}>\count\tw@ - \repeat - \expandafter\let\csname POL@arrayC\the\count@\endcsname\POL@tmp -}% - -%% POWERS (SCALAR EXPONENT...) -\def\POL@pow #1#2{% - \POL@polglobalfalse - \begingroup - \protected\def\POL@result{#1}% - #1% - \expandafter - \endgroup - \expandafter\def\expandafter\POL@A\expandafter{\POL@result}% - \unless\ifPOL@pol - \edef\POL@A{\xintScalarPow{#1}{#2}}% no error check - \xintiiifZero{\POL@A}% - {\protected\def\POL@result{-1.\POL@empty{0/1[0]}}}% - {\protected\edef\POL@result{0.\POL@empty{\POL@A}}}% - \else - \edef\POL@B{\numexpr\xintNum{#2}\relax}% no check on exponent >= 0 - \ifcase\POL@B - \protected\def\POL@result{0.\POL@empty{1/1[0]}}% - \or - \let\POL@result\POL@A - \else - \POL@@pow@check - \fi - \fi - \POL@polglobaltrue -}% -\def\POL@@pow@check {% -% no problem here with leftover tokens! -% should I have used that I-don't-care technique more elsewhere? - \ifnum\@ne>\POL@A - % polynomial is a constant, must get rid of dot and \empty (\POL@empty) - \edef\POL@A{\expandafter\xintScalarPow\romannumeral`^^@% - \expandafter\xint_gob_til_dot\POL@A{\POL@B}}% - \xintiiifZero{\POL@A}% - {\protected\def\POL@result{-1.\POL@empty{0/1[0]}}}% - {\protected\edef\POL@result{0.\POL@empty{\POL@A}}}% - \else - \ifnum\@ne=\POL@A - % perhaps a constant times X, check constant term - \xintiiifZero - {\expandafter\xint_firstoftwo\romannumeral`^^@% - \expandafter\xint_gob_til_dot\POL@A} - {\protected\edef\POL@result - {\the\POL@B.% here at least 2. - \POL@empty - \romannumeral\xintreplicate{\POL@B}{{0/1[0]}}% - {\xintScalarPow - {\expandafter\xint_secondoftwo\romannumeral`^^@% - \expandafter\xint_gob_til_dot\POL@A}% - {\POL@B}}}}% - {\POL@@pow}% not constant times X, use general recursion - \else - \POL@@pow% general recursion - \fi\fi -}% -\def\POL@@pow@recurse#1#2{% - \begingroup - #1% - \expandafter - \endgroup - \expandafter\def\expandafter\POL@A\expandafter{\POL@result}% - \edef\POL@B{\numexpr\xintNum{#2}\relax}% - \ifcase\POL@B - \POL@thisshouldneverhappen - \or - \let\POL@result\POL@A - \else - \expandafter\POL@@pow - \fi -}% -\def\POL@@pow {% - \let\POL@pow@exp\POL@B - \let\POL@B\POL@A - \POL@@mul - \let\POL@sqA\POL@result - \ifodd\POL@pow@exp\space - \expandafter\POL@@pow@odd - \the\numexpr(\POL@pow@exp+\@ne)/\tw@-\@ne\expandafter.% - \else - \expandafter\POL@@pow@even - \the\numexpr(\POL@pow@exp+\@ne)/\tw@-\@ne\expandafter.% - \fi -}% -\def\POL@@pow@even#1.{% - \expandafter\POL@@pow@recurse\expandafter - {\expandafter\def\expandafter\POL@result\expandafter{\POL@sqA}}% - {#1}% -}% -\def\POL@@pow@odd#1.{% - \expandafter\POL@@pow@odd@i\expandafter{\POL@A}{#1}% -}% -\def\POL@@pow@odd@i #1#2{% - \expandafter\POL@@pow@recurse\expandafter - {\expandafter\def\expandafter\POL@result\expandafter{\POL@sqA}}% - {#2}% - \expandafter\POL@mul\expandafter - {\expandafter\def\expandafter\POL@result\expandafter - {\POL@result}\POL@polglobaltrue}% - {\protected\def\POL@result{#1}\POL@polglobaltrue}% -}% - -%% DIVISION -%% no check on divisor being non-zero -\def\POL@div {\POL@get\POL@A\POL@div@b}% -\def\POL@div@b{\POL@get\POL@B\POL@div@c}% -\def\POL@div@c{% - \POL@polglobaltrue - \expandafter\POL@split\POL@A;\POL@degA\POL@polA - \expandafter\POL@split\POL@B;\POL@degB\POL@polB - \ifnum\POL@degA<\POL@degB\space - \@namedef{POL@arrayQ1}{0/1[0]}% - \def\POL@degQ{-1}% - \else - \xintAssignArray\POL@polA\to\POL@arrayR - \xintAssignArray\POL@polB\to\POL@arrayB - \POL@@div - \fi - \count@\numexpr\POL@degQ+\@ne\relax - \POL@resultfromarray Q% -}% -\def\POL@@div{% - \xintAssignArray\POL@polA\to\POL@arrayR - \xintAssignArray\POL@polB\to\POL@arrayB - \edef\POL@B@leading{\csname POL@arrayB\the\numexpr\POL@degB+\@ne\endcsname}% - \edef\POL@degQ{\the\numexpr\POL@degA-\POL@degB}% - \count@\numexpr\POL@degA+\@ne\relax - \count\tw@\numexpr\POL@degQ+\@ne\relax - \xintloop - \POL@@div@loopbody - \ifnum\count\tw@>\z@ - \repeat - %%\expandafter\def\csname POL@arrayR0\endcsname{1}% - \xintloop - \xintiiifZero{\csname POL@arrayR\the\count@\endcsname}% - {\iftrue}% - {\iffalse}% - \advance\count@\m@ne - \repeat - \edef\POL@degR{\the\numexpr\count@-\@ne}% -}% -\def\POL@@div@loopbody{% - \edef\POL@@div@ratio{% - \xintScalarDiv{\csname POL@arrayR\the\count@\endcsname}% - {\POL@B@leading}}% - \expandafter\let\csname POL@arrayQ\the\count\tw@\endcsname - \POL@@div@ratio - \advance\count@\m@ne - \advance\count\tw@\m@ne - \count4 \count@ - \count6 \POL@degB\space - \xintloop - \ifnum\count6>\z@ - \expandafter\edef\csname POL@arrayR\the\count4\endcsname - {\xintScalarSub - {\csname POL@arrayR\the\count4\endcsname}% - {\xintScalarMul - {\POL@@div@ratio}% - {\csname POL@arrayB\the\count6\endcsname}}}% - \advance\count4 \m@ne - \advance\count6 \m@ne - \repeat -}% - -%% MINUS SIGN AS UNARY OPERATOR -\def\POL@opp #1{% - \POL@polglobalfalse - \begingroup - \protected\def\POL@result{#1}% - #1% - \expandafter - \endgroup - \expandafter\def\expandafter\POL@A\expandafter{\POL@result}% - \unless\ifPOL@pol - \edef\POL@A{\xintScalarOpp{#1}}% - \xintiiifZero{\POL@A}% - {\protected\def\POL@result{-1.\POL@empty{0/1[0]}}}% - {\protected\edef\POL@result{0.\POL@empty{\POL@A}}}% - \else - \edef\POL@B{0.\POL@empty{-1/1[0]}}% - \POL@@mul - \fi - \POL@polglobaltrue -}% - - -%% EXPANDABLE MACROS -\def\POL@eval@fork#1\At#2#3\krof{#2}% -\newcommand\PolEval[3]{\romannumeral`^^@\POL@eval@fork - #2\PolEvalAt - \At\PolEvalAtExpr\krof {#1}{#3}% -}% -\newcommand\PolEvalAt[2] - {\xintpraw{\csname XINT_expr_polfunc_#1\endcsname{#2}}}% -\newcommand\POL@eval[2] - {\csname XINT_expr_polfunc_#1\endcsname{#2}}% -\newcommand\PolEvalAtExpr[2]{\xinttheexpr #1(#2)\relax}% -% -\newcommand\PolEvalReduced[3]{\romannumeral`^^@\POL@eval@fork - #2\PolEvalReducedAt - \At\PolEvalReducedAtExpr\krof {#1}{#3}% -}% -\newcommand\PolEvalReducedAt[2]{% - \xintpraw % in order not to print denominator if the latter equals 1 - {\xintIrr{\csname XINT_expr_polfunc_#1\endcsname{#2}}[0]}% -}% -\newcommand\PolEvalReducedAtExpr[2]{% - \xintpraw - {\expandafter\xintIrr\romannumeral`^^@\xintthebareeval#1(#2)\relax[0]}% -}% -% -\newcommand\PolFloatEval[3]{\romannumeral`^^@\POL@eval@fork - #2\PolFloatEvalAt - \At\PolFloatEvalAtExpr\krof {#1}{#3}% -}% -\newcommand\PolFloatEvalAt[2] - {\xintpfloat{\csname XINT_flexpr_polfunc_#1\endcsname{#2}}}% -\newcommand\PolFloatEvalAtExpr[2]{\xintthefloatexpr #1(#2)\relax}% - - -\newcommand\PolSturmIntervalIndex[3]{\the\numexpr\POL@eval@fork +\def\PolSturmIntervalIndex#1#2#3{\the\numexpr\POL@eval@fork #2\PolSturmIntervalIndexAt \At\PolSturmIntervalIndexAtExpr\krof {#1}{#3}% }% -\newcommand\PolSturmIntervalIndexAtExpr[2] - {\PolSturmIntervalIndexAt{#1}{\xinttheexpr#2\relax}}% -\newcommand\PolSturmIntervalIndexAt[2] - {\expandafter\POL@sturm@index@at\romannumeral`^^@#2!{#1}\xint_bye\relax}% +\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}% + \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 @@ -2906,19 +1667,18 @@ }% {}% }% - % catcode of ! is 11 in polexpr.sty + % 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}% -\newcommand\PolSturmNbOfRootsOf[3]{\romannumeral`^^@\POL@leq@fork +\def\PolSturmNbOfRootsOf#1#2#3{\romannumeral`&&@\POL@leq@fork #2\PolNbOfRootsLessThanOrEqualTo \LessThanOrEqualTo\PolNbOfRootsLessThanOrEqualToExpr\krof {#1}{#3}% }% -\newcommand\PolNbOfRootsLessThanOrEqualToExpr[2] +\def\PolNbOfRootsLessThanOrEqualToExpr#1#2 {\PolNbOfRootsLessThanOrEqualTo{#1}{\xinttheexpr#2\relax}}% -\newcommand\PolNbOfRootsLessThanOrEqualTo[1]{% +\def\PolNbOfRootsLessThanOrEqualTo#1{% \ifnum\PolSturmNbOfIsolatedZeros{#1}=\z@ \expandafter\xint_firstofthree\expandafter0% \else @@ -2927,7 +1687,7 @@ }% \def\PolNbOfRootsLessThanOrEqualTo@ #1#2% {% - \expandafter\POL@nbofrootsleq@prep\romannumeral`^^@#2!{#1}% + \expandafter\POL@nbofrootsleq@prep\romannumeral`&&@#2!{#1}% }% \def\POL@nbofrootsleq@prep#1!#2% {% @@ -2959,16 +1719,16 @@ \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}% - - -\newcommand\PolSturmNbWithMultOfRootsOf[3] -{\the\numexpr0\POL@leq@fork +% +\def\PolSturmNbWithMultOfRootsOf#1#2#3{% + \the\numexpr0\POL@leq@fork #2\PolNbWithMultOfRootsLessThanOrEqualTo \LessThanOrEqualTo\PolNbWithMultOfRootsLessThanOrEqualToExpr\krof {#1}{#3}% }% -\newcommand\PolNbWithMultOfRootsLessThanOrEqualToExpr[2] - {\PolNbWithMultOfRootsLessThanOrEqualTo{#1}{\xinttheexpr#2\relax}}% -\newcommand\PolNbWithMultOfRootsLessThanOrEqualTo[1]{% +\def\PolNbWithMultOfRootsLessThanOrEqualToExpr#1#2{% + \PolNbWithMultOfRootsLessThanOrEqualTo{#1}{\xinttheexpr#2\relax}% +}% +\def\PolNbWithMultOfRootsLessThanOrEqualTo#1{% \ifnum\PolSturmNbOfIsolatedZeros{#1}=\z@ \expandafter\POL@nbwmofroots@noroots \else @@ -2978,7 +1738,7 @@ \def\POL@nbwmofroots@noroots#1#2{\relax}% \def\PolNbWithMultOfRootsLessThanOrEqualTo@ #1#2% {% - \expandafter\POL@nbwmofrootsleq@prep\romannumeral`^^@#2!{#1}% + \expandafter\POL@nbwmofrootsleq@prep\romannumeral`&&@#2!{#1}% }% \def\POL@nbwmofrootsleq@prep#1!#2% {% @@ -3012,153 +1772,4 @@ #1!#2!#3!{#4}% }% \def\POL@nbwmofrootsleq@return #1!#2!#3!#4!#5{#1\relax}% - - -\newcommand\PolLeadingCoeff[1]{% - \romannumeral`^^@\expandafter\expandafter\expandafter\xintlastitem - \expandafter\expandafter\expandafter - {\csname POLuserpol@#1\endcsname}% -}% -% -\newcommand\PolNthCoeff[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? -\newcommand\PolDegree[1]{\romannumeral`^^@\expandafter\expandafter\expandafter - \POL@degree\csname POLuserpol@#1\endcsname;}% -\def\POL@degree #1.#2;{#1}% -% -\newcommand\PolToList[1]{\romannumeral`^^@\expandafter\expandafter\expandafter - \xint_gob_til_dot\csname POLuserpol@#1\endcsname}% -% -\newcommand\PolToCSV[1]{\romannumeral0\xintlistwithsep{, }{\PolToList{#1}}}% - - -\newcommand\PolToExprCmd[1]{\xintPRaw{\xintRawWithZeros{#1}}}% -\newcommand\PolToFloatExprCmd[1]{\xintFloat{#1}}% -\let\PolToExprTermPrefix\PolTypesetCmdPrefix -\newcommand\PolToExprOneTermStyleA[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^\xintiiAbs{#2}% - \fi -}% -\let\PolToExprOneTerm\PolToExprOneTermStyleA -\newcommand\PolToExprOneTermStyleB[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^\xintiiAbs{#2}% - \fi - \xintiiifOne{\xintDenominator{#1}}{}{/\xintDenominator{#1}}% -}% -\newcommand\PolToFloatExprOneTerm[2]{% - \ifnum#2=\z@ - \PolToFloatExprCmd{#1}% - \else - \PolToFloatExprCmd{#1}\PolToExprTimes - \fi - \ifcase\xintiiAbs{#2} %<-- space here mandatory - \or\PolToExprVar - \else\PolToExprVar^\xintiiAbs{#2}% - \fi -}% -\newcommand\PolToExprTimes{*}% -\newcommand\PolToExprVar{x}% -\newcommand\PolToExpr[1]{% - \if*\noexpand#1\expandafter\xint_firstoftwo\else - \expandafter\xint_secondoftwo\fi - \PolToExprAscending\PolToExprDescending{#1}}% -\newcommand\PolToFloatExpr[1]{% - \if*\noexpand#1\expandafter\xint_firstoftwo\else - \expandafter\xint_secondoftwo\fi - \PolToFloatExprAscending\PolToFloatExprDescending{#1}}% -\newcommand\PolToExprAscending[2]{% - \expandafter\POL@toexpr\csname POLuserpol@#2\endcsname - \PolToExprOneTerm\POL@toexprA}% -\newcommand\PolToFloatExprAscending[2]{% - \expandafter\POL@toexpr\csname POLuserpol@#2\endcsname - \PolToFloatExprOneTerm\POL@toexprA}% -\newcommand\PolToExprDescending[1]{% - \expandafter\POL@toexpr\csname POLuserpol@#1\endcsname - \PolToExprOneTerm\POL@toexprD}% -\newcommand\PolToFloatExprDescending[1]{% - \expandafter\POL@toexpr\csname POLuserpol@#1\endcsname - \PolToFloatExprOneTerm\POL@toexprD}% -% -\def\POL@toexpr#1#2#3{\expandafter\POL@toexpr@ - \expandafter#3\expandafter#2#1\relax}% -\def\POL@toexpr@#1#2#3.{% - \ifnum#3<\z@ - #2{0/1[0]}{0}\expandafter\xint_gobble_v - \else - \expandafter#1% - \fi {#3}#2}% -% -\def\POL@toexprA #1#2\POL@empty#3{% - \ifpoltoexprall\expandafter\POL@toexprall@b - \else\expandafter\POL@toexpr@b - \fi {#3}#2{0}1.% -}% -\def\POL@toexprD #1#2#3\relax{% #3 has \empty (\POL@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.% -}% - - -\POL@restorecatcodes \endinput diff --git a/Master/tlpkg/libexec/ctan2tds b/Master/tlpkg/libexec/ctan2tds index 76dba200a16..72e2dcbed4c 100755 --- a/Master/tlpkg/libexec/ctan2tds +++ b/Master/tlpkg/libexec/ctan2tds @@ -2130,6 +2130,7 @@ $standardtex 'plnfss', '\.tex|\.pfd', 'plstmary', '^stmary.tex', 'pmx', 'pmx\.tex|' . $standardtex, + 'polexpr', 'polexpr.*\.tex|' . $standardtex, 'poormanlog', 'poormanlog\.tex|' . $standardtex, 'poster-mac', 'poster\.tex|' . $standardtex, 'poetrytex', 'poetrytex\.sty$', # not -style |