diff options
Diffstat (limited to 'Master')
-rw-r--r-- | Master/texmf-dist/doc/latex/polexpr/README.md | 4 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/polexpr/polexpr.html | 1271 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/polexpr/polexpr.txt | 813 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/polexpr/polexpr.sty | 1168 |
4 files changed, 2365 insertions, 891 deletions
diff --git a/Master/texmf-dist/doc/latex/polexpr/README.md b/Master/texmf-dist/doc/latex/polexpr/README.md index 405f832ae75..d0275013301 100644 --- a/Master/texmf-dist/doc/latex/polexpr/README.md +++ b/Master/texmf-dist/doc/latex/polexpr/README.md @@ -73,8 +73,10 @@ Releases The `'` character can be used in polynomial names. - 0.6 (2018/11/20) New feature: multiplicity of roots. +- 0.7 (2018/12/08) + New feature: finding all rational roots. -Files of 0.6 release: +Files of 0.7 release: - README.md, - polexpr.sty (package file), diff --git a/Master/texmf-dist/doc/latex/polexpr/polexpr.html b/Master/texmf-dist/doc/latex/polexpr/polexpr.html index 5408f16b65e..71e7ef3d019 100644 --- a/Master/texmf-dist/doc/latex/polexpr/polexpr.html +++ b/Master/texmf-dist/doc/latex/polexpr/polexpr.html @@ -362,137 +362,160 @@ ul.auto-toc { <body> <div class="document" id="package-polexpr-documentation"> <h1 class="title">Package polexpr documentation</h1> -<h2 class="subtitle" id="id1">0.6 (2018/11/20)</h2> +<h2 class="subtitle" id="id1">0.7 (2018/12/08)</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-examples" id="id36">Basic Examples</a></li> -<li><a class="reference internal" href="#examples-of-localization-of-roots" id="id37">Examples of localization of roots</a><ul> -<li><a class="reference internal" href="#a-typical-example" id="id38">A typical example</a></li> -<li><a class="reference internal" href="#a-degree-four-polynomial-with-nearby-roots" id="id39">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="id40">The degree nine polynomial with 0.99, 0.999, 0.9999 as triple roots</a></li> -<li><a class="reference internal" href="#a-mignotte-type-polynomial" id="id41">A Mignotte type 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="id42">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="id43">Roots of Chebyshev polynomials</a></li> +<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-degree-41-polynomial-with-2-1-9-1-8-0-0-1-1-9-2-as-roots" id="id46">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="id47">Roots of Chebyshev polynomials</a></li> </ul> </li> -<li><a class="reference internal" href="#non-expandable-macros" id="id44">Non-expandable macros</a><ul> -<li><a class="reference internal" href="#poldef-polname-letter-expression-in-letter" id="id45"><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="id46"><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="id47"><tt class="docutils literal">\PolGenFloatVariant{polname}</tt></a></li> -<li><a class="reference internal" href="#pollet-polname-2-polname-1" id="id48"><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="id49"><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="id50"><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="id51"><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="id52"><tt class="docutils literal"><span class="pre">\PolFromCSV{polname}{<csv>}</span></tt></a></li> -<li><a class="reference internal" href="#poltypeset-polname" id="id53"><tt class="docutils literal">\PolTypeset{polname}</tt></a><ul> -<li><a class="reference internal" href="#poltypesetcmd-raw-coeff" id="id54"><tt class="docutils literal">\PolTypesetCmd{raw_coeff}</tt></a></li> -<li><a class="reference internal" href="#poltypesetone-raw-coeff" id="id55"><tt class="docutils literal">\PolTypesetOne{raw_coeff}</tt></a></li> -<li><a class="reference internal" href="#id6" id="id56"><tt class="docutils literal">\PolTypesetMonomialCmd</tt></a></li> -<li><a class="reference internal" href="#poltypesetcmdprefix-raw-coeff" id="id57"><tt class="docutils literal">\PolTypesetCmdPrefix{raw_coeff}</tt></a></li> +<li><a class="reference internal" href="#non-expandable-macros" id="id48">Non-expandable macros</a><ul> +<li><a class="reference internal" href="#poldef-polname-letter-expression-in-letter" id="id49"><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="id50"><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="id51"><tt class="docutils literal">\PolGenFloatVariant{polname}</tt></a></li> +<li><a class="reference internal" href="#pollet-polname-2-polname-1" id="id52"><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="id53"><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="id54"><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="id55"><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="id56"><tt class="docutils literal"><span class="pre">\PolFromCSV{polname}{<csv>}</span></tt></a></li> +<li><a class="reference internal" href="#poltypeset-polname" id="id57"><tt class="docutils literal">\PolTypeset{polname}</tt></a><ul> +<li><a class="reference internal" href="#poltypesetcmd-raw-coeff" id="id58"><tt class="docutils literal">\PolTypesetCmd{raw_coeff}</tt></a></li> +<li><a class="reference internal" href="#poltypesetone-raw-coeff" id="id59"><tt class="docutils literal">\PolTypesetOne{raw_coeff}</tt></a></li> +<li><a class="reference internal" href="#id6" id="id60"><tt class="docutils literal">\PolTypesetMonomialCmd</tt></a></li> +<li><a class="reference internal" href="#poltypesetcmdprefix-raw-coeff" id="id61"><tt class="docutils literal">\PolTypesetCmdPrefix{raw_coeff}</tt></a></li> </ul> </li> -<li><a class="reference internal" href="#id8" id="id58"><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="id59"><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="id60"><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="id61"><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="id62"><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="id63"><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="id64"><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="id65"><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="id66"><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="id67"><tt class="docutils literal"><span class="pre">\PolToSturm{polname}{sturmname}</span></tt></a></li> -<li><a class="reference internal" href="#id10" id="id68"><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="id69"><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="id70"><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="id71"><tt class="docutils literal">\PolSturmIsolateZeros{sturmname}</tt></a></li> -<li><a class="reference internal" href="#id12" id="id72"><tt class="docutils literal"><span class="pre">\PolSturmIsolateZeros*{sturmname}</span></tt></a></li> -<li><a class="reference internal" href="#polsturmisolatezerosandgetmultiplicities-sturmname" id="id73"><tt class="docutils literal">\PolSturmIsolateZerosAndGetMultiplicities{sturmname}</tt></a></li> -<li><a class="reference internal" href="#polrefineinterval-sturmname-index" id="id74"><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="id75"><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="id76"><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="id77"><tt class="docutils literal"><span class="pre">\PolEnsureIntervalLengths{sturmname}{E}</span></tt></a></li> -<li><a class="reference internal" href="#polprintintervals-varname-sturmname" id="id78"><tt class="docutils literal"><span class="pre">\PolPrintIntervals[varname]{sturmname}</span></tt></a><ul> -<li><a class="reference internal" href="#id13" id="id79"><tt class="docutils literal">\PolPrintIntervalsPrintExactZero</tt></a></li> -<li><a class="reference internal" href="#id14" id="id80"><tt class="docutils literal">\PolPrintIntervalsPrintLeftEndPoint</tt></a></li> -<li><a class="reference internal" href="#id15" id="id81"><tt class="docutils literal">\PolPrintIntervalsPrintRightEndPoint</tt></a></li> +<li><a class="reference internal" href="#id8" id="id62"><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="id63"><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="id64"><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="id65"><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="id66"><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="id67"><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="id68"><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="id69"><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="id70"><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="id71"><tt class="docutils literal"><span class="pre">\PolToSturm{polname}{sturmname}</span></tt></a></li> +<li><a class="reference internal" href="#id10" id="id72"><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="id73"><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="id74"><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="id75"><tt class="docutils literal">\PolSturmIsolateZeros{sturmname}</tt></a></li> +<li><a class="reference internal" href="#id12" id="id76"><tt class="docutils literal"><span class="pre">\PolSturmIsolateZeros*{sturmname}</span></tt></a></li> +<li><a class="reference internal" href="#id14" id="id77"><tt class="docutils literal"><span class="pre">\PolSturmIsolateZeros**{sturmname}</span></tt></a></li> +<li><a class="reference internal" href="#polsturmisolatezerosandgetmultiplicities-sturmname" id="id78"><tt class="docutils literal">\PolSturmIsolateZerosAndGetMultiplicities{sturmname}</tt></a></li> +<li><a class="reference internal" href="#polsturmisolatezerosgetmultiplicitiesandrationalroots-sturmname" id="id79"><tt class="docutils literal">\PolSturmIsolateZerosGetMultiplicitiesAndRationalRoots{sturmname}</tt></a></li> +<li><a class="reference internal" href="#polsturmisolatezerosandfindrationalroots-sturmname" id="id80"><tt class="docutils literal">\PolSturmIsolateZerosAndFindRationalRoots{sturmname}</tt></a></li> +<li><a class="reference internal" href="#polrefineinterval-sturmname-index" id="id81"><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="id82"><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="id83"><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="id84"><tt class="docutils literal"><span class="pre">\PolEnsureIntervalLengths{sturmname}{E}</span></tt></a></li> +<li><a class="reference internal" href="#polprintintervals-varname-sturmname" id="id85"><tt class="docutils literal"><span class="pre">\PolPrintIntervals[varname]{sturmname}</span></tt></a><ul> +<li><a class="reference internal" href="#polprintintervalsnorealroots" id="id86"><tt class="docutils literal">\PolPrintIntervalsNoRealRoots</tt></a></li> +<li><a class="reference internal" href="#polprintintervalsbeginenv" id="id87"><tt class="docutils literal">\PolPrintIntervalsBeginEnv</tt></a></li> +<li><a class="reference internal" href="#polprintintervalsendenv" id="id88"><tt class="docutils literal">\PolPrintIntervalsEndEnv</tt></a></li> +<li><a class="reference internal" href="#polprintintervalsknownroot" id="id89"><tt class="docutils literal">\PolPrintIntervalsKnownRoot</tt></a></li> +<li><a class="reference internal" href="#polprintintervalsunknownroot" id="id90"><tt class="docutils literal">\PolPrintIntervalsUnknownRoot</tt></a></li> +<li><a class="reference internal" href="#id15" id="id91"><tt class="docutils literal">\PolPrintIntervalsPrintExactZero</tt></a></li> +<li><a class="reference internal" href="#id16" id="id92"><tt class="docutils literal">\PolPrintIntervalsPrintLeftEndPoint</tt></a></li> +<li><a class="reference internal" href="#id17" id="id93"><tt class="docutils literal">\PolPrintIntervalsPrintRightEndPoint</tt></a></li> </ul> </li> -<li><a class="reference internal" href="#polmapcoeffs-macro-polname" id="id82"><tt class="docutils literal"><span class="pre">\PolMapCoeffs{\macro}{polname}</span></tt></a></li> -<li><a class="reference internal" href="#polreducecoeffs-polname" id="id83"><tt class="docutils literal">\PolReduceCoeffs{polname}</tt></a></li> -<li><a class="reference internal" href="#id17" id="id84"><tt class="docutils literal"><span class="pre">\PolReduceCoeffs*{polname}</span></tt></a></li> -<li><a class="reference internal" href="#polmakemonic-polname" id="id85"><tt class="docutils literal">\PolMakeMonic{polname}</tt></a></li> -<li><a class="reference internal" href="#polmakeprimitive-polname" id="id86"><tt class="docutils literal">\PolMakePrimitive{polname}</tt></a></li> +<li><a class="reference internal" href="#id19" id="id94"><tt class="docutils literal"><span class="pre">\PolPrintIntervals*[varname]{sturmname}</span></tt></a><ul> +<li><a class="reference internal" href="#polprintintervalsprintmultiplicity" id="id95"><tt class="docutils literal">\PolPrintIntervalsPrintMultiplicity</tt></a></li> </ul> </li> -<li><a class="reference internal" href="#expandable-macros" id="id87">Expandable macros</a><ul> -<li><a class="reference internal" href="#poleval-polname-atexpr-numerical-expression" id="id88"><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="id89"><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="id90"><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="id91"><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="id92"><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="id93"><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="id94"><tt class="docutils literal"><span class="pre">\PolIfCoeffIsPlusOrMinusOne{A}{B}</span></tt></a></li> -<li><a class="reference internal" href="#polleadingcoeff-polname" id="id95"><tt class="docutils literal">\PolLeadingCoeff{polname}</tt></a></li> -<li><a class="reference internal" href="#polnthcoeff-polname-number" id="id96"><tt class="docutils literal"><span class="pre">\PolNthCoeff{polname}{number}</span></tt></a></li> -<li><a class="reference internal" href="#poldegree-polname" id="id97"><tt class="docutils literal">\PolDegree{polname}</tt></a></li> -<li><a class="reference internal" href="#policontent-polname" id="id98"><tt class="docutils literal">\PolIContent{polname}</tt></a></li> -<li><a class="reference internal" href="#poltoexpr-polname" id="id99"><tt class="docutils literal">\PolToExpr{polname}</tt></a><ul> -<li><a class="reference internal" href="#poltoexproneterm-raw-coeff-number" id="id100"><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="id101"><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="id102"><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="id103"><tt class="docutils literal">\PolToExprCmd{raw_coeff}</tt></a></li> -<li><a class="reference internal" href="#poltoexprtermprefix-raw-coeff" id="id104"><tt class="docutils literal">\PolToExprTermPrefix{raw_coeff}</tt></a></li> -<li><a class="reference internal" href="#id24" id="id105"><tt class="docutils literal">\PolToExprVar</tt></a></li> -<li><a class="reference internal" href="#id25" id="id106"><tt class="docutils literal">\PolToExprTimes</tt></a></li> +<li><a class="reference internal" href="#polmapcoeffs-macro-polname" id="id96"><tt class="docutils literal"><span class="pre">\PolMapCoeffs{\macro}{polname}</span></tt></a></li> +<li><a class="reference internal" href="#polreducecoeffs-polname" id="id97"><tt class="docutils literal">\PolReduceCoeffs{polname}</tt></a></li> +<li><a class="reference internal" href="#id21" id="id98"><tt class="docutils literal"><span class="pre">\PolReduceCoeffs*{polname}</span></tt></a></li> +<li><a class="reference internal" href="#polmakemonic-polname" id="id99"><tt class="docutils literal">\PolMakeMonic{polname}</tt></a></li> +<li><a class="reference internal" href="#polmakeprimitive-polname" id="id100"><tt class="docutils literal">\PolMakePrimitive{polname}</tt></a></li> </ul> </li> -<li><a class="reference internal" href="#id27" id="id107"><tt class="docutils literal"><span class="pre">\PolToExpr*{polname}</span></tt></a></li> -<li><a class="reference internal" href="#poltofloatexpr-polname" id="id108"><tt class="docutils literal">\PolToFloatExpr{polname}</tt></a><ul> -<li><a class="reference internal" href="#poltofloatexproneterm-raw-coeff-number" id="id109"><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="id110"><tt class="docutils literal">\PolToFloatExprCmd{raw_coeff}</tt></a></li> +<li><a class="reference internal" href="#expandable-macros" id="id101">Expandable macros</a><ul> +<li><a class="reference internal" href="#poleval-polname-atexpr-numerical-expression" id="id102"><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="id103"><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="id104"><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="id105"><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="id106"><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="id107"><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="id108"><tt class="docutils literal"><span class="pre">\PolIfCoeffIsPlusOrMinusOne{A}{B}</span></tt></a></li> +<li><a class="reference internal" href="#polleadingcoeff-polname" id="id109"><tt class="docutils literal">\PolLeadingCoeff{polname}</tt></a></li> +<li><a class="reference internal" href="#polnthcoeff-polname-number" id="id110"><tt class="docutils literal"><span class="pre">\PolNthCoeff{polname}{number}</span></tt></a></li> +<li><a class="reference internal" href="#poldegree-polname" id="id111"><tt class="docutils literal">\PolDegree{polname}</tt></a></li> +<li><a class="reference internal" href="#policontent-polname" id="id112"><tt class="docutils literal">\PolIContent{polname}</tt></a></li> +<li><a class="reference internal" href="#poltoexpr-polname" id="id113"><tt class="docutils literal">\PolToExpr{polname}</tt></a><ul> +<li><a class="reference internal" href="#poltoexproneterm-raw-coeff-number" id="id114"><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="id115"><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="id116"><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="id117"><tt class="docutils literal">\PolToExprCmd{raw_coeff}</tt></a></li> +<li><a class="reference internal" href="#poltoexprtermprefix-raw-coeff" id="id118"><tt class="docutils literal">\PolToExprTermPrefix{raw_coeff}</tt></a></li> +<li><a class="reference internal" href="#id28" id="id119"><tt class="docutils literal">\PolToExprVar</tt></a></li> +<li><a class="reference internal" href="#id29" id="id120"><tt class="docutils literal">\PolToExprTimes</tt></a></li> </ul> </li> -<li><a class="reference internal" href="#id31" id="id111"><tt class="docutils literal"><span class="pre">\PolToFloatExpr*{polname}</span></tt></a></li> -<li><a class="reference internal" href="#poltolist-polname" id="id112"><tt class="docutils literal">\PolToList{polname}</tt></a></li> -<li><a class="reference internal" href="#poltocsv-polname" id="id113"><tt class="docutils literal">\PolToCSV{polname}</tt></a></li> -<li><a class="reference internal" href="#polsturmchainlength-sturmname" id="id114"><tt class="docutils literal">\PolSturmChainLength{sturmname}</tt></a></li> -<li><a class="reference internal" href="#polsturmifzeroexactlyknown-sturmname-index-a-b" id="id115"><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="id116"><tt class="docutils literal"><span class="pre">\PolSturmIsolatedZeroLeft{sturmname}{index}</span></tt></a></li> -<li><a class="reference internal" href="#polsturmisolatedzeroright-sturmname-index" id="id117"><tt class="docutils literal"><span class="pre">\PolSturmIsolatedZeroRight{sturmname}{index}</span></tt></a></li> -<li><a class="reference internal" href="#polsturmisolatedzeromultiplicity-sturmname-index" id="id118"><tt class="docutils literal"><span class="pre">\PolSturmIsolatedZeroMultiplicity{sturmname}{index}</span></tt></a></li> -<li><a class="reference internal" href="#polsturmnbofisolatedzeros-sturmname" id="id119"><tt class="docutils literal">\PolSturmNbOfIsolatedZeros{sturmname}</tt></a></li> -<li><a class="reference internal" href="#polsturmnbofrootsof-sturmname-lessthanorequalto-value" id="id120"><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="id121"><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="id122"><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="id123"><tt class="docutils literal"><span class="pre">\PolSturmNbWithMultOfRootsOf{sturmname}\LessThanOrEqualToExpr{expression}</span></tt></a></li> -<li><a class="reference internal" href="#polintervalwidth-sturmname-index" id="id124"><tt class="docutils literal"><span class="pre">\PolIntervalWidth{sturmname}{index}</span></tt></a></li> -<li><a class="reference internal" href="#macros-for-use-within-execution-of-polprintintervals" id="id125">Macros for use within execution of <tt class="docutils literal">\PolPrintIntervals</tt></a><ul> -<li><a class="reference internal" href="#id32" id="id126"><tt class="docutils literal">\PolPrintIntervalsTheEndPoint</tt></a></li> -<li><a class="reference internal" href="#id33" id="id127"><tt class="docutils literal">\PolPrintIntervalsTheIndex</tt></a></li> -<li><a class="reference internal" href="#polifendpointispositive-a-b" id="id128"><tt class="docutils literal"><span class="pre">\PolIfEndPointIsPositive{A}{B}</span></tt></a></li> -<li><a class="reference internal" href="#polifendpointisnegative-a-b" id="id129"><tt class="docutils literal"><span class="pre">\PolIfEndPointIsNegative{A}{B}</span></tt></a></li> -<li><a class="reference internal" href="#polifendpointiszero-a-b" id="id130"><tt class="docutils literal"><span class="pre">\PolIfEndPointIsZero{A}{B}</span></tt></a></li> +<li><a class="reference internal" href="#id31" id="id121"><tt class="docutils literal"><span class="pre">\PolToExpr*{polname}</span></tt></a></li> +<li><a class="reference internal" href="#poltofloatexpr-polname" id="id122"><tt class="docutils literal">\PolToFloatExpr{polname}</tt></a><ul> +<li><a class="reference internal" href="#poltofloatexproneterm-raw-coeff-number" id="id123"><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="id124"><tt class="docutils literal">\PolToFloatExprCmd{raw_coeff}</tt></a></li> </ul> </li> -<li><a class="reference internal" href="#poldectostring-decimal-number" id="id131"><tt class="docutils literal">\PolDecToString{decimal number}</tt></a></li> +<li><a class="reference internal" href="#id35" id="id125"><tt class="docutils literal"><span class="pre">\PolToFloatExpr*{polname}</span></tt></a></li> +<li><a class="reference internal" href="#poltolist-polname" id="id126"><tt class="docutils literal">\PolToList{polname}</tt></a></li> +<li><a class="reference internal" href="#poltocsv-polname" id="id127"><tt class="docutils literal">\PolToCSV{polname}</tt></a></li> +<li><a class="reference internal" href="#polsturmchainlength-sturmname" id="id128"><tt class="docutils literal">\PolSturmChainLength{sturmname}</tt></a></li> +<li><a class="reference internal" href="#polsturmifzeroexactlyknown-sturmname-index-a-b" id="id129"><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="id130"><tt class="docutils literal"><span class="pre">\PolSturmIsolatedZeroLeft{sturmname}{index}</span></tt></a></li> +<li><a class="reference internal" href="#polsturmisolatedzeroright-sturmname-index" id="id131"><tt class="docutils literal"><span class="pre">\PolSturmIsolatedZeroRight{sturmname}{index}</span></tt></a></li> +<li><a class="reference internal" href="#polsturmisolatedzeromultiplicity-sturmname-index" id="id132"><tt class="docutils literal"><span class="pre">\PolSturmIsolatedZeroMultiplicity{sturmname}{index}</span></tt></a></li> +<li><a class="reference internal" href="#polsturmnbofisolatedzeros-sturmname" id="id133"><tt class="docutils literal">\PolSturmNbOfIsolatedZeros{sturmname}</tt></a><ul> +<li><a class="reference internal" href="#polsturmnbofrootsof-sturmname-lessthanorequalto-value" id="id134"><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="id135"><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="id136"><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="id137"><tt class="docutils literal"><span class="pre">\PolSturmNbWithMultOfRootsOf{sturmname}\LessThanOrEqualToExpr{expression}</span></tt></a></li> </ul> </li> -<li><a class="reference internal" href="#booleans-with-default-setting-as-indicated" id="id132">Booleans (with default setting as indicated)</a><ul> -<li><a class="reference internal" href="#xintverbosefalse" id="id133"><tt class="docutils literal">\xintverbosefalse</tt></a></li> -<li><a class="reference internal" href="#poltypesetallfalse" id="id134"><tt class="docutils literal">\poltypesetallfalse</tt></a></li> -<li><a class="reference internal" href="#poltoexprallfalse" id="id135"><tt class="docutils literal">\poltoexprallfalse</tt></a></li> +<li><a class="reference internal" href="#polsturmnbofrationalroots-sturmname" id="id138"><tt class="docutils literal">\PolSturmNbOfRationalRoots{sturmname}</tt></a></li> +<li><a class="reference internal" href="#polsturmnbofrationalrootswithmultiplicities-sturmname" id="id139"><tt class="docutils literal">\PolSturmNbOfRationalRootsWithMultiplicities{sturmname}</tt></a></li> +<li><a class="reference internal" href="#polsturmrationalroot-sturmname-k" id="id140"><tt class="docutils literal"><span class="pre">\PolSturmRationalRoot{sturmname}{k}</span></tt></a></li> +<li><a class="reference internal" href="#polsturmrationalrootindex-sturmname-k" id="id141"><tt class="docutils literal"><span class="pre">\PolSturmRationalRootIndex{sturmname}{k}</span></tt></a></li> +<li><a class="reference internal" href="#polsturmrationalrootmultiplicity-sturmname-k" id="id142"><tt class="docutils literal"><span class="pre">\PolSturmRationalRootMultiplicity{sturmname}{k}</span></tt></a></li> +<li><a class="reference internal" href="#polintervalwidth-sturmname-index" id="id143"><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="id144">Expandable macros for use within execution of <tt class="docutils literal">\PolPrintIntervals</tt></a><ul> +<li><a class="reference internal" href="#polprintintervalsthevar" id="id145"><tt class="docutils literal">\PolPrintIntervalsTheVar</tt></a></li> +<li><a class="reference internal" href="#polprintintervalstheindex" id="id146"><tt class="docutils literal">\PolPrintIntervalsTheIndex</tt></a></li> +<li><a class="reference internal" href="#polprintintervalsthesturmname" id="id147"><tt class="docutils literal">\PolPrintIntervalsTheSturmName</tt></a></li> +<li><a class="reference internal" href="#polprintintervalstheleftendpoint" id="id148"><tt class="docutils literal">\PolPrintIntervalsTheLeftEndPoint</tt></a></li> +<li><a class="reference internal" href="#polprintintervalstherightendpoint" id="id149"><tt class="docutils literal">\PolPrintIntervalsTheRightEndPoint</tt></a></li> +<li><a class="reference internal" href="#polprintintervalsthemultiplicity" id="id150"><tt class="docutils literal">\PolPrintIntervalsTheMultiplicity</tt></a></li> </ul> </li> -<li><a class="reference internal" href="#technicalities" id="id136">Technicalities</a></li> -<li><a class="reference internal" href="#change-log" id="id137">CHANGE LOG</a></li> -<li><a class="reference internal" href="#acknowledgments" id="id138">Acknowledgments</a></li> +<li><a class="reference internal" href="#poldectostring-decimal-number" id="id151"><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="id152">Booleans (with default setting as indicated)</a><ul> +<li><a class="reference internal" href="#xintverbosefalse" id="id153"><tt class="docutils literal">\xintverbosefalse</tt></a></li> +<li><a class="reference internal" href="#poltypesetallfalse" id="id154"><tt class="docutils literal">\poltypesetallfalse</tt></a></li> +<li><a class="reference internal" href="#poltoexprallfalse" id="id155"><tt class="docutils literal">\poltoexprallfalse</tt></a></li> +</ul> +</li> +<li><a class="reference internal" href="#polexprsetup" id="id156"><tt class="docutils literal">\polexprsetup</tt></a></li> +<li><a class="reference internal" href="#technicalities" id="id157">Technicalities</a></li> +<li><a class="reference internal" href="#change-log" id="id158">CHANGE LOG</a></li> +<li><a class="reference internal" href="#acknowledgments" id="id159">Acknowledgments</a></li> </ul> </div> -<div class="section" id="basic-examples"> -<h1><a class="toc-backref" href="#id36">Basic Examples</a></h1> +<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; @@ -613,7 +636,7 @@ PSTricks-compatible; the letter used in output can be </dl> </div> <div class="section" id="examples-of-localization-of-roots"> -<h1><a class="toc-backref" href="#id37">Examples of localization of roots</a></h1> +<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> @@ -632,17 +655,12 @@ that one can also do:</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">To make producing this documentation simpler, the results from execution -of the code snippets are not included. Please try them out yourself...</p> +<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="#id38">A typical example</a></h2> -<p>In this example the polynomial is square-free; we can make sure of that by -comparing the degree of the first element of the Sturm chain with the -degree of the original polynomial. In such case the second element of -the Sturm chain is still the polynomial first derivative, because there -was no further reduction.</p> +<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; @@ -658,11 +676,11 @@ 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 same as $\PolDegree{f}$ we know that the latter was square free. -So the derivative is up to a constant \PolTypeset{f_1} (in fact here +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}% -It has \PolSturmNbOfIsolatedZeros{f_1} distinct real +The derivative has \PolSturmNbOfIsolatedZeros{f_1} distinct real roots: \PolPrintIntervals[W]{f_1} \PolEnsureIntervalLengths{f_1}{-10}% @@ -683,7 +701,12 @@ 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="#id39">A degree four polynomial with nearby roots</a></h2> +<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} @@ -706,7 +729,7 @@ to give the exact value for $X_2$! </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="#id40">The degree nine polynomial with 0.99, 0.999, 0.9999 as triple roots</a></h2> +<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" @@ -738,10 +761,10 @@ 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. But multiplicity -computation works also with (decimal) roots not yet identified or with -non-decimal or irrational roots.</p> -<p>Try it out!</p> +<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"> @@ -776,10 +799,49 @@ The multiplicity is 1 for the root such that 0.9899888032 < x < 0.98998880 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> -<p>Try obtaining this with your pocket calculator! (or IEEE-7554 numerics...)</p> +</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="#id41">A Mignotte type polynomial</a></h2> +<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 @@ -805,8 +867,89 @@ Finally, we display 20 digits of the second root: 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-degree-41-polynomial-with-2-1-9-1-8-0-0-1-1-9-2-as-roots"> -<h2><a class="toc-backref" href="#id42">The degree 41 polynomial with -2, -1.9, -1.8, ..., 0, 0.1, ..., 1.9, 2 as roots</a></h2> +<h2><a class="toc-backref" href="#id46">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> @@ -845,26 +988,26 @@ x^41 <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 experimental addition of optional argument +<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>, extremities assumed to not be roots. -Thus here:</p> -<pre class="literal-block"> -\PolSturmIsolateZeros[1]{S} -</pre> -<p>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">This will probably get replaced in future by the specification of -a general interval.</p> +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="#id43">Roots of Chebyshev polynomials</a></h2> +<h2><a class="toc-backref" href="#id47">Roots of Chebyshev polynomials</a></h2> <pre class="literal-block"> \newcount\mycount \poldef T_0(x) := 1; @@ -887,9 +1030,9 @@ a general interval.</p> </div> </div> <div class="section" id="non-expandable-macros"> -<h1><a class="toc-backref" href="#id44">Non-expandable macros</a></h1> +<h1><a class="toc-backref" href="#id48">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="#id45"><tt class="docutils literal">\poldef <span class="pre">polname(letter):=</span> expression in letter;</tt></a></h2> +<span id="poldef"></span><h2><a class="toc-backref" href="#id49"><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, @@ -926,7 +1069,7 @@ 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="#id46"><tt class="docutils literal"><span class="pre">\PolDef[letter]{polname}{expression</span> in letter}</tt></a></h2> +<span id="id2"></span><h2><a class="toc-backref" href="#id50"><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 @@ -934,7 +1077,7 @@ 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="#id47"><tt class="docutils literal">\PolGenFloatVariant{polname}</tt></a></h2> +<span id="polgenfloatvariant"></span><h2><a class="toc-backref" href="#id51"><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 @@ -953,7 +1096,7 @@ context.</p> </blockquote> </div> <div class="section" id="pollet-polname-2-polname-1"> -<span id="pollet"></span><h2><a class="toc-backref" href="#id48"><tt class="docutils literal"><span class="pre">\PolLet{polname_2}={polname_1}</span></tt></a></h2> +<span id="pollet"></span><h2><a class="toc-backref" href="#id52"><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 @@ -961,12 +1104,12 @@ new one <tt class="docutils literal">polname_2</tt>. Same effect as <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="#id49"><tt class="docutils literal"><span class="pre">\PolGlobalLet{polname_2}={polname_1}</span></tt></a></h2> +<span id="polgloballet"></span><h2><a class="toc-backref" href="#id53"><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="#id50"><tt class="docutils literal"><span class="pre">\PolAssign{polname}\toarray\macro</span></tt></a></h2> +<span id="polassign"></span><h2><a class="toc-backref" href="#id54"><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> @@ -989,7 +1132,7 @@ 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="#id51"><tt class="docutils literal"><span class="pre">\PolGet{polname}\fromarray\macro</span></tt></a></h2> +<span id="polget"></span><h2><a class="toc-backref" href="#id55"><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 @@ -1010,19 +1153,19 @@ via <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</ </blockquote> </div> <div class="section" id="polfromcsv-polname-csv"> -<span id="polfromcsv"></span><h2><a class="toc-backref" href="#id52"><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 constant term being the first item. No validity checks. Spaces -from the list argument are trimmed. 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>Leading zero coefficients are removed:</p> +<span id="polfromcsv"></span><h2><a class="toc-backref" href="#id56"><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 has only one (zero) coefficient.</p> +<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> @@ -1032,7 +1175,7 @@ macro <tt class="docutils literal">\xintRaw</tt>.</p> </blockquote> </div> <div class="section" id="poltypeset-polname"> -<span id="poltypeset"></span><h2><a class="toc-backref" href="#id53"><tt class="docutils literal">\PolTypeset{polname}</tt></a></h2> +<span id="poltypeset"></span><h2><a class="toc-backref" href="#id57"><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> @@ -1046,7 +1189,7 @@ 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="#id54"><tt class="docutils literal">\PolTypesetCmd{raw_coeff}</tt></a></h3> +<span id="poltypesetcmd"></span><h3><a class="toc-backref" href="#id58"><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 @@ -1056,7 +1199,7 @@ minus one is handled by <a class="reference internal" href="#poltypesetone-raw-c </blockquote> </div> <div class="section" id="poltypesetone-raw-coeff"> -<span id="poltypesetone"></span><h3><a class="toc-backref" href="#id55"><tt class="docutils literal">\PolTypesetOne{raw_coeff}</tt></a></h3> +<span id="poltypesetone"></span><h3><a class="toc-backref" href="#id59"><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> @@ -1081,7 +1224,7 @@ 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="#id56"><tt class="docutils literal">\PolTypesetMonomialCmd</tt></a></h3> +<span id="poltypesetmonomialcmd"></span><h3><a class="toc-backref" href="#id60"><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 @@ -1091,7 +1234,7 @@ for the constant term, <tt class="docutils literal">\PolVar</tt> for the first d <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="#id57"><tt class="docutils literal">\PolTypesetCmdPrefix{raw_coeff}</tt></a></h3> +<span id="poltypesetcmdprefix"></span><h3><a class="toc-backref" href="#id61"><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 @@ -1102,13 +1245,13 @@ for the first term.</blockquote> </div> </div> <div class="section" id="id8"> -<span id="id7"></span><h2><a class="toc-backref" href="#id58"><tt class="docutils literal"><span class="pre">\PolTypeset*{polname}</span></tt></a></h2> +<span id="id7"></span><h2><a class="toc-backref" href="#id62"><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="#id59"><tt class="docutils literal"><span class="pre">\PolDiff{polname_1}{polname_2}</span></tt></a></h2> +<span id="poldiff"></span><h2><a class="toc-backref" href="#id63"><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> @@ -1118,7 +1261,7 @@ by <tt class="docutils literal">f'</tt>.</p> </blockquote> </div> <div class="section" id="poldiff-n-polname-1-polname-2"> -<span id="poldiff-n"></span><h2><a class="toc-backref" href="#id60"><tt class="docutils literal"><span class="pre">\PolDiff[N]{polname_1}{polname_2}</span></tt></a></h2> +<span id="poldiff-n"></span><h2><a class="toc-backref" href="#id64"><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 @@ -1126,7 +1269,7 @@ Identical arguments is allowed. With <tt class="docutils literal">N=0</tt>, same 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="#id61"><tt class="docutils literal"><span class="pre">\PolAntiDiff{polname_1}{polname_2}</span></tt></a></h2> +<span id="polantidiff"></span><h2><a class="toc-backref" href="#id65"><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> @@ -1135,32 +1278,32 @@ at zero.</p> </blockquote> </div> <div class="section" id="polantidiff-n-polname-1-polname-2"> -<span id="polantidiff-n"></span><h2><a class="toc-backref" href="#id62"><tt class="docutils literal"><span class="pre">\PolAntiDiff[N]{polname_1}{polname_2}</span></tt></a></h2> +<span id="polantidiff-n"></span><h2><a class="toc-backref" href="#id66"><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="#id63"><tt class="docutils literal"><span class="pre">\PolDivide{polname_1}{polname_2}{polname_Q}{polname_R}</span></tt></a></h2> +<span id="poldivide"></span><h2><a class="toc-backref" href="#id67"><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="#id64"><tt class="docutils literal"><span class="pre">\PolQuo{polname_1}{polname_2}{polname_Q}</span></tt></a></h2> +<span id="polquo"></span><h2><a class="toc-backref" href="#id68"><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="#id65"><tt class="docutils literal"><span class="pre">\PolRem{polname_1}{polname_2}{polname_R}</span></tt></a></h2> +<span id="polrem"></span><h2><a class="toc-backref" href="#id69"><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="#id66"><tt class="docutils literal"><span class="pre">\PolGCD{polname_1}{polname_2}{polname_GCD}</span></tt></a></h2> +<span id="polgcd"></span><h2><a class="toc-backref" href="#id70"><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> @@ -1186,7 +1329,7 @@ polynomial.</blockquote> no common factor among the coefficients. --> </div> <div class="section" id="poltosturm-polname-sturmname"> -<span id="poltosturm"></span><h2><a class="toc-backref" href="#id67"><tt class="docutils literal"><span class="pre">\PolToSturm{polname}{sturmname}</span></tt></a></h2> +<span id="poltosturm"></span><h2><a class="toc-backref" href="#id71"><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 @@ -1219,19 +1362,22 @@ not done if this last one is the constant <tt class="docutils literal">1</tt> or 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.</p> +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>These polynomials <tt class="docutils literal">sturmname_k</tt> (contrarily to the -<tt class="docutils literal">sturmname_k_</tt> ones) are usable after the macro execution but -their main utility is for the execution of -<a class="reference internal" href="#polsturmisolatezeros-sturmname">\PolSturmIsolateZeros{sturmname}</a>.</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> and +before executing <span class="pre">``\PolSturmIsolateZeros{sturmname}</span></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="#id68"><tt class="docutils literal"><span class="pre">\PolToSturm*{polname}{sturmname}</span></tt></a></h2> +<span id="id9"></span><h2><a class="toc-backref" href="#id72"><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 @@ -1242,10 +1388,20 @@ polynomials <tt class="docutils literal">sturmname_k_</tt>, <tt class="docutils <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="#id69"><tt class="docutils literal"><span class="pre">\PolSetToSturmChainSignChangesAt{\macro}{sturmname}{fraction}</span></tt></a></h2> +<span id="polsettosturmchainsignchangesat"></span><h2><a class="toc-backref" href="#id73"><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> @@ -1262,7 +1418,7 @@ use <tt class="docutils literal">[\empty]</tt> as extra optional argument.</p> </blockquote> </div> <div class="section" id="polsettonbofzeroswithin-macro-sturmname-value-a-value-b"> -<span id="polsettonbofzeroswithin"></span><h2><a class="toc-backref" href="#id70"><tt class="docutils literal"><span class="pre">\PolSetToNbOfZerosWithin{\macro}{sturmname}{value_a}{value_b}</span></tt></a></h2> +<span id="polsettonbofzeroswithin"></span><h2><a class="toc-backref" href="#id74"><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, @@ -1291,12 +1447,12 @@ which requires prior execution of </blockquote> </div> <div class="section" id="polsturmisolatezeros-sturmname"> -<span id="polsturmisolatezeros"></span><h2><a class="toc-backref" href="#id71"><tt class="docutils literal">\PolSturmIsolateZeros{sturmname}</tt></a></h2> +<span id="polsturmisolatezeros"></span><h2><a class="toc-backref" href="#id75"><tt class="docutils literal">\PolSturmIsolateZeros{sturmname}</tt></a></h2> <blockquote> -<p>First, it evaluates using <a class="reference external" href="https://en.wikipedia.org/wiki/Sturm%27s_theorem">Sturm theorem</a> the number of distinct -real roots of <tt class="docutils literal">sturmname_0</tt>.</p> -<div class="admonition note"> -<p class="first admonition-title">Note</p> +<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, @@ -1311,47 +1467,63 @@ polynomials <tt class="docutils literal">f_0</tt>, <tt class="docutils literal"> 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>Then it locates, again using <a class="reference external" href="https://en.wikipedia.org/wiki/Sturm%27s_theorem">Sturm theorem</a>, as many disjoint -intervals as there are roots. Some intervals reduce to singleton -which are roots. Non-singleton intervals get refined to make sure -none of their two limit points is a root: they contain each a single -root, in their respective interiors.</p> -<!-- This procedure is covariant -with the independent variable ``x`` becoming ``-x``. -Hmm, pas sûr et trop fatigué --> +<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>; if zero is a root it is always -identified individually. The non-singleton intervals are of the +<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 <tt class="docutils literal">a</tt> and <tt class="docutils literal">a+1</tt> are both positive -or both negative.</p> +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>Also two macro arrays (in the sense of -<a class="reference external" href="http://www.ctan.org/pkg/xint">xinttools</a>'s <tt class="docutils literal">\xintAssignArray</tt>) are created for holding the -interval end-points written out in standard decimal notation -(see <a class="reference internal" href="#poldectostring-decimal-number">\PolDecToString{decimal number}</a>). -To access these values, 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.</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 these stored decimal numbers are significant: -they are also present in the decimal expansion of the exact root.</p> -</div> -<div class="admonition note"> -<p class="first admonition-title">Note</p> -<p class="last">The actual array macros are <tt class="docutils literal">\POL_ZeroInt<sturmname>L</tt> and -<tt class="docutils literal">\POL_ZeroInt<sturmname>R</tt> but as these names use the -non-letter character <tt class="docutils literal">_</tt> and possibly also digits from -<tt class="docutils literal">sturmname</tt>, the accessor macros above have been made part of -the package.</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 @@ -1359,24 +1531,19 @@ 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-lessthanorequalto-value">\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualTo{value}</a> and <a class="reference internal" href="#polsturmnbofrootsof-sturmname-lessthanorequaltoexpr-expression">\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualToExpr{expression}</a>. -will expandably act as their names indicate.</p> +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 <tt class="docutils literal"><span class="pre"><sturmname>...</span></tt> <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> variables -and the <tt class="docutils literal"><span class="pre">\POL_ZeroInt...</span></tt> arrays are globally defined. On the +<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 class="last">When two successive roots are located in adjacent intervals, the -separation between them is not lower bounded. See -<a class="reference internal" href="#polrefineinterval-sturmname-index">\PolRefineInterval*{sturmname}{index}</a>.</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> @@ -1390,7 +1557,7 @@ are studied in numerical mathematics.</p> </blockquote> </div> <div class="section" id="id12"> -<span id="id11"></span><h2><a class="toc-backref" href="#id72"><tt class="docutils literal"><span class="pre">\PolSturmIsolateZeros*{sturmname}</span></tt></a></h2> +<span id="id11"></span><h2><a class="toc-backref" href="#id76"><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 @@ -1400,9 +1567,9 @@ after executing this macro, 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>Also, the -<a class="reference internal" href="#polsturmnbwithmultofrootsof-sturmname-lessthanorequalto-value">\PolSturmNbWithMultOfRootsOf{sturmname}\LessThanOrEqualTo{value}</a> -will be operant.</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 @@ -1412,19 +1579,76 @@ 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 of use.</p> +roots</a> for an example.</p> +</blockquote> +</div> +<div class="section" id="id14"> +<span id="id13"></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="#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="#id73"><tt class="docutils literal">\PolSturmIsolateZerosAndGetMultiplicities{sturmname}</tt></a></h2> +<span id="polsturmisolatezerosandgetmultiplicities"></span><h2><a class="toc-backref" href="#id78"><tt class="docutils literal">\PolSturmIsolateZerosAndGetMultiplicities{sturmname}</tt></a></h2> <blockquote> -<p>This is another name for <a class="reference internal" href="#id12">\PolSturmIsolateZeros*{sturmname}</a>.</p> -<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> +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="#id79"><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="#id80"><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="#id74"><tt class="docutils literal"><span class="pre">\PolRefineInterval*{sturmname}{index}</span></tt></a></h2> +<span id="polrefineinterval"></span><h2><a class="toc-backref" href="#id81"><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 @@ -1433,21 +1657,21 @@ the original interval. This means that the <tt class="docutils literal">k</tt>th 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="#id75"><tt class="docutils literal"><span class="pre">\PolRefineInterval[N]{sturmname}{index}</span></tt></a></h2> +<span id="polrefineinterval-n"></span><h2><a class="toc-backref" href="#id82"><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="#id76"><tt class="docutils literal"><span class="pre">\PolEnsureIntervalLength{sturmname}{index}{E}</span></tt></a></h2> +<span id="polensureintervallength"></span><h2><a class="toc-backref" href="#id83"><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="#id77"><tt class="docutils literal"><span class="pre">\PolEnsureIntervalLengths{sturmname}{E}</span></tt></a></h2> +<span id="polensureintervallengths"></span><h2><a class="toc-backref" href="#id84"><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 @@ -1458,63 +1682,136 @@ than <tt class="docutils literal">10^E</tt> in output only if it did not change </blockquote> </div> <div class="section" id="polprintintervals-varname-sturmname"> -<span id="polprintintervals"></span><h2><a class="toc-backref" href="#id78"><tt class="docutils literal"><span class="pre">\PolPrintIntervals[varname]{sturmname}</span></tt></a></h2> +<span id="polprintintervals"></span><h2><a class="toc-backref" href="#id85"><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 in a +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. The user is invited to renewcommand the macro if some other -type of tabular environment for example is wanted.</p> -<p>In each array cell the corresponding interval end-point (which may -be an exactly known root) is available as macro -<a class="reference internal" href="#polprintintervalstheendpoint">\PolPrintIntervalsTheEndPoint</a> (in decimal notation). And the -corresponding interval index is available as -<a class="reference internal" href="#polprintintervalstheindex">\PolPrintIntervalsTheIndex</a>.</p> -<p>These values may be tested to decide some on-the-fly customization -(color for example), via the following auxiliaries which can be -modified by user. Furthermore these auxiliaries can also use the -following conditionals: <a class="reference internal" href="#polifendpointispositive-a-b">\PolIfEndPointIsPositive{A}{B}</a>, -<a class="reference internal" href="#polifendpointisnegative-a-b">\PolIfEndPointIsNegative{A}{B}</a>, <a class="reference internal" href="#polifendpointiszero-a-b">\PolIfEndPointIsZero{A}{B}</a>.</p> +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="id13"> -<span id="polprintintervalsprintexactzero"></span><h3><a class="toc-backref" href="#id79"><tt class="docutils literal">\PolPrintIntervalsPrintExactZero</tt></a></h3> +<div class="section" id="polprintintervalsnorealroots"> +<h3><a class="toc-backref" href="#id86"><tt class="docutils literal">\PolPrintIntervalsNoRealRoots</tt></a></h3> <blockquote> -<p>This is provided to help customize how an exactly known root is -printed in the right most column of the array. The package -definition is:</p> +<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\PolPrintIntervalsPrintExactZero{\PolPrintIntervalsTheEndPoint}% +\newcommand\PolPrintIntervalsNoRealRoots{} </pre> -<p>Recall that this is expanded in an array cell.</p> -<p>If for example you want to print in red the third root, known -exactly, the macro could make a test for the value of -<a class="reference internal" href="#polprintintervalstheindex">\PolPrintIntervalsTheIndex</a> and act accordingly.</p> </blockquote> </div> -<div class="section" id="id14"> -<span id="polprintintervalsprintleftendpoint"></span><h3><a class="toc-backref" href="#id80"><tt class="docutils literal">\PolPrintIntervalsPrintLeftEndPoint</tt></a></h3> +<div class="section" id="polprintintervalsbeginenv"> +<h3><a class="toc-backref" href="#id87"><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="#id88"><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="#id89"><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="#id90"><tt class="docutils literal">\PolPrintIntervalsUnknownRoot</tt></a></h3> <blockquote> -<p>Package definition is:</p> +<p>Default definition:</p> <pre class="literal-block"> -\newcommand\PolPrintIntervalsPrintLeftEndPoint{\PolPrintIntervalsTheEndPoint}% +\newcommand\PolPrintIntervalsUnknownRoot{% + \PolPrintIntervalsPrintLeftEndPoint&<&% + \PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}&<&% + \PolPrintIntervalsPrintRightEndPoint +} </pre> </blockquote> </div> <div class="section" id="id15"> -<span id="polprintintervalsprintrightendpoint"></span><h3><a class="toc-backref" href="#id81"><tt class="docutils literal">\PolPrintIntervalsPrintRightEndPoint</tt></a></h3> +<span id="polprintintervalsprintexactzero"></span><h3><a class="toc-backref" href="#id91"><tt class="docutils literal">\PolPrintIntervalsPrintExactZero</tt></a></h3> <blockquote> -<p>Package definition is:</p> +<p>Default definition:</p> <pre class="literal-block"> -\newcommand\PolPrintIntervalsPrintRightEndPoint{\PolPrintIntervalsTheEndPoint}% +\newcommand\PolPrintIntervalsPrintExactZero{\PolPrintIntervalsTheLeftEndPoint} +</pre> +</blockquote> +</div> +<div class="section" id="id16"> +<span id="polprintintervalsprintleftendpoint"></span><h3><a class="toc-backref" href="#id92"><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="#id93"><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="#id94"><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="#id95"><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="#id82"><tt class="docutils literal"><span class="pre">\PolMapCoeffs{\macro}{polname}</span></tt></a></h2> +<span id="polmapcoeffs"></span><h2><a class="toc-backref" href="#id96"><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 @@ -1534,15 +1831,15 @@ will have to be expressed in terms of macros from <a class="reference external" </blockquote> </div> <div class="section" id="polreducecoeffs-polname"> -<span id="polreducecoeffs"></span><h2><a class="toc-backref" href="#id83"><tt class="docutils literal">\PolReduceCoeffs{polname}</tt></a></h2> +<span id="polreducecoeffs"></span><h2><a class="toc-backref" href="#id97"><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="id17"> -<span id="id16"></span><h2><a class="toc-backref" href="#id84"><tt class="docutils literal"><span class="pre">\PolReduceCoeffs*{polname}</span></tt></a></h2> +<div class="section" id="id21"> +<span id="id20"></span><h2><a class="toc-backref" href="#id98"><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 @@ -1561,16 +1858,16 @@ expansion speed of the <a class="reference external" href="http://www.ctan.org/p </blockquote> </div> <div class="section" id="polmakemonic-polname"> -<span id="polmakemonic"></span><h2><a class="toc-backref" href="#id85"><tt class="docutils literal">\PolMakeMonic{polname}</tt></a></h2> +<span id="polmakemonic"></span><h2><a class="toc-backref" href="#id99"><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="#id17">\PolReduceCoeffs*{polname}</a> immediately afterwards. This is not +<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="#id86"><tt class="docutils literal">\PolMakePrimitive{polname}</tt></a></h2> +<span id="polmakeprimitive"></span><h2><a class="toc-backref" href="#id100"><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 @@ -1578,60 +1875,60 @@ coefficient is not modified.</blockquote> </div> </div> <div class="section" id="expandable-macros"> -<h1><a class="toc-backref" href="#id87">Expandable macros</a></h1> +<h1><a class="toc-backref" href="#id101">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="#id88"><tt class="docutils literal"><span class="pre">\PolEval{polname}\AtExpr{numerical</span> expression}</tt></a></h2> +<span id="polevalatexpr"></span><h2><a class="toc-backref" href="#id102"><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="#id89"><tt class="docutils literal"><span class="pre">\PolEval{polname}\At{fraction}</span></tt></a></h2> +<span id="polevalat"></span><h2><a class="toc-backref" href="#id103"><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="#id90"><tt class="docutils literal"><span class="pre">\PolEvalReduced{polname}\AtExpr{numerical</span> expression}</tt></a></h2> +<span id="polevalreducedatexpr"></span><h2><a class="toc-backref" href="#id104"><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="#id91"><tt class="docutils literal"><span class="pre">\PolEvalReduced{polname}\At{fraction}</span></tt></a></h2> +<span id="polevalreducedat"></span><h2><a class="toc-backref" href="#id105"><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="#id92"><tt class="docutils literal"><span class="pre">\PolFloatEval{polname}\AtExpr{numerical</span> expression}</tt></a></h2> +<span id="polfloatevalatexpr"></span><h2><a class="toc-backref" href="#id106"><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="#id20" id="id18">[2]</a> To use the <em>exact coefficients</em> with <em>exactly +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="#id21" id="id19">[3]</a></p> +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="id20" rules="none"> +<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="#id18">[2]</a></td><td>Anyway each floating point operation starts by rounding its +<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="id21" rules="none"> +<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="#id19">[3]</a></td><td>The <tt class="docutils literal">\xintexpr</tt> here could be <tt class="docutils literal">\xinttheexpr</tt> but that +<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> @@ -1639,14 +1936,14 @@ nested expressions.</td></tr> </blockquote> </div> <div class="section" id="polfloateval-polname-at-fraction"> -<span id="polfloatevalat"></span><h2><a class="toc-backref" href="#id93"><tt class="docutils literal"><span class="pre">\PolFloatEval{polname}\At{fraction}</span></tt></a></h2> +<span id="polfloatevalat"></span><h2><a class="toc-backref" href="#id107"><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="#id94"><tt class="docutils literal"><span class="pre">\PolIfCoeffIsPlusOrMinusOne{A}{B}</span></tt></a></h2> +<span id="polifcoeffisplusorminusone"></span><h2><a class="toc-backref" href="#id108"><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 @@ -1658,25 +1955,25 @@ 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="#id95"><tt class="docutils literal">\PolLeadingCoeff{polname}</tt></a></h2> +<span id="polleadingcoeff"></span><h2><a class="toc-backref" href="#id109"><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="#id96"><tt class="docutils literal"><span class="pre">\PolNthCoeff{polname}{number}</span></tt></a></h2> +<span id="polnthcoeff"></span><h2><a class="toc-backref" href="#id110"><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="#id97"><tt class="docutils literal">\PolDegree{polname}</tt></a></h2> +<span id="poldegree"></span><h2><a class="toc-backref" href="#id111"><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="#id98"><tt class="docutils literal">\PolIContent{polname}</tt></a></h2> +<span id="policontent"></span><h2><a class="toc-backref" href="#id112"><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 @@ -1685,13 +1982,13 @@ with integer coefficients having no common prime divisor.</p> </blockquote> </div> <div class="section" id="poltoexpr-polname"> -<span id="poltoexpr"></span><h2><a class="toc-backref" href="#id99"><tt class="docutils literal">\PolToExpr{polname}</tt></a></h2> +<span id="poltoexpr"></span><h2><a class="toc-backref" href="#id113"><tt class="docutils literal">\PolToExpr{polname}</tt></a></h2> <blockquote> -<p>Expands <a class="footnote-reference" href="#id23" id="id22">[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="id23" rules="none"> +<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="#id22">[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 +<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> @@ -1710,7 +2007,7 @@ of <tt class="docutils literal">\PolToExpr{f}</tt>, but a simple <tt class="docu the identical result.</p> </blockquote> <div class="section" id="poltoexproneterm-raw-coeff-number"> -<span id="poltoexproneterm"></span><h3><a class="toc-backref" href="#id100"><tt class="docutils literal"><span class="pre">\PolToExprOneTerm{raw_coeff}{number}</span></tt></a></h3> +<span id="poltoexproneterm"></span><h3><a class="toc-backref" href="#id114"><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 @@ -1723,13 +2020,13 @@ or a minus one. See <a class="reference internal" href="#poltoexprtimes">\PolToE </blockquote> </div> <div class="section" id="poltoexpronetermstylea-raw-coeff-number"> -<span id="poltoexpronetermstylea"></span><h3><a class="toc-backref" href="#id101"><tt class="docutils literal"><span class="pre">\PolToExprOneTermStyleA{raw_coeff}{number}</span></tt></a></h3> +<span id="poltoexpronetermstylea"></span><h3><a class="toc-backref" href="#id115"><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="#id102"><tt class="docutils literal"><span class="pre">\PolToExprOneTermStyleB{raw_coeff}{number}</span></tt></a></h3> +<span id="poltoexpronetermstyleb"></span><h3><a class="toc-backref" href="#id116"><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"> @@ -1743,7 +2040,7 @@ To revert to package default, issue </blockquote> </div> <div class="section" id="poltoexprcmd-raw-coeff"> -<span id="poltoexprcmd"></span><h3><a class="toc-backref" href="#id103"><tt class="docutils literal">\PolToExprCmd{raw_coeff}</tt></a></h3> +<span id="poltoexprcmd"></span><h3><a class="toc-backref" href="#id117"><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 @@ -1753,21 +2050,21 @@ to <tt class="docutils literal"><span class="pre">\xintIrr{#1}</span></tt> or to output forcefully reduced coefficients.</blockquote> </div> <div class="section" id="poltoexprtermprefix-raw-coeff"> -<span id="poltoexprtermprefix"></span><h3><a class="toc-backref" href="#id104"><tt class="docutils literal">\PolToExprTermPrefix{raw_coeff}</tt></a></h3> +<span id="poltoexprtermprefix"></span><h3><a class="toc-backref" href="#id118"><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="id24"> -<span id="poltoexprvar"></span><h3><a class="toc-backref" href="#id105"><tt class="docutils literal">\PolToExprVar</tt></a></h3> +<div class="section" id="id28"> +<span id="poltoexprvar"></span><h3><a class="toc-backref" href="#id119"><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="id25"> -<span id="poltoexprtimes"></span><h3><a class="toc-backref" href="#id106"><tt class="docutils literal">\PolToExprTimes</tt></a></h3> +<div class="section" id="id29"> +<span id="poltoexprtimes"></span><h3><a class="toc-backref" href="#id120"><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 @@ -1776,14 +2073,14 @@ this will give output incompatible with some professional computer algebra software).</blockquote> </div> </div> -<div class="section" id="id27"> -<span id="id26"></span><h2><a class="toc-backref" href="#id107"><tt class="docutils literal"><span class="pre">\PolToExpr*{polname}</span></tt></a></h2> +<div class="section" id="id31"> +<span id="id30"></span><h2><a class="toc-backref" href="#id121"><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="#id108"><tt class="docutils literal">\PolToFloatExpr{polname}</tt></a></h2> +<span id="poltofloatexpr"></span><h2><a class="toc-backref" href="#id122"><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 @@ -1802,13 +2099,13 @@ 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="#id109"><tt class="docutils literal"><span class="pre">\PolToFloatExprOneTerm{raw_coeff}{number}</span></tt></a></h3> +<span id="poltofloatexproneterm"></span><h3><a class="toc-backref" href="#id123"><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="id29"></span><h3><a class="toc-backref" href="#id110"><tt class="docutils literal">\PolToFloatExprCmd{raw_coeff}</tt></a></h3> +<span id="id33"></span><h3><a class="toc-backref" href="#id124"><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> @@ -1830,26 +2127,28 @@ in <tt class="docutils literal">xintfrac</tt> raw format.</p> </blockquote> </div> </div> -<div class="section" id="id31"> -<span id="id30"></span><h2><a class="toc-backref" href="#id111"><tt class="docutils literal"><span class="pre">\PolToFloatExpr*{polname}</span></tt></a></h2> +<div class="section" id="id35"> +<span id="id34"></span><h2><a class="toc-backref" href="#id125"><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="#id112"><tt class="docutils literal">\PolToList{polname}</tt></a></h2> +<span id="poltolist"></span><h2><a class="toc-backref" href="#id126"><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 -(except zero polynomial which does give <tt class="docutils literal">{0/1[0]}</tt> and not an +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="#id113"><tt class="docutils literal">\PolToCSV{polname}</tt></a></h2> +<span id="poltocsv"></span><h2><a class="toc-backref" href="#id127"><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>. Converse +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="#id114"><tt class="docutils literal">\PolSturmChainLength{sturmname}</tt></a></h2> +<span id="polsturmchainlength"></span><h2><a class="toc-backref" href="#id128"><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> @@ -1857,43 +2156,44 @@ in the Sturm chain <tt class="docutils literal">sturmname_0</tt>, <tt class="doc </blockquote> </div> <div class="section" id="polsturmifzeroexactlyknown-sturmname-index-a-b"> -<span id="polsturmifzeroexactlyknown"></span><h2><a class="toc-backref" href="#id115"><tt class="docutils literal"><span class="pre">\PolSturmIfZeroExactlyKnown{sturmname}{index}{A}{B}</span></tt></a></h2> +<span id="polsturmifzeroexactlyknown"></span><h2><a class="toc-backref" href="#id129"><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><tt class="docutils literal">index</tt> may be a TeX count, or a <tt class="docutils literal">\value{latexcounter}</tt>, or a -numerical expression as parsable by <tt class="docutils literal">\numexpr</tt>: it does not -have to be given via explicit digits.</p> -<p class="last">This remark applies also to the other package macros with -<tt class="docutils literal">index</tt> being the name of the argument in this documentation. -There is also an out-of-range check done for some reasonable -error message (right before everything goes haywire).</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="#id116"><tt class="docutils literal"><span class="pre">\PolSturmIsolatedZeroLeft{sturmname}{index}</span></tt></a></h2> +<span id="polsturmisolatedzeroleft"></span><h2><a class="toc-backref" href="#id130"><tt class="docutils literal"><span class="pre">\PolSturmIsolatedZeroLeft{sturmname}{index}</span></tt></a></h2> <blockquote> -Expands to the left end-point for the <tt class="docutils literal">index</tt>-th interval -obtained via <a class="reference internal" href="#polsturmisolatezeros-sturmname">\PolSturmIsolateZeros{sturmname}</a> and possibly -refined afterwards.</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="#id117"><tt class="docutils literal"><span class="pre">\PolSturmIsolatedZeroRight{sturmname}{index}</span></tt></a></h2> +<span id="polsturmisolatedzeroright"></span><h2><a class="toc-backref" href="#id131"><tt class="docutils literal"><span class="pre">\PolSturmIsolatedZeroRight{sturmname}{index}</span></tt></a></h2> <blockquote> -Expands to the right end-point for the <tt class="docutils literal">index</tt>-th interval -obtained via <a class="reference internal" href="#polsturmisolatezeros-sturmname">\PolSturmIsolateZeros{sturmname}</a> and possibly -refined afterwards.</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="#id118"><tt class="docutils literal"><span class="pre">\PolSturmIsolatedZeroMultiplicity{sturmname}{index}</span></tt></a></h2> +<span id="polsturmisolatedzeromultiplicity"></span><h2><a class="toc-backref" href="#id132"><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 as determined by -<a class="reference internal" href="#id12">\PolSturmIsolateZeros*{sturmname}</a> and possibly refined -afterwards.</p> +<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> @@ -1903,15 +2203,22 @@ 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="#id119"><tt class="docutils literal">\PolSturmNbOfIsolatedZeros{sturmname}</tt></a></h2> +<span id="polsturmnbofisolatedzeros"></span><h2><a class="toc-backref" href="#id133"><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> (which is the number of distinct real roots of the -polynomial used to create the Sturm chain via +<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"> -<h2><a class="toc-backref" href="#id120"><tt class="docutils literal"><span class="pre">\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualTo{value}</span></tt></a></h2> +<h3><a class="toc-backref" href="#id134"><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 @@ -1927,7 +2234,7 @@ of the above constraint.</p> </blockquote> </div> <div class="section" id="polsturmnbofrootsof-sturmname-lessthanorequaltoexpr-expression"> -<h2><a class="toc-backref" href="#id121"><tt class="docutils literal"><span class="pre">\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualToExpr{expression}</span></tt></a></h2> +<h3><a class="toc-backref" href="#id135"><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 @@ -1940,91 +2247,160 @@ beforehand.</p> </blockquote> </div> <div class="section" id="polsturmnbwithmultofrootsof-sturmname-lessthanorequalto-value"> -<h2><a class="toc-backref" href="#id122"><tt class="docutils literal"><span class="pre">\PolSturmNbWithMultOfRootsOf{sturmname}\LessThanOrEqualTo{value}</span></tt></a></h2> +<h3><a class="toc-backref" href="#id136"><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 its alias -<a class="reference internal" href="#polsturmisolatezerosandgetmultiplicities-sturmname">\PolSturmIsolateZerosAndGetMultiplicities{sturmname}</a> -must have been executed -beforehand.</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"> -<h2><a class="toc-backref" href="#id123"><tt class="docutils literal"><span class="pre">\PolSturmNbWithMultOfRootsOf{sturmname}\LessThanOrEqualToExpr{expression}</span></tt></a></h2> +<h3><a class="toc-backref" href="#id137"><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 its alias -<a class="reference internal" href="#polsturmisolatezerosandgetmultiplicities-sturmname">\PolSturmIsolateZerosAndGetMultiplicities{sturmname}</a> -must have been executed +<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="#id138"><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="#id139"><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="#id140"><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="#id141"><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="#id142"><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="#id124"><tt class="docutils literal"><span class="pre">\PolIntervalWidth{sturmname}{index}</span></tt></a></h2> +<span id="polintervalwidth"></span><h2><a class="toc-backref" href="#id143"><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="macros-for-use-within-execution-of-polprintintervals"> -<h2><a class="toc-backref" href="#id125">Macros for use within execution of <tt class="docutils literal">\PolPrintIntervals</tt></a></h2> -<p>More precisely, they can be used within the replacement texts of the -<a class="reference internal" href="#polprintintervalsprintleftendpoint">\PolPrintIntervalsPrintLeftEndPoint</a>, etc, macros.</p> -<div class="section" id="id32"> -<span id="polprintintervalstheendpoint"></span><h3><a class="toc-backref" href="#id126"><tt class="docutils literal">\PolPrintIntervalsTheEndPoint</tt></a></h3> +<div class="section" id="expandable-macros-for-use-within-execution-of-polprintintervals"> +<h2><a class="toc-backref" href="#id144">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="#id145"><tt class="docutils literal">\PolPrintIntervalsTheVar</tt></a></h3> <blockquote> -Within a custom <a class="reference internal" href="#polprintintervalsprintleftendpoint">\PolPrintIntervalsPrintLeftEndPoint</a>, custom -<a class="reference internal" href="#polprintintervalsprintrightendpoint">\PolPrintIntervalsPrintRightEndPoint</a>, or custom -<a class="reference internal" href="#polprintintervalsprintexactzero">\PolPrintIntervalsPrintExactZero</a> this macro expands to the left -or right end point of the considered interval. Serves as default -replacement for <a class="reference internal" href="#polprintintervalsprintleftendpoint">\PolPrintIntervalsPrintLeftEndPoint</a> , etc...</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="id33"> -<span id="polprintintervalstheindex"></span><h3><a class="toc-backref" href="#id127"><tt class="docutils literal">\PolPrintIntervalsTheIndex</tt></a></h3> +<div class="section" id="polprintintervalstheindex"> +<h3><a class="toc-backref" href="#id146"><tt class="docutils literal">\PolPrintIntervalsTheIndex</tt></a></h3> <blockquote> -Within a custom <a class="reference internal" href="#polprintintervalsprintleftendpoint">\PolPrintIntervalsPrintLeftEndPoint</a>, custom -<a class="reference internal" href="#polprintintervalsprintrightendpoint">\PolPrintIntervalsPrintRightEndPoint</a>, or custom -<a class="reference internal" href="#polprintintervalsprintexactzero">\PolPrintIntervalsPrintExactZero</a> this macro expands to the index -of the considered interval. For example if user wants to print the -corresponding end points in red, the index value can thus be tested -in the replacement text of <a class="reference internal" href="#polprintintervalsprintleftendpoint">\PolPrintIntervalsPrintLeftEndPoint</a> and -the other two similar macros.</blockquote> +Expands to the index of the considered interval (indexing starting +at 1 for the leftmost interval).</blockquote> </div> -<div class="section" id="polifendpointispositive-a-b"> -<span id="polifendpointispositive"></span><h3><a class="toc-backref" href="#id128"><tt class="docutils literal"><span class="pre">\PolIfEndPointIsPositive{A}{B}</span></tt></a></h3> +<div class="section" id="polprintintervalsthesturmname"> +<h3><a class="toc-backref" href="#id147"><tt class="docutils literal">\PolPrintIntervalsTheSturmName</tt></a></h3> <blockquote> -Within a custom <a class="reference internal" href="#polprintintervalsprintleftendpoint">\PolPrintIntervalsPrintLeftEndPoint</a>, custom -<a class="reference internal" href="#polprintintervalsprintrightendpoint">\PolPrintIntervalsPrintRightEndPoint</a>, or custom -<a class="reference internal" href="#polprintintervalsprintexactzero">\PolPrintIntervalsPrintExactZero</a> this macro executes <tt class="docutils literal">A</tt> if -the considered interval end-point is positive, else <tt class="docutils literal">B</tt>.</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="polifendpointisnegative-a-b"> -<span id="polifendpointisnegative"></span><h3><a class="toc-backref" href="#id129"><tt class="docutils literal"><span class="pre">\PolIfEndPointIsNegative{A}{B}</span></tt></a></h3> +<div class="section" id="polprintintervalstheleftendpoint"> +<h3><a class="toc-backref" href="#id148"><tt class="docutils literal">\PolPrintIntervalsTheLeftEndPoint</tt></a></h3> <blockquote> -Within a custom <a class="reference internal" href="#polprintintervalsprintleftendpoint">\PolPrintIntervalsPrintLeftEndPoint</a>, custom -<a class="reference internal" href="#polprintintervalsprintrightendpoint">\PolPrintIntervalsPrintRightEndPoint</a>, or custom -<a class="reference internal" href="#polprintintervalsprintexactzero">\PolPrintIntervalsPrintExactZero</a> this macro executes <tt class="docutils literal">A</tt> if -the considered interval end-point is negative, else <tt class="docutils literal">B</tt>.</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="polifendpointiszero-a-b"> -<span id="polifendpointiszero"></span><h3><a class="toc-backref" href="#id130"><tt class="docutils literal"><span class="pre">\PolIfEndPointIsZero{A}{B}</span></tt></a></h3> +<div class="section" id="polprintintervalstherightendpoint"> +<h3><a class="toc-backref" href="#id149"><tt class="docutils literal">\PolPrintIntervalsTheRightEndPoint</tt></a></h3> <blockquote> -Within a custom <a class="reference internal" href="#polprintintervalsprintleftendpoint">\PolPrintIntervalsPrintLeftEndPoint</a>, custom -<a class="reference internal" href="#polprintintervalsprintrightendpoint">\PolPrintIntervalsPrintRightEndPoint</a>, or custom -<a class="reference internal" href="#polprintintervalsprintexactzero">\PolPrintIntervalsPrintExactZero</a> this macro executes <tt class="docutils literal">A</tt> if -the considered interval end-point is zero, else <tt class="docutils literal">B</tt>.</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="#id150"><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="#id131"><tt class="docutils literal">\PolDecToString{decimal number}</tt></a></h2> +<span id="poldectostring"></span><h2><a class="toc-backref" href="#id151"><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 @@ -2035,15 +2411,15 @@ now an alias to it.</p> 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 exact behaviour of this macro may evolve in future releases of +<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="#id132">Booleans (with default setting as indicated)</a></h1> +<h1><a class="toc-backref" href="#id152">Booleans (with default setting as indicated)</a></h1> <div class="section" id="xintverbosefalse"> -<h2><a class="toc-backref" href="#id133"><tt class="docutils literal">\xintverbosefalse</tt></a></h2> +<h2><a class="toc-backref" href="#id153"><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 @@ -2056,20 +2432,41 @@ unstable and undocumented internal structures.</p> </blockquote> </div> <div class="section" id="poltypesetallfalse"> -<h2><a class="toc-backref" href="#id134"><tt class="docutils literal">\poltypesetallfalse</tt></a></h2> +<h2><a class="toc-backref" href="#id154"><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="#id135"><tt class="docutils literal">\poltoexprallfalse</tt></a></h2> +<h2><a class="toc-backref" href="#id155"><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="#id156"><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="#id136">Technicalities</a></h1> +<h1><a class="toc-backref" href="#id157">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 @@ -2078,7 +2475,7 @@ 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="#id35" id="id34">[5]</a>, user-chosen common +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; @@ -2094,10 +2491,10 @@ denominators survive additions and multiplications. For example, this:</p> 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="id35" rules="none"> +<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="#id34">[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 +<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> @@ -2126,7 +2523,7 @@ documented and unstable. Don't use them.</p> </ul> </div> <div class="section" id="change-log"> -<h1><a class="toc-backref" href="#id137">CHANGE LOG</a></h1> +<h1><a class="toc-backref" href="#id158">CHANGE LOG</a></h1> <ul> <li><p class="first">v0.1 (2018/01/11): initial release. Features:</p> <ul class="simple"> @@ -2166,7 +2563,7 @@ using expressions in the second argument.</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="#id26">\PolToExpr*</a> for <em>ascending</em> powers.</li> +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 @@ -2183,7 +2580,7 @@ removed; the former meaning is available as <a class="reference internal" href=" <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="#id29">\PolToFloatExprCmd</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> @@ -2268,7 +2665,7 @@ they actually make pre-existing such variant undefined.</p> <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="#id16">\PolReduceCoeffs*</a></li> +<li><a class="reference internal" href="#id20">\PolReduceCoeffs*</a></li> <li><a class="reference internal" href="#polmakemonic">\PolMakeMonic</a></li> </ul> </li> @@ -2282,11 +2679,11 @@ they actually make pre-existing such variant undefined.</p> <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><a class="reference internal" href="#polprintintervalstheendpoint">\PolPrintIntervalsTheEndPoint</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><a class="reference internal" href="#polifendpointispositive">\PolIfEndPointIsPositive</a></li> -<li><a class="reference internal" href="#polifendpointisnegative">\PolIfEndPointIsNegative</a></li> -<li><a class="reference internal" href="#polifendpointiszero">\PolIfEndPointIsZero</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> @@ -2371,15 +2768,65 @@ acts like the <a class="reference internal" href="#polsturmisolatezeros">non-sta </li> </ul> </li> +<li><p class="first">v0.7 (2018/12/08)</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> </ul> </div> <div class="section" id="acknowledgments"> -<h1><a class="toc-backref" href="#id138">Acknowledgments</a></h1> +<h1><a class="toc-backref" href="#id159">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> release for their +<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> diff --git a/Master/texmf-dist/doc/latex/polexpr/polexpr.txt b/Master/texmf-dist/doc/latex/polexpr/polexpr.txt index da2cbb77790..51008763dcf 100644 --- a/Master/texmf-dist/doc/latex/polexpr/polexpr.txt +++ b/Master/texmf-dist/doc/latex/polexpr/polexpr.txt @@ -4,13 +4,13 @@ Package polexpr documentation =============================== -0.6 (2018/11/20) +0.7 (2018/12/08) ================ .. contents:: -Basic Examples --------------- +Basic syntax +------------ The syntax is:: @@ -161,18 +161,13 @@ Examples of localization of roots - For extra info in log file use ``\xintverbosetrue``. -- To make producing this documentation simpler, the results from execution - of the code snippets are not included. Please try them out yourself... +- Only for some of these examples is the output included here. A typical example ~~~~~~~~~~~~~~~~~ -In this example the polynomial is square-free; we can make sure of that by -comparing the degree of the first element of the Sturm chain with the -degree of the original polynomial. In such case the second element of -the Sturm chain is still the polynomial first derivative, because there -was no further reduction. +In this example the polynomial is square-free. :: @@ -190,11 +185,11 @@ was no further reduction. \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 same as $\PolDegree{f}$ we know that the latter was square free. - So the derivative is up to a constant \PolTypeset{f_1} (in fact here + 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}% - It has \PolSturmNbOfIsolatedZeros{f_1} distinct real + The derivative has \PolSturmNbOfIsolatedZeros{f_1} distinct real roots: \PolPrintIntervals[W]{f_1} \PolEnsureIntervalLengths{f_1}{-10}% @@ -216,6 +211,13 @@ was no further reduction. 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)} @@ -273,11 +275,10 @@ In this example, the output will look like this (but using math mode):: 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. But multiplicity -computation works also with (decimal) roots not yet identified or with -non-decimal or irrational roots. - -Try it out! +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:: @@ -313,7 +314,46 @@ which produces:: 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 -Try obtaining this with your pocket calculator! (or IEEE-7554 numerics...) +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 @@ -344,6 +384,93 @@ 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 degree 41 polynomial with -2, -1.9, -1.8, ..., 0, 0.1, ..., 1.9, 2 as roots ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -391,23 +518,23 @@ 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 + Release ``0.5`` has *experimental* addition of optional argument ``E`` to ``\PolSturmIsolateZeros``. It instructs to search roots only - in interval ``(-10^E, 10^E)``, extremities assumed to not be roots. - Thus here:: - - \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. + 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. - This will probably get replaced in future by the specification of - a general 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 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -584,18 +711,18 @@ Non-expandable macros ``\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 constant term being the first item. No validity checks. Spaces - from the list argument are trimmed. List items are each expanded in - an ``\edef`` and then put into normalized form via xintfrac_\ 's - macro ``\xintRaw``. + 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``. - Leading zero coefficients are removed:: + As leading zero coefficients are removed:: \PolFromCSV{f}{0, 0, 0, 0, 0, 0, 0, 0, 0, 0} - defines the zero polynomial, which has only one (zero) coefficient. + defines the zero polynomial, which holds only one coefficient. See also expandable macro `\\PolToCSV <\\PolToCSV{polname}_>`_. @@ -825,15 +952,18 @@ Non-expandable macros 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. + 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. - These polynomials ``sturmname_k`` (contrarily to the - ``sturmname_k_`` ones) are usable after the macro execution but - their main utility is for the execution of - `\\PolSturmIsolateZeros{sturmname}`_. + 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. @@ -853,6 +983,16 @@ Non-expandable macros 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}`` @@ -913,10 +1053,10 @@ Non-expandable macros ``\PolSturmIsolateZeros{sturmname}`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - First, it evaluates using `Sturm theorem`_ the number of distinct - real roots of ``sturmname_0``. + The macros locates, using `Sturm theorem`_, as many disjoint + intervals as there are (real) roots. - .. note:: + .. important:: The Sturm chain must have been produced by an earlier `\\PolToSturm{polname}{sturmname}`_. @@ -935,23 +1075,42 @@ Non-expandable macros to ``\PolToSturm`` must have been made at any rate for ``\PolSturmIsolateZeros`` to be usable. - Then it locates, again using `Sturm theorem`_, as many disjoint - intervals as there are roots. Some intervals reduce to singleton - which are roots. Non-singleton intervals get refined to make sure - none of their two limit points is a root: they contain each a single - root, in their respective interiors. + After its execution they are two types of such intervals (stored in + memory and accessible via macros or xintexpr_ variables, see below): - .. This procedure is covariant - with the independent variable ``x`` becoming ``-x``. - Hmm, pas sûr et trop fatigué + - 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)``; if zero is a root it is always - identified individually. The non-singleton intervals are of the + ``(-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 ``a`` and ``a+1`` are both positive - or both negative. + 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 @@ -960,26 +1119,27 @@ Non-expandable macros ``<sturmname>R_1``, ``<sturmname>R_2``, ..., for the right end-points. - Also two macro arrays (in the sense of - xinttools_'s ``\xintAssignArray``) are created for holding the - interval end-points written out in standard decimal notation - (see `\\PolDecToString{decimal number}`_). - To access these values, macros - `\\PolSturmIsolatedZeroLeft{sturmname}{index}`_ and - `\\PolSturmIsolatedZeroRight{sturmname}{index}`_ are provided. + 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. - .. important:: + 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}`_. - Trailing zeroes in these stored decimal numbers are significant: - they are also present in the decimal expansion of the exact root. + .. important:: - .. note:: + 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. - The actual array macros are ``\POL_ZeroInt<sturmname>L`` and - ``\POL_ZeroInt<sturmname>R`` but as these names use the - non-letter character ``_`` and possibly also digits from - ``sturmname``, the accessor macros above have been made part of - the package. + 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} @@ -992,25 +1152,20 @@ Non-expandable macros `\\PolSturmNbOfIsolatedZeros{sturmname}`_. Furthermore - `\\PolSturmNbOfRootsOf{sturmname}\\LessThanOrEqualTo{value}`_ - and + `\\PolSturmNbOfRootsOf{sturmname}\\LessThanOrEqualTo{value}`_ and `\\PolSturmNbOfRootsOf{sturmname}\\LessThanOrEqualToExpr{expression}`_. - will expandably act as their names indicate. + 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 ``<sturmname>...`` xintexpr_ variables - and the ``\POL_ZeroInt...`` arrays are globally defined. On the + 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:: - When two successive roots are located in adjacent intervals, the - separation between them is not lower bounded. See - `\\PolRefineInterval*{sturmname}{index}`_. - - .. 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. @@ -1036,9 +1191,9 @@ Non-expandable macros interval (intervals are enumerated from left to right, with index starting at ``1``). - Also, the - `\\PolSturmNbWithMultOfRootsOf{sturmname}\\LessThanOrEqualTo{value}`_ - will be operant. + Furthermore, if for example the ``sturmname`` is ``f``, xintexpr_ + variables ``fM_1``, ``fM_2``... hold the multiplicities thus + computed. .. note:: @@ -1049,7 +1204,36 @@ Non-expandable macros genuine polynomials. See `The degree nine polynomial with 0.99, 0.999, 0.9999 as triple - roots`_ for an example of use. + 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: @@ -1058,8 +1242,44 @@ Non-expandable macros This is another name for `\\PolSturmIsolateZeros*{sturmname}`_. - See `The degree nine polynomial with 0.99, 0.999, 0.9999 as triple - roots`_ for an example of use. +.. _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*: @@ -1110,40 +1330,73 @@ Non-expandable macros 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 in a + 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. The user is invited to renewcommand the macro if some other - type of tabular environment for example is wanted. + exactly. - In each array cell the corresponding interval end-point (which may - be an exactly known root) is available as macro - `\\PolPrintIntervalsTheEndPoint`_ (in decimal notation). And the - corresponding interval index is available as - `\\PolPrintIntervalsTheIndex`_. + .. 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 + } - These values may be tested to decide some on-the-fly customization - (color for example), via the following auxiliaries which can be - modified by user. Furthermore these auxiliaries can also use the - following conditionals: `\\PolIfEndPointIsPositive{A}{B}`_, - `\\PolIfEndPointIsNegative{A}{B}`_, `\\PolIfEndPointIsZero{A}{B}`_. .. _PolPrintIntervalsPrintExactZero: ``\PolPrintIntervalsPrintExactZero`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - This is provided to help customize how an exactly known root is - printed in the right most column of the array. The package - definition is:: - \newcommand\PolPrintIntervalsPrintExactZero{\PolPrintIntervalsTheEndPoint}% + Default definition:: - Recall that this is expanded in an array cell. - - If for example you want to print in red the third root, known - exactly, the macro could make a test for the value of - `\\PolPrintIntervalsTheIndex`_ and act accordingly. + \newcommand\PolPrintIntervalsPrintExactZero{\PolPrintIntervalsTheLeftEndPoint} .. _PolPrintIntervalsPrintLeftEndPoint: @@ -1151,18 +1404,48 @@ Non-expandable macros ``\PolPrintIntervalsPrintLeftEndPoint`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Package definition is:: + Default definition:: - \newcommand\PolPrintIntervalsPrintLeftEndPoint{\PolPrintIntervalsTheEndPoint}% + \newcommand\PolPrintIntervalsPrintLeftEndPoint{\PolPrintIntervalsTheLeftEndPoint} .. _PolPrintIntervalsPrintRightEndPoint: ``\PolPrintIntervalsPrintRightEndPoint`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Package definition is:: + 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)} - \newcommand\PolPrintIntervalsPrintRightEndPoint{\PolPrintIntervalsTheEndPoint}% .. _PolMapCoeffs: @@ -1549,8 +1832,9 @@ and ``\PolToFloatExpr`` (and their auxiliaries) which need a ``\PolToList{polname}`` ~~~~~~~~~~~~~~~~~~~~~~~ - Expands to ``{coeff_0}{coeff_1}...{coeff_N}`` with ``N`` = degree - (except zero polynomial which does give ``{0/1[0]}`` and not an + 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: @@ -1558,7 +1842,8 @@ and ``\PolToFloatExpr`` (and their auxiliaries) which need a ``\PolToCSV{polname}`` ~~~~~~~~~~~~~~~~~~~~~~ - Expands to ``coeff_0, coeff_1, coeff_2, ....., coeff_N``. Converse + 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: @@ -1581,32 +1866,36 @@ and ``\PolToFloatExpr`` (and their auxiliaries) which need a .. note:: - ``index`` may be a TeX count, or a ``\value{latexcounter}``, or a - numerical expression as parsable by ``\numexpr``: it does not - have to be given via explicit digits. - - This remark applies also to the other package macros with - ``index`` being the name of the argument in this documentation. - There is also an out-of-range check done for some reasonable - error message (right before everything goes haywire). + ``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 - obtained via `\\PolSturmIsolateZeros{sturmname}`_ and possibly - refined afterwards. + 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 - obtained via `\\PolSturmIsolateZeros{sturmname}`_ and possibly - refined afterwards. + 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: @@ -1614,9 +1903,7 @@ and ``\PolToFloatExpr`` (and their auxiliaries) which need a ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Expands to the multiplicity of the unique root contained in the - ``index``\ -th interval as determined by - `\\PolSturmIsolateZeros*{sturmname}`_ and possibly refined - afterwards. + ``index``\ -th interval. .. attention:: @@ -1631,12 +1918,20 @@ and ``\PolToFloatExpr`` (and their auxiliaries) which need a ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Expands to the number of real roots of the polynomial - ``<sturmname>_0`` (which is the number of distinct real roots of the - polynomial used to create the Sturm chain via + ``<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 @@ -1652,7 +1947,7 @@ and ``\PolToFloatExpr`` (and their auxiliaries) which need a 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 @@ -1664,7 +1959,7 @@ and ``\PolToFloatExpr`` (and their auxiliaries) which need a 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 @@ -1672,22 +1967,74 @@ and ``\PolToFloatExpr`` (and their auxiliaries) which need a .. attention:: - `\\PolSturmIsolateZeros*{sturmname}`_ or its alias - `\\PolSturmIsolateZerosAndGetMultiplicities{sturmname}`_ - must have been executed - beforehand. + `\\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 its alias - `\\PolSturmIsolateZerosAndGetMultiplicities{sturmname}`_ - must have been executed + `\\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: @@ -1698,66 +2045,66 @@ and ``\PolToFloatExpr`` (and their auxiliaries) which need a The ``10^E`` width of the current ``index``\ -th root localization interval. Output is in xintfrac_ raw ``1/1[E]`` format (if not zero). -Macros for use within execution of ``\PolPrintIntervals`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -More precisely, they can be used within the replacement texts of the -`\\PolPrintIntervalsPrintLeftEndPoint`_, etc, macros. +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). -.. _PolPrintIntervalsTheEndPoint: +.. attention:: -``\PolPrintIntervalsTheEndPoint`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Some macros formerly mentioned here got removed at 0.7: + ``\PolPrintIntervalsTheEndPoint``, + ``\PolIfEndPointIsPositive{A}{B}``, + ``\PolIfEndPointIsNegative{A}{B}``, + ``\PolIfEndPointIsZero{A}{B}``. - Within a custom `\\PolPrintIntervalsPrintLeftEndPoint`_, custom - `\\PolPrintIntervalsPrintRightEndPoint`_, or custom - `\\PolPrintIntervalsPrintExactZero`_ this macro expands to the left - or right end point of the considered interval. Serves as default - replacement for `\\PolPrintIntervalsPrintLeftEndPoint`_ , etc... +``\PolPrintIntervalsTheVar`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. _PolPrintIntervalsTheIndex: + Expands to the name (default ``Z``) used for representing the roots, + which was passed as optional argument ``varname`` to + `\\PolPrintIntervals[varname]{sturmname}`_. ``\PolPrintIntervalsTheIndex`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Within a custom `\\PolPrintIntervalsPrintLeftEndPoint`_, custom - `\\PolPrintIntervalsPrintRightEndPoint`_, or custom - `\\PolPrintIntervalsPrintExactZero`_ this macro expands to the index - of the considered interval. For example if user wants to print the - corresponding end points in red, the index value can thus be tested - in the replacement text of `\\PolPrintIntervalsPrintLeftEndPoint`_ and - the other two similar macros. - -.. _PolIfEndPointIsPositive: + Expands to the index of the considered interval (indexing starting + at 1 for the leftmost interval). -``\PolIfEndPointIsPositive{A}{B}`` +``\PolPrintIntervalsTheSturmName`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Within a custom `\\PolPrintIntervalsPrintLeftEndPoint`_, custom - `\\PolPrintIntervalsPrintRightEndPoint`_, or custom - `\\PolPrintIntervalsPrintExactZero`_ this macro executes ``A`` if - the considered interval end-point is positive, else ``B``. + Expands to the argument which was passed as ``sturmname`` to + `\\PolPrintIntervals[varname]{sturmname}`_. -.. _PolIfEndPointIsNegative: +``\PolPrintIntervalsTheLeftEndPoint`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -``\PolIfEndPointIsNegative{A}{B}`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 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`_. - Within a custom `\\PolPrintIntervalsPrintLeftEndPoint`_, custom - `\\PolPrintIntervalsPrintRightEndPoint`_, or custom - `\\PolPrintIntervalsPrintExactZero`_ this macro executes ``A`` if - the considered interval end-point is negative, else ``B``. +``\PolPrintIntervalsTheRightEndPoint`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. _PolIfEndPointIsZero: + The right end point of the interval, as would be produced by + `\\\PolSturmIsolatedZeroRight <PolSturmIsolatedZeroRight_>`_ for + this Sturm chain name and index. -``\PolIfEndPointIsZero{A}{B}`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +``\PolPrintIntervalsTheMultiplicity`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Within a custom `\\PolPrintIntervalsPrintLeftEndPoint`_, custom - `\\PolPrintIntervalsPrintRightEndPoint`_, or custom - `\\PolPrintIntervalsPrintExactZero`_ this macro executes ``A`` if - the considered interval end-point is zero, else ``B``. + 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: @@ -1775,7 +2122,7 @@ More precisely, they can be used within the replacement texts of the illustrates that trailing zeros are not trimmed. To trim trailing zeroes, one can use ``\PolDecToString{\xintREZ{#1}}``. - The exact behaviour of this macro may evolve in future releases of + The precise behaviour of this macro may evolve in future releases of xint_. Booleans (with default setting as indicated) @@ -1806,6 +2153,26 @@ Booleans (with default setting as indicated) 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 -------------- @@ -2001,11 +2368,11 @@ CHANGE LOG - `\\PolSturmIfZeroExactlyKnown <PolSturmIfZeroExactlyKnown_>`_ - `\\PolSturmIsolatedZeroLeft <PolSturmIsolatedZeroLeft_>`_ - `\\PolSturmIsolatedZeroRight <PolSturmIsolatedZeroRight_>`_ - - `\\PolPrintIntervalsTheEndPoint <PolPrintIntervalsTheEndPoint_>`_ - - `\\PolPrintIntervalsTheIndex <PolPrintIntervalsTheIndex_>`_ - - `\\PolIfEndPointIsPositive <PolIfEndPointIsPositive_>`_ - - `\\PolIfEndPointIsNegative <PolIfEndPointIsNegative_>`_ - - `\\PolIfEndPointIsZero <PolIfEndPointIsZero_>`_ + - ``\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: @@ -2081,6 +2448,54 @@ CHANGE LOG - `\\PolSturmNbWithMultOfRootsOf{sturmname}\\LessThanOrEqualTo{value}`_ - `\\PolSturmNbWithMultOfRootsOf{sturmname}\\LessThanOrEqualToExpr{expression}`_ +- v0.7 (2018/12/08) + + * 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`_ + Acknowledgments --------------- @@ -2090,7 +2505,7 @@ 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`` release for their +Renewed thanks to them on occasion of the ``0.6`` and ``0.7`` releases for their continued interest. See README.md for the License. @@ -2100,6 +2515,8 @@ See README.md for the License. .. _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 diff --git a/Master/texmf-dist/tex/latex/polexpr/polexpr.sty b/Master/texmf-dist/tex/latex/polexpr/polexpr.sty index f163fe10f29..601446cf671 100644 --- a/Master/texmf-dist/tex/latex/polexpr/polexpr.sty +++ b/Master/texmf-dist/tex/latex/polexpr/polexpr.sty @@ -1,7 +1,7 @@ % author: Jean-François Burnol % License: LPPL 1.3c (author-maintained) \ProvidesPackage{polexpr}% - [2018/11/20 v0.6 Polynomial expressions with rational coefficients (JFB)]% + [2018/12/08 v0.7 Polynomial expressions with rational coefficients (JFB)]% \RequirePackage{xintexpr}[2018/06/17]% xint 1.3c for \ifxintglobaldefs boolean \edef\POL@restorecatcodes {\catcode`\noexpand\_ \the\catcode`\_ % @@ -28,11 +28,28 @@ }% %% 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\ifPOL@pol \newif\ifxintveryverbose \newif\ifpoltypesetall -\newif\ifPOL@sturm@declareunnormalized +\newif\ifPOL@tosturm@makefirstprimitive +\POL@tosturm@makefirstprimitivetrue \newif\ifPOL@isolz@nextwillneedrefine \newif\ifpoltoexprall %% the main exchange structure (stored in macros \POLuserpol@<name>) @@ -681,9 +698,16 @@ \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}% +}% %% Sturm Algorithm (polexpr 0.4) @@ -696,15 +720,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 - {\POL@sturm@declareunnormalizedtrue\POL@ToSturm}% - {\POL@sturm@declareunnormalizedfalse\POL@ToSturm}% -}% +\newcommand\PolToSturm{\@ifstar{\PolToSturm@@}{\PolToSturm@}}% \def\POL@aux@toint#1{\xintREZ{\xintNum{#1}}}% for polynomials with int. coeffs! -\def\POL@ToSturm#1#2{% +%% Attention that some macros rely upon this one setting \POL@sturmname +%% and \POL@sturm@N as it does +\def\PolToSturm@#1#2{% \edef\POL@sturmname{#2}% % 0.6 uses 2 underscores (one before index, one after) to keep in memory % the unnormalized chain + % This supposes #1 to be a genuine polynomial, not only a name with + % a \POLuserpol@#1 macro \POL@let{\POL@sturmname _0_}{#1}% \ifnum\PolDegree{#1}=\z@ \def\POL@sturm@N{0}% @@ -713,7 +738,8 @@ % if constant is negative. I also don't worry if polynomial is zero. \@namedef{POLuserpol@\POL@sturmname _0}{0.\empty{1/1[0]}}% \else - \POL@ToSturm@DoSturm + \ifPOL@tosturm@makefirstprimitive\POL@makeprimitive{\POL@sturmname _0_}\fi + \POL@tosturm@dosturm \fi \expandafter \let\csname PolSturmChainLength_\POL@sturmname\endcsname\POL@sturm@N @@ -724,22 +750,21 @@ \unless\ifnum\POL@sturm@N=\POL@count \advance\POL@count\@ne \repeat +}% +\def\PolToSturm@@#1#2{\PolToSturm@{#1}{#2}\POL@tosturm@declareunnormalized}% +\def\POL@tosturm@declareunnormalized{% % optionally declare also the unnormalized ones \POL@count\z@ - \ifPOL@sturm@declareunnormalized - \POL@count\z@ - \xintloop - \POL@newpol{\POL@sturmname _\the\POL@count _}% - \unless\ifnum\POL@sturm@N=\POL@count - \advance\POL@count\@ne - \repeat - \fi + \xintloop + \POL@newpol{\POL@sturmname _\the\POL@count _}% + \unless\ifnum\POL@sturm@N=\POL@count + \advance\POL@count\@ne + \repeat }% -\def\POL@ToSturm@DoSturm{% - \PolMakePrimitive{\POL@sturmname _0_}% +\def\POL@tosturm@dosturm{% \POL@Diff@@one{\POL@sturmname _0_}{\POL@sturmname _1_}% % re-utiliser \POL@varcoeffs directement? - \PolMakePrimitive{\POL@sturmname _1_}% + \POL@makeprimitive{\POL@sturmname _1_}% does not do \POL@newpol \POL@count\@ne \xintloop \POL@divide{\POL@sturmname _\the\numexpr\POL@count-\@ne\relax _}% @@ -750,6 +775,7 @@ \expandafter\let \csname POLuserpol@\POL@sturmname _\the\POL@count _\endcsname\POL@R \edef\POL@makeprim@icontent{-\POL@icontent\POL@polR}% + % this avoids the \POL@newpol from \PolMapCoeffs \POL@mapcoeffs\POL@makeprim@macro{\POL@sturmname _\the\POL@count _}% \repeat \edef\POL@sturm@N{\the\POL@count}% @@ -763,13 +789,13 @@ \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}% + \POL@mapcoeffs\POL@aux@toint{\POL@sturmname _\the\POL@count}% \ifnum\POL@count>\z@ \repeat \@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\@ne % attention to include last one also + \xintloop \advance\POL@count\m@ne \expandafter\let \csname POLuserpol@\POL@sturmname _\the\POL@count\expandafter\endcsname @@ -777,7 +803,7 @@ \ifnum\POL@count>\z@ \repeat \fi - % Back to \POL@ToSturm + % Back to \PolToSturm@, \POL@count holds 0 }% \newcommand\PolSturmChainLength[1] {\romannumeral`^^@\csname PolSturmChainLength_#1\endcsname}% @@ -791,19 +817,19 @@ }% \def\POL@sturmchain@getSV@at#1{% ATTENTION USES \POL@count \def\POL@sturmchain@SV{0}% - \edef\POL@sturmchain@sign{\xintiiSgn{\Pol@Eval{\POL@sturmname _0}{#1}}}% + \edef\POL@sturmchain@sign{\xintiiSgn{\POL@eval{\POL@sturmname _0}{#1}}}% \let\POL@isolz@lastsign\POL@sturmchain@sign \POL@count \z@ \ifnum\POL@isolz@lastsign=\z@ \edef\POL@isolz@lastsign - {\xintiiSgn{\Pol@Eval{\POL@sturmname _1}{#1}}}% + {\xintiiSgn{\POL@eval{\POL@sturmname _1}{#1}}}% \POL@count \@ne \fi \xintloop \unless\ifnum\POL@sturmlength=\POL@count \advance\POL@count \@ne \edef\POL@isolz@newsign - {\xintiiSgn{\Pol@Eval{\POL@sturmname _\the\POL@count}{#1}}}% + {\xintiiSgn{\POL@eval{\POL@sturmname _\the\POL@count}{#1}}}% \ifnum\POL@isolz@newsign=\numexpr-\POL@isolz@lastsign\relax \edef\POL@sturmchain@SV{\the\numexpr\POL@sturmchain@SV+\@ne}% \let\POL@isolz@lastsign=\POL@isolz@newsign @@ -827,11 +853,431 @@ }% +% 0.6 added starred variant to count multiplicities +% 0.7 added double starred variant to locate all rational roots \newcommand\PolSturmIsolateZeros{\@ifstar {\PolSturmIsolateZerosAndGetMultiplicities}% {\PolSturmIsolateZeros@}% }% -\newcommand\PolSturmIsolateZerosAndGetMultiplicities[2][\empty]{% +\newcommand\PolSturmIsolateZerosAndGetMultiplicities{\@ifstar + {\PolSturmIsolateZerosGetMultiplicitiesAndRationalRoots}% + {\PolSturmIsolateZerosAndGetMultiplicities@}% +}% +% on aurait besoin de ça dans xint, mais il aurait un \xintRaw{#1} alors +\def\POL@xintfrac@getNDE #1% + {\expandafter\POL@xintfrac@getNDE@i\romannumeral`^^@#1}% +\def\POL@xintfrac@getNDE@i #1/#2[#3]#4#5#6{\def#4{#1}\def#5{#2}\def#6{#3}}% +\newcommand\PolSturmIsolateZerosGetMultiplicitiesAndRationalRoots[2][\empty]{% + \PolSturmIsolateZerosAndFindRationalRoots[#1]{#2}% + \ifnum\POL@isolz@NbOfRoots>\z@ + % get multiplicities of irrational (real) roots, if any + \ifnum\POL@findrat@nbofirrroots>\z@ + \POL@findrat@getirrmult + \fi + \POL@isolzmult@defvar@M + \fi +}% +% added at 0.7 +\newcommand\PolSturmIsolateZerosAndFindRationalRoots[2][\empty]{% + % #1 optional E such that roots are searched in -10^E < x < 10^E + % both -10^E and +10^E must not be roots! + % #2 name of Sturm chain (already pre-computed) + \edef\POL@sturmname{#2}% + \edef\POL@sturm@N{\@nameuse{PolSturmChainLength_\POL@sturmname}}% + % isolate the roots (detects case of constant polynomial) + \PolSturmIsolateZeros@{\POL@sturmname}% + \ifnum\POL@isolz@NbOfRoots=\z@ + % no real roots, define empty arrays nevertheless + \begingroup\globaldefs\@ne + \expandafter\xintAssignArray\expandafter\to\csname POL_ZeroMult\POL@sturmname\endcsname + \expandafter\xintAssignArray\expandafter\to\csname POL_RRIndex\POL@sturmname\endcsname + \endgroup + \else + % all we currently know is that multiplicities are at least one + \begingroup\globaldefs\@ne + \expandafter\POL@initarray\csname POL_ZeroMult\POL@sturmname\endcsname{1}% + \endgroup + % on ne va pas utiliser de Horner, mais des divisions par X - x, et ces + % choses vont évoluer, ainsi que le coefficient dominant entier + % (pour \POL@divide entre autres if faut des noms de user pol) + \expandafter\let + \csname POLuserpol@\POL@sturmname\POL@sqfnorr\expandafter\endcsname + \csname POLuserpol@\POL@sturmname _0\endcsname + \expandafter\let + \csname POLuserpol@\POL@sturmname\POL@norr\expandafter\endcsname + \csname POLuserpol@\POL@sturmname _0_\endcsname + % attention formé avec\xintREZ d'où le \xintAbs pas \xintiiAbs + % D and its exponent E will get updated along the way + \edef\POL@findrat@D{\xintAbs{\PolLeadingCoeff{\POL@sturmname _0}}}% + \POL@xintfrac@getNDE\POL@findrat@D\POL@findrat@Dint\POL@_\POL@findrat@Dexp + \xintiiifOne{\POL@findrat@Dint} + {\let\POL@findrat@E\POL@findrat@Dexp} % aussi ok pour 1[0] + {\edef\POL@findrat@E{\the\numexpr\xintLen{\POL@findrat@Dint}% + +\POL@findrat@Dexp}}% + \POL@initarray\POL@IfMultIsKnown\xint_secondoftwo + \let\POL@findrat@nbofirrroots\POL@isolz@NbOfRoots + % find all rational roots, and their multiplicities, + % factor them out in passing from original (Sturm root) polynomial + \ifnum\POL@findrat@E<7 + \PolEnsureIntervalLength{\POL@sturmname}{1}{-\POL@findrat@E}% + \def\POL@findrat@index{1}% + \POL@findrat@loop@secondpass@direct + \else + % we do a first pass scanning for "small" roots p/q (i.e. q < 1000) + \def\POL@findrat@index{1}% + \POL@findrat@loop@firstpass + % and now we do the final pass finding them all + \def\POL@findrat@index{1}% + \PolEnsureIntervalLength{\POL@sturmname}{1}{-\POL@findrat@E}% + \POL@findrat@loop@secondpass + \fi + % declare the new polynomials + \POL@newpol{\POL@sturmname\POL@sqfnorr}% without multiplicities + \POL@newpol{\POL@sturmname\POL@norr}% with multiplicities + % declare the array holding the interval indices for the rational roots + \expandafter\POL@findrat@doRRarray\csname POL_RRIndex\POL@sturmname\endcsname + \fi +}% +\def\POL@findrat@doRRarray#1{% + % il faudrait un \xintAssignArray* qui fasse même expansion que \xintFor* + \edef\POL@temp{% + \xintiloop[1+1] + \romannumeral0\csname POL_ZeroIsKnown\POL@sturmname\xintiloopindex\endcsname + \xintbracediloopindex % I should have named it \xintiloopbracedindex... + {}% + \ifnum\xintiloopindex<\POL@isolz@NbOfRoots\space + \repeat }% + \begingroup\globaldefs1 + % attention de ne surtout pas faire un \expandafter ici, car en cas d'un + % seul item, \xintAssignArray l'unbraces... + \xintAssignArray\POL@temp\to#1% + \endgroup +}% +\def\POL@findrat@loop@firstpass{% + \PolSturmIfZeroExactlyKnown{\POL@sturmname}{\POL@findrat@index}% + \POL@findrat@loop@decimal% get its multiplicity + \POL@findrat@loop@a + \edef\POL@findrat@index{\the\numexpr\POL@findrat@index+\@ne}% + \ifnum\POL@findrat@index>\POL@isolz@NbOfRoots + \else + \expandafter\POL@findrat@loop@firstpass + \fi +}% +\def\POL@findrat@loop@secondpass{% + \PolSturmIfZeroExactlyKnown{\POL@sturmname}{\POL@findrat@index}% + {}% nothing more to be done, already stored + \POL@findrat@loop@b + \edef\POL@findrat@index{\the\numexpr\POL@findrat@index+\@ne}% + \ifnum\POL@findrat@index>\POL@isolz@NbOfRoots + \else + \PolEnsureIntervalLength + {\POL@sturmname}{\POL@findrat@index}{-\POL@findrat@E}% dynamic + \expandafter\POL@findrat@loop@secondpass + \fi +}% +\def\POL@findrat@loop@secondpass@direct{% + \PolSturmIfZeroExactlyKnown{\POL@sturmname}{\POL@findrat@index}% + \POL@findrat@loop@decimal + \POL@findrat@loop@b + \edef\POL@findrat@index{\the\numexpr\POL@findrat@index+\@ne}% + \ifnum\POL@findrat@index>\POL@isolz@NbOfRoots + \else + \PolEnsureIntervalLength + {\POL@sturmname}{\POL@findrat@index}{-\POL@findrat@E}% dynamic + \expandafter\POL@findrat@loop@secondpass@direct + \fi +}% +\def\POL@findrat@loop@decimal{% we have an already found decimal root + % we do not go via @storeit, as it is already stored + % j'ai beaucoup hésité néanmoins, car je pourrais faire \xintIrr ici, + % mais attention aussi à l'interaction avec le \PolDecToString. Les racines + % trouvées directement (qui peuvent être des nombres décimaux) sont elles + % stockées comme fraction irréductibles (modulo action additionnelle de + % \PolDecToString). + \POL@xintfrac@getNDE + {\xintIrr{\POL@xintexprGetVar{\POL@sturmname L_\POL@findrat@index}}[0]}% + \POL@findrat@xN\POL@findrat@xD\POl@_ + % we can't move this to updatequotients because other branch will + % need to do the division first anyhow + \edef\POLuserpol@_findrat@oneterm{1.\noexpand\empty + {\xintiiOpp\POL@findrat@xN/1[0]}{\POL@findrat@xD/1[0]}}% + \POL@divide{\POL@sturmname\POL@sqfnorr}{_findrat@oneterm}% the one without mult. + \POL@findrat@loop@updatequotients + \POL@findrat@loop@getmultiplicity +}% +% lacking from xint 1.3c, but \xintSgn has overhead, so we define ii version +\def\xintiiifNeg{\romannumeral0\xintiiifneg }% +\def\xintiiifneg #1% +{% + \ifcase \xintiiSgn{#1} + \expandafter\xint_stop_atsecondoftwo + \or\expandafter\xint_stop_atsecondoftwo + \else\expandafter\xint_stop_atfirstoftwo + \fi +}% +\def\POL@findrat@getE #1/1[#2]{#2}% /1 as it should be there. +% so an error will arise if not but cf \POL@refine@getE where I did not put it +\def\POL@findrat@loop@a{% + % we do a first pass to identify roots with denominators < 1000 + \PolEnsureIntervalLength{\POL@sturmname}{\POL@findrat@index}{-6}% + % attention that the width may have been already smaller than 10^{-6} + % also attention that one of the bound may be zero + \POL@get@IsoLeft@rawin + \POL@get@IsoRight@rawin + \edef\POL@findrat@localW + {\the\numexpr-\expandafter\POL@findrat@getE + % do I really need the \xintREZ? + \romannumeral0\xintrez + {\xintSub{\POL@IsoRight@rawin}{\POL@IsoLeft@rawin}}% + }% at least 6, maybe larger + \expandafter\POL@get@Int@aux + \POL@IsoLeft@rawin\POL@IsoLeft@Int{-\POL@findrat@localW}% + \expandafter\POL@get@Int@aux + \POL@IsoRight@rawin\POL@IsoRight@Int{-\POL@findrat@localW}% + % in case of odd, some waste here + \edef\POL@findrat@halflocalW{\the\numexpr(\POL@findrat@localW+1)/2-1}% + % Legendre Theorem will be used now but we separate a branch where + % everything can be done with \numexpr + \ifnum\POL@findrat@localW>10 + % not implemented yet by lazyness! + % this root will be handled in second pass only + \else + \POL@findrat@gcdloop + \fi +}% +\def\POL@findrat@gcdloop{% + % we must be careful with sign (attention one of the bounds may be zero) + \let\POL@findrat@IfNeg\xint_secondoftwo + \xintiiifSgn\POL@IsoLeft@Int + \POL@findrat@gcdloop@n + \POL@findrat@gcdloop@zero + \POL@findrat@gcdloop@p +}% +\def\POL@findrat@gcdloop@n{% + \let\POL@findrat@IfNeg\xint_firstoftwo + \let\POL@temp\POL@IsoRight@Int + \edef\POL@IsoRight@Int{\xintiiOpp{\POL@IsoLeft@Int}}% + \edef\POL@IsoLeft@Int{\xintiiOpp{\POL@temp}}% + \xintiiifSgn\POL@IsoLeft@Int + \POL@error % impossible branch + \POL@findrat@gcdloop@zero + \POL@findrat@gcdloop@p +}% +\def\POL@findrat@gcdloop@zero{% + % the continued fraction would be the one of 1/2, so only 1/2 to test... + \edef\POL@findrat@x + {1/2\romannumeral\xintreplicate{\POL@findrat@localW}{0}[0]}% + \POL@findrat@gcdloop@testit +}% +\def\POL@findrat@gcdloop@p{% + \edef\POL@findrat@gcdloop@Ap{\xintDec{\xintDouble\POL@IsoRight@Int}}% + \edef\POL@findrat@gcdloop@A + {2\romannumeral\xintreplicate\POL@findrat@localW{0}}% + \xintAssign + \xintiiDivision\POL@findrat@gcdloop@Ap\POL@findrat@gcdloop@A + \to\POL@findrat@gcdloop@B\POL@findrat@gcdloop@An + % on fait de la tambouille pour n'utiliser que \numexpr par la suite + % le reste @An est < 2.10^10 au pire donc ok pour \numexpr + % we will drop integral part in our updating P + \let\POL@findrat@gcdloop@Binitial\POL@findrat@gcdloop@B + \def\POL@findrat@gcdloop@B{0}% do as if B1 = 0 + \def\POL@findrat@gcdloop@Pp{1}% P0 + \def\POL@findrat@gcdloop@P{0}% P1 + \def\POL@findrat@gcdloop@Qp{0}% Q0 + \def\POL@findrat@gcdloop@Q{1}% Q1 + % A2=An can not be zero, as Ap (=A0) is odd and A (=A1=200...000) is even + % first Binitial + P1/Q1 ( = Binitial) can not be root + \let\POL@findrat@gcdloop@Ap\POL@findrat@gcdloop@A % A1 + \let\POL@findrat@gcdloop@A\POL@findrat@gcdloop@An % A2 + \def\next{\POL@findrat@gcdloop@update}% + \def\POL@findrat@gcdloop@done{0}% + \POL@findrat@gcdloop@body +}% +\def\POL@findrat@gcdloop@body{% + % annoying that \numexpr has no divmod... use counts? but groups annoying + \edef\POL@findrat@gcdloop@B + {\the\numexpr(\POL@findrat@gcdloop@Ap+\POL@findrat@gcdloop@A/2)/% + \POL@findrat@gcdloop@A - \@ne}% + \edef\POL@findrat@gcdloop@An + {\the\numexpr\POL@findrat@gcdloop@Ap-% + \POL@findrat@gcdloop@B*\POL@findrat@gcdloop@A}% + \edef\POL@findrat@gcdloop@Pn + {\the\numexpr\POL@findrat@gcdloop@Pp+% + \POL@findrat@gcdloop@B*\POL@findrat@gcdloop@P}% + \edef\POL@findrat@gcdloop@Qn + {\the\numexpr\POL@findrat@gcdloop@Qp+% + \POL@findrat@gcdloop@B*\POL@findrat@gcdloop@Q}% + \ifnum\expandafter\xintLength\expandafter{\POL@findrat@gcdloop@Qn}% + >\POL@findrat@halflocalW\space + \let\next\empty % no solution was found + \else + % with these conditions on denom, only candidates are by Legendre + % theorem among the convergents as computed here + \ifnum\POL@findrat@gcdloop@Qn>\POL@findrat@gcdloop@An\space + % means that P/Q is in interval and is thus a candidate + % it is automatically irreducible + \edef\POL@findrat@x{\xintiiAdd + {\xintiiMul{\POL@findrat@gcdloop@Qn}{\POL@findrat@gcdloop@Binitial}}% + {\POL@findrat@gcdloop@Pn}/\POL@findrat@gcdloop@Qn[0]}% + \POL@findrat@gcdloop@testit + \if1\POL@findrat@gcdloop@done + \let\next\empty % a solution was found + \fi + \fi + \fi + \next +}% +\def\POL@findrat@gcdloop@update{% + \ifnum\POL@findrat@gcdloop@An>\z@ + \let\POL@findrat@gcdloop@Ap\POL@findrat@gcdloop@A + \let\POL@findrat@gcdloop@A\POL@findrat@gcdloop@An + \let\POL@findrat@gcdloop@Pp\POL@findrat@gcdloop@P + \let\POL@findrat@gcdloop@P\POL@findrat@gcdloop@Pn + \let\POL@findrat@gcdloop@Qp\POL@findrat@gcdloop@Q + \let\POL@findrat@gcdloop@Q\POL@findrat@gcdloop@Qn + \expandafter\POL@findrat@gcdloop@body + \fi +}% +\def\POL@findrat@gcdloop@testit{% + % zero should never occur here + \POL@findrat@IfNeg{\edef\POL@findrat@x{-\POL@findrat@x}}{}% + \POL@xintfrac@getNDE\POL@findrat@x\POL@findrat@xN\POL@findrat@xD\POL@_ + \edef\POLuserpol@_findrat@oneterm{1.\noexpand\empty + {\xintiiOpp{\POL@findrat@xN}/1[0]}{\POL@findrat@xD/1[0]}}% + \POL@divide{\POL@sturmname\POL@sqfnorr}{_findrat@oneterm}% the one without mult. + \expandafter\POL@split\POL@R;\POL@degR\POL@polR + \ifnum\POL@degR=\m@ne % found a root + \POL@findrat@loop@storeit + \POL@findrat@loop@updatequotients + \POL@findrat@loop@getmultiplicity % will continue updating the mult. one + \def\POL@findrat@gcdloop@done{1}% + \else + \fi +}% +% This is second phase +\def\POL@findrat@loop@b{% + \edef\POL@findrat@Lscaled{\xintMul{\POL@findrat@D}% + {\POL@xintexprGetVar{\POL@sturmname L_\POL@findrat@index}}}% + \edef\POL@findrat@Rscaled{\xintMul{\POL@findrat@D}% + {\POL@xintexprGetVar{\POL@sturmname R_\POL@findrat@index}}}% + \xintiiifNeg{\POL@findrat@Lscaled}% using ii version is an abuse + {% negative interval (right bound possibly zero!) + % truncate towards zero (i.e. to the right) the left bound + \edef\POL@findrat@Num{\xintNum{\POL@findrat@Lscaled}/1[0]}% + % interval boundaries are not root hence in case that was exact + % this will not be found as a root; check if in interval + \xintifLt\POL@findrat@Num\POL@findrat@Rscaled + \POL@findrat@loop@c + {}% iterate + }% + {% positive interval (left bound possibly zero!) + % truncate towards zero (i.e. to the left) the right bound + \edef\POL@findrat@Num{\xintNum{\POL@findrat@Rscaled}/1[0]}% + % check if in interval + \xintifGt\POL@findrat@Num\POL@findrat@Lscaled + \POL@findrat@loop@c + {}% iterate + }% +}% +\def\POL@findrat@loop@c{% + % safer to do the edef as \POL@findrat@x used later in storeit + \edef\POL@findrat@x{\xintIrr{\xintDiv\POL@findrat@Num\POL@findrat@D}[0]}% + \POL@xintfrac@getNDE\POL@findrat@x\POL@findrat@xN\POL@findrat@xD\POL@_ + \edef\POLuserpol@_findrat@oneterm{1.\noexpand\empty + {\xintiiOpp{\POL@findrat@xN}/1[0]}{\POL@findrat@xD/1[0]}}% + \POL@divide{\POL@sturmname\POL@sqfnorr}{_findrat@oneterm}% the one without mult. + \expandafter\POL@split\POL@R;\POL@degR\POL@polR + \ifnum\POL@degR=\m@ne % found a root + \POL@findrat@loop@storeit + \POL@findrat@loop@updatequotients + \POL@findrat@loop@getmultiplicity % will continue updating the mult. one + \fi + % iterate +}% +\def\POL@findrat@loop@storeit{% + % update storage, I can not use storeleftandright here (due to rawout etc...) + \expandafter + \xdef\csname POL_ZeroInt\POL@sturmname L\POL@findrat@index\endcsname + {\PolDecToString{\POL@findrat@x}}% + \global\expandafter + \let\csname POL_ZeroInt\POL@sturmname R\POL@findrat@index\expandafter\endcsname + \csname POL_ZeroInt\POL@sturmname L\POL@findrat@index\endcsname + \global\expandafter + \let\csname POL_ZeroIsKnown\POL@sturmname\POL@findrat@index\endcsname + \xint_stop_atfirstoftwo + \begingroup\xintglobaldefstrue + \xintdefvar + \POL@sturmname L_\POL@findrat@index,% + \POL@sturmname R_\POL@findrat@index,% + \POL@sturmname Z_\POL@findrat@index _isknown + := qfrac(\POL@findrat@x),qfrac(\POL@findrat@x),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 + % 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 + \POL@mapcoeffs\POL@aux@toint{\POL@sturmname\POL@norr} + % updating of \POL@findrat@D at end of execution of getmultiplicity +}% +\def\POL@findrat@loop@getmultiplicity{% + % the one without multiplicity must not be divided again! + % check if we have remaining multiplicity + \POL@divide{\POL@sturmname\POL@norr}{_findrat@oneterm}% + \expandafter\POL@split\POL@R;\POL@degR\POL@polR + \ifnum\POL@degR=\m@ne % yes + \expandafter\let\csname POLuserpol@\POL@sturmname\POL@norr\endcsname\POL@Q + \POL@mapcoeffs\POL@aux@toint{\POL@sturmname\POL@norr}% + \expandafter + \xdef + \csname POL_ZeroMult\POL@sturmname\POL@findrat@index\endcsname + {\the\numexpr + \csname POL_ZeroMult\POL@sturmname\POL@findrat@index\endcsname+\@ne}% + \expandafter\POL@findrat@loop@getmultiplicity + \else + % done with multiplicity for this rational root, update stuff + \edef\POL@findrat@nbofirrroots + {\the\numexpr\POL@findrat@nbofirrroots-\@ne}% + \@namedef{POL@IfMultIsKnown\POL@findrat@index}{\xint_firstoftwo}% + \edef\POL@findrat@D{\xintAbs{\PolLeadingCoeff{\POL@sturmname\POL@sqfnorr}}}% + \POL@xintfrac@getNDE\POL@findrat@D\POL@findrat@Dint\POL@_\POL@findrat@Dexp + \xintiiifOne{\POL@findrat@Dint} + {\let\POL@findrat@E\POL@findrat@Dexp} % aussi ok pour 1[0] + {\edef\POL@findrat@E{\the\numexpr\xintLen{\POL@findrat@Dint}% + +\POL@findrat@Dexp}}% + \fi +}% +\def\POL@findrat@getirrmult{% + % first get the GCD of remaining pol with its derivative + \POL@divide{\POL@sturmname\POL@norr}{\POL@sturmname\POL@sqfnorr}% + \expandafter\let + % attention au _ (cf. grosse astuce pour \POL@isolzmult@loop) + \csname POLuserpol@@_1\POL@sturmname _\endcsname\POL@Q + \ifnum\PolDegree{@_1\POL@sturmname _}>\z@ + % il reste des multiplicités (mais peut-être pour des racines complexes) + % (ou pour des racines en-dehors de l'intervalle optionnel) + % attention recyclage ici de \POL@isolzmult@loop qui dépend de + % la grosse astuce avec \@gobble + \POL@makeprimitive{@_1\POL@sturmname _}% + \let\POL@originalsturmname\POL@sturmname + % trick to get isolzmult@loop to define @@lastGCD to @_1sturmname_ + % because it will do \POL@sturmname _\POL@sturm@N _ + \edef\POL@sturmname{@_1\POL@sturmname}% + \let\POL@sturm@N\@gobble% ! + \let\POL@isolz@NbOfRoots@with_unknown_mult\POL@findrat@nbofirrroots + \POL@tosturm@makefirstprimitivefalse + \POL@isolzmult@loop + \POL@tosturm@makefirstprimitivetrue + \let\POL@sturmname\POL@originalsturmname + \fi +}% + + +\newcommand\PolSturmIsolateZerosAndGetMultiplicities@[2][\empty]{% % #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) @@ -845,9 +1291,6 @@ \expandafter\xintAssignArray\expandafter\to\csname POL_ZeroMult\POL@sturmname\endcsname \endgroup \else - % store Sturm chain name for usage in the main loop - \let\POL@originalsturmname\POL@sturmname - \edef\POL@isolzmult@indices{\xintSeq{1}{\POL@isolz@NbOfRoots}}% % all we currently know is that multiplicities are at least one \begingroup\globaldefs\@ne \expandafter\POL@initarray\csname POL_ZeroMult\POL@sturmname\endcsname{1}% @@ -857,61 +1300,92 @@ \ifnum\PolDegree{\POL@sturmname _\POL@sturm@N _}>\z@ % scratch array of flags to signal known multiplicities \POL@initarray\POL@IfMultIsKnown\xint_secondoftwo + % this count has utility for the case there are other roots + % either complex or outside interval (in case of optional argument) \let\POL@isolz@NbOfRoots@with_unknown_mult\POL@isolz@NbOfRoots - \expandafter\expandafter\expandafter\POL@isolzmult@loop + % store Sturm chain name, it is needed and altered in isolzmult@loop + \let\POL@originalsturmname\POL@sturmname + \POL@tosturm@makefirstprimitivefalse + \POL@isolzmult@loop + \POL@tosturm@makefirstprimitivetrue + \let\POL@sturmname\POL@originalsturmname \fi + \POL@isolzmult@defvar@M \fi }% +\def\POL@isolzmult@defvar@M{% + % Attention that is used not only in ...GetMultiplicities@ but also + % in FindRationalRoots + \begingroup\xintglobaldefstrue + % added at 0.7 + \let\x\POL@isolz@NbOfRoots + \xintloop + \xintdefvar \POL@sturmname M_\x + := \csname POL_ZeroMult\POL@sturmname\x\endcsname ;% + \edef\x{\the\numexpr\x-\@ne}% + \ifnum\x>\z@ + \repeat + \endgroup +}% \def\POL@isolzmult@loop{% - % we are here only if last iteration gave a new PGCD still of degree > 0 - % As 0.6 \PolToSturm keeps memory of unnormalized Sturm chain, we use the - % PGCD from last iteration and generate a new Sturm chain. - % ATTENTION: first argument of \PolToSturm MUST NOT CONTAIN \POL@sturmname - \let\POL@@sturmname\POL@sturmname - % ATTENTION: we could use an underscore prefix to the name, but attention - % to tacit multiplication if used in an expression; however \PolEvalAt - % does not use expression parsing as \PolEvalAtExpr so this would be - % relatively safe. We must also not overwrite privately used names - % by polexpr or xint... Using prefix @_1 appears safe. They will accumulate. - % As the loop may break at any moment, depending on original P, not only - % on current polynomial which is examined to see if it has zeros, it does - % not seem to make sense to think about interface to keep memory of all - % the defined polynomials. - % \POL@sturm@N supposedly the one from last iteration - \PolToSturm{\POL@@sturmname _\POL@sturm@N _}{@_1\POL@@sturmname}% + % we are here only if last iteration gave a new GCD still of degree > 0 + % \POL@sturm@N is the one from last iteration + % Attention to not use \POL@sturmname directly in first arg. of \PolToSturm + % Attention that we need for the case of known roots also to have the last + % GCD (with its multiplicities) known as a genuine polynomial + % - because of usage of \POL@eval in @isknown branch + % - because \PolToSturm@ does a \POL@let which would be anomalous + % if the extended structure is not existing + \edef\POL@isolzmult@lastGCD{\POL@sturmname _\POL@sturm@N _}% + \edef\POL@isolzmult@newsturmname{@_1\POL@sturmname}% + \POL@newpol{\POL@isolzmult@lastGCD}% + \PolToSturm@{\POL@isolzmult@lastGCD}{\POL@isolzmult@newsturmname}% % now both \POL@sturmname and \POL@sturm@N have changed - % if GCD is now a constant, we will not come back here - \edef\POL@sturmfinaldeg{\PolDegree{\POL@sturmname _\POL@sturm@N _}}% - \xintFor* ##1 in {\POL@isolzmult@indices}\do - {% - \csname POL@IfMultIsKnown##1\endcsname - {}% nothing to do - {\def\POL@isolzmult@index{##1}% - \POL@SturmIfZeroExactlyKnown{\POL@originalsturmname}{##1}% - \POL@isolzmult@loop@zero_isknown - \POL@isolzmult@loop@zero_isnotknown - \POL@isolzmult@loop@sharedbody - }% - }% - \ifnum\POL@sturmfinaldeg>\z@ + \edef\POL@isolzmult@newGCDdegree{\PolDegree{\POL@sturmname _\POL@sturm@N _}}% + \let\POL@isolzmult@index\POL@isolz@NbOfRoots + \xintloop + % ATTENTION that this executes macros which also modifies \POL@sturmname! + % (but not \POL@sturm@N) + \POL@isolzmult@doone + \edef\POL@isolzmult@index{\the\numexpr\POL@isolzmult@index-\@ne}% + \if1\ifnum\POL@isolz@NbOfRoots@with_unknown_mult=\z@ 0\fi + \ifnum\POL@isolzmult@index=\z@ 0\fi 1% + \repeat + \let\POL@sturmname\POL@isolzmult@newsturmname + \if1\ifnum\POL@isolz@NbOfRoots@with_unknown_mult=\z@ 0\fi + % (if new GCD is constant, time to abort) + \ifnum\POL@isolzmult@newGCDdegree=\z@ 0\fi 1% \expandafter\POL@isolzmult@loop \fi }% -\def\POL@isolzmult@loop@zero_isknown{% +\def\POL@isolzmult@doone{% + \csname POL@IfMultIsKnown\POL@isolzmult@index\endcsname + {}% nothing to do + {\POL@SturmIfZeroExactlyKnown{\POL@originalsturmname}% + {\POL@isolzmult@index}% + \POL@isolzmult@loop@isknown + \POL@isolzmult@loop@isnotknown + \POL@isolzmult@loop@sharedbody + }% +}% +\def\POL@isolzmult@loop@isknown{% \xintifZero - {\Pol@Eval{\POL@sturmname _0_}% + % attention that \POL@eval requires a declared polynomial + {\POL@eval{\POL@isolzmult@lastGCD}% {\POL@xintexprGetVar{\POL@originalsturmname L_\POL@isolzmult@index}}}% {\let\POL@isolzmult@haszero\@ne}% {\let\POL@isolzmult@haszero\z@}% }% -\def\POL@isolzmult@loop@zero_isnotknown{% +\def\POL@isolzmult@loop@isnotknown{% \edef\POL@isolzmult@loop@A {\POL@xintexprGetVar{\POL@originalsturmname L_\POL@isolzmult@index}} \edef\POL@isolzmult@loop@B - {\POL@xintexprGetVar{\POL@originalsturmname R_\POL@isolzmult@index}} + {\POL@xintexprGetVar{\POL@originalsturmname + R_\POL@isolzmult@index}} + % attention that \PolSetToNbOfZerosWithin sets \POL@sturmname to 2nd argument \PolSetToNbOfZerosWithin \POL@isolzmult@haszero % nb of zeros A < x <= B, here 0 or 1 - \POL@sturmname + \POL@isolzmult@newsturmname \POL@isolzmult@loop@A \POL@isolzmult@loop@B }% @@ -928,10 +1402,6 @@ \@namedef{POL@IfMultIsKnown\POL@isolzmult@index}{\xint_firstoftwo}% \edef\POL@isolz@NbOfRoots@with_unknown_mult {\the\numexpr\POL@isolz@NbOfRoots@with_unknown_mult-\@ne}% - \ifnum\POL@isolz@NbOfRoots@with_unknown_mult=\z@ - \def\POL@sturmfinaldeg{0}% flag to force termination - \expandafter\expandafter\expandafter\xintBreakFor - \fi \fi }% @@ -1039,7 +1509,7 @@ }% % utility macro for a priori bound on root decimal exponent, via Float Rounding \def\POL@isolz@updateE #1e#2;% -{\unless\ifnum#2<\POL@isolz@E\space\edef\POL@isolz@E{\the\numexpr#2+\@ne}\fi}% + {\unless\ifnum#2<\POL@isolz@E\space\edef\POL@isolz@E{\the\numexpr#2+\@ne}\fi}% \def\POL@isolz@getaprioribound{% \PolAssign{\POL@sturmname _0}\toarray\POL@arrayA \edef\POL@isolz@leading{\POL@arrayA{\POL@arrayA{0}}}% @@ -1067,12 +1537,14 @@ \def\POL@IsoRight@raw{\POL@IsoRight@Int/1[\POL@isolz@E]}% \def\POL@IsoLeft@raw {\POL@IsoLeft@Int/1[\POL@isolz@E]}% \def\POL@IsoRight@rawout{% - \ifnum\POL@IsoRightSign=\z@\expandafter\xintREZ\fi\POL@IsoRight@raw}% + \ifnum\POL@IsoRightSign=\z@\expandafter\xintREZ\fi\POL@IsoRight@raw +}% \def\POL@IsoLeft@rawout{% \ifnum\POL@IsoRightSign=\z@ \expandafter\xint_firstoftwo\else\expandafter\xint_secondoftwo \fi{\xintREZ\POL@IsoRight@raw}% - {\POL@IsoLeft@Int/1[\POL@isolz@E]}}% + {\POL@IsoLeft@Int/1[\POL@isolz@E]}% +}% \def\POL@isolz@main {% % NOTE 2018/02/16. THIS WILL PRESUMABLY BE RE-ORGANIZED IN FUTURE TO DO % FIRST POSITIVE ROOTS THEN NEGATIVE ROOTS VIA CHANGE OF VARIABLE TO OPPOSITE. @@ -1090,116 +1562,137 @@ \edef\POL@IsoRightSV{\the\numexpr\POL@IsoRightSV+\@ne}% % subtlety here if original polynomial had multiplicities, but ok. I checked! \edef\POL@IsoRightSign % evaluated twice, but that's not so bad - {\xintiiOpp{\xintiiSgn{\Pol@Eval{\POL@sturmname _1}{0/1[0]}}}}% + {\xintiiOpp{\xintiiSgn{\POL@eval{\POL@sturmname _1}{0/1[0]}}}}% \fi \def\POL@IsoLeft@Int{-1}% -10^E isn't a root! \let\POL@IsoLeftSV \POL@isolz@minusinf@SV \let\POL@IsoLeftSign\POL@isolz@minusinf@sign + % \POL@IsoRight@SV was modified if zero is a root \edef\POL@isolz@NbOfNegRoots{\the\numexpr\POL@IsoLeftSV-\POL@IsoRightSV}% \gdef\POL@isolz@IntervalIndex{0}% - \begingroup - \let\POL@IsoAtZeroSV\POL@IsoRightSV % locally shifted if root at zero - \let\POL@IsoAtZeroSign\POL@IsoRightSign + \let\POL@isolz@@E\POL@isolz@E \ifnum\POL@isolz@NbOfNegRoots>\z@ - \def\POL@IsoRight@Int{-1}% - \xintloop - \edef\POL@isolz@E{\the\numexpr\POL@isolz@E-\@ne}% - \POL@sturmchain@getSV@at\POL@IsoRight@raw - \let\POL@IsoRightSV \POL@sturmchain@SV - \let\POL@IsoRightSign\POL@sturmchain@sign - % would an \ifx test be quicker? (to be checked) - \ifnum\POL@IsoRightSV=\POL@IsoLeftSV\space - % no roots in-between, sign and SV kept - \repeat - \def\POL@IsoLeft@Int{-10}% - \let\POL@@IsoRightSign\POL@IsoRightSign % zero possible - \let\POL@@IsoRightSV\POL@IsoRightSV - \xintloop - \edef\POL@IsoRight@Int{\the\numexpr\POL@IsoLeft@Int+\@ne}% -% we could arguably do a more efficient dichotomy here - \POL@sturmchain@getSV@at\POL@IsoRight@raw - \let\POL@IsoRightSV \POL@sturmchain@SV - \let\POL@IsoRightSign\POL@sturmchain@sign - \POL@isolz@check - \ifnum\POL@isolz@IntervalIndex=\POL@isolz@NbOfNegRoots\space - \expandafter\xintbreakloop - \fi - \let\POL@IsoLeft@Int\POL@IsoRight@Int - \let\POL@IsoLeftSign\POL@IsoRightSign - \let\POL@IsoLeftSV\POL@IsoRightSV - \ifnum\POL@IsoRight@Int < -\tw@ - \repeat - \ifnum\POL@isolz@IntervalIndex<\POL@isolz@NbOfNegRoots\space - \def\POL@IsoRight@Int{-1}% - \let\POL@IsoRightSign\POL@@IsoRightSign - \let\POL@IsoRightSV\POL@@IsoRightSV - \POL@isolz@check - \ifnum\POL@isolz@IntervalIndex<\POL@isolz@NbOfNegRoots\space - \def\POL@IsoLeft@Int{-1}% - \let\POL@IsoLeftSign\POL@IsoRightSign - \let\POL@IsoLeftSV\POL@IsoRightSV - \def\POL@IsoRight@Int{0}% - \let\POL@IsoRightSV\POL@IsoAtZeroSV % altered if 0 was a root - \let\POL@IsoRightSign\POL@IsoAtZeroSign% id. -% this will recurse to locate roots with smaller decimal exponents - \POL@isolz@check % attention that this should not re-evaluate at 0 - \fi - \fi +% refactored at 0.7 to fix cases leading to an intervals with zero as end-point + \POL@isolz@findroots@neg \fi - \endgroup + \let\POL@isolz@E\POL@isolz@@E \def\POL@IsoLeft@Int{0}% - \let\POL@IsoLeftSV \POL@IsoAtZeroSV - \let\POL@IsoLeftSign\POL@IsoAtZeroSign + \let\POL@IsoLeftSV \POL@IsoAtZeroSV % véritable SV en zéro + \let\POL@IsoLeftSign\POL@IsoAtZeroSign% véritable signe en zéro \ifnum\POL@IsoLeftSign=\z@ \xdef\POL@isolz@IntervalIndex{\the\numexpr\POL@isolz@IntervalIndex+\@ne}% - \global\POL@isolz@nextwillneedrefinetrue - \else - \global\POL@isolz@nextwillneedrefinefalse \fi \let\POL@@IsoRightSV \POL@isolz@plusinf@SV \let\POL@@IsoRightSign\POL@isolz@plusinf@sign % 10^E not a root! \edef\POL@isolz@NbOfPosRoots {\the\numexpr\POL@IsoLeftSV-\POL@@IsoRightSV}% attention @@ \ifnum\POL@isolz@NbOfPosRoots>\z@ - \def\POL@IsoRight@Int{1}% - \xintloop - \edef\POL@isolz@E{\the\numexpr\POL@isolz@E-\@ne}% - \POL@sturmchain@getSV@at\POL@IsoRight@raw - \let\POL@IsoRightSV \POL@sturmchain@SV - \let\POL@IsoRightSign\POL@sturmchain@sign - \ifnum\POL@IsoRightSV=\POL@@IsoRightSV\space - \let\POL@@IsoRightSign\POL@IsoRightSign % root here possible! - \repeat - \unless\ifnum\POL@IsoRightSV=\POL@IsoLeftSV\space - \POL@isolz@check % will recurse inside groups if needed - \fi - \def\POL@IsoLeft@Int{1}% - \let\POL@IsoLeftSV\POL@IsoRightSV - \let\POL@IsoLeftSign\POL@IsoRightSign - \xintloop -% we could arguably do a more efficient dichotomy here - \edef\POL@IsoRight@Int{\the\numexpr\POL@IsoLeft@Int+\@ne}% - \POL@sturmchain@getSV@at\POL@IsoRight@raw - \let\POL@IsoRightSV \POL@sturmchain@SV - \let\POL@IsoRightSign\POL@sturmchain@sign - \POL@isolz@check - \let\POL@IsoLeft@Int\POL@IsoRight@Int - \let\POL@IsoLeftSign\POL@IsoRightSign - \let\POL@IsoLeftSV\POL@IsoRightSV - \ifnum\POL@isolz@IntervalIndex=\POL@isolz@NbOfRoots\space - \expandafter\xintbreakloop - \fi - \ifnum\POL@IsoLeft@Int < \xint_c_ix - \repeat - \ifnum\POL@isolz@IntervalIndex<\POL@isolz@NbOfRoots\space - % get now the last, rightmost, root (or roots) - \def\POL@IsoRight@Int{10}% - \let\POL@IsoRightSign\POL@@IsoRightSign - \let\POL@IsoRightSV\POL@@IsoRightSV - \POL@isolz@check - \fi + % always do that to avoid zero as end-point whether it is a root or not + \global\POL@isolz@nextwillneedrefinetrue + \POL@isolz@findroots@pos + \fi +}% +\def\POL@isolz@findroots@neg{% + \def\POL@IsoRight@Int{-1}% + \POL@isolz@findnextzeroboundeddecade@neg + \def\POL@IsoLeft@Int{-10}% + \let\POL@@IsoRightSign\POL@IsoRightSign % a zero there is possible + \let\POL@@IsoRightSV \POL@IsoRightSV + % this will do possibly recursive \POL@isolz@check's + \POL@isolz@explorenexteightsubdecades@neg + \ifnum\POL@isolz@IntervalIndex<\POL@isolz@NbOfNegRoots\space + % above did not explore -2, -1 for this optimization (SV known at Right) + \def\POL@IsoRight@Int{-1}% + \let\POL@IsoRightSign\POL@@IsoRightSign + \let\POL@IsoRightSV \POL@@IsoRightSV + \POL@isolz@check + \ifnum\POL@isolz@IntervalIndex<\POL@isolz@NbOfNegRoots\space + \def\POL@IsoLeft@Int{-1}% + \let\POL@IsoLeftSign\POL@@IsoRightSign + \let\POL@IsoLeftSV \POL@@IsoRightSV + % I don't like being inside TeX conditionals + \expandafter\expandafter\expandafter\POL@isolz@findroots@neg + \fi + \fi +}% +\def\POL@isolz@findnextzeroboundeddecade@neg{% + \xintloop + \edef\POL@isolz@E{\the\numexpr\POL@isolz@E-\@ne}% + \POL@sturmchain@getSV@at\POL@IsoRight@raw + \let\POL@IsoRightSV \POL@sturmchain@SV + \let\POL@IsoRightSign\POL@sturmchain@sign + % would an \ifx test be quicker? (to be checked) + \ifnum\POL@IsoRightSV=\POL@IsoLeftSV\space + % no roots in-between, iterate + \repeat +}% +\def\POL@isolz@explorenexteightsubdecades@neg{% + \xintloop + \edef\POL@IsoRight@Int{\the\numexpr\POL@IsoLeft@Int+\@ne}% + % we could arguably do a more efficient dichotomy here + \POL@sturmchain@getSV@at\POL@IsoRight@raw + \let\POL@IsoRightSV \POL@sturmchain@SV + \let\POL@IsoRightSign\POL@sturmchain@sign + \POL@isolz@check % may recurse if multiple roots are to be found + \ifnum\POL@isolz@IntervalIndex=\POL@isolz@NbOfNegRoots\space + \expandafter\xintbreakloop + \fi + \let\POL@IsoLeft@Int\POL@IsoRight@Int + \let\POL@IsoLeftSign\POL@IsoRightSign + \let\POL@IsoLeftSV\POL@IsoRightSV + \ifnum\POL@IsoRight@Int < -\tw@ + \repeat +}% +\def\POL@isolz@findroots@pos{% + % remark (2018/12/08), this needs some refactoring, I hardly understand + % the logic and it hides most into the recursion done by \POL@isolz@check + % It would probably make more sense to proceed like done for the negative + % but here finding the largest roots first. + \def\POL@IsoRight@Int{1}% + \POL@isolz@findnextzeroboundeddecade@pos + \unless\ifnum\POL@IsoRightSV=\POL@IsoLeftSV\space + % this actually explores the whole of some interval (0, 10^{e-1}] + % in a context where some roots are known to be in (10^{e-1}, 10^{e}] + % and none are larger + \POL@isolz@check % will recurse inside groups if needed with modified E + \fi + % we know get the roots in the last 9 decades from 10^{e-1} to 10^{e} + % we should arguably do a more efficient dichotomy here + \def\POL@IsoLeft@Int{1}% + \let\POL@IsoLeftSV\POL@IsoRightSV + \let\POL@IsoLeftSign\POL@IsoRightSign + \xintloop + \edef\POL@IsoRight@Int{\the\numexpr\POL@IsoLeft@Int+\@ne}% + \POL@sturmchain@getSV@at\POL@IsoRight@raw + \let\POL@IsoRightSV \POL@sturmchain@SV + \let\POL@IsoRightSign\POL@sturmchain@sign + \POL@isolz@check % recurses in needed + \let\POL@IsoLeft@Int\POL@IsoRight@Int + \let\POL@IsoLeftSign\POL@IsoRightSign + \let\POL@IsoLeftSV\POL@IsoRightSV + \ifnum\POL@isolz@IntervalIndex=\POL@isolz@NbOfRoots\space + \expandafter\xintbreakloop + \fi + \ifnum\POL@IsoLeft@Int < \xint_c_ix + \repeat + \ifnum\POL@isolz@IntervalIndex<\POL@isolz@NbOfRoots\space + % get now the last, rightmost, root (or roots) + \def\POL@IsoRight@Int{10}% + \let\POL@IsoRightSign\POL@@IsoRightSign + \let\POL@IsoRightSV\POL@@IsoRightSV + \POL@isolz@check \fi }% +\def\POL@isolz@findnextzeroboundeddecade@pos{% + \xintloop + \edef\POL@isolz@E{\the\numexpr\POL@isolz@E-\@ne}% + \POL@sturmchain@getSV@at\POL@IsoRight@raw + \let\POL@IsoRightSV \POL@sturmchain@SV + \let\POL@IsoRightSign\POL@sturmchain@sign + \ifnum\POL@IsoRightSV=\POL@@IsoRightSV\space + \let\POL@@IsoRightSign\POL@IsoRightSign % root here possible! + \repeat +}% \def\POL@isolz@check{% \POL@IsoRightSign must be ready for use here % \ifxintverbose % \xintMessage{polexpr}{Info}% @@ -1220,7 +1713,7 @@ \ifPOL@isolz@nextwillneedrefine \expandafter\expandafter\expandafter\POL@isolz@refine \else - % \POL@IsoRightSign is zero iff root now exactly know + % \POL@IsoRightSign is zero iff root now exactly known \POL@refine@storeleftandright \ifnum\POL@IsoRightSign=\z@ \global\POL@isolz@nextwillneedrefinetrue @@ -1275,7 +1768,7 @@ \edef\POL@IsoLeft@Int {\xintDSL{\POL@IsoLeft@Int}}% \edef\POL@IsoRight@Int{\xintInc{\POL@IsoLeft@Int}}% \edef\POL@IsoRightSign - {\xintiiSgn{\Pol@Eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% + {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% \ifnum\POL@IsoRightSign=\POL@@IsoRightSign\space \repeat % now second root has been separated from the one at left end point @@ -1294,7 +1787,7 @@ \else \edef\POL@IsoRight@Int{\xintDec{\POL@@IsoRight@Int}}% \edef\POL@IsoRightSign - {\xintiiSgn{\Pol@Eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% + {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% \ifnum\POL@IsoRightSign=\POL@@IsoRightSign\space \POL@refine@doonce % we need to locate in interval (1, 9) in local scale \else @@ -1319,17 +1812,17 @@ \let\POL@@IsoRightSign\POL@IsoRightSign \edef\POL@IsoRight@Int{\xintiiAdd{4}{\POL@IsoLeft@Int}}% 5 \edef\POL@IsoRightSign - {\xintiiSgn{\Pol@Eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% + {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% \ifnum\POL@IsoRightSign=\POL@IsoLeftSign\space \let\POL@IsoLeft@Int\POL@IsoRight@Int % 5 \edef\POL@IsoRight@Int{\xintiiAdd{2}{\POL@IsoLeft@Int}}% \edef\POL@IsoRightSign - {\xintiiSgn{\Pol@Eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% + {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% \ifnum\POL@IsoRightSign=\POL@IsoLeftSign\space \let\POL@IsoLeft@Int\POL@IsoRight@Int % 7 \edef\POL@IsoRight@Int{\xintInc{\POL@IsoLeft@Int}}% \edef\POL@IsoRightSign - {\xintiiSgn{\Pol@Eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% + {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% \ifnum\POL@IsoRightSign=\POL@IsoLeftSign\space \let\POL@IsoLeft@Int\POL@IsoRight@Int % 8 \let\POL@IsoRight@Int\POL@@IsoRight@Int % 9 @@ -1343,7 +1836,7 @@ \let\POL@@IsoRight@Int\POL@IsoRight@Int % 7 \edef\POL@IsoRight@Int{\xintInc{\POL@IsoLeft@Int}}% 6 \edef\POL@IsoRightSign - {\xintiiSgn{\Pol@Eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% + {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% \ifnum\POL@IsoRightSign=\POL@IsoLeftSign\space \let\POL@IsoLeft@Int\POL@IsoRight@Int % 6 \let\POL@IsoRight@Int\POL@@IsoRight@Int % 7 @@ -1358,12 +1851,12 @@ \let\POL@@IsoRight@Int\POL@IsoRight@Int % 5 \edef\POL@IsoRight@Int{\xintiiAdd{2}{\POL@IsoLeft@Int}}% \edef\POL@IsoRightSign - {\xintiiSgn{\Pol@Eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% + {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% \ifnum\POL@IsoRightSign=\POL@IsoLeftSign\space \let\POL@IsoLeft@Int\POL@IsoRight@Int % 3 \edef\POL@IsoRight@Int{\xintInc{\POL@IsoLeft@Int}}% 4 \edef\POL@IsoRightSign - {\xintiiSgn{\Pol@Eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% + {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% \ifnum\POL@IsoRightSign=\POL@IsoLeftSign\space \let\POL@IsoLeft@Int\POL@IsoRight@Int % 4 \let\POL@IsoRight@Int\POL@@IsoRight@Int % 5 @@ -1377,7 +1870,7 @@ \let\POL@@IsoRight@Int\POL@IsoRight@Int % 3 \edef\POL@IsoRight@Int{\xintInc{\POL@IsoLeft@Int}}% 2 \edef\POL@IsoRightSign - {\xintiiSgn{\Pol@Eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% + {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% \ifnum\POL@IsoRightSign=\POL@IsoLeftSign\space \let\POL@IsoLeft@Int\POL@IsoRight@Int % 2 \let\POL@IsoRight@Int\POL@@IsoRight@Int % 3 @@ -1395,35 +1888,43 @@ \xdef\csname POL_ZeroInt\POL@sturmname R\POL@isolz@IntervalIndex\endcsname {\PolDecToString{\POL@IsoRight@rawout}}% - \begingroup\xintglobaldefstrue - \xintdefvar\POL@sturmname - L_\POL@isolz@IntervalIndex:=qfrac(\POL@IsoLeft@rawout);% - \xintdefvar\POL@sturmname - R_\POL@isolz@IntervalIndex:=qfrac(\POL@IsoRight@rawout);% - \endgroup - % added at 0.6+ + % added at 0.6 \ifnum\POL@IsoRightSign=\z@ \global \expandafter \let\csname POL_ZeroIsKnown\POL@sturmname\POL@isolz@IntervalIndex\endcsname \xint_stop_atfirstoftwo \fi + \begingroup\xintglobaldefstrue + \xintdefvar + \POL@sturmname L_\POL@isolz@IntervalIndex,% + \POL@sturmname R_\POL@isolz@IntervalIndex,% + % added at 0.7 + \POL@sturmname Z_\POL@isolz@IntervalIndex _isknown + := qfrac(\POL@IsoLeft@rawout),% + qfrac(\POL@IsoRight@rawout),% + \ifnum\POL@IsoRightSign=\z@ 1\else 0\fi;% + \endgroup }% %% \PolRefineInterval \def\POL@xintexprGetVar#1{\expandafter\expandafter\expandafter \XINT_expr_unlock\csname XINT_expr_var_#1\endcsname}% -\def\POL@set@IsoLeft@rawin{% +% attention, also used by \POL@findrat@loop@a +\def\POL@get@IsoLeft@rawin{% \edef\POL@IsoLeft@rawin {\POL@xintexprGetVar{\POL@sturmname L_\POL@isolz@IntervalIndex}}% }% -\def\POL@set@IsoRight@rawin{% +% attention, also used by \POL@findrat@loop@a +\def\POL@get@IsoRight@rawin{% \edef\POL@IsoRight@rawin {\POL@xintexprGetVar{\POL@sturmname R_\POL@isolz@IntervalIndex}}% }% -\def\POL@set@IsoLeft@Int #1/1[#2]{% - \edef\POL@IsoLeft@Int{\xintDSH{\POL@isolz@E-#2}{#1}}% +% attention, also used by \POL@findrat@loop@a +\def\POL@get@Int@aux #1/1[#2]#3#4{\edef#3{\xintDSH{#4-#2}{#1}}}% +\def\POL@get@IsoLeft@Int{% + \expandafter\POL@get@Int@aux\POL@IsoLeft@rawin\POL@IsoLeft@Int\POL@isolz@E }% \newcommand\PolRefineInterval{\@ifstar\POL@srefine@start\POL@refine@start}% \newcommand\POL@refine@start[3][1]{% @@ -1441,19 +1942,19 @@ \POL@refine@main}% }% \def\POL@refine@sharedbody#1{% - \POL@set@IsoLeft@rawin + \POL@get@IsoLeft@rawin \edef\POL@IsoLeftSign - {\xintiiSgn{\Pol@Eval{\POL@sturmname _0}{\POL@IsoLeft@rawin}}}% + {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoLeft@rawin}}}% \ifnum\POL@IsoLeftSign=\z@ % do nothing if that interval was already a singleton \else % else both end-points are not roots and there is a single one in-between - \POL@set@IsoRight@rawin + \POL@get@IsoRight@rawin \edef\POL@IsoRightSign{\the\numexpr-\POL@IsoLeftSign}% \edef\POL@isolz@E{\expandafter\POL@refine@getE % je pense que le xintrez ici est superflu \romannumeral0\xintrez{\xintSub{\POL@IsoRight@rawin}{\POL@IsoLeft@rawin}}}% - \expandafter\POL@set@IsoLeft@Int\POL@IsoLeft@rawin + \POL@get@IsoLeft@Int \edef\POL@IsoRight@Int{\xintInc{\POL@IsoLeft@Int}}% #1% \POL@refine@storeleftandright % \POL@IsoRightSign not zero @@ -1478,7 +1979,7 @@ \let\POL@@IsoRightSign\POL@IsoRightSign \edef\POL@IsoRight@Int{\xintInc{\POL@IsoLeft@Int}}% \edef\POL@IsoRightSign - {\xintiiSgn{\Pol@Eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% + {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% \ifnum\POL@IsoRightSign=\z@ \let\POL@IsoLeft@Int\POL@IsoRight@Int % root at 1 \def\POL@IsoLeftSign{0}% @@ -1491,7 +1992,7 @@ \let\POL@IsoLeft@Int\POL@IsoRight@Int \edef\POL@IsoRight@Int{\xintDec{\POL@@IsoRight@Int}}% \edef\POL@IsoRightSign - {\xintiiSgn{\Pol@Eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% + {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% \ifnum\POL@IsoRightSign=\z@ \let\POL@IsoLeft@Int\POL@IsoRight@Int % root at 9 \def\POL@IsoLeftSign{0}% @@ -1525,11 +2026,16 @@ \newcommand\PolEnsureIntervalLengths[2]{% #1 = Sturm chain name, % localize roots in intervals of length at most 10^{#2} - \POL@count\z@ - % \POL@count used by \POL@sturmchain@getSV@at but latter not used \edef\POL@sturmname{#1}% \edef\POL@ensure@targetE{\the\numexpr#2}% - \edef\POL@nbofroots{\csname POL_ZeroInt\POL@sturmname L\endcsname 0}% + \edef\POL@nbofroots{\csname POL_ZeroInt\POL@sturmname L0\endcsname}% + \ifnum\POL@nbofroots>\z@ + \expandafter\POL@ensureintervallengths + \fi +}% +\def\POL@ensureintervallengths{% + \POL@count\z@ + % \POL@count used by \POL@sturmchain@getSV@at but latter not used \xintloop \advance\POL@count\@ne \edef\POL@isolz@IntervalIndex{\the\POL@count}% @@ -1543,20 +2049,27 @@ \edef\POL@sturmname{#1}% \edef\POL@ensure@targetE{\the\numexpr#3}% \edef\POL@isolz@IntervalIndex{\the\numexpr#2}% - \POL@ensure@one +% peut-être autoriser -1, -2, ... ? + \ifnum\POL@isolz@IntervalIndex>\z@ +% 0.7, add this safeguard but attention means this structure must be in place + \ifnum\csname POL_ZeroInt\POL@sturmname L0\endcsname>\z@ +% je ne fais pas les \expandafter mais je préfèrerai ne pas être à l'intérieur + \POL@ensure@one + \fi + \fi }% \def\POL@ensure@one{% - \POL@set@IsoLeft@rawin - \POL@set@IsoRight@rawin + \POL@get@IsoLeft@rawin + \POL@get@IsoRight@rawin \edef\POL@ensure@delta{\xintREZ{\xintSub{\POL@IsoRight@rawin}{\POL@IsoLeft@rawin}}}% \xintiiifZero{\POL@ensure@delta} {} {\edef\POL@isolz@E{\expandafter\POL@refine@getE\POL@ensure@delta}% - \expandafter\POL@set@IsoLeft@Int\POL@IsoLeft@rawin + \POL@get@IsoLeft@Int \edef\POL@IsoRight@Int{\xintInc{\POL@IsoLeft@Int}}% \ifnum\POL@isolz@E>\POL@ensure@targetE\space \edef\POL@IsoLeftSign - {\xintiiSgn{\Pol@Eval{\POL@sturmname _0}{\POL@IsoLeft@raw}}}% + {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoLeft@raw}}}% % at start left and right are not roots, and values of opposite signs % \edef\POL@IsoRightSign{\the\numexpr-\POL@IsoLeftSign}% \xintloop @@ -1576,7 +2089,7 @@ \xintloop \edef\POL@IsoRight@Int{\xintInc{\POL@IsoLeft@Int}}% \edef\POL@IsoRightSign - {\xintiiSgn{\Pol@Eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% + {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% % if we have found a zero at right boundary the \ifnum test will fail % and we exit the loop % else we exit the loop if sign at right boundary is opposite of @@ -1595,54 +2108,119 @@ \catcode`_ 8 -\newcommand\PolPrintIntervals[2][Z]{% - \POL@count \@nameuse{POL_ZeroInt#2L}{0} - \ifnum\POL@count=\z@ -% No real roots.\par +\newcommand\PolPrintIntervals + {\@ifstar{\PolPrintIntervals@@}{\PolPrintIntervals@}}% +\newcommand\PolPrintIntervals@@{% + \begingroup + \def\POL@AfterPrintIntervals{\endgroup}% + \def\arraystretch{2}% + \let\PolPrintIntervalsPrintExactZero\POL@@PrintIntervalsPrintExactZero + \let\PolPrintIntervalsUnknownRoot\POL@@PrintIntervalsUnknownRoot + \let\PolPrintIntervalsKnownRoot\POL@@PrintIntervalsKnownRoot + \def\PolPrintIntervalsBeginEnv{\[\begin{array}{cl}}%\] + \def\PolPrintIntervalsEndEnv{\end{array}\]}% + \PolPrintIntervals@ +}% +\newcommand\PolPrintIntervals@[2][Z]{\POL@PrintIntervals{#1}{#2}}% +\newcommand\POL@PrintIntervals[2]{% + \def\PolPrintIntervalsTheSturmName{#2}% + \def\PolPrintIntervalsTheVar{#1}% + \ifnum\@nameuse{POL_ZeroInt#2L}{0}=\z@ + \PolPrintIntervalsNoRealRoots \else -% There are \the\POL@count\space distinct real roots:\par - \[\count@\POL@count - \global\POL@count\@ne - \begin{array}{rcccl} - \xintloop - \POL@SturmIfZeroExactlyKnown{#2}\POL@count - {% exact root - && - #1_{\the\POL@count}&=& - \POL@printintervals@prepare{#2R}% - \PolPrintIntervalsPrintExactZero - }% - {% interval with root in its strict interior - \POL@printintervals@prepare{#2L}% - \PolPrintIntervalsPrintLeftEndPoint&<& - #1_{\the\POL@count}&<& - \POL@printintervals@prepare{#2R}% - \PolPrintIntervalsPrintRightEndPoint - }% - \global\advance\POL@count\@ne - \unless\ifnum\POL@count>\count@ - \\% - \repeat - \end{array}\] + \gdef\PolPrintIntervalsTheIndex{1}% + \POL@PrintIntervals@DoDefs + \begingroup\edef\POL@tmp{\endgroup + \unexpanded\expandafter{\PolPrintIntervalsBeginEnv}% + \unexpanded\expandafter{\POL@PrintIntervals@Loop}% + \unexpanded\expandafter{\PolPrintIntervalsEndEnv}% + }\POL@tmp \fi + \POL@AfterPrintIntervals +}% +\let\POL@AfterPrintIntervals\@empty +\newcommand\PolPrintIntervalsNoRealRoots{}% +\newcommand\PolPrintIntervalsBeginEnv{\[\begin{array}{rcccl}}% +\newcommand\PolPrintIntervalsEndEnv{\end{array}\]}% +\newcommand\PolPrintIntervalsKnownRoot{% + &&\PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}% + &=&\PolPrintIntervalsPrintExactZero +}% +\newcommand\PolPrintIntervalsUnknownRoot{% + \PolPrintIntervalsPrintLeftEndPoint&<&% + \PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}&<&% + \PolPrintIntervalsPrintRightEndPoint +}% +\newcommand\PolPrintIntervalsPrintExactZero {\PolPrintIntervalsTheLeftEndPoint}% +\newcommand\PolPrintIntervalsPrintLeftEndPoint {\PolPrintIntervalsTheLeftEndPoint}% +\newcommand\PolPrintIntervalsPrintRightEndPoint{\PolPrintIntervalsTheRightEndPoint}% +\newcommand\PolPrintIntervalsPrintMultiplicity{(\mbox{mult. }\PolPrintIntervalsTheMultiplicity)}% +% +\newcommand\POL@@PrintIntervalsKnownRoot{% + \PolPrintIntervalsPrintMultiplicity&% + \PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}=% + \PolPrintIntervalsPrintExactZero +}% +\newcommand\POL@@PrintIntervalsPrintExactZero{% + \displaystyle + \xintSignedFrac{\PolPrintIntervalsTheLeftEndPoint}% +}% +\newcommand\POL@@PrintIntervalsUnknownRoot{% + \PolPrintIntervalsPrintMultiplicity&% + \xintifSgn{\PolPrintIntervalsTheLeftEndPoint}% + {\xintifSgn{\PolPrintIntervalsTheRightEndPoint} + {\PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}=% + \PolPrintIntervalsPrintRightEndPoint\dots}% + {0>\PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}>% + \PolPrintIntervalsPrintLeftEndPoint}% + {\PolErrorThisShouldNotHappenPleaseReportToAuthorA}}% + {\xintifSgn{\PolPrintIntervalsTheRightEndPoint} + {\PolErrorThisShouldNotHappenPleaseReportToAuthorB}% + {\PolErrorThisShouldNotHappenPleaseReportToAuthorC}% + {0<\PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}<% + \PolPrintIntervalsPrintRightEndPoint}}% + {\xintifSgn{\PolPrintIntervalsTheRightEndPoint} + {\PolErrorThisShouldNotHappenPleaseReportToAuthorD}% + {\PolErrorThisShouldNotHappenPleaseReportToAuthorE}% + {\PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}=% + \PolPrintIntervalsPrintLeftEndPoint\dots}}% }% +% \catcode`_ 11 -\newcommand\PolPrintIntervalsPrintExactZero {\PolPrintIntervalsTheEndPoint}% -\newcommand\PolPrintIntervalsPrintLeftEndPoint {\PolPrintIntervalsTheEndPoint}% -\newcommand\PolPrintIntervalsPrintRightEndPoint{\PolPrintIntervalsTheEndPoint}% -\def\POL@printintervals@prepare#1{% - \edef\PolPrintIntervalsTheIndex{\the\POL@count}% - \edef\PolPrintIntervalsTheEndPoint{\@nameuse{POL_ZeroInt#1}\POL@count}% - \xintiiifSgn{\POL@xintexprGetVar{#1_\PolPrintIntervalsTheIndex}} - {\let\PolIfEndPointIsPositive\xint_secondoftwo - \let\PolIfEndPointIsNegative\xint_firstoftwo - \let\PolIfEndPointIsZero\xint_secondoftwo} - {\let\PolIfEndPointIsPositive\xint_secondoftwo - \let\PolIfEndPointIsNegative\xint_secondoftwo - \let\PolIfEndPointIsZero\xint_firstoftwo} - {\let\PolIfEndPointIsPositive\xint_firstoftwo - \let\PolIfEndPointIsNegative\xint_secondoftwo - \let\PolIfEndPointIsZero\xint_secondoftwo}% +\def\POL@PrintIntervals@Loop{% + \POL@SturmIfZeroExactlyKnown\PolPrintIntervalsTheSturmName + \PolPrintIntervalsTheIndex + \PolPrintIntervalsKnownRoot + \PolPrintIntervalsUnknownRoot + \xdef\PolPrintIntervalsTheIndex{\the\numexpr\PolPrintIntervalsTheIndex+\@ne}% + \unless\ifnum\PolPrintIntervalsTheIndex> + \@nameuse{POL_ZeroInt\PolPrintIntervalsTheSturmName L0} + \POL@PrintIntervals@DoDefs + \xint_afterfi{\\\POL@PrintIntervals@Loop}% + \fi +}% +\def\POL@PrintIntervals@DoDefs{% + \xdef\PolPrintIntervalsTheLeftEndPoint{% + \csname POL_ZeroInt% + \PolPrintIntervalsTheSturmName L\PolPrintIntervalsTheIndex + \endcsname + }% + \xdef\PolPrintIntervalsTheRightEndPoint{% + \csname POL_ZeroInt% + \PolPrintIntervalsTheSturmName R\PolPrintIntervalsTheIndex + \endcsname + }% + \xdef\PolPrintIntervalsTheMultiplicity{% + \ifcsname POL_ZeroMult% + \PolPrintIntervalsTheSturmName\PolPrintIntervalsTheIndex + \endcsname + \csname POL_ZeroMult% + \PolPrintIntervalsTheSturmName\PolPrintIntervalsTheIndex + \endcsname + \else + ?% or use 0 ? + \fi + }% }% @@ -1650,18 +2228,38 @@ \romannumeral0\csname POL_ZeroIsKnown#1\endcsname{#2}% }% \newcommand\POL@SturmIfZeroExactlyKnown[2]{% #1 = sturmname, #2=index - \romannumeral0\csname POL_ZeroIsKnown#1\the\numexpr#2\relax\endcsname + \romannumeral0\csname POL_ZeroIsKnown#1\the\numexpr#2\endcsname }% \newcommand\PolSturmIsolatedZeroMultiplicity[2]{% \romannumeral`^^@\csname POL_ZeroMult#1\endcsname{#2}% }% \newcommand\PolSturmIsolatedZeroLeft[2]{% - \romannumeral`^^@\csname POL_ZeroInt#1L\endcsname{#2}}% + \romannumeral`^^@\csname POL_ZeroInt#1L\endcsname{#2}% +}% \newcommand\PolSturmIsolatedZeroRight[2]{% - \romannumeral`^^@\csname POL_ZeroInt#1R\endcsname{#2}}% + \romannumeral`^^@\csname POL_ZeroInt#1R\endcsname{#2}% +}% \newcommand\PolSturmNbOfIsolatedZeros[1]{% \romannumeral`^^@\csname POL_ZeroInt#1L0\endcsname }% +\newcommand\PolSturmRationalRoot[2]{% + \romannumeral`^^@\csname POL_ZeroInt#1L% + \csname POL_RRIndex#1\endcsname{#2}\endcsname +}% +\newcommand\PolSturmRationalRootIndex[2]{% + \romannumeral`^^@\csname POL_RRIndex#1\endcsname{#2}% +}% +\newcommand\PolSturmRationalRootMultiplicity[2]{% + \romannumeral`^^@\csname POL_ZeroMult#1% + \csname POL_RRIndex#1\endcsname{#2}\endcsname +}% +\newcommand\PolSturmNbOfRationalRoots[1]{% + \romannumeral`^^@\csname POL_RRIndex#10\endcsname +}% +\newcommand\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 @@ -2023,18 +2621,18 @@ %% EXPANDABLE MACROS -\def\Pol@Eval@fork#1\At#2#3\krof{#2}% -\newcommand\PolEval[3]{\romannumeral`^^@\Pol@Eval@fork +\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_userfunc_#1\endcsname{#2}}}% -\newcommand\Pol@Eval[2] +\newcommand\POL@eval[2] {\csname XINT_expr_userfunc_#1\endcsname{#2}}% \newcommand\PolEvalAtExpr[2]{\xinttheexpr #1(#2)\relax}% % -\newcommand\PolEvalReduced[3]{\romannumeral`^^@\Pol@Eval@fork +\newcommand\PolEvalReduced[3]{\romannumeral`^^@\POL@eval@fork #2\PolEvalReducedAt \At\PolEvalReducedAtExpr\krof {#1}{#3}% }% @@ -2047,7 +2645,7 @@ {\xintIrr{\romannumeral`^^@\xintthebareeval#1(#2)\relax}[0]}% }% % -\newcommand\PolFloatEval[3]{\romannumeral`^^@\Pol@Eval@fork +\newcommand\PolFloatEval[3]{\romannumeral`^^@\POL@eval@fork #2\PolFloatEvalAt \At\PolFloatEvalAtExpr\krof {#1}{#3}% }% @@ -2056,37 +2654,48 @@ \newcommand\PolFloatEvalAtExpr[2]{\xintthefloatexpr #1(#2)\relax}% -\newcommand\PolSturmMultiplicity[3]{\romannumeral`^^@\Pol@Eval@fork - #2\PolSturmMultiplicityAt - \At\PolSturmMultiplicityAtExpr\krof {#1}{#3}% +\newcommand\PolSturmIntervalIndex[3]{\the\numexpr\POL@eval@fork + #2\PolSturmIntervalIndexAt + \At\PolSturmIntervalIndexAtExpr\krof {#1}{#3}% }% -\newcommand\PolSturmMultiplicityAtExpr[2] - {\PolSturmMultiplicityAt{#1}{\xinttheexpr#2\relax}}% -\newcommand\PolSturmMultiplicityAt[2] - {\expandafter\POL@sturm@mult@at\romannumeral`^^@#2!{#1}}% -\def\POL@sturm@mult@at#1!#2% +\newcommand\PolSturmIntervalIndexAtExpr[2] + {\PolSturmIntervalIndexAt{#1}{\xinttheexpr#2\relax}}% +\newcommand\PolSturmIntervalIndexAt[2] + {\expandafter\POL@sturm@index@at\romannumeral`^^@#2!{#1}\xint_bye\relax}% +\def\POL@sturm@index@at#1!#2% {% - \xintifZero{\Pol@Eval{#2_0}{#1}}% - {\POL@sturm@mult@at@iloop 1!{#2}{#1}}% we have a zero - 0% not a zero + \expandafter\POL@sturm@index@at@iloop + \romannumeral`^^@\PolSturmNbOfIsolatedZeros{#2}!{#2}{#1}% }% -\def\POL@sturm@mult@at@iloop #1!#2#3% +% implementation is sub-optimal as it should use some kind of binary tree +% search rather than comparing to the intervals from right to left as here +\def\POL@sturm@index@at@iloop #1!% +{% + \ifnum #1=\z@ 0\expandafter\xint_bye\fi + \POL@sturm@index@at@iloop@a #1!% +}% +\def\POL@sturm@index@at@iloop@a #1!#2#3% {% #1 = index, #2 = sturmname, #3 value - \PolSturmIfZeroExactlyKnown{#2}{#1}% - {\xintifEq{\POL@xintexprGetVar{#2L_#1}}{#3}% - {\PolSturmIsolatedZeroMultiplicity{#2}{#1}}% -% catcode of ! is 11 in polexpr.sty - {\expandafter\POL@sturm@mult@at@iloop\the\numexpr#1+\@ne !{#2}{#3}}% + \PolSturmIfZeroExactlyKnown{#2}{#1} + {\xintifCmp{#3}{\POL@xintexprGetVar{#2L_#1}}% + {}% + {#1\xint_bye}% + {0\xint_bye}% }% - {\xintifLt{#3}{\POL@xintexprGetVar{#2R_#1}}% - {\PolSturmIsolatedZeroMultiplicity{#2}{#1}}% - {\expandafter\POL@sturm@mult@at@iloop\the\numexpr#1+\@ne !{#2}{#3}}% + {\xintifGt{#3}{\POL@xintexprGetVar{#2L_#1}}% + {\xintifLt{#3}{\POL@xintexprGetVar{#2R_#1}}% + {#1\xint_bye}% + {0\xint_bye}% + }% + {}% }% + % catcode of ! is 11 in polexpr.sty + \expandafter\POL@sturm@index@at@iloop\the\numexpr#1-\@ne !{#2}{#3}% }% -\def\Pol@LessThanOrEqualTo@fork#1\LessThanOrEqualTo#2#3\krof{#2}% -\newcommand\PolSturmNbOfRootsOf[3]{\romannumeral`^^@\Pol@LessThanOrEqualTo@fork +\def\POL@leq@fork#1\LessThanOrEqualTo#2#3\krof{#2}% +\newcommand\PolSturmNbOfRootsOf[3]{\romannumeral`^^@\POL@leq@fork #2\PolNbOfRootsLessThanOrEqualTo \LessThanOrEqualTo\PolNbOfRootsLessThanOrEqualToExpr\krof {#1}{#3}% }% @@ -2106,7 +2715,7 @@ \def\POL@nbofrootsleq@prep#1!#2% {% \expandafter\POL@nbofrootsleq@iloop\expandafter 1\expandafter !% - \romannumeral0\xintsgn{\Pol@Eval{#2_0}{#1}}!% + \romannumeral0\xintsgn{\POL@eval{#2_0}{#1}}!% #1!{#2}% }% \def\POL@nbofrootsleq@iloop#1!#2!#3!#4% @@ -2120,7 +2729,7 @@ % the test \xintifLt will be negative {\xintifLt{#3}{\POL@xintexprGetVar{#4R_#1}}% {\POL@nbofrootsleq@return - #1\ifnum#2=\xintSgn{\Pol@Eval{#4_0}{\POL@xintexprGetVar{#4L_#1}}} + #1\ifnum#2=\xintSgn{\POL@eval{#4_0}{\POL@xintexprGetVar{#4L_#1}}} -\@ne\fi !% }% {\ifnum#1=\PolSturmNbOfIsolatedZeros{#4} @@ -2135,9 +2744,8 @@ \the\numexpr\@ne+#1!#2!#3!#4{#1}% -\def\Pol@LessThanOrEqualTo@fork#1\LessThanOrEqualTo#2#3\krof{#2}% \newcommand\PolSturmNbWithMultOfRootsOf[3] -{\the\numexpr0\Pol@LessThanOrEqualTo@fork +{\the\numexpr0\POL@leq@fork #2\PolNbWithMultOfRootsLessThanOrEqualTo \LessThanOrEqualTo\PolNbWithMultOfRootsLessThanOrEqualToExpr\krof {#1}{#3}% }% @@ -2158,7 +2766,7 @@ \def\POL@nbwmofrootsleq@prep#1!#2% {% \expandafter\POL@nbwmofrootsleq@iloop\expandafter 1\expandafter !% - \romannumeral0\xintsgn{\Pol@Eval{#2_0}{#1}}!% + \romannumeral0\xintsgn{\POL@eval{#2_0}{#1}}!% #1!{#2}% }% \def\POL@nbwmofrootsleq@iloop#1!#2!#3!#4% @@ -2174,7 +2782,7 @@ {\xintifLt{#3}{\POL@xintexprGetVar{#4R_#1}}% {\POL@nbwmofrootsleq@return \unless - \ifnum#2=\xintSgn{\Pol@Eval{#4_0}{\POL@xintexprGetVar{#4L_#1}}} + \ifnum#2=\xintSgn{\POL@eval{#4_0}{\POL@xintexprGetVar{#4L_#1}}} +\PolSturmIsolatedZeroMultiplicity{#4}{#1}\fi !% }% {+\PolSturmIsolatedZeroMultiplicity{#4}{#1}% |